Hello there, Guile seems to segfault when trying to print certain backtraces with a 'call-with-values' stack frame. Here's a minimal reproducer program:
(symbol? (call-with-values (lambda () (error 'oh-no)) list)) If you eval this at the REPL and enter ,bt in the debugger, Guile should segfault. Relevant gdb backtrace: #0 0x00007ffff7f43397 in scm_is_values (x=<error reading variable: ERROR: Cannot access memory at address 0x0>0x0) at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/values.h:30 #1 vm_regular_engine (thread=0x7ffff7401900) at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/vm-engine.c:974 #2 0x00007ffff7f50db5 in scm_call_n (proc=<optimized out>, argv=<optimized out>, nargs=4) at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/vm.c:1615 #3 0x00007ffff7ebb674 in scm_call_4 (proc=<optimized out>, arg1=<optimized out>, arg2=<optimized out>, arg3=<optimized out>, arg4=<optimized out>) at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/eval.c:517 #4 0x00007ffff7eb801b in display_backtrace_body (a=0x7fffed68e6a0) at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/backtrace.c:239 #5 0x00007ffff7f62092 in scm_c_with_exception_handler.constprop.0 (type=#t, handler_data=handler_data@entry=0x7fffed68e630, thunk_data=thunk_data@entry=0x7fffed68e630, thunk=<optimized out>, handler=<optimized out>) at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/exceptions.c:170 >From what I can tell, in vm-engine.c, in the subr-call op, 'scm_apply_subr (sp, idx, FRAME_LOCALS_COUNT ())' is called and returns an SCM object, which is stored in the local variable 'ret'. Then 'scm_is_values (ret)' is called, and the segfault occurs due to a null pointer dereference. At the time of the segfault, 'idx' is 1130, corresponding to the 'frame-local-ref' subr. Makes sense since it's the backtrace printer that crashes Guile. It seems that the data stored in the stack frames for 'call-with-values' calls is incorrect and the backtrace printer wants to display 3 arguments for the call when the procedure only accepts 2 arguments. This can be clearly seen by running another small program that happens to not segfault: (call-with-values (lambda () (error 'oh-no)) list) Check out the backtrace and you'll see a frame like this: (_ #<procedure b34e28 at <unknown port>:8:18 ()> #<procedure list _> 1) The first 2 arguments are as expected, but why is there a 1 at the end? For another example that doesn't crash but has an even more clearly messed up backtrace, try this: (append '(a b c) (call-with-values (lambda () (error 'oh-no)) list)) You'll see a frame like this: (_ #<procedure b39730 at <unknown port>:10:35 ()> #<procedure list _> . #<unknown-type (0xb . 0x304) @ 0x7f50dd792050>) At Spritely we've reproduced this issue on multiple machines with both Guile 3.0.7 and 3.0.9. - Dave