Browse Source

Fix for https://github.com/marcobambini/gravity/issues/132 and https://github.com/marcobambini/gravity/issues/131

Marco Bambini 8 years ago
parent
commit
00e53c3626
4 changed files with 19 additions and 8 deletions
  1. 12 8
      src/runtime/gravity_core.c
  2. 1 0
      src/runtime/gravity_vm.c
  3. 5 0
      src/shared/gravity_value.c
  4. 1 0
      src/shared/gravity_value.h

+ 12 - 8
src/runtime/gravity_core.c

@@ -827,6 +827,8 @@ static bool list_exec (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, ui
     
     uint32_t n = (uint32_t)VALUE_AS_INT(GET_VALUE(1));
     gravity_list_t *list = gravity_list_new(vm, n);
+    if (!list) RETURN_ERROR("Maximum List allocation size reached (%d).", MAX_ALLOCATION);
+    
     for (uint32_t i=0; i<n; ++i) marray_push(gravity_value_t, list->array, VALUE_FROM_NULL);
     
     RETURN_VALUE(VALUE_FROM_OBJECT(list), rindex);
@@ -1583,21 +1585,23 @@ static bool string_repeat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs
 	
 	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 	gravity_int_t times_to_repeat = VALUE_AS_INT(GET_VALUE(1));
-	if (times_to_repeat < 1) {
-		RETURN_ERROR("String.repeat() expects an integer >= 1");
+	if (times_to_repeat < 1 || times_to_repeat > MAX_ALLOCATION) {
+		RETURN_ERROR("String.repeat() expects a value >= 1 and < %d", MAX_ALLOCATION);
 	}
 
 	// figure out the size of the array we need to make to hold the new string
 	uint32_t new_size = (uint32_t)(main_str->len * times_to_repeat);
-	char new_str[new_size+1];
+	char *new_str = mem_alloc(new_size+1);
+	if (!new_str) RETURN_ERROR("Unable to allocate a String so big (%d)", new_size);
 	
-	// this code could be much faster with a memcpy
-	strcpy(new_str, main_str->s);
-	for (int i = 0; i < times_to_repeat-1; ++i) {
-		strcat(new_str, main_str->s);
+    uint32_t seek = 0;
+	for (uint32_t i = 0; i < times_to_repeat-1; ++i) {
+        memcpy(new_str+seek, main_str->s, main_str->len);
+        seek += main_str->len;
 	}
 
-	RETURN_VALUE(VALUE_FROM_CSTRING(vm, new_str), rindex);
+    gravity_string_t *s = gravity_string_new(vm, new_str, new_size, new_size);
+	RETURN_VALUE(VALUE_FROM_OBJECT(s), rindex);
 }
 
 static bool string_upper (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {

+ 1 - 0
src/runtime/gravity_vm.c

@@ -1143,6 +1143,7 @@ static bool gravity_vm_exec (gravity_vm *vm) {
 				DEBUG_VM("LISTNEW %d %d", r1, n);
 				
 				gravity_list_t *list = gravity_list_new(vm, n);
+                if (!list) RUNTIME_ERROR("Unable allocate a List");
 				SETVALUE(r1, VALUE_FROM_OBJECT(list));
 				DISPATCH();
 			}

+ 5 - 0
src/shared/gravity_value.c

@@ -849,6 +849,8 @@ gravity_function_t *gravity_function_deserialize (gravity_vm *vm, json_value *js
 					case json_array: {
 						uint32_t count = r->u.array.length;
 						gravity_list_t *list = gravity_list_new(NULL, count);
+                        if (!list) continue;
+                        
 						for (uint32_t k=0; k<count; ++k) {
 							json_value *jsonv = r->u.array.values[k];
 							gravity_value_t v;
@@ -865,6 +867,7 @@ gravity_function_t *gravity_function_deserialize (gravity_vm *vm, json_value *js
 							marray_push(gravity_value_t, list->array, v);
 						}
 						gravity_function_cpool_add(vm, f, VALUE_FROM_OBJECT(list));
+                        break;
 					}
 						
 					case json_none:
@@ -1672,6 +1675,8 @@ void gravity_value_dump (gravity_value_t v, char *buffer, uint16_t len) {
 
 // MARK: -
 gravity_list_t *gravity_list_new (gravity_vm *vm, uint32_t n) {
+    if (n > MAX_ALLOCATION) return NULL;
+    
 	gravity_list_t *list = (gravity_list_t *)mem_alloc(sizeof(gravity_list_t));
 	
 	list->isa = gravity_class_list;

+ 1 - 0
src/shared/gravity_value.h

@@ -111,6 +111,7 @@ extern "C" {
 #define MAX_INLINE_INT						131072		// 32 - 6 (OPCODE) - 8 (register) - 1 bit sign = 17
 #define MAX_FIELDSxFLUSH					64			// used in list/map serialization
 #define MAX_IVARS							768			// 2^10 - 2^8
+#define MAX_ALLOCATION                      4194304     // 1024 * 1024 * 4 (about 4 millions entry)
 
 #define DEFAULT_CONTEXT_SIZE				256			// default VM context entries (can grow)
 #define DEFAULT_MINSTRING_SIZE				64			// minimum string allocation size