From 2e1169bddaa424ae5eef36e2ec12e2a3cb0adc68 Mon Sep 17 00:00:00 2001 From: Nicolas Pennequin Date: Sun, 15 Apr 2007 02:59:34 +0000 Subject: * Make the WPS parser close open conditionals on new sublines and comments as well as new lines. * Make the displaying code check for invalid conditional constructs in order to avoid some rare cases of infinite looping. * Make the WPS parser check that it doesn't read more strings than it can. * Increase the string buffer size (from 512 to 1024, to accomodate the TextBox WPS which uses a lot of unicode characters). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13162 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/gwps-common.c | 8 +++++-- apps/gui/gwps.h | 2 +- apps/gui/wps_debug.c | 13 ++++++---- apps/gui/wps_parser.c | 64 +++++++++++++++++++++++++++++++------------------- 4 files changed, 55 insertions(+), 32 deletions(-) (limited to 'apps/gui') diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index 6c58c1d666..b4a2cf9596 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c @@ -1279,9 +1279,9 @@ static int find_conditional_end(struct wps_data *data, int index) } int ret = index; - do + while (data->tokens[ret].value.i != 0 + && data->tokens[data->tokens[ret].value.i].type != WPS_TOKEN_CONDITIONAL_END) ret = data->tokens[ret].value.i; - while (data->tokens[ret].type != WPS_TOKEN_CONDITIONAL_END); /* ret now is the index to the end token for the conditional. */ return ret; @@ -1307,6 +1307,10 @@ static int evaluate_conditional(struct gui_wps *gwps, int cond_index) && cond_start < data->num_tokens) cond_start++; + /* if the number of options is 0, the conditional is invalid */ + if (num_options == 0) + return cond_start; + /* treat ?xx constructs as if they had 2 options. */ if (num_options < 2) num_options = 2; diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h index 7d20bc94cf..801a37902e 100644 --- a/apps/gui/gwps.h +++ b/apps/gui/gwps.h @@ -76,7 +76,7 @@ struct align_pos { #define WPS_MAX_SUBLINES (WPS_MAX_LINES*3) #define WPS_MAX_TOKENS 1024 #define WPS_MAX_STRINGS 128 -#define STRING_BUFFER_SIZE 512 +#define STRING_BUFFER_SIZE 1024 #define WPS_MAX_COND_LEVEL 10 #else diff --git a/apps/gui/wps_debug.c b/apps/gui/wps_debug.c index 96f3e57038..e7d3f4592a 100644 --- a/apps/gui/wps_debug.c +++ b/apps/gui/wps_debug.c @@ -398,13 +398,16 @@ void print_line_info(struct wps_data *data) void print_wps_strings(struct wps_data *data) { DEBUGF("Strings:\n"); - int i, len = 0; - for (i=0; i < data->num_strings; i++) + int i, len = 0, buf_used = 0; + for (i = 0; i < data->num_strings; i++) { len += strlen(data->strings[i]); - DEBUGF("%2d: '%s'\n", i, data->strings[i]); + buf_used += strlen(data->strings[i]) + 1; + DEBUGF("%2d: (%2d) '%s'\n", i, strlen(data->strings[i]), data->strings[i]); } - DEBUGF("Total length: %d\n", len); + DEBUGF("\n"); + DEBUGF("Total string length: %d\n", len); + DEBUGF("String buffer used: %d out of %d bytes\n", buf_used, STRING_BUFFER_SIZE); DEBUGF("\n"); } @@ -413,7 +416,7 @@ void print_img_cond_indexes(struct wps_data *data) { DEBUGF("Image conditional indexes:\n"); int i; - for (i=0; i < MAX_IMAGES; i++) + for (i = 0; i < MAX_IMAGES; i++) { if (data->img[i].cond_index) DEBUGF("%2d: %d\n", i, data->img[i].cond_index); diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_parser.c index e72079ce71..2c7a000367 100644 --- a/apps/gui/wps_parser.c +++ b/apps/gui/wps_parser.c @@ -270,12 +270,29 @@ static int skip_end_of_line(const char *wps_bufptr) } /* Starts a new subline in the current line during parsing */ -static void wps_start_new_subline(struct wps_data *data) { +static void wps_start_new_subline(struct wps_data *data) +{ data->num_sublines++; data->sublines[data->num_sublines].first_token_idx = data->num_tokens; data->lines[data->num_lines].num_sublines++; } +static void close_conditionals(struct wps_data *data, int n) +{ + int i; + for (i = 0; i < n; i++) + { + data->tokens[data->num_tokens].type = WPS_TOKEN_CONDITIONAL_END; + if (lastcond[level]) + data->tokens[lastcond[level]].value.i = data->num_tokens; + + lastcond[level] = 0; + data->num_tokens++; + data->tokens[condindex[level]].value.i = numoptions[level]; + level--; + } +} + #ifdef HAVE_LCD_BITMAP static int parse_statusbar_enable(const char *wps_bufptr, @@ -638,6 +655,7 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr) return false; char *current_string = data->string_buffer; + int stringbuf_used = 0; while(*wps_bufptr && data->num_tokens < WPS_MAX_TOKENS - 1 && data->num_lines < WPS_MAX_LINES) @@ -652,6 +670,9 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr) /* Alternating sublines separator */ case ';': + if (level >= 0) + close_conditionals(data, level + 1); + if (data->num_sublines+1 < WPS_MAX_SUBLINES) wps_start_new_subline(data); else @@ -670,17 +691,7 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr) if (level < 0) /* not in a conditional, ignore the char */ break; -condlistend: /* close a conditional. sometimes we want to close them even when - we don't have a closing token, e.g. at the end of a line. */ - - data->tokens[data->num_tokens].type = WPS_TOKEN_CONDITIONAL_END; - if (lastcond[level]) - data->tokens[lastcond[level]].value.i = data->num_tokens; - - lastcond[level] = 0; - data->num_tokens++; - data->tokens[condindex[level]].value.i = numoptions[level]; - level--; + close_conditionals(data, 1); break; /* Conditional list option */ @@ -699,19 +710,17 @@ condlistend: /* close a conditional. sometimes we want to close them even when /* Comment */ case '#': + if (level >= 0) + close_conditionals(data, level + 1); + wps_bufptr += skip_end_of_line(wps_bufptr); break; /* End of this line */ case '\n': if (level >= 0) - { - /* We have unclosed conditionals, so we - close them before adding the EOL token */ - wps_bufptr--; - goto condlistend; - break; - } + close_conditionals(data, level + 1); + wps_start_new_subline(data); data->num_lines++; /* Start a new line */ @@ -726,29 +735,36 @@ condlistend: /* close a conditional. sometimes we want to close them even when /* String */ default: - if (data->num_strings < WPS_MAX_STRINGS) + if (data->num_strings < WPS_MAX_STRINGS + && stringbuf_used < STRING_BUFFER_SIZE - 1) { data->tokens[data->num_tokens].type = WPS_TOKEN_STRING; data->strings[data->num_strings] = current_string; - data->tokens[data->num_tokens].value.i = data->num_strings++; + data->tokens[data->num_tokens].value.i = data->num_strings; data->num_tokens++; /* Copy the first byte */ *current_string++ = *(wps_bufptr - 1); + stringbuf_used++; - /* continue until we hit something that ends the string */ + /* continue until we hit something that ends the string + or we run out of memory */ while(wps_bufptr && *wps_bufptr != '#' && *wps_bufptr != '%' && *wps_bufptr != ';' && *wps_bufptr != '<' && *wps_bufptr != '>' && - *wps_bufptr != '|' && *wps_bufptr != '\n') + *wps_bufptr != '|' && *wps_bufptr != '\n' && + stringbuf_used < STRING_BUFFER_SIZE - 1) { *current_string++ = *wps_bufptr++; + stringbuf_used++; } /* null terminate the string */ *current_string++ = '\0'; - } + stringbuf_used++; + data->num_strings++; + } break; } } -- cgit v1.2.3