From: Ben Dooks <ben-linux@xxxxxxxxx> The original update to evaluate.c did the va-arg checking before the standard checks. This is due to degernate() removing expr->string so save the string before the loop and then use it afterwards. -> to push back into evaluate.c if no other options available. --- evaluate.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/evaluate.c b/evaluate.c index a21bc3f..29c3470 100644 --- a/evaluate.c +++ b/evaluate.c @@ -2685,20 +2685,14 @@ static int parse_format_printf(const char **fmtstring, return 1; } -/* attempt to run through a printf format string and work out the types - * it specifies. The format is parsed from the __attribute__(format()) - * in the parser code which stores the positions of the message and arg - * start in the ctype. - */ -static void evaluate_format_printf(struct symbol *fn, struct expression_list *head) +static const char *get_printf_fmt(struct symbol *fn, struct expression_list *head) { - struct format_state state = { }; struct expression *expr; - const char *fmt_string = NULL; + const char *fmt_string; expr = get_expression_n(head, fn->ctype.printf_msg-1); if (!expr) - return; + return NULL; if (expr->string && expr->string->length) fmt_string = expr->string->data; if (!fmt_string) { @@ -2709,6 +2703,23 @@ static void evaluate_format_printf(struct symbol *fn, struct expression_list *he fmt_string = sym->initializer->string->data; } + return fmt_string; +} + +/* attempt to run through a printf format string and work out the types + * it specifies. The format is parsed from the __attribute__(format()) + * in the parser code which stores the positions of the message and arg + * start in the ctype. + */ +static void evaluate_format_printf(const char *fmt_string, struct symbol *fn, struct expression_list *head) +{ + struct format_state state = { }; + struct expression *expr; + + expr = get_expression_n(head, fn->ctype.printf_msg-1); + if (!expr) + return; + state.expr = expr; state.va_start = fn->ctype.printf_va_start; state.arg_index = fn->ctype.printf_va_start; @@ -2737,14 +2748,16 @@ static int evaluate_arguments(struct symbol *fn, struct expression_list *head) { struct expression *expr; struct symbol_list *argument_types = fn->arguments; + static const char *fmt_string = NULL; struct symbol *argtype; int i = 1; /* do this first, otherwise the arugment info may get lost or changed - * later on in the evaluation loop. + * later on in the evaluation loop by degenerate() */ if (Wformat && fn->ctype.printf_va_start) - evaluate_format_printf(fn, head); + fmt_string =get_printf_fmt(fn, head); + PREPARE_PTR_LIST(argument_types, argtype); FOR_EACH_PTR (head, expr) { @@ -2782,6 +2795,10 @@ static int evaluate_arguments(struct symbol *fn, struct expression_list *head) NEXT_PTR_LIST(argtype); } END_FOR_EACH_PTR(expr); FINISH_PTR_LIST(argtype); + + if (Wformat && fn->ctype.printf_va_start) + evaluate_format_printf(fmt_string, fn, head); + return 1; } -- 2.20.1