Skip to content

bug: ON ERROR GOTO to a module-level handler keeps the failing procedure's frame #483

Description

@metaneutrons

Reproducer

declare sub dowork()

dim as integer marker = 4711
dim as integer counter = 13
on error goto handler

dowork()
print "no error"
end 1

handler:
print "marker="; marker; " counter="; counter
end 0

sub dowork()
    dim as integer f = freefile
    open "/nonexistent/x" for input as #f
    close #f
end sub

Build and run with fbc -e locals.bas && ./locals.

Expected behavior

The handler prints marker= 4711 counter= 13.

Actual behavior

The handler runs with the failing procedure's stack and frame pointer instead of the handler's. On current master (5714d10) this reproduces with the C and GAS64 backends:

backend optimization result
gcc (C backend) -O 0 garbage module-local values
gcc (C backend) -O 2 SIGSEGV
clang (C backend) -O 0 garbage module-local values
gas64 -O 0 and -O 2 garbage module-local values

ON LOCAL ERROR GOTO is unaffected because its handler remains in the same procedure.

Cause

fb_ErrorThrow*() returns ctx->handler, then generated code jumps to that address. If the error was raised in a procedure and the handler is at module level, the transfer does not restore the handler frame. The module-level handler reads locals through the wrong frame pointer; with optimized C output the stack can also violate the platform ABI and crash in the next runtime call.

Required direction

A correct nonlocal handler transfer needs to capture the handler context where ON ERROR GOTO installs it and restore it before entering the handler, similar to setjmp/longjmp. That has a RESUME consequence: a transfer that unwinds the failing procedure cannot later resume inside it. A same-procedure handler can retain ordinary RESUME behavior.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions