Skip to content

Catching SPL exceptions potentially invokes undefined behavior #24

Description

@cmlsharp

Source

Stack unwinding is simulated in exception.{h,c} by utilizing the setjmp and longjmp functions from the C standard library. These functions dynamically create for non-local gotos, allowing control flow to be transferred from one function to an arbitrary location in another.

There functions, while useful, carry a subtle "gotcha". When control flow is transferred, whether or not registers are restored is unspecified (it is undefined in GCC, not sure about clang), meaning the values of non-volatile variables with automatic storage duration that have changed between the setjmp and longjmp calls are unspecified.

Example of the UB:

int foo(int);
void bar(int, int);

int main(void)
{
    int x = 10, y = 5;
   // Do stuff with x and y
    try { // setjmp is called in the expansion of `try`
        x = foo(y); // x is modified
        bar(x,y); // Throws an exception, which calls longjmp
    } catch (ANY) {
         // x might have been in a register but it's value has (maybe) been clobbered
         fprintf(stderr, "The value of x is %d", x); 
    }
}

Recommendation

I don't think that leaving potentially UB-causing constructs in a library designed for students. I would propose removing this feature and refactoring the library to function without it.

Activity

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

Metadata

Metadata

Assignees

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