Skip to content

Catching SPL exceptions potentially invokes undefined behavior #24

@cmlsharp

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.

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