Subject: bug#63279: closed (Segfault when printing a call-with-values stack frame in backtrace)

From: [email-masked] (GNU bug Tracking System)
Date: Mon, 08 May 2023 14:16:01 +0000

Your bug report

#63279: Segfault when printing a call-with-values stack frame in backtrace

which was filed against the guile package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
63279: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=63279
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Segfault when printing a call-with-values stack frame in backtrace
From: "Thompson, David" <[email-masked]>
To: [email-masked]
Date: Mon, 8 May 2023 10:15:04 -0400
List-Id: <debbugs-submit.debbugs.gnu.org>

Andy fixed this in commit 6efc0b8159f0fc74c0eafec988fe5434fb4d9f51.
Thank you, Andy!

Closing.

- Dave

Subject: Segfault when printing a call-with-values stack frame in backtrace
From: "Thompson, David" <[email-masked]>
To: [email-masked]
Date: Thu, 4 May 2023 12:29:40 -0400
List-Id: <debbugs-submit.debbugs.gnu.org>

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