Jelajahi Sumber

[GDScript] Fix `range` helper method using 32-bit ints for arguments.

Pāvels Nadtočajevs 1 bulan lalu
induk
melakukan
b21e6529e6

+ 16 - 13
modules/gdscript/gdscript_utility_functions.cpp

@@ -139,7 +139,7 @@ struct GDScriptUtilityFunctionsDefinitions {
 			case 1: {
 				DEBUG_VALIDATE_ARG_TYPE(0, Variant::INT);
 
-				int count = *p_args[0];
+				int64_t count = *p_args[0];
 
 				Array arr;
 				if (count <= 0) {
@@ -147,10 +147,11 @@ struct GDScriptUtilityFunctionsDefinitions {
 					return;
 				}
 
+				GDFUNC_FAIL_COND_MSG(count > INT32_MAX, RTR("Range too big."));
 				Error err = arr.resize(count);
 				GDFUNC_FAIL_COND_MSG(err != OK, RTR("Cannot resize array."));
 
-				for (int i = 0; i < count; i++) {
+				for (int64_t i = 0; i < count; i++) {
 					arr[i] = i;
 				}
 
@@ -160,8 +161,8 @@ struct GDScriptUtilityFunctionsDefinitions {
 				DEBUG_VALIDATE_ARG_TYPE(0, Variant::INT);
 				DEBUG_VALIDATE_ARG_TYPE(1, Variant::INT);
 
-				int from = *p_args[0];
-				int to = *p_args[1];
+				int64_t from = *p_args[0];
+				int64_t to = *p_args[1];
 
 				Array arr;
 				if (from >= to) {
@@ -169,10 +170,11 @@ struct GDScriptUtilityFunctionsDefinitions {
 					return;
 				}
 
+				GDFUNC_FAIL_COND_MSG(to - from > INT32_MAX, RTR("Range too big."));
 				Error err = arr.resize(to - from);
 				GDFUNC_FAIL_COND_MSG(err != OK, RTR("Cannot resize array."));
 
-				for (int i = from; i < to; i++) {
+				for (int64_t i = from; i < to; i++) {
 					arr[i - from] = i;
 				}
 
@@ -183,9 +185,9 @@ struct GDScriptUtilityFunctionsDefinitions {
 				DEBUG_VALIDATE_ARG_TYPE(1, Variant::INT);
 				DEBUG_VALIDATE_ARG_TYPE(2, Variant::INT);
 
-				int from = *p_args[0];
-				int to = *p_args[1];
-				int incr = *p_args[2];
+				int64_t from = *p_args[0];
+				int64_t to = *p_args[1];
+				int64_t incr = *p_args[2];
 
 				VALIDATE_ARG_CUSTOM(2, Variant::INT, incr == 0, RTR("Step argument is zero!"));
 
@@ -200,24 +202,25 @@ struct GDScriptUtilityFunctionsDefinitions {
 				}
 
 				// Calculate how many.
-				int count = 0;
+				int64_t count = 0;
 				if (incr > 0) {
 					count = Math::division_round_up(to - from, incr);
 				} else {
 					count = Math::division_round_up(from - to, -incr);
 				}
 
+				GDFUNC_FAIL_COND_MSG(count > INT32_MAX, RTR("Range too big."));
 				Error err = arr.resize(count);
 				GDFUNC_FAIL_COND_MSG(err != OK, RTR("Cannot resize array."));
 
 				if (incr > 0) {
-					int idx = 0;
-					for (int i = from; i < to; i += incr) {
+					int64_t idx = 0;
+					for (int64_t i = from; i < to; i += incr) {
 						arr[idx++] = i;
 					}
 				} else {
-					int idx = 0;
-					for (int i = from; i > to; i += incr) {
+					int64_t idx = 0;
+					for (int64_t i = from; i > to; i += incr) {
 						arr[idx++] = i;
 					}
 				}

+ 13 - 0
modules/gdscript/tests/scripts/runtime/features/range_large_ints.gd

@@ -0,0 +1,13 @@
+func test():
+	# GH-109376
+	# Note: unlike "for range", which is iterated in place, this helper function generates an array of all values in range.
+	var result
+
+	result = range(2147483640, 2147483647) # Range below 32-bit size limit.
+	print(result)
+
+	result = range(2147483640, 2147483647 + 1) # Range 1 over 32-bit size limit.
+	print(result)
+
+	result = range(9922147483640, 9922147483647) # Range significantly over 32-bit size limit.
+	print(result)

+ 4 - 0
modules/gdscript/tests/scripts/runtime/features/range_large_ints.out

@@ -0,0 +1,4 @@
+GDTEST_OK
+[2147483640, 2147483641, 2147483642, 2147483643, 2147483644, 2147483645, 2147483646]
+[2147483640, 2147483641, 2147483642, 2147483643, 2147483644, 2147483645, 2147483646, 2147483647]
+[9922147483640, 9922147483641, 9922147483642, 9922147483643, 9922147483644, 9922147483645, 9922147483646]