From 4230295683d1ae86f2765ce7eaa42dacc0957021 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Thu, 23 Apr 2015 15:06:49 -0400 Subject: [PATCH] Fix load_varargs to prevent local var corruption Assigning to a varargs variable that is not passed by the C caller can result in corruption of another parameter. EG: the var contains data for another parameter, which is then changed unexpectedly. The code was rewritten to assign to a new variable, to prevent this from happening. --- cgen.scm | 6 ++++-- runtime.h | 39 +++++++++++++++++++-------------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/cgen.scm b/cgen.scm index 74e9ba4f..f4845183 100644 --- a/cgen.scm +++ b/cgen.scm @@ -878,7 +878,7 @@ ((pair? (cdr formals)) (string-append ", " (c-compile-formals (cdr formals) type))) ((not (equal? 'args:fixed type)) - (string-append ", object " (mangle (cdr formals)) ", ...")) + (string-append ", object " (mangle (cdr formals)) "_raw, ...")) (else ""))))) @@ -925,7 +925,9 @@ ; (number->string (length (lambda-formals->list exp))) ");" "load_varargs(" (mangle (lambda-varargs-var exp)) - ", argc - " (number->string + ", " + (mangle (lambda-varargs-var exp)) + "_raw, argc - " (number->string (- (length (lambda-formals->list exp)) 1 (if has-closure? 1 0))) diff --git a/runtime.h b/runtime.h index 43a1352b..40ab7bff 100644 --- a/runtime.h +++ b/runtime.h @@ -37,28 +37,27 @@ static object cell_get(object cell){ our compiler will compute the difference between the number of required args and the number of provided ones, and pass the difference as 'count' */ -#define load_varargs(var, count) { \ - int i; \ - object tmp; \ - list args = nil; \ - va_list va; \ - if (count > 0) { \ - args = alloca(sizeof(cons_type)*count); \ - va_start(va, var); \ - for (i = 0; i < count; i++) { \ - if (i) { \ - tmp = va_arg(va, object); \ - } else { \ - tmp = var; \ +#define load_varargs(var, arg_var, count) \ + list var = (count > 0) ? alloca(sizeof(cons_type)*count) : nil; \ + { \ + int i; \ + object tmp; \ + va_list va; \ + if (count > 0) { \ + va_start(va, arg_var); \ + for (i = 0; i < count; i++) { \ + if (i) { \ + tmp = va_arg(va, object); \ + } else { \ + tmp = arg_var; \ + } \ + var[i].tag = cons_tag; \ + var[i].cons_car = tmp; \ + var[i].cons_cdr = (i == (count-1)) ? nil : &var[i + 1]; \ } \ - args[i].tag = cons_tag; \ - args[i].cons_car = tmp; \ - args[i].cons_cdr = (i == (count-1)) ? nil : &args[i + 1]; \ + va_end(va); \ } \ - va_end(va); \ - } \ - var = args; \ -} + } /* Prototypes for Lisp built-in functions. */