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;
|
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;
|
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. */
|
/* ret now is the index to the end token for the conditional. */
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1307,6 +1307,10 @@ static int evaluate_conditional(struct gui_wps *gwps, int cond_index)
|
||||||
&& cond_start < data->num_tokens)
|
&& cond_start < data->num_tokens)
|
||||||
cond_start++;
|
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. */
|
/* treat ?xx<true> constructs as if they had 2 options. */
|
||||||
if (num_options < 2)
|
if (num_options < 2)
|
||||||
num_options = 2;
|
num_options = 2;
|
||||||
|
|
|
@ -76,7 +76,7 @@ struct align_pos {
|
||||||
#define WPS_MAX_SUBLINES (WPS_MAX_LINES*3)
|
#define WPS_MAX_SUBLINES (WPS_MAX_LINES*3)
|
||||||
#define WPS_MAX_TOKENS 1024
|
#define WPS_MAX_TOKENS 1024
|
||||||
#define WPS_MAX_STRINGS 128
|
#define WPS_MAX_STRINGS 128
|
||||||
#define STRING_BUFFER_SIZE 512
|
#define STRING_BUFFER_SIZE 1024
|
||||||
#define WPS_MAX_COND_LEVEL 10
|
#define WPS_MAX_COND_LEVEL 10
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -398,13 +398,16 @@ void print_line_info(struct wps_data *data)
|
||||||
void print_wps_strings(struct wps_data *data)
|
void print_wps_strings(struct wps_data *data)
|
||||||
{
|
{
|
||||||
DEBUGF("Strings:\n");
|
DEBUGF("Strings:\n");
|
||||||
int i, len = 0;
|
int i, len = 0, buf_used = 0;
|
||||||
for (i = 0; i < data->num_strings; i++)
|
for (i = 0; i < data->num_strings; i++)
|
||||||
{
|
{
|
||||||
len += strlen(data->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");
|
DEBUGF("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -270,12 +270,29 @@ static int skip_end_of_line(const char *wps_bufptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Starts a new subline in the current line during parsing */
|
/* 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->num_sublines++;
|
||||||
data->sublines[data->num_sublines].first_token_idx = data->num_tokens;
|
data->sublines[data->num_sublines].first_token_idx = data->num_tokens;
|
||||||
data->lines[data->num_lines].num_sublines++;
|
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
|
#ifdef HAVE_LCD_BITMAP
|
||||||
|
|
||||||
static int parse_statusbar_enable(const char *wps_bufptr,
|
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;
|
return false;
|
||||||
|
|
||||||
char *current_string = data->string_buffer;
|
char *current_string = data->string_buffer;
|
||||||
|
int stringbuf_used = 0;
|
||||||
|
|
||||||
while(*wps_bufptr && data->num_tokens < WPS_MAX_TOKENS - 1
|
while(*wps_bufptr && data->num_tokens < WPS_MAX_TOKENS - 1
|
||||||
&& data->num_lines < WPS_MAX_LINES)
|
&& 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 */
|
/* Alternating sublines separator */
|
||||||
case ';':
|
case ';':
|
||||||
|
if (level >= 0)
|
||||||
|
close_conditionals(data, level + 1);
|
||||||
|
|
||||||
if (data->num_sublines+1 < WPS_MAX_SUBLINES)
|
if (data->num_sublines+1 < WPS_MAX_SUBLINES)
|
||||||
wps_start_new_subline(data);
|
wps_start_new_subline(data);
|
||||||
else
|
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 */
|
if (level < 0) /* not in a conditional, ignore the char */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
condlistend: /* close a conditional. sometimes we want to close them even when
|
close_conditionals(data, 1);
|
||||||
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--;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Conditional list option */
|
/* Conditional list option */
|
||||||
|
@ -699,19 +710,17 @@ condlistend: /* close a conditional. sometimes we want to close them even when
|
||||||
|
|
||||||
/* Comment */
|
/* Comment */
|
||||||
case '#':
|
case '#':
|
||||||
|
if (level >= 0)
|
||||||
|
close_conditionals(data, level + 1);
|
||||||
|
|
||||||
wps_bufptr += skip_end_of_line(wps_bufptr);
|
wps_bufptr += skip_end_of_line(wps_bufptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* End of this line */
|
/* End of this line */
|
||||||
case '\n':
|
case '\n':
|
||||||
if (level >= 0)
|
if (level >= 0)
|
||||||
{
|
close_conditionals(data, level + 1);
|
||||||
/* We have unclosed conditionals, so we
|
|
||||||
close them before adding the EOL token */
|
|
||||||
wps_bufptr--;
|
|
||||||
goto condlistend;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wps_start_new_subline(data);
|
wps_start_new_subline(data);
|
||||||
data->num_lines++; /* Start a new line */
|
data->num_lines++; /* Start a new line */
|
||||||
|
|
||||||
|
@ -726,29 +735,36 @@ condlistend: /* close a conditional. sometimes we want to close them even when
|
||||||
|
|
||||||
/* String */
|
/* String */
|
||||||
default:
|
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->tokens[data->num_tokens].type = WPS_TOKEN_STRING;
|
||||||
data->strings[data->num_strings] = current_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++;
|
data->num_tokens++;
|
||||||
|
|
||||||
/* Copy the first byte */
|
/* Copy the first byte */
|
||||||
*current_string++ = *(wps_bufptr - 1);
|
*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 != '#' &&
|
while(wps_bufptr && *wps_bufptr != '#' &&
|
||||||
*wps_bufptr != '%' && *wps_bufptr != ';' &&
|
*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++;
|
*current_string++ = *wps_bufptr++;
|
||||||
|
stringbuf_used++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* null terminate the string */
|
/* null terminate the string */
|
||||||
*current_string++ = '\0';
|
*current_string++ = '\0';
|
||||||
}
|
stringbuf_used++;
|
||||||
|
|
||||||
|
data->num_strings++;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue