summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2010-09-26 06:43:33 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2010-09-26 06:43:33 +0000
commit562437b8e7e2c7f3bd65b3d6e4bd4c196fa77f35 (patch)
tree2945c24ab7c93cdec6d4825db610883d647b20fc /apps
parent3131fb9712be306789b23507ad8b491cd505f702 (diff)
downloadrockbox-562437b8e7e2c7f3bd65b3d6e4bd4c196fa77f35.zip
rockbox-562437b8e7e2c7f3bd65b3d6e4bd4c196fa77f35.tar.gz
rockbox-562437b8e7e2c7f3bd65b3d6e4bd4c196fa77f35.tar.bz2
rockbox-562437b8e7e2c7f3bd65b3d6e4bd4c196fa77f35.tar.xz
Fix FS#1159 - stack overflow in the skin engine when there is too many nested conditionals
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28167 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/gui/skin_engine/skin_render.c3
-rw-r--r--apps/gui/skin_engine/skin_tokens.c128
2 files changed, 69 insertions, 62 deletions
diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c
index 4fbd550..baa1f82 100644
--- a/apps/gui/skin_engine/skin_render.c
+++ b/apps/gui/skin_engine/skin_render.c
@@ -382,11 +382,9 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i
struct skin_element *child = line->children[0];
struct conditional *conditional;
skin_render_func func = skin_render_line;
- char tempbuf[128];
int old_refresh_mode = info->refresh_type;
while (child)
{
- tempbuf[0] = '\0';
switch (child->type)
{
case CONDITIONAL:
@@ -447,6 +445,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i
}
if (!do_non_text_tags(info->gwps, info, child, &info->skin_vp->vp))
{
+ static char tempbuf[128];
const char *value = get_token_value(info->gwps, child->data,
info->offset, tempbuf,
sizeof(tempbuf), NULL);
diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c
index 1bfc861..df4e7d9 100644
--- a/apps/gui/skin_engine/skin_tokens.c
+++ b/apps/gui/skin_engine/skin_tokens.c
@@ -552,6 +552,73 @@ static struct mp3entry* get_mp3entry_from_offset(int offset, char **filename)
return pid3;
}
+static const char* get_lif_token_value(struct gui_wps *gwps,
+ struct logical_if *lif,
+ int offset, char *buf, int buf_size)
+{
+ int a = lif->num_options;
+ int b;
+ const char* out_text = get_token_value(gwps, lif->token, offset,
+ buf, buf_size, &a);
+ if (a == -1 && lif->token->type != SKIN_TOKEN_VOLUME)
+ a = (out_text && *out_text) ? 1 : 0;
+ switch (lif->operand.type)
+ {
+ case STRING:
+ if (lif->op == IF_EQUALS)
+ return strcmp(out_text, lif->operand.data.text) == 0 ?
+ "eq" : NULL;
+ else
+ return NULL;
+ break;
+ case INTEGER:
+ case DECIMAL:
+ b = lif->operand.data.number;
+ break;
+ case CODE:
+ {
+ char temp_buf[MAX_PATH];
+ const char *outb;
+ struct wps_token *token = lif->operand.data.code->data;
+ b = lif->num_options;
+ outb = get_token_value(gwps, token, offset, temp_buf,
+ sizeof(temp_buf), &b);
+ if (b == -1 && lif->token->type != SKIN_TOKEN_VOLUME)
+ {
+ if (!out_text || !outb)
+ return (lif->op == IF_EQUALS) ? NULL : "neq";
+ bool equal = strcmp(out_text, outb) == 0;
+ if (lif->op == IF_EQUALS)
+ return equal ? "eq" : NULL;
+ else if (lif->op == IF_NOTEQUALS)
+ return !equal ? "neq" : NULL;
+ else
+ b = (outb && *outb) ? 1 : 0;
+ }
+ }
+ break;
+ case DEFAULT:
+ break;
+ }
+
+ switch (lif->op)
+ {
+ case IF_EQUALS:
+ return a == b ? "eq" : NULL;
+ case IF_NOTEQUALS:
+ return a != b ? "neq" : NULL;
+ case IF_LESSTHAN:
+ return a < b ? "lt" : NULL;
+ case IF_LESSTHAN_EQ:
+ return a <= b ? "lte" : NULL;
+ case IF_GREATERTHAN:
+ return a > b ? "gt" : NULL;
+ case IF_GREATERTHAN_EQ:
+ return a >= b ? "gte" : NULL;
+ }
+ return NULL;
+}
+
/* Return the tags value as text. buf should be used as temp storage if needed.
intval is used with conditionals/enums: when this function is called,
@@ -626,66 +693,7 @@ const char *get_token_value(struct gui_wps *gwps,
case SKIN_TOKEN_LOGICAL_IF:
{
struct logical_if *lif = token->value.data;
- int a = lif->num_options;
- int b;
- out_text = get_token_value(gwps, lif->token, offset, buf, buf_size, &a);
- if (a == -1 && lif->token->type != SKIN_TOKEN_VOLUME)
- a = (out_text && *out_text) ? 1 : 0;
- switch (lif->operand.type)
- {
- case STRING:
- if (lif->op == IF_EQUALS)
- return strcmp(out_text, lif->operand.data.text) == 0 ?
- "eq" : NULL;
- else
- return NULL;
- break;
- case INTEGER:
- case DECIMAL:
- b = lif->operand.data.number;
- break;
- case CODE:
- {
- char temp_buf[MAX_PATH];
- const char *outb;
- struct wps_token *token = lif->operand.data.code->data;
- b = lif->num_options;
- outb = get_token_value(gwps, token, offset, temp_buf,
- sizeof(temp_buf), &b);
- if (b == -1 && lif->token->type != SKIN_TOKEN_VOLUME)
- {
- if (!out_text || !outb)
- return (lif->op == IF_EQUALS) ? NULL : "neq";
- bool equal = strcmp(out_text, outb) == 0;
- if (lif->op == IF_EQUALS)
- return equal ? "eq" : NULL;
- else if (lif->op == IF_NOTEQUALS)
- return !equal ? "neq" : NULL;
- else
- b = (outb && *outb) ? 1 : 0;
- }
- }
- break;
- case DEFAULT:
- break;
- }
-
- switch (lif->op)
- {
- case IF_EQUALS:
- return a == b ? "eq" : NULL;
- case IF_NOTEQUALS:
- return a != b ? "neq" : NULL;
- case IF_LESSTHAN:
- return a < b ? "lt" : NULL;
- case IF_LESSTHAN_EQ:
- return a <= b ? "lte" : NULL;
- case IF_GREATERTHAN:
- return a > b ? "gt" : NULL;
- case IF_GREATERTHAN_EQ:
- return a >= b ? "gte" : NULL;
- }
- return NULL;
+ return get_lif_token_value(gwps, lif, offset, buf, buf_size);
}
break;