summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Pennequin <nicolas.pennequin@free.fr>2007-04-15 02:59:34 +0000
committerNicolas Pennequin <nicolas.pennequin@free.fr>2007-04-15 02:59:34 +0000
commit2e1169bddaa424ae5eef36e2ec12e2a3cb0adc68 (patch)
tree6967092524e64d2365034073efef820b41d31a2d
parentac946416060c19eb6cfe9da3d1885baee329df30 (diff)
downloadrockbox-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.c8
-rw-r--r--apps/gui/gwps.h2
-rw-r--r--apps/gui/wps_debug.c13
-rw-r--r--apps/gui/wps_parser.c64
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)
398void print_wps_strings(struct wps_data *data) 398void 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 */
273static void wps_start_new_subline(struct wps_data *data) { 273static 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
280static 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
281static int parse_statusbar_enable(const char *wps_bufptr, 298static 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
673condlistend: /* 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 }