summaryrefslogtreecommitdiff
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
parent3131fb9712be306789b23507ad8b491cd505f702 (diff)
downloadrockbox-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
-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 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
555static 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