From 562437b8e7e2c7f3bd65b3d6e4bd4c196fa77f35 Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Sun, 26 Sep 2010 06:43:33 +0000 Subject: 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 --- apps/gui/skin_engine/skin_render.c | 3 +- apps/gui/skin_engine/skin_tokens.c | 128 ++++++++++++++++++++----------------- 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 4fbd550c72..baa1f82b43 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 1bfc861624..df4e7d9b1a 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; -- cgit v1.2.3