diff options
author | Jonathan Gordon <rockbox@jdgordon.info> | 2010-09-26 06:43:33 +0000 |
---|---|---|
committer | Jonathan Gordon <rockbox@jdgordon.info> | 2010-09-26 06:43:33 +0000 |
commit | 562437b8e7e2c7f3bd65b3d6e4bd4c196fa77f35 (patch) | |
tree | 2945c24ab7c93cdec6d4825db610883d647b20fc /apps/gui | |
parent | 3131fb9712be306789b23507ad8b491cd505f702 (diff) | |
download | rockbox-562437b8e7e2c7f3bd65b3d6e4bd4c196fa77f35.tar.gz rockbox-562437b8e7e2c7f3bd65b3d6e4bd4c196fa77f35.zip |
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/gui')
-rw-r--r-- | apps/gui/skin_engine/skin_render.c | 3 | ||||
-rw-r--r-- | 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 | |||
382 | struct skin_element *child = line->children[0]; | 382 | struct skin_element *child = line->children[0]; |
383 | struct conditional *conditional; | 383 | struct conditional *conditional; |
384 | skin_render_func func = skin_render_line; | 384 | skin_render_func func = skin_render_line; |
385 | char tempbuf[128]; | ||
386 | int old_refresh_mode = info->refresh_type; | 385 | int old_refresh_mode = info->refresh_type; |
387 | while (child) | 386 | while (child) |
388 | { | 387 | { |
389 | tempbuf[0] = '\0'; | ||
390 | switch (child->type) | 388 | switch (child->type) |
391 | { | 389 | { |
392 | case CONDITIONAL: | 390 | case CONDITIONAL: |
@@ -447,6 +445,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i | |||
447 | } | 445 | } |
448 | if (!do_non_text_tags(info->gwps, info, child, &info->skin_vp->vp)) | 446 | if (!do_non_text_tags(info->gwps, info, child, &info->skin_vp->vp)) |
449 | { | 447 | { |
448 | static char tempbuf[128]; | ||
450 | const char *value = get_token_value(info->gwps, child->data, | 449 | const char *value = get_token_value(info->gwps, child->data, |
451 | info->offset, tempbuf, | 450 | info->offset, tempbuf, |
452 | sizeof(tempbuf), NULL); | 451 | 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) | |||
552 | return pid3; | 552 | return pid3; |
553 | } | 553 | } |
554 | 554 | ||
555 | static const char* get_lif_token_value(struct gui_wps *gwps, | ||
556 | struct logical_if *lif, | ||
557 | int offset, char *buf, int buf_size) | ||
558 | { | ||
559 | int a = lif->num_options; | ||
560 | int b; | ||
561 | const char* out_text = get_token_value(gwps, lif->token, offset, | ||
562 | buf, buf_size, &a); | ||
563 | if (a == -1 && lif->token->type != SKIN_TOKEN_VOLUME) | ||
564 | a = (out_text && *out_text) ? 1 : 0; | ||
565 | switch (lif->operand.type) | ||
566 | { | ||
567 | case STRING: | ||
568 | if (lif->op == IF_EQUALS) | ||
569 | return strcmp(out_text, lif->operand.data.text) == 0 ? | ||
570 | "eq" : NULL; | ||
571 | else | ||
572 | return NULL; | ||
573 | break; | ||
574 | case INTEGER: | ||
575 | case DECIMAL: | ||
576 | b = lif->operand.data.number; | ||
577 | break; | ||
578 | case CODE: | ||
579 | { | ||
580 | char temp_buf[MAX_PATH]; | ||
581 | const char *outb; | ||
582 | struct wps_token *token = lif->operand.data.code->data; | ||
583 | b = lif->num_options; | ||
584 | outb = get_token_value(gwps, token, offset, temp_buf, | ||
585 | sizeof(temp_buf), &b); | ||
586 | if (b == -1 && lif->token->type != SKIN_TOKEN_VOLUME) | ||
587 | { | ||
588 | if (!out_text || !outb) | ||
589 | return (lif->op == IF_EQUALS) ? NULL : "neq"; | ||
590 | bool equal = strcmp(out_text, outb) == 0; | ||
591 | if (lif->op == IF_EQUALS) | ||
592 | return equal ? "eq" : NULL; | ||
593 | else if (lif->op == IF_NOTEQUALS) | ||
594 | return !equal ? "neq" : NULL; | ||
595 | else | ||
596 | b = (outb && *outb) ? 1 : 0; | ||
597 | } | ||
598 | } | ||
599 | break; | ||
600 | case DEFAULT: | ||
601 | break; | ||
602 | } | ||
603 | |||
604 | switch (lif->op) | ||
605 | { | ||
606 | case IF_EQUALS: | ||
607 | return a == b ? "eq" : NULL; | ||
608 | case IF_NOTEQUALS: | ||
609 | return a != b ? "neq" : NULL; | ||
610 | case IF_LESSTHAN: | ||
611 | return a < b ? "lt" : NULL; | ||
612 | case IF_LESSTHAN_EQ: | ||
613 | return a <= b ? "lte" : NULL; | ||
614 | case IF_GREATERTHAN: | ||
615 | return a > b ? "gt" : NULL; | ||
616 | case IF_GREATERTHAN_EQ: | ||
617 | return a >= b ? "gte" : NULL; | ||
618 | } | ||
619 | return NULL; | ||
620 | } | ||
621 | |||
555 | /* Return the tags value as text. buf should be used as temp storage if needed. | 622 | /* Return the tags value as text. buf should be used as temp storage if needed. |
556 | 623 | ||
557 | intval is used with conditionals/enums: when this function is called, | 624 | intval is used with conditionals/enums: when this function is called, |
@@ -626,66 +693,7 @@ const char *get_token_value(struct gui_wps *gwps, | |||
626 | case SKIN_TOKEN_LOGICAL_IF: | 693 | case SKIN_TOKEN_LOGICAL_IF: |
627 | { | 694 | { |
628 | struct logical_if *lif = token->value.data; | 695 | struct logical_if *lif = token->value.data; |
629 | int a = lif->num_options; | 696 | return get_lif_token_value(gwps, lif, offset, buf, buf_size); |
630 | int b; | ||
631 | out_text = get_token_value(gwps, lif->token, offset, buf, buf_size, &a); | ||
632 | if (a == -1 && lif->token->type != SKIN_TOKEN_VOLUME) | ||
633 | a = (out_text && *out_text) ? 1 : 0; | ||
634 | switch (lif->operand.type) | ||
635 | { | ||
636 | case STRING: | ||
637 | if (lif->op == IF_EQUALS) | ||
638 | return strcmp(out_text, lif->operand.data.text) == 0 ? | ||
639 | "eq" : NULL; | ||
640 | else | ||
641 | return NULL; | ||
642 | break; | ||
643 | case INTEGER: | ||
644 | case DECIMAL: | ||
645 | b = lif->operand.data.number; | ||
646 | break; | ||
647 | case CODE: | ||
648 | { | ||
649 | char temp_buf[MAX_PATH]; | ||
650 | const char *outb; | ||
651 | struct wps_token *token = lif->operand.data.code->data; | ||
652 | b = lif->num_options; | ||
653 | outb = get_token_value(gwps, token, offset, temp_buf, | ||
654 | sizeof(temp_buf), &b); | ||
655 | if (b == -1 && lif->token->type != SKIN_TOKEN_VOLUME) | ||
656 | { | ||
657 | if (!out_text || !outb) | ||
658 | return (lif->op == IF_EQUALS) ? NULL : "neq"; | ||
659 | bool equal = strcmp(out_text, outb) == 0; | ||
660 | if (lif->op == IF_EQUALS) | ||
661 | return equal ? "eq" : NULL; | ||
662 | else if (lif->op == IF_NOTEQUALS) | ||
663 | return !equal ? "neq" : NULL; | ||
664 | else | ||
665 | b = (outb && *outb) ? 1 : 0; | ||
666 | } | ||
667 | } | ||
668 | break; | ||
669 | case DEFAULT: | ||
670 | break; | ||
671 | } | ||
672 | |||
673 | switch (lif->op) | ||
674 | { | ||
675 | case IF_EQUALS: | ||
676 | return a == b ? "eq" : NULL; | ||
677 | case IF_NOTEQUALS: | ||
678 | return a != b ? "neq" : NULL; | ||
679 | case IF_LESSTHAN: | ||
680 | return a < b ? "lt" : NULL; | ||
681 | case IF_LESSTHAN_EQ: | ||
682 | return a <= b ? "lte" : NULL; | ||
683 | case IF_GREATERTHAN: | ||
684 | return a > b ? "gt" : NULL; | ||
685 | case IF_GREATERTHAN_EQ: | ||
686 | return a >= b ? "gte" : NULL; | ||
687 | } | ||
688 | return NULL; | ||
689 | } | 697 | } |
690 | break; | 698 | break; |
691 | 699 | ||