From a2f2ca6119f74532a16c07199bd478c5a34f2301 Mon Sep 17 00:00:00 2001 From: Georgia Garcia Date: Thu, 31 Jul 2025 18:04:16 -0300 Subject: [PATCH] parser: fix variable expansion When the variable was being expanded, it needed to be reevaluated to check if there was still unresolved variables. That allowed for a weird bug to happen: If the string contained a variable preceded by @, like in "user@@{uid}" and the variable was resolved to a case where { is used, like in @{uid}={[0-9],[1-9][0-9]}, then on the second pass, the parser would try to resolve the following variable @{[0-9],[1-9][0-9]}, which is incorrect behavior. Fix it by not including part of the string that was already resolved on the subsequent passes. Signed-off-by: Georgia Garcia --- .../vars/vars_file_evaluation_17.sd | 7 ++++ parser/variable.cc | 34 +++++++++++++------ 2 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 parser/tst/simple_tests/vars/vars_file_evaluation_17.sd diff --git a/parser/tst/simple_tests/vars/vars_file_evaluation_17.sd b/parser/tst/simple_tests/vars/vars_file_evaluation_17.sd new file mode 100644 index 000000000..b83f3bc7a --- /dev/null +++ b/parser/tst/simple_tests/vars/vars_file_evaluation_17.sd @@ -0,0 +1,7 @@ +#=DESCRIPTION expansion of alternation after extra, unescaped @ +#=EXRESULT PASS +@{uid} = {[0-9],[1-9][0-9]} + +/usr/bin/foo { + /sys/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r, +} diff --git a/parser/variable.cc b/parser/variable.cc index b0deb4097..47dfd6e82 100644 --- a/parser/variable.cc +++ b/parser/variable.cc @@ -189,11 +189,23 @@ static void trim_trailing_slash(std::string& str) str.clear(); // str is all '/' } +int copy_value_to_name(std::string value, char **name) +{ + free(*name); + *name = strdup(value.c_str()); + if (!*name) { + errno = ENOMEM; + return -1; + } + return 0; +} + int variable::expand_by_alternation(char **name) { std::string expanded_name = ""; bool filter_leading_slash = false; bool filter_trailing_slash = false; + int ret = 0; if (!name) { PERROR("ASSERT: name to be expanded cannot be NULL\n"); @@ -226,8 +238,6 @@ int variable::expand_by_alternation(char **name) return 1; } - free(*name); - size_t setsize = ref->expanded.size(); auto i = ref->expanded.begin(); @@ -252,15 +262,19 @@ int variable::expand_by_alternation(char **name) if (setsize > 1) { expanded_name += "}"; } - - expanded_name = prefix + expanded_name + suffix; - *name = strdup(expanded_name.c_str()); - if (!*name) { - errno = ENOMEM; - return -1; - } + /* don't include prefix */ + expanded_name = expanded_name + suffix; + ret = copy_value_to_name(expanded_name, name); + if (ret) + return ret; /* recursive until no variables are found in *name */ - return expand_by_alternation(name); + ret = expand_by_alternation(name); + if (ret == 0) { + /* return prefix to name */ + expanded_name = prefix + std::string(*name); + ret = copy_value_to_name(expanded_name, name); + } + return ret; } int variable::expand_variable()