From bd2fb077ac4547705d83c3d0ec0c597b4074657c Mon Sep 17 00:00:00 2001 From: George Joseph Date: Tue, 13 Sep 2022 07:14:37 -0600 Subject: [PATCH] res_geolocation: Fix segfault when there's an empty element Fixed a segfault caused by var_list_from_loc_info() encountering an empty location info element. Fixed an issue in ast_strsep() where a value with only whitespace wasn't being preserved. Fixed an issue in ast_variable_list_from_quoted_string() where an empty value was considered a failure. ASTERISK-30215 Reported by: Dan Cropp Change-Id: Ieca64e061a6d9298f0196c694b60d986ef82613a --- include/asterisk/strings.h | 1 + main/config.c | 13 +++++-------- main/utils.c | 10 ++++++++-- res/res_geolocation/geoloc_eprofile.c | 8 +++++++- tests/test_config.c | 4 ++-- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/include/asterisk/strings.h b/include/asterisk/strings.h index d0a4cbb02a..f8ad4140d8 100644 --- a/include/asterisk/strings.h +++ b/include/asterisk/strings.h @@ -265,6 +265,7 @@ enum ast_strsep_flags { \param sep A single character delimiter. \param flags Controls post-processing of the result. AST_STRSEP_TRIM trims all leading and trailing whitespace from the result. + If the result containes only whitespace, it'll be passed through unchanged. AST_STRSEP_STRIP does a trim then strips the outermost quotes. You may want to trim again after the strip. Just OR both the TRIM and STRIP flags. AST_STRSEP_UNESCAPE unescapes '\' sequences. diff --git a/main/config.c b/main/config.c index 0e27d76640..1074407967 100644 --- a/main/config.c +++ b/main/config.c @@ -646,15 +646,16 @@ struct ast_variable *ast_variable_list_sort(struct ast_variable *start) struct ast_variable *ast_variable_list_append_hint(struct ast_variable **head, struct ast_variable *search_hint, struct ast_variable *newvar) { struct ast_variable *curr; + struct ast_variable *sh = search_hint; ast_assert(head != NULL); if (!*head) { *head = newvar; } else { - if (search_hint == NULL) { - search_hint = *head; + if (sh == NULL) { + sh = *head; } - for (curr = search_hint; curr->next; curr = curr->next); + for (curr = sh; curr->next; curr = curr->next); curr->next = newvar; } @@ -752,12 +753,8 @@ struct ast_variable *ast_variable_list_from_quoted_string(const char *input, con } item_value = ast_strsep_quoted(&item, nv_sep, quote, AST_STRSEP_ALL); - if (!item_value) { - ast_variables_destroy(new_list); - return NULL; - } - new_var = ast_variable_new(item_name, item_value, ""); + new_var = ast_variable_new(item_name, item_value ?: "", ""); if (!new_var) { ast_variables_destroy(new_list); return NULL; diff --git a/main/utils.c b/main/utils.c index 3ab6dc1e70..6111b86dda 100644 --- a/main/utils.c +++ b/main/utils.c @@ -1849,7 +1849,10 @@ char *ast_strsep(char **iss, const char sep, uint32_t flags) } if (flags & AST_STRSEP_TRIM) { - st = ast_strip(st); + char *trimmed = ast_strip(st); + if (!ast_strlen_zero(trimmed)) { + st = trimmed; + } } if (flags & AST_STRSEP_UNESCAPE) { @@ -1910,7 +1913,10 @@ char *ast_strsep_quoted(char **iss, const char sep, const char quote, uint32_t f } if (flags & AST_STRSEP_TRIM) { - st = ast_strip(st); + char *trimmed = ast_strip(st); + if (!ast_strlen_zero(trimmed)) { + st = trimmed; + } } if (flags & AST_STRSEP_UNESCAPE) { diff --git a/res/res_geolocation/geoloc_eprofile.c b/res/res_geolocation/geoloc_eprofile.c index 864dd23b24..09a06c6141 100644 --- a/res/res_geolocation/geoloc_eprofile.c +++ b/res/res_geolocation/geoloc_eprofile.c @@ -498,6 +498,7 @@ static struct ast_variable *var_list_from_loc_info(struct ast_xml_node *locinfo, enum ast_geoloc_format format, const char *ref_str) { struct ast_variable *list = NULL; + struct ast_variable *locinfo_list = NULL; struct ast_xml_node *container; struct ast_variable *var = NULL; const char *attr; @@ -531,7 +532,12 @@ static struct ast_variable *var_list_from_loc_info(struct ast_xml_node *locinfo, ast_variable_list_append(&list, var); } - ast_variable_list_append(&list, var_list_from_node(container, ref_str)); + locinfo_list = var_list_from_node(container, ref_str); + if (locinfo_list == NULL) { + ast_log(LOG_WARNING, "%s: There were no elements in the location info\n", ref_str); + SCOPE_EXIT_RTN_VALUE(list, "%s: There were no elements in the location info\n", ref_str); + } + ast_variable_list_append(&list, locinfo_list); if (TRACE_ATLEAST(5)) { struct ast_str *buf = NULL; diff --git a/tests/test_config.c b/tests/test_config.c index 166879a820..1d44e5d5ba 100644 --- a/tests/test_config.c +++ b/tests/test_config.c @@ -1961,13 +1961,13 @@ AST_TEST_DEFINE(variable_list_from_string) break; } - parse_string = "abc = 'def', ghi = 'j,kl', mno='pq=r', stu = 'vwx=\"yz\", ABC = \"DEF\"'"; + parse_string = "000= '', 111=, 222 = , 333 = ' ', abc = 'def', ghi = 'j,kl', mno='pq=r', stu = 'vwx=\"yz\", ABC = \"DEF\"'"; list = ast_variable_list_from_quoted_string(parse_string, ",", "=", "'"); ast_test_validate(test, list != NULL); str = ast_variable_list_join(list, "|", "^", "@", NULL); ast_test_validate(test, - strcmp(ast_str_buffer(str), "abc^@def@|ghi^@j,kl@|mno^@pq=r@|stu^@vwx=\"yz\", ABC = \"DEF\"@") == 0); + strcmp(ast_str_buffer(str), "000^@@|111^@@|222^@@|333^@ @|abc^@def@|ghi^@j,kl@|mno^@pq=r@|stu^@vwx=\"yz\", ABC = \"DEF\"@") == 0); return AST_TEST_PASS; }