Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: make the examples work on more compilers

...

Code Block
bgColor#FFCCCC
langc
jmp_buf buf;
unsigned char b[] = {0xe5, 0x06, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00};

int main(void) {
  setup();
  do_stuff();
  return 0;
}

void setup(void) {
  f();
}

void f(void) {
  g();
}

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

static jmp_buf buf;
static void bad(void);

static void g(void) {
  if (setjmp(buf) == 0) {
    printf("setjmp() invoked\n");
  } else {
    printf("longjmp() invoked\n");
  }
}

static void do_stufff(void) {
  char a[8];
  memcpy(a, b, 8)g();
}

static void setup(void) {
  f();
}

void do_stuff(void) {
  void (*b)(void) = bad;
  /* ... */
  longjmp(buf, 1);
}

static void bad(void) {
  printf("Should not be called!\n");
  exit(1);
}

int main(void) {
  setup();
  do_stuff();
}

Implementation Details

Compiled at -O0 for x86-64 using GCC 4.1.2 or Clang on Linux, the preceding the preceding example outputs the following when run:

...

Code Block
bgColor#ccccff
langc
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>

static jmp_buf buf;
unsignedstatic char b[] = {0xe5, 0x06, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}void bad(void);

intvoid maindo_stuff(void) {
  ifvoid (setjmp*b)(bufvoid) == 0) {
    printf("setjmp() invoked\n");
  } else bad;
  /* ... */
  longjmp(buf, 1);
}

static void bad(void) {
    printf("longjmp() invokedShould not be called!\n");
  }
  do_stuff();
  return 0exit(1);
}

voidint do_stuffmain(void) {
  char a[8];
  memcpy(a, b, 8);
  /* ... */
  longjmp(buf, 1);
}

void bad(void)if (setjmp(buf) == 0) {
    printf("setjmp() invoked\n");
  } else {
    printf("Should not be called!longjmp() invoked\n");
  }
  exitdo_stuff(1);
}
 

There is no risk of overwriting a return address because the stack frame of main() (the function that invoked setjmp()) is still on the stack; so when do_stuff() is invoked, the two stack frames will not overlap.

...