Bug 15417 – Wrong parameter passing for variadic nested functions within aggregate

Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-12-07T22:16:00Z
Last change time
2016-01-03T14:02:47Z
Keywords
industry, wrong-code
Assigned to
nobody
Creator
mathias.lang

Comments

Comment #0 by mathias.lang — 2015-12-07T22:16:03Z
``` import core.stdc.stdarg; class C { private void method () { void test (ulong c1, ...) { va_list ap; va_start(ap, _argptr); assert(char.init == va_arg!(char)(ap)); } test(4242UL, char.init); } } void main () { auto c = new C; c.method; } ``` Result in a SEGV: ``` Program received signal SIGSEGV, Segmentation fault. core.stdc.stdarg.va_arg!(char).va_arg(core.stdc.stdarg.__va_list_tag*, ref char) (parmn=@0x7fffffffd6c0: 255 '\377', apx=0x0) at /usr/include/dmd/druntime/import/core/stdc/stdarg.d:233 233 if (ap.offset_regs < 6 * 8 && T.sizeof <= 8) (gdb) bt #0 core.stdc.stdarg.va_arg!(char).va_arg(core.stdc.stdarg.__va_list_tag*, ref char) (parmn=@0x7fffffffd6c0: 255 '\377', apx=0x0) at /usr/include/dmd/druntime/import/core/stdc/stdarg.d:233 #1 0x000000000041f391 in core.stdc.stdarg.va_arg!(char).va_arg(core.stdc.stdarg.__va_list_tag*) (ap=0x0) at /usr/include/dmd/druntime/import/core/stdc/stdarg.d:198 #2 0x000000000041f33b in vararg.C.method().test(ulong, ...) ( this=0x7ffff7eec000, _arguments_typeinfo=0x648360 <TypeInfo_B1a.init$>, c1=4242) at vararg.d:11 #3 0x000000000041f2d7 in vararg.C.method() (this=0x7ffff7eec000) at vararg.d:13 #4 0x000000000041f36a in D main () at vararg.d:20 ``` Tested with struct too. Tested with 2.066.1, 2.069, and master as of now (v2.069-devel-4afb98f)
Comment #1 by ibuclaw — 2015-12-08T10:16:24Z
If only dmd warned you against bad code: --- $ gdc valist.d valist.d: In function ‘test’: valist.d:10:13: warning: second parameter of ‘va_start’ not last named argument [-Wvarargs] va_start(ap, _argptr); ^ --- Use `va_start(ap, c1);' Besides, if _argptr isn't initialized properly (it segfaults when you use it directly) that is a bug.
Comment #2 by mathias.lang — 2015-12-08T11:03:55Z
Oops :P Well, using `c1` doesn't change a thing here (and va_start is not needed here according to the docs). Test case closer to the original bug: ``` import std.stdio, core.stdc.stdarg; class C { private void method () { void test (ulong c1, ...) { check(c1, _argptr, _arguments); } test(4242UL, char.init); } } void check (ulong c1, va_list arglist, TypeInfo[] ti) { assert(ti.length == 1); assert(ti[0].toString() == "char"); writeln("Now Segv"); assert(char.init == va_arg!(char)(arglist)); } void main () { auto c = new C; c.method; } ``` This is technically a regression (worked in D1). And obviously it works with GDC :)
Comment #3 by bugzilla — 2015-12-20T05:52:15Z
_argptr and _arguments are there for "D style variadics". core.stdc.stdarg is for "C style variadics". I.e. using va_arg for C-style will not work.
Comment #4 by ibuclaw — 2015-12-26T10:12:13Z
(In reply to Walter Bright from comment #3) > _argptr and _arguments are there for "D style variadics". core.stdc.stdarg > is for "C style variadics". I.e. using va_arg for C-style will not work. I beg your pardon? The _argptr variable is computed from va_start, so is perfectly valid for use in va_arg. See for example, std.format.doFormat!()
Comment #5 by ibuclaw — 2015-12-26T10:21:47Z
(In reply to Mathias Lang from comment #2) > assert(char.init == va_arg!(char)(arglist)); Is it the same if you do. char buf; va_arg(ap, arglist[0], &buf); assert(char.init == buf);
Comment #6 by bugzilla — 2015-12-30T08:42:35Z
Comment #7 by github-bugzilla — 2015-12-30T20:54:44Z
Commits pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/1ececafda7a8d3879d2d20bae4427f3a1e6e79a3 fix Issue 15417 - Wrong parameter passing for variadic nested functions within aggregate https://github.com/D-Programming-Language/dmd/commit/675a2d4e2f1f26df4f4b156181aae0c0f4c3001c Merge pull request #5326 from WalterBright/fix15417 fix Issue 15417 - Wrong parameter passing for variadic nested functio…
Comment #8 by github-bugzilla — 2016-01-03T14:02:47Z
Commits pushed to stable at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/1ececafda7a8d3879d2d20bae4427f3a1e6e79a3 fix Issue 15417 - Wrong parameter passing for variadic nested functions within aggregate https://github.com/D-Programming-Language/dmd/commit/675a2d4e2f1f26df4f4b156181aae0c0f4c3001c Merge pull request #5326 from WalterBright/fix15417