forked from len0rd/rockbox
* 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
This commit is contained in:
parent
ac94641606
commit
2e1169bdda
4 changed files with 55 additions and 32 deletions
|
@ -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<true> constructs as if they had 2 options. */
|
||||
if (num_options < 2)
|
||||
num_options = 2;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue