diff options
author | Nicolas Pennequin <nicolas.pennequin@free.fr> | 2007-04-15 02:59:34 +0000 |
---|---|---|
committer | Nicolas Pennequin <nicolas.pennequin@free.fr> | 2007-04-15 02:59:34 +0000 |
commit | 2e1169bddaa424ae5eef36e2ec12e2a3cb0adc68 (patch) | |
tree | 6967092524e64d2365034073efef820b41d31a2d | |
parent | ac946416060c19eb6cfe9da3d1885baee329df30 (diff) | |
download | rockbox-2e1169bddaa424ae5eef36e2ec12e2a3cb0adc68.tar.gz rockbox-2e1169bddaa424ae5eef36e2ec12e2a3cb0adc68.zip |
* 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
-rw-r--r-- | apps/gui/gwps-common.c | 8 | ||||
-rw-r--r-- | apps/gui/gwps.h | 2 | ||||
-rw-r--r-- | apps/gui/wps_debug.c | 13 | ||||
-rw-r--r-- | apps/gui/wps_parser.c | 64 |
4 files changed, 55 insertions, 32 deletions
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) | |||
1279 | } | 1279 | } |
1280 | 1280 | ||
1281 | int ret = index; | 1281 | int ret = index; |
1282 | do | 1282 | while (data->tokens[ret].value.i != 0 |
1283 | && data->tokens[data->tokens[ret].value.i].type != WPS_TOKEN_CONDITIONAL_END) | ||
1283 | ret = data->tokens[ret].value.i; | 1284 | ret = data->tokens[ret].value.i; |
1284 | while (data->tokens[ret].type != WPS_TOKEN_CONDITIONAL_END); | ||
1285 | 1285 | ||
1286 | /* ret now is the index to the end token for the conditional. */ | 1286 | /* ret now is the index to the end token for the conditional. */ |
1287 | return ret; | 1287 | return ret; |
@@ -1307,6 +1307,10 @@ static int evaluate_conditional(struct gui_wps *gwps, int cond_index) | |||
1307 | && cond_start < data->num_tokens) | 1307 | && cond_start < data->num_tokens) |
1308 | cond_start++; | 1308 | cond_start++; |
1309 | 1309 | ||
1310 | /* if the number of options is 0, the conditional is invalid */ | ||
1311 | if (num_options == 0) | ||
1312 | return cond_start; | ||
1313 | |||
1310 | /* treat ?xx<true> constructs as if they had 2 options. */ | 1314 | /* treat ?xx<true> constructs as if they had 2 options. */ |
1311 | if (num_options < 2) | 1315 | if (num_options < 2) |
1312 | num_options = 2; | 1316 | 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 { | |||
76 | #define WPS_MAX_SUBLINES (WPS_MAX_LINES*3) | 76 | #define WPS_MAX_SUBLINES (WPS_MAX_LINES*3) |
77 | #define WPS_MAX_TOKENS 1024 | 77 | #define WPS_MAX_TOKENS 1024 |
78 | #define WPS_MAX_STRINGS 128 | 78 | #define WPS_MAX_STRINGS 128 |
79 | #define STRING_BUFFER_SIZE 512 | 79 | #define STRING_BUFFER_SIZE 1024 |
80 | #define WPS_MAX_COND_LEVEL 10 | 80 | #define WPS_MAX_COND_LEVEL 10 |
81 | 81 | ||
82 | #else | 82 | #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) | |||
398 | void print_wps_strings(struct wps_data *data) | 398 | void print_wps_strings(struct wps_data *data) |
399 | { | 399 | { |
400 | DEBUGF("Strings:\n"); | 400 | DEBUGF("Strings:\n"); |
401 | int i, len = 0; | 401 | int i, len = 0, buf_used = 0; |
402 | for (i=0; i < data->num_strings; i++) | 402 | for (i = 0; i < data->num_strings; i++) |
403 | { | 403 | { |
404 | len += strlen(data->strings[i]); | 404 | len += strlen(data->strings[i]); |
405 | DEBUGF("%2d: '%s'\n", i, data->strings[i]); | 405 | buf_used += strlen(data->strings[i]) + 1; |
406 | DEBUGF("%2d: (%2d) '%s'\n", i, strlen(data->strings[i]), data->strings[i]); | ||
406 | } | 407 | } |
407 | DEBUGF("Total length: %d\n", len); | 408 | DEBUGF("\n"); |
409 | DEBUGF("Total string length: %d\n", len); | ||
410 | DEBUGF("String buffer used: %d out of %d bytes\n", buf_used, STRING_BUFFER_SIZE); | ||
408 | DEBUGF("\n"); | 411 | DEBUGF("\n"); |
409 | } | 412 | } |
410 | 413 | ||
@@ -413,7 +416,7 @@ void print_img_cond_indexes(struct wps_data *data) | |||
413 | { | 416 | { |
414 | DEBUGF("Image conditional indexes:\n"); | 417 | DEBUGF("Image conditional indexes:\n"); |
415 | int i; | 418 | int i; |
416 | for (i=0; i < MAX_IMAGES; i++) | 419 | for (i = 0; i < MAX_IMAGES; i++) |
417 | { | 420 | { |
418 | if (data->img[i].cond_index) | 421 | if (data->img[i].cond_index) |
419 | DEBUGF("%2d: %d\n", i, data->img[i].cond_index); | 422 | 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) | |||
270 | } | 270 | } |
271 | 271 | ||
272 | /* Starts a new subline in the current line during parsing */ | 272 | /* Starts a new subline in the current line during parsing */ |
273 | static void wps_start_new_subline(struct wps_data *data) { | 273 | static void wps_start_new_subline(struct wps_data *data) |
274 | { | ||
274 | data->num_sublines++; | 275 | data->num_sublines++; |
275 | data->sublines[data->num_sublines].first_token_idx = data->num_tokens; | 276 | data->sublines[data->num_sublines].first_token_idx = data->num_tokens; |
276 | data->lines[data->num_lines].num_sublines++; | 277 | data->lines[data->num_lines].num_sublines++; |
277 | } | 278 | } |
278 | 279 | ||
280 | static void close_conditionals(struct wps_data *data, int n) | ||
281 | { | ||
282 | int i; | ||
283 | for (i = 0; i < n; i++) | ||
284 | { | ||
285 | data->tokens[data->num_tokens].type = WPS_TOKEN_CONDITIONAL_END; | ||
286 | if (lastcond[level]) | ||
287 | data->tokens[lastcond[level]].value.i = data->num_tokens; | ||
288 | |||
289 | lastcond[level] = 0; | ||
290 | data->num_tokens++; | ||
291 | data->tokens[condindex[level]].value.i = numoptions[level]; | ||
292 | level--; | ||
293 | } | ||
294 | } | ||
295 | |||
279 | #ifdef HAVE_LCD_BITMAP | 296 | #ifdef HAVE_LCD_BITMAP |
280 | 297 | ||
281 | static int parse_statusbar_enable(const char *wps_bufptr, | 298 | 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) | |||
638 | return false; | 655 | return false; |
639 | 656 | ||
640 | char *current_string = data->string_buffer; | 657 | char *current_string = data->string_buffer; |
658 | int stringbuf_used = 0; | ||
641 | 659 | ||
642 | while(*wps_bufptr && data->num_tokens < WPS_MAX_TOKENS - 1 | 660 | while(*wps_bufptr && data->num_tokens < WPS_MAX_TOKENS - 1 |
643 | && data->num_lines < WPS_MAX_LINES) | 661 | && data->num_lines < WPS_MAX_LINES) |
@@ -652,6 +670,9 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr) | |||
652 | 670 | ||
653 | /* Alternating sublines separator */ | 671 | /* Alternating sublines separator */ |
654 | case ';': | 672 | case ';': |
673 | if (level >= 0) | ||
674 | close_conditionals(data, level + 1); | ||
675 | |||
655 | if (data->num_sublines+1 < WPS_MAX_SUBLINES) | 676 | if (data->num_sublines+1 < WPS_MAX_SUBLINES) |
656 | wps_start_new_subline(data); | 677 | wps_start_new_subline(data); |
657 | else | 678 | else |
@@ -670,17 +691,7 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr) | |||
670 | if (level < 0) /* not in a conditional, ignore the char */ | 691 | if (level < 0) /* not in a conditional, ignore the char */ |
671 | break; | 692 | break; |
672 | 693 | ||
673 | condlistend: /* close a conditional. sometimes we want to close them even when | 694 | close_conditionals(data, 1); |
674 | we don't have a closing token, e.g. at the end of a line. */ | ||
675 | |||
676 | data->tokens[data->num_tokens].type = WPS_TOKEN_CONDITIONAL_END; | ||
677 | if (lastcond[level]) | ||
678 | data->tokens[lastcond[level]].value.i = data->num_tokens; | ||
679 | |||
680 | lastcond[level] = 0; | ||
681 | data->num_tokens++; | ||
682 | data->tokens[condindex[level]].value.i = numoptions[level]; | ||
683 | level--; | ||
684 | break; | 695 | break; |
685 | 696 | ||
686 | /* Conditional list option */ | 697 | /* Conditional list option */ |
@@ -699,19 +710,17 @@ condlistend: /* close a conditional. sometimes we want to close them even when | |||
699 | 710 | ||
700 | /* Comment */ | 711 | /* Comment */ |
701 | case '#': | 712 | case '#': |
713 | if (level >= 0) | ||
714 | close_conditionals(data, level + 1); | ||
715 | |||
702 | wps_bufptr += skip_end_of_line(wps_bufptr); | 716 | wps_bufptr += skip_end_of_line(wps_bufptr); |
703 | break; | 717 | break; |
704 | 718 | ||
705 | /* End of this line */ | 719 | /* End of this line */ |
706 | case '\n': | 720 | case '\n': |
707 | if (level >= 0) | 721 | if (level >= 0) |
708 | { | 722 | close_conditionals(data, level + 1); |
709 | /* We have unclosed conditionals, so we | 723 | |
710 | close them before adding the EOL token */ | ||
711 | wps_bufptr--; | ||
712 | goto condlistend; | ||
713 | break; | ||
714 | } | ||
715 | wps_start_new_subline(data); | 724 | wps_start_new_subline(data); |
716 | data->num_lines++; /* Start a new line */ | 725 | data->num_lines++; /* Start a new line */ |
717 | 726 | ||
@@ -726,29 +735,36 @@ condlistend: /* close a conditional. sometimes we want to close them even when | |||
726 | 735 | ||
727 | /* String */ | 736 | /* String */ |
728 | default: | 737 | default: |
729 | if (data->num_strings < WPS_MAX_STRINGS) | 738 | if (data->num_strings < WPS_MAX_STRINGS |
739 | && stringbuf_used < STRING_BUFFER_SIZE - 1) | ||
730 | { | 740 | { |
731 | data->tokens[data->num_tokens].type = WPS_TOKEN_STRING; | 741 | data->tokens[data->num_tokens].type = WPS_TOKEN_STRING; |
732 | data->strings[data->num_strings] = current_string; | 742 | data->strings[data->num_strings] = current_string; |
733 | data->tokens[data->num_tokens].value.i = data->num_strings++; | 743 | data->tokens[data->num_tokens].value.i = data->num_strings; |
734 | data->num_tokens++; | 744 | data->num_tokens++; |
735 | 745 | ||
736 | /* Copy the first byte */ | 746 | /* Copy the first byte */ |
737 | *current_string++ = *(wps_bufptr - 1); | 747 | *current_string++ = *(wps_bufptr - 1); |
748 | stringbuf_used++; | ||
738 | 749 | ||
739 | /* continue until we hit something that ends the string */ | 750 | /* continue until we hit something that ends the string |
751 | or we run out of memory */ | ||
740 | while(wps_bufptr && *wps_bufptr != '#' && | 752 | while(wps_bufptr && *wps_bufptr != '#' && |
741 | *wps_bufptr != '%' && *wps_bufptr != ';' && | 753 | *wps_bufptr != '%' && *wps_bufptr != ';' && |
742 | *wps_bufptr != '<' && *wps_bufptr != '>' && | 754 | *wps_bufptr != '<' && *wps_bufptr != '>' && |
743 | *wps_bufptr != '|' && *wps_bufptr != '\n') | 755 | *wps_bufptr != '|' && *wps_bufptr != '\n' && |
756 | stringbuf_used < STRING_BUFFER_SIZE - 1) | ||
744 | { | 757 | { |
745 | *current_string++ = *wps_bufptr++; | 758 | *current_string++ = *wps_bufptr++; |
759 | stringbuf_used++; | ||
746 | } | 760 | } |
747 | 761 | ||
748 | /* null terminate the string */ | 762 | /* null terminate the string */ |
749 | *current_string++ = '\0'; | 763 | *current_string++ = '\0'; |
750 | } | 764 | stringbuf_used++; |
751 | 765 | ||
766 | data->num_strings++; | ||
767 | } | ||
752 | break; | 768 | break; |
753 | } | 769 | } |
754 | } | 770 | } |