From 8a61b74ec1eb5cc959cac9e1004545fe4703f035 Mon Sep 17 00:00:00 2001 From: Walter Doekes Date: Tue, 23 Apr 2024 11:20:08 +0200 Subject: [PATCH] Band-aid around missing line numbers in XML parse errors Suggested and reviewed by Michael Stovenour (@mstovenour). Closes: #721 (along with #725) --- include/xp_parser.h | 1 + src/scenario.cpp | 3 ++- src/xp_parser.c | 54 ++++++++++++++++++++++++++++++++++++--------- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/include/xp_parser.h b/include/xp_parser.h index b9d5bd615..663e08d85 100644 --- a/include/xp_parser.h +++ b/include/xp_parser.h @@ -29,6 +29,7 @@ int xp_set_xml_buffer_from_file(const char *filename); char* xp_open_element(int index); void xp_close_element(void); int xp_is_invalid(); +int xp_get_invalid_line(); const char* xp_get_value(const char *name); char* xp_get_cdata(void); int xp_get_content_length(const char *P_buffer); diff --git a/src/scenario.cpp b/src/scenario.cpp index 0ab5757da..e0e3915b5 100644 --- a/src/scenario.cpp +++ b/src/scenario.cpp @@ -1026,7 +1026,8 @@ scenario::scenario(char * filename, int deflt) /* Close scenario element */ xp_close_element(); if (xp_is_invalid()) { - ERROR("Invalid XML in scenario. See: https://github.com/SIPp/sipp/issues/414"); + ERROR("Invalid XML in scenario near line %d. See: https://github.com/SIPp/sipp/issues/414", + xp_get_invalid_line()); } str_int_map::iterator label_it = labelMap.find("_unexp.main"); diff --git a/src/xp_parser.c b/src/xp_parser.c index 0c40d2315..26cb06a75 100644 --- a/src/xp_parser.c +++ b/src/xp_parser.c @@ -51,7 +51,7 @@ static char xp_file[XP_MAX_FILE_LEN + 1]; static char *xp_position[XP_MAX_STACK_LEN]; static int xp_stack = 0; -static int xp_stack_invalid = 0; +static int xp_stack_invalid_line = 0; static char xp_history[XP_MAX_FILE_LEN + 1]; static char *xp_history_pos; @@ -119,6 +119,27 @@ static const char *xp_find_escape(const char *escape, size_t len) return NULL; } +static int xp_get_lineno(const char *endpos) +{ + const char *p = xp_file; + int lf_count = 0; + + if (p < xp_file || p > xp_file + sizeof(xp_file)) { + return -1; + } + + while (p < endpos) { + if (*p == '\n') { + lf_count += 1; + } else if (*p == '\0') { + break; + } + ++p; + } + + return lf_count + 1; +} + #if 0 static void xp_history_debug() { char *p = &xp_history[0]; @@ -280,7 +301,7 @@ int xp_set_xml_buffer_from_string(const char *str) } strcpy(xp_file, str); - xp_stack = xp_stack_invalid = 0; + xp_stack = xp_stack_invalid_line = 0; xp_history_reset(); xp_position[xp_stack] = xp_file; @@ -310,7 +331,7 @@ int xp_set_xml_buffer_from_file(const char *filename) xp_file[index++] = c; if (index >= XP_MAX_FILE_LEN) { xp_file[index++] = 0; - xp_stack = xp_stack_invalid = 0; + xp_stack = xp_stack_invalid_line = 0; xp_history_reset(); xp_position[xp_stack] = xp_file; fclose(f); @@ -320,7 +341,7 @@ int xp_set_xml_buffer_from_file(const char *filename) xp_file[index++] = 0; fclose(f); - xp_stack = xp_stack_invalid = 0; + xp_stack = xp_stack_invalid_line = 0; xp_history_reset(); xp_position[xp_stack] = xp_file; @@ -382,10 +403,10 @@ char *xp_open_element(int index) return NULL; xp_history_pop(); - if (strcmp(xp_history_pos + 1, name) && !xp_stack_invalid) { - xp_stack_invalid = 1; - fprintf(stderr, "Unexpected (expected )\n", - name, xp_history_pos + 1); + if (strcmp(xp_history_pos + 1, name) && !xp_stack_invalid_line) { + xp_stack_invalid_line = xp_get_lineno(ptr); + fprintf(stderr, "Unexpected (expected ) near line %d\n", + name, xp_history_pos + 1, xp_stack_invalid_line); } } else { char *end = xp_find_start_tag_end(ptr + 1); @@ -422,7 +443,7 @@ char *xp_open_element(int index) void xp_close_element() { if (!xp_stack) { - xp_stack_invalid = 1; + xp_stack_invalid_line = -1; return; } xp_stack--; @@ -431,10 +452,12 @@ void xp_close_element() int xp_is_invalid(void) { const char *elem; - if (xp_stack_invalid) { + if (xp_stack_invalid_line) { + /* Found different closing element */ return 1; } if (xp_stack) { + /* Does not happen because main parser never goes deep */ return 1; } if ((elem = xp_open_element(1))) { /* anything after ? */ @@ -444,6 +467,17 @@ int xp_is_invalid(void) return 0; } +int xp_get_invalid_line(void) +{ + if (xp_stack_invalid_line) { + return xp_stack_invalid_line; + } else if (xp_stack == 0) { + return xp_get_lineno(xp_position[1]); + } else { + return -1; + } +} + const char *xp_get_value(const char *name) { int index = 0;