Bug 70515 - Nested lambdas causing invalid captured pointers on some platforms
Summary: Nested lambdas causing invalid captured pointers on some platforms
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 5.3.1
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: c++-lambda, wrong-code
Depends on:
Blocks: lambdas
  Show dependency treegraph
 
Reported: 2016-04-02 11:49 UTC by Norgg
Modified: 2022-03-11 00:32 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 5.3.1, 6.3.0, 7.0
Last reconfirmed: 2018-04-24 00:00:00


Attachments
Minimal testcase (212 bytes, text/plain)
2016-04-02 11:49 UTC, Norgg
Details
Preprocessed file (71.09 KB, text/plain)
2016-04-02 11:51 UTC, Norgg
Details
gcc -v output for gcc 5.4.0 (677 bytes, text/plain)
2017-03-17 15:05 UTC, Norgg
Details
gcc -v output for gcc 6.2.0 (677 bytes, text/plain)
2017-03-17 15:06 UTC, Norgg
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Norgg 2016-04-02 11:49:45 UTC
Created attachment 38163 [details]
Minimal testcase

The attached code causes a segfault at runtime due to an invalid read when trying to dereference j on some platforms but not others across multiple versions of GCC.

We can replicate this on various machines with:

Ubuntu g++ 5.3.1 / 5.1.1 / 4.8.4
Gentoo g++ 5.3.0

But not on:

OSX g++ 5.3.0 / 6.0.0
Debian g++ 5.3.1

The command line used to compile and run was: 

g++ -std=c++11 lambdabug.cpp -o lambdabug && ./lambdabug
Comment 1 Norgg 2016-04-02 11:51:06 UTC
Created attachment 38164 [details]
Preprocessed file
Comment 2 Andrew Pinski 2016-08-06 05:17:47 UTC
Can't reproduce this on aarch64-linux-gnu with GCC 6.1.0.
Comment 3 Martin Sebor 2017-03-16 02:34:10 UTC
I also cannot reproduce it with 7.0 on powepc64le or with 5.x on x86_64.  Can you please list the processor architectures you see this problem on?  (Providing the output of gcc -v should help.)
Comment 4 Norgg 2017-03-17 15:05:49 UTC
Created attachment 40993 [details]
gcc -v output for gcc 5.4.0

(In reply to Martin Sebor from comment #3)
> I also cannot reproduce it with 7.0 on powepc64le or with 5.x on x86_64. 
> Can you please list the processor architectures you see this problem on? 
> (Providing the output of gcc -v should help.)

I can still reproduce this on my x86_64 Ubuntu system, in both g++ 5.4.1 and 6.2.0, gcc -v output from each attached.
Comment 5 Norgg 2017-03-17 15:06:30 UTC
Created attachment 40994 [details]
gcc -v output for gcc 6.2.0
Comment 6 Martin Sebor 2017-03-17 17:46:11 UTC
Thank you.  I still can't reproduce the problem with -O0 but I do see a SIGSEGV on x86_64 when I compile the test case with -O1 or higher, with all of GCC 5.x, 6.x, and 7.0.  Thus confirmed.

$ /ssd/build/gcc-6-branch/gcc/xg++ -B /ssd/build/gcc-6-branch/gcc -nostdinc++ -I /ssd/build/gcc-6-branch/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu -I /ssd/build/gcc-6-branch/x86_64-pc-linux-gnu/libstdc++-v3/include -I /src/gcc/6-branch/libstdc++-v3/libsupc++ -I /src/gcc/6-branch/libstdc++-v3/include/backward -I /src/gcc/6-branch/libstdc++-v3/testsuite/util -L /ssd/build/gcc-6-branch/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs -std=gnu++1z -g -O1 t.C && gdb -batch -q -ex r -ex bt a.out 

Program received signal SIGSEGV, Segmentation fault.
0x000000000040064c in <lambda()>::operator() (__closure=0x7fffffffde68) at t.C:9
9	    auto lambda1 = [&]{ (*j)++; };
#0  0x000000000040064c in <lambda()>::operator() (__closure=0x7fffffffde68) at t.C:9
#1  <lambda()>::operator() (__closure=0x7fffffffdea0, __closure@entry=0x7fffffffde30) at t.C:10
#2  std::_Function_handler<void(), main()::<lambda()> >::_M_invoke(const std::_Any_data &) (__functor=...) at /ssd/build/gcc-6-branch/x86_64-pc-linux-gnu/libstdc++-v3/include/functional:1731
#3  0x00000000004006bf in std::function<void ()>::operator()() const (this=0x7fffffffdea0) at /ssd/build/gcc-6-branch/x86_64-pc-linux-gnu/libstdc++-v3/include/functional:2127
#4  main () at t.C:16
Comment 7 Jason Merrill 2019-03-25 21:10:52 UTC
lambda2 captures lambda1 by reference, and is then copied into func.  When their block ends lambda1 no longer exists, so the reference in func is dangling, and so invoking it has undefined behavior.