shithub: femtolisp

Download patch

ref: e732a668e856a6eebd755eddbbc37f6b822f3217
parent: b81e574fb493d4354196d9e2a9adf8f76eab5e76
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Mon Nov 11 14:59:11 EST 2024

import from Julia: "fix a possible flisp memory bug", by Jeff Bezanson

This is 1a81a4770cba7b078a28a52dfd5bb630977561c9 in Julia:

"in very rare circumstances this could cause a closure to spill over the heap".

--- a/flisp.c
+++ b/flisp.c
@@ -287,7 +287,7 @@
 
 	assert(n > 0);
 	n = LLT_ALIGN(n, 2);   // only allocate multiples of 2 words
-	if(__unlikely((value_t*)FL(curheap) > ((value_t*)FL(lim))+2-n)){
+	if(__unlikely((value_t*)FL(curheap) > (value_t*)FL(lim)+2-n)){
 		gc(0);
 		while((value_t*)FL(curheap) > ((value_t*)FL(lim))+2-n)
 			gc(1);
@@ -521,8 +521,12 @@
 		}
 		FL(grew) = !FL(grew);
 	}
-	if(FL(curheap) > FL(lim))  // all data was live
+	if(__unlikely((value_t*)FL(curheap) > (value_t*)FL(lim)-2)){
+		// all data was live; gc again and grow heap.
+		// but also always leave at least 4 words available, so a closure
+		// can be allocated without an extra check.
 		gc(0);
+	}
 }
 
 static void
@@ -1191,7 +1195,7 @@
 			}else{
 				PUSH(FL(stack)[bp]); // env has already been captured; share
 			}
-			if(FL(curheap) > FL(lim)-2)
+			if(__unlikely((value_t*)FL(curheap) > (value_t*)FL(lim)-2))
 				gc(0);
 			pv = (value_t*)FL(curheap);
 			FL(curheap) += 4*sizeof(value_t);