From ed3035cb99e2c93b1256e478ff46a3128c44b8b4 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sat, 1 Jan 2022 22:42:42 -0600 Subject: [PATCH] Fix bug in code for varargs functions with multiple fixed parameters. This was broken by the varargs changes in commit a20d69a211980. The code was not accounting for the internal representation of the parameters being in reverse order, so it was basing address calculations on the first fixed parameter rather than the last one, resulting in the wrong number of bytes being removed from the stack (generally causing a crash). This affected the c99stdio.c test case, and is now also covered in c99stdarg.c. --- Symbol.pas | 20 ++++++++++++++++---- Tests/Conformance/c99stdarg.c | 8 ++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Symbol.pas b/Symbol.pas index b602aac..d4f7588 100644 --- a/Symbol.pas +++ b/Symbol.pas @@ -967,10 +967,10 @@ var size: integer; {size of the parameter} sp: identPtr; {symbol pointer} tk: tokenType; {symbol name token} + first: boolean; {first iteration of loop over params?} begin {GenParameters} -pln := 0; -size := 0; +first := true; if pp <> nil then begin {prototyped parameters} tk.kind := ident; tk.numString := nil; @@ -993,6 +993,11 @@ if pp <> nil then begin {prototyped parameters} Gen3(dc_prm, pln, size, sp^.pdisp); end; {else} sp^.pln := pln; + if first then begin + first := false; + lastParameterLLN := pln; + lastParameterSize := size; + end; {if} pp := pp^.next; end; {while} end {if} @@ -1013,13 +1018,20 @@ else begin {K&R parameters} size := 2; Gen3(dc_prm, sp^.lln, size, sp^.pdisp); end; {else} + if first then begin + first := false; + lastParameterLLN := pln; + lastParameterSize := size; + end; {if} end; {if} sp := sp^.next; end; {while} end; {for} + if first then begin + lastParameterLLN := 0; + lastParameterSize := 0; + end; {if} end; {else} -lastParameterLLN := pln; -lastParameterSize := size; end; {GenParameters} diff --git a/Tests/Conformance/c99stdarg.c b/Tests/Conformance/c99stdarg.c index 7df0920..b596fd3 100644 --- a/Tests/Conformance/c99stdarg.c +++ b/Tests/Conformance/c99stdarg.c @@ -22,12 +22,12 @@ int va_list_fn(va_list ap) { return 1; } -int va_fn(int x, ...) { +int va_fn(int x, int y, int z, ...) { va_list ap, ap2; int i, *ip = &i; /* Test basic varargs functionality */ - va_start(ap, x); + va_start(ap, z); if (va_arg(ap, int) != 12345) return 0; @@ -46,7 +46,7 @@ int va_fn(int x, ...) { va_end(ap2); /* Test that varargs processing can be restarted */ - va_start(ap, x); + va_start(ap, z); if (va_arg(ap, int) != 12345) return 0; va_end(ap); @@ -60,7 +60,7 @@ int va_fn(int x, ...) { int main(void) { - if (!va_fn(1, 12345, 67890.0, 1234567890L)) + if (!va_fn(1, 2, 3, 12345, 67890.0, 1234567890L)) goto Fail; printf ("Passed Conformance Test c99stdarg\n");