~ chicken-core (chicken-5) dc5bd1e06894ee98d46223c784724dc95907f6cf


commit dc5bd1e06894ee98d46223c784724dc95907f6cf
Author:     Peter Bex <peter@more-magic.net>
AuthorDate: Wed Dec 28 19:04:12 2016 +0100
Commit:     Christian Kellermann <ckeen@pestilenz.org>
CommitDate: Wed Dec 28 23:51:32 2016 +0100

    Fix crashes in callbacks after GC (#1337).
    
    This was caused by keeping argvector in temp stack, similar to 9eed2742.
    Instead, we also copy the argvector into the stack before re-invoking
    the trampoline when in a callback context, just like a regular CPS
    context.
    
    Also, fix an off-by-one in the number of arguments which
    allocate_vector_2 accepts; simply passing the original argcount doesn't
    allow for the extra 'mode' argument which gets added onto the front of
    the stack.
    
    Signed-off-by: Christian Kellermann <ckeen@pestilenz.org>

diff --git a/NEWS b/NEWS
index 6a347081..ac516597 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,7 @@
 
 - Runtime system:
   - "time" macro now shows peak memory usage (#1318, thanks to Kooda).
+  - Avoid crashes in ffi callbacks after GC (#1337, thanks to cosarara).
 
 - Core libraries:
   - Keywords are more consistently read/written, like symbols (#1332).
diff --git a/runtime.c b/runtime.c
index 4b6300f1..d9ee0009 100644
--- a/runtime.c
+++ b/runtime.c
@@ -1504,6 +1504,9 @@ C_word CHICKEN_run(void *toplevel)
   serious_signal_occurred = 0;
 
   if(!return_to_host) {
+    /* We must copy the argvector onto the stack, because
+     * any subsequent save() will otherwise clobber it.
+     */
     int argcount = C_temporary_stack_bottom - C_temporary_stack;
     C_word *p = C_alloc(argcount);
     C_memcpy(p, C_temporary_stack, argcount * sizeof(C_word));
@@ -2007,8 +2010,11 @@ C_word C_fcall C_callback(C_word closure, int argc)
   serious_signal_occurred = 0;
 
   if(!callback_returned_flag) {
-    C_word *p = C_temporary_stack;
-    
+    /* We must copy the argvector onto the stack, because
+     * any subsequent save() will otherwise clobber it.
+     */
+    C_word *p = C_alloc(C_restart_c);
+    C_memcpy(p, C_temporary_stack, C_restart_c * sizeof(C_word));
     C_temporary_stack = C_temporary_stack_bottom;
     ((C_proc)C_restart_trampoline)(C_restart_c, p);
   }
@@ -7508,7 +7514,10 @@ void C_ccall C_allocate_vector(C_word c, C_word *av)
       C_fromspace_top = C_fromspace_limit; /* trigger major GC */
   
     C_save(C_SCHEME_TRUE);
-    C_reclaim((void *)allocate_vector_2, c);
+    /* We explicitly pass 7 here, that's the number of things saved.
+     * That's the arguments, plus one additional thing: the mode.
+     */
+    C_reclaim((void *)allocate_vector_2, 7);
   }
 
   C_save(C_SCHEME_FALSE);
Trap