diff options
author | Gene Cumm <gene.cumm@gmail.com> | 2016-01-19 06:37:41 -0500 |
---|---|---|
committer | Gene Cumm <gene.cumm@gmail.com> | 2016-01-19 06:41:59 -0500 |
commit | 7cd1ed60e37f36db859a2ca3d6ee261f98dafdac (patch) | |
tree | faa89c0124e259f8d63bb1da2755b9da42b14e6e /core/elflink/load_env32.c | |
parent | 496bb8c2a19ccf9e8c6c67b925c492c924c9378a (diff) | |
parent | 19d0d592ee115e8772b7dc6d5594748a49b63b0c (diff) | |
download | syslinux-7cd1ed60e37f36db859a2ca3d6ee261f98dafdac.tar.gz |
Merge 'git://github.com/Celelibi/syslinux.git/fix/bios/tail-call-stack-overflows'
FIXME: this circumvents some of the issue but is not the cleanest and may
reoccur.
Diffstat (limited to 'core/elflink/load_env32.c')
-rw-r--r-- | core/elflink/load_env32.c | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c index 492cc095..db19c7aa 100644 --- a/core/elflink/load_env32.c +++ b/core/elflink/load_env32.c @@ -55,7 +55,7 @@ void init_module_subsystem(struct elf_module *module) list_add(&module->list, &modules_head); } -__export int start_ldlinux(int argc, char **argv) +static int _start_ldlinux(int argc, char **argv) { int rv; @@ -96,6 +96,62 @@ again: return rv; } +__export int start_ldlinux(int argc, char **argv) +{ + /* These variables are static to survive the longjmp. */ + static int has_jmpbuf = 0; + static jmp_buf restart; + static int savedargc; + static char *heapargs; + static size_t argsmem = 0; + char **stackargv; + char *stackargs; + char *p, *q; + int i; + + + /* 1. Save the arguments on the heap */ + for (i = 0; i < argc; i++) + argsmem += strlen(argv[i]) + 1; + + savedargc = argc; + heapargs = malloc(argsmem); + + p = heapargs; + for (i = 0; i < savedargc; i++) { + q = argv[i]; + while (*q) + *p++ = *q++; + + *p++ = '\0'; + } + + /* 2. Undo the stack if we're restarting ldlinux */ + if (has_jmpbuf) + longjmp(restart, 1); + + setjmp(restart); + has_jmpbuf = 1; + + /* 3. Convert the heap memory to stack memory to avoid memory leaks */ + stackargs = alloca(argsmem); + stackargv = alloca(savedargc * (sizeof(char *) + 1)); + + memcpy(stackargs, heapargs, argsmem); + + p = stackargs; + for (i = 0; i < savedargc; i++) { + stackargv[i] = p; + p += strlen(p) + 1; + } + + stackargv[savedargc] = NULL; + + free(heapargs); + + return _start_ldlinux(savedargc, stackargv); +} + /* note to self: do _*NOT*_ use static key word on this function */ void load_env32(com32sys_t * regs __unused) { |