D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 16555 - Stack corruption when calling multi-parameter outer function from nested function
Summary: Stack corruption when calling multi-parameter outer function from nested func...
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 Linux
: P1 normal
Assignee: No Owner
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2016-09-27 20:56 UTC by Lars T. Kyllingstad
Modified: 2018-03-03 08:55 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Lars T. Kyllingstad 2016-09-27 20:56:24 UTC
When a nested function calls an outer function with a large number of parameters, the first argument becomes corrupted.

Test case:

    void outer(
        double x,
        double a, double b, double c, double d,
        double e, double f, double g, double h)
    {
        import std.stdio;
        writefln("x=%s a=%s b=%s c=%s d=%s e=%s f=%s g=%s h=%s",
            x, a, b, c, d, e, f, g, h);
    }

    void main()
    {
        void inner(double x)
        {
            outer(x, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
        }

        inner(999.0);
    }

Here, the value of x in outer() is garbage.  That is, the program SHOULD print:

    x=999 a=1 b=2 c=3 d=4 e=5 f=6 g=7 h=8

But instead, it prints something like:

    x=6.95253e-310 a=1 b=2 c=3 d=4 e=5 f=6 g=7 h=8

Reducing the number of parameters of outer() makes the problem go away.  Also, interestingly, if the program is compiled with -O or -inline, the correct behaviour is restored.
Comment 1 Steven Schveighoffer 2016-09-27 22:33:08 UTC
The stack corruption I think is on the expected location of x when calling the function.

Note that outer function is not needed, this also produces (same) corrupt output:

import std.stdio;

void main()
{
    void inner(double x)
    {
        if(x == 999) // to show that x itself isn't corrupt
        {
            writefln("x=%s a=%s b=%s c=%s d=%s e=%s f=%s g=%s h=%s", x, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
            //outer(x, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
        }
    }

    inner(999.0);
}

Not sure how to edit the description, but definitely the number of parameters plays a role, and probably the inner function.
Comment 2 Walter Bright 2016-10-30 05:18:15 UTC
https://github.com/dlang/dmd/pull/6171
Comment 3 github-bugzilla 2018-03-03 08:55:49 UTC
Commits pushed to master at https://github.com/dlang/dmd

https://github.com/dlang/dmd/commit/815bb8f7b37882d6590281b3542548632c47be22
Fix issue 16555 - Generate correct code for pushing scalar parameters.

https://github.com/dlang/dmd/commit/d91b678235d5357957762005bce7c4b46f265f62
Merge pull request #7890 from JinShil/fix_16555

Fix issue 16555 - Generate correct code for pushing scalar parameters.
merged-on-behalf-of: Jacob Carlborg <jacob-carlborg@users.noreply.github.com>