stackless-dev / stackless

The Stackless Python programming language
http://www.stackless.com/
Other
1.02k stars 60 forks source link

gcc compiler optimizations cause stack corruption #97

Closed ghost closed 6 years ago

ghost commented 7 years ago

Originally reported by: David Gervais (Bitbucket: drgervais, GitHub: Unknown)


When compiling 32-bit builds of stackless 2.7.x using gcc versions 4.8.4 and higher on a variant of Ubuntu linux, compiler optimizations lead to segfaults as a result of apparent stack corruption.

Confirmed issues using gcc 4.8.4 and 5.3.1 across the stackless 2.7-slp branch.

Indications are that the issue is specific to the slp_transfer.c functions. I can get all unit tests to pass (i.e. Stackless/unittests/runAll.py) only if I use the attached patch that disables compiler optimizations across slp_transfer.c defined functions. Using anything other than O0 in these functions results in a segfault and similar stacktrace.

The base compiler flags used during my test compilation are:

#!bash
  CFLAGS: -m32 -march=opteron -mno-3dnow -ggdb -O2 -Wall
  CXXFLAGS: -m32 -march=opteron -mno-3dnow -ggdb -O2
  LDFLAGS: -m32

with config.status snippet:

#!bash
S["BASECFLAGS"]=" -fno-strict-aliasing -DSTACKLESS_FRHACK=0"
S["OPT"]="-DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes"

gdb stack snippet running unittests with 2.7.12-slp and gcc 5.3.1:

#!bash
testSimpleLeakage (test_generator.TestGarbageCollection) ... ok
testSimpleLeakage_H (test_generator.TestGarbageCollection) ... ok
testReceiveOnMain (test_watchdog.TestDeadlock)
(soft) Thest that we get a deadock exception if main tries to block ... ok
testReceiveOnMain_H (test_watchdog.TestDeadlock)
(hard) Thest that we get a deadock exception if main tries to block ... ok
test_error_propagation_when_not_deadlock (test_watchdog.TestDeadlock) ...
Program received signal SIGSEGV, Segmentation fault.
0x081a4dd4 in slp_transfer (cstprev=cstprev@entry=0x82480ac, cst=<optimized out>, cst@entry=0x0, prev=prev@entry=0x0) at ./Stackless/core/slp_transfer.c:157
157             ts->st.serial_last_jump = _cst->serial;
(gdb) bt
#0  0x081a4dd4 in slp_transfer (cstprev=cstprev@entry=0x82480ac, cst=<optimized out>, cst@entry=0x0, prev=prev@entry=0x0) at ./Stackless/core/slp_transfer.c:157
#1  0x08104369 in make_initial_stub () at Stackless/core/stacklesseval.c:255
#2  slp_eval_frame (f=<optimized out>) at Stackless/core/stacklesseval.c:321
#3  climb_stack_and_eval_frame (f=<optimized out>) at Stackless/core/stacklesseval.c:290
#4  0x0810438d in slp_eval_frame (f=0xf7d2202c) at Stackless/core/stacklesseval.c:319
#5  climb_stack_and_eval_frame (f=<optimized out>) at Stackless/core/stacklesseval.c:290
#6  0x0810438d in slp_eval_frame (f=0xf7d2202c) at Stackless/core/stacklesseval.c:319
#7  climb_stack_and_eval_frame (f=<optimized out>) at Stackless/core/stacklesseval.c:290
#8  0x0810438d in slp_eval_frame (f=0xf7d2202c) at Stackless/core/stacklesseval.c:319
#9  climb_stack_and_eval_frame (f=<optimized out>) at Stackless/core/stacklesseval.c:290
#10 0x0810438d in slp_eval_frame (f=0xf7d2202c) at Stackless/core/stacklesseval.c:319
#11 climb_stack_and_eval_frame (f=<optimized out>) at Stackless/core/stacklesseval.c:290
...
#710 0x0810438d in slp_eval_frame (f=0xf7d2202c) at Stackless/core/stacklesseval.c:319
#711 climb_stack_and_eval_frame (f=<optimized out>) at Stackless/core/stacklesseval.c:290
#712 0x0810447f in slp_eval_frame (f=0xf7d2202c) at Stackless/core/stacklesseval.c:319
#713 0x080f7b1c in PyEval_EvalCodeEx (co=0xf7d2202c, co@entry=0xf7c8aa88, globals=globals@entry=0xf7d1946c, locals=locals@entry=0xf7d1946c, args=args@entry=0x0,
    argcount=argcount@entry=0, kws=kws@entry=0x0, kwcount=kwcount@entry=0, defs=defs@entry=0x0, defcount=defcount@entry=0, closure=closure@entry=0x0) at Python/ceval.c:4034
#714 0x080f7ed7 in PyEval_EvalCode (co=co@entry=0xf7c8aa88, globals=globals@entry=0xf7d1946c, locals=locals@entry=0xf7d1946c) at Python/ceval.c:671
#715 0x0813d335 in run_mod (arena=0x827d120, flags=0xffffd908, locals=0xf7d1946c, globals=0xf7d1946c,
    filename=0xffffdbec "stackless/stackless-2712-export/Stackless/unittests/runAll.py", mod=<optimized out>) at Python/pythonrun.c:1414
#716 PyRun_FileExFlags (fp=0x8284108, filename=0xffffdbec "stackless/stackless-2712-export/Stackless/unittests/runAll.py", start=257, globals=0xf7d1946c,
    locals=0xf7d1946c, closeit=1, flags=0xffffd908) at Python/pythonrun.c:1398
---Type <return> to continue, or q <return> to quit---
#717 0x0813f030 in PyRun_SimpleFileExFlags (fp=0x8284108, filename=0xffffdbec "stackless/stackless-2712-export/Stackless/unittests/runAll.py", closeit=1, flags=0xffffd908)
    at Python/pythonrun.c:966
#718 0x0805c235 in Py_Main (argc=argc@entry=2, argv=argv@entry=0xffffda44) at Modules/main.c:640
#719 0x0805b29b in main (argc=2, argv=0xffffda44) at ./Modules/python.c:2

compiler_optimization_hack.patch.zip


ghost commented 7 years ago

Original comment by Anselm Kruis (Bitbucket: akruis, GitHub: akruis):


Fixed:

ghost commented 7 years ago

Original comment by Anselm Kruis (Bitbucket: akruis, GitHub: akruis):


To be ported to 3.x-slp.

ghost commented 7 years ago

Original comment by Anselm Kruis (Bitbucket: akruis, GitHub: akruis):


I can reproduce the problem.

It is caused by a bug in Stackless/platf/switch_x86_unix.h. It declares the function int slp_switch() as static. The problem is: the ABI specification for i386 does not apply the static functions. Therefore the compile is free to optimize. I fixed the header for i386 and for other UNIX-like architectures with the same problem.

Additionally I recycled the buggy FRHACK to omit the code for saving the frame pointer. The Unix configure compiles slp_transfer.c with -fno-omit-frame-pointer (except on Darwin). Therefore the compiler preserves the frame pointer register by default and there is no need to save it explicitly.

I also changed the optimization flags for slp_transfer.c from the unspecific -O2 to the specific -fno-inline-functions. This way it is clear, what optimization must be avoided.

Unfortunately, I have only i386/amd64 based systems for testing.

Fixed for 2.7-slp by 4f7698499ad5

ghost commented 7 years ago

Original comment by Anselm Kruis (Bitbucket: akruis, GitHub: akruis):


Thanks for the report, I'll have a look at it.