Bug 21301 – Wrong values being passed in long parameter list

Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2020-10-10T21:49:59Z
Last change time
2022-11-10T09:25:13Z
Keywords
pull
Assigned to
No Owner
Creator
Thibaut CHARLES
See also
https://issues.dlang.org/show_bug.cgi?id=22583, https://issues.dlang.org/show_bug.cgi?id=23450

Comments

Comment #0 by cromfr — 2020-10-10T21:49:59Z
Since DMD 2.084.0, the following code fails: ``` void main() { void func(T...)(T args){ // here args[1] is received as [0, 0, 64, 64, 38, 86, 0, 0, 1, 2, 3, 4] assert(args[1][0 .. 12] == [1,2,3,4,5,6,7,8,9,10,11,12]); } func( ubyte(0), cast(ubyte[12])[1,2,3,4,5,6,7,8,9,10,11,12], cast(float[3])[1f,2f,3f], 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, uint(0), [0,1,2,3,4], uint(0), ); } ``` This code works correctly on DMD 2.083.1, but fails on 2.084.0 and 2.084.1-beta. Adding or removing arguments in the func call (like adding one more 0f value) makes func work correctly and pass its assert. Changing the value of the first ubyte(0) changes the data received as args[1] (but still fails on the assert) args[1] seems to be shifted by 8 bytes
Comment #1 by dkorpel — 2022-03-17T12:13:38Z
This is not about variadic parameters, it also happens when you spell them out: ``` void main() { void func( ubyte p0, ubyte[12] p1, float[3] p2, float p3, float p4, float p5, float p6, float p7, float p8, float p9, float p10, float p11, uint p12, int[] p13, uint p14 ) { // here args[1] is received as [0, 0, 64, 64, 38, 86, 0, 0, 1, 2, 3, 4] assert(p1[0 .. 12] == [1,2,3,4,5,6,7,8,9,10,11,12]); } func(0, cast(ubyte[12])[1,2,3,4,5,6,7,8,9,10,11,12], [0, 0, 0], 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , uint(0), [], uint(0), ); } ```
Comment #2 by kdevel — 2022-03-17T15:22:04Z
---v.d import std.stdio; unittest { void func(T...)(T args) { writeln ("args = ", args); asssert(args[1][0 .. 12] == [1,2,3,4,5,6,7,8,9,10,11,12]); } byte[12] f2 = [1,2,3,4,5,6,7,8,9,10,11,12]; float[3] f3 = [1f,2f,3f]; func( 0, f2, f3, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0, 0, 0, 0, ); } --- $ dmd --version DMD64 D Compiler v2.099.0 Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved written by Walter Bright $ dmd -g -m64 -unittest -checkaction=context -main -run v std.exception.ErrnoException@[...]/dmd2/linux/bin64/../../src/phobos/std/stdio.d(3170): Enforcement failed (Bad address) ... $ dmd -g -m32 -unittest -checkaction=context -main -run v args = 0[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12][1, 2, 3]0000000000000 1 modules passed unittests
Comment #3 by dkorpel — 2022-11-02T12:18:15Z
Here's a bit more test code, reducing it to only using int and float, and using hex values as arguments that are easy to identify: ``` import core.stdc.stdio; union U { int[22] i = [ 0xAAAA_0000, 0xAAAA_0001, 0xAAAA_0002, 0xAAAA_0003, 0xFFFF_0004, 0xFFFF_0005, 0xFFFF_0006, 0xFFFF_0007, 0xFFFF_0008, 0xFFFF_0009, 0xFFFF_0010, 0xFFFF_0011, 0xFFFF_0012, 0xFFFF_0013, 0xFFFF_0014, 0xFFFF_0015, 0xAAAA_0016, 0xAAAA_0017, 0xAAAA_0018, 0xAAAA_0019, 0xAAAA_0020, 0xAAAA_0021, ]; float[22] f; } void print(int x) { printf("int %08X\n", x); } void print(float x) { printf("float %08X\n", *(cast(int*) &x)); } void main() { void func( int p0, int[3] p1, float[3] p2, float p3, float p4, float p5, float p6, float p7, float p8, float p9, float p10, float p11, int p12, int[2] p13, int p14, int p15, int p16 ) { print(p0); print(p1[0]); print(p1[1]); print(p1[2]); print(p2[0]); print(p2[1]); print(p2[2]); print(p3); print(p4); print(p5); print(p6); print(p7); print(p8); print(p9); print(p10); print(p11); print(p12); print(p13[0]); print(p13[1]); print(p14); print(p15); print(p16); } func(U.init.i[0], [U.init.i[1], U.init.i[2], U.init.i[3]], [U.init.f[4], U.init.f[5], U.init.f[6]], U.init.f[7], U.init.f[8], U.init.f[9], U.init.f[10], U.init.f[11], U.init.f[12], U.init.f[13], U.init.f[14], U.init.f[15], U.init.i[16], [U.init.i[17], U.init.i[18]], U.init.i[19], U.init.i[20], U.init.i[21] ); } ``` Expected / ldc output: ``` int AAAA0000 int AAAA0001 int AAAA0002 int AAAA0003 float FFFF0004 float FFFF0005 float FFFF0006 float FFFF0007 float FFFF0008 float FFFF0009 float FFFF0010 float FFFF0011 float FFFF0012 float FFFF0013 float FFFF0014 float FFFF0015 int AAAA0016 int AAAA0017 int AAAA0018 int AAAA0019 int AAAA0020 int AAAA0021 ``` DMD output: ``` int AAAA0003 int FFFF0006 int 00007FFE int AAAA0001 float EA9E9130 float 00007FFE float FFFF0004 float FFFF0007 float FFFF0008 float FFFF0009 float FFFF0010 float FFFF0011 float FFFF0012 float FFFF0013 float FFFF0014 float FFFF0015 int AAAA0016 int AAAA0017 int AAAA0018 int AAAA0019 int AAAA0020 int AAAA0021 ``` So it's the first 7 arguments which are garbage or reading from another parameter.
Comment #4 by dlang-bot — 2022-11-08T07:51:58Z
@WalterBright created dlang/dmd pull request #14629 "fix Issue 21301 - Wrong values being passed in long parameter list" fixing this issue: - fix Issue 21301 - Wrong values being passed in long parameter list https://github.com/dlang/dmd/pull/14629
Comment #5 by dlang-bot — 2022-11-10T09:25:13Z
dlang/dmd pull request #14629 "fix Issue 21301 - Wrong values being passed in long parameter list" was merged into master: - 0317665d516966417e3a0ceeb12b0ede9cee862b by Walter Bright: fix Issue 21301 - Wrong values being passed in long parameter list https://github.com/dlang/dmd/pull/14629