Jacopo Notarstefano
Jacopo Notarstefano

Reputation: 373

`longjmp` into a terminated function

Exercise 6.2 in "The Linux Programming Interface" by Michael Kerrisk asks:

Write a program to see what happens if we try to longjmp() into a function that has already terminated.

I was thinking that this program ought do the trick:

#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>

static jmp_buf env;

void foo (void);
void bar (void);
void baz (void);

int
main (int argc, char *argv[])
{
    foo();
    bar();

    exit(EXIT_SUCCESS);
}

void
foo (void)
{
    printf("foo start\n");

    switch (setjmp(env)) {
    case 0:
        printf("foo branch 0\n");
        break;
    case 1:
        printf("foo branch 1\n");
        break;
    }

    printf("foo end\n");
    return;
}

void
bar (void)
{
    printf("bar start\n");

    baz();

    printf("bar end\n");
    return;
}

void
baz (void)
{
    printf("baz start\n");

    longjmp(env, 1);

    printf("baz end\n");
    return;
}

Instead, this prints:

$ ./setjmp
foo start
foo branch 0
foo end
bar start
baz start
foo branch 1
foo end

That is, the behaviour I would have expected if foo had not terminated. Why is that? How can I modify my program to achieve a longjmp into a terminated function?

Upvotes: 2

Views: 611

Answers (1)

user1508519
user1508519

Reputation:

Wikipedia. Take with a grain of salt.

Jumping to a function that has already terminated by return or longjmp is undefined.[6] However, most implementations of longjmp do not specifically destroy local variables when performing the jump. Since the context survives until its local variables are erased, it could actually be restored by setjmp.

Luckily, they do quote the (albeit old) standard.

§7.13.2.1/2

The longjmp function restores the environment saved by the most recent invocation of the setjmp macro in the same invocation of the program with the corresponding jmp_buf argument. If there has been no such invocation, or if the function containing the invocation of the setjmp macro has terminated execution211) in the interim, or if the invocation of the setjmp macro was within the scope of an identifier with variably modified type and execution has left that scope in the interim, the behavior is undefined.

211) For example, by executing a return statement or because another longjmp call has caused a transfer to a setjmp invocation in a function earlier in the set of nested calls.

Upvotes: 4

Related Questions