The linearization of switches & cases makes the assumption that the expressions for the cases are constants (EXPR_VALUE). So, the corresponding values are dereferenced without checks. However, if the code uses a non-constant case, this dereference produces a random value, probably one corresponding to some pointers belonging to the real type of the expression. Fix this by checking during linearization the constness of the expression and ignore the non-constant ones. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- linearize.c | 7 ++++-- validation/linear/non-const-case.c | 37 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 validation/linear/non-const-case.c diff --git a/linearize.c b/linearize.c index 670e38303..ac9131313 100644 --- a/linearize.c +++ b/linearize.c @@ -2230,12 +2230,15 @@ static pseudo_t linearize_switch(struct entrypoint *ep, struct statement *stmt) if (!case_stmt->case_expression) { default_case = bb_case; continue; + } else if (case_stmt->case_expression->type != EXPR_VALUE) { + continue; } else { + struct expression *case_to = case_stmt->case_to; long long begin, end; begin = end = case_stmt->case_expression->value; - if (case_stmt->case_to) - end = case_stmt->case_to->value; + if (case_to && case_to->type == EXPR_VALUE) + end = case_to->value; if (begin > end) jmp = alloc_multijmp(bb_case, end, begin); else diff --git a/validation/linear/non-const-case.c b/validation/linear/non-const-case.c new file mode 100644 index 000000000..7291589cb --- /dev/null +++ b/validation/linear/non-const-case.c @@ -0,0 +1,37 @@ +static int foo(int a) +{ + switch (a) { + case 0: + return a; + case a: + return 0; + case (a - a): + return 1; + default: + return a; + } +} + +static int bar(int a) +{ + switch (a) { + case 0: + break; + case a: + a++; +label: + return a; + } + + goto label; +} + + +/* + * check-name: non-const-case + * check-command: test-linearize -Wno-decl $file + * + * check-error-ignore + * check-output-ignore + * check-output-excludes:switch \\. + */ -- 2.19.0