2
0
Эх сурвалжийг харах

Fix crash when division by zero/modulo by zero happen on vectors

Chaosus 1 жил өмнө
parent
commit
0524e29b5c

+ 19 - 2
modules/gdscript/gdscript_byte_codegen.cpp

@@ -585,8 +585,25 @@ void GDScriptByteCodeGenerator::write_unary_operator(const Address &p_target, Va
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_binary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) {
 void GDScriptByteCodeGenerator::write_binary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) {
-	// Avoid validated evaluator for modulo and division when operands are int, since there's no check for division by zero.
-	if (HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand) && ((p_operator != Variant::OP_DIVIDE && p_operator != Variant::OP_MODULE) || p_left_operand.type.builtin_type != Variant::INT || p_right_operand.type.builtin_type != Variant::INT)) {
+	bool valid = HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand);
+
+	// Avoid validated evaluator for modulo and division when operands are int or integer vector, since there's no check for division by zero.
+	if (valid && (p_operator == Variant::OP_DIVIDE || p_operator == Variant::OP_MODULE)) {
+		switch (p_left_operand.type.builtin_type) {
+			case Variant::INT:
+				valid = p_right_operand.type.builtin_type != Variant::INT;
+				break;
+			case Variant::VECTOR2I:
+			case Variant::VECTOR3I:
+			case Variant::VECTOR4I:
+				valid = p_right_operand.type.builtin_type != Variant::INT && p_right_operand.type.builtin_type != p_left_operand.type.builtin_type;
+				break;
+			default:
+				break;
+		}
+	}
+
+	if (valid) {
 		if (p_target.mode == Address::TEMPORARY) {
 		if (p_target.mode == Address::TEMPORARY) {
 			Variant::Type result_type = Variant::get_operator_return_type(p_operator, p_left_operand.type.builtin_type, p_right_operand.type.builtin_type);
 			Variant::Type result_type = Variant::get_operator_return_type(p_operator, p_left_operand.type.builtin_type, p_right_operand.type.builtin_type);
 			Variant::Type temp_type = temporaries[p_target.address].type;
 			Variant::Type temp_type = temporaries[p_target.address].type;

+ 3 - 0
modules/gdscript/tests/scripts/runtime/errors/division_by_zero.gd

@@ -0,0 +1,3 @@
+func test():
+	var integer: int = 1
+	integer /= 0

+ 6 - 0
modules/gdscript/tests/scripts/runtime/errors/division_by_zero.out

@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/division_by_zero.gd
+>> 3
+>> Division by zero error in operator '/'.

+ 3 - 0
modules/gdscript/tests/scripts/runtime/errors/modulo_by_zero.gd

@@ -0,0 +1,3 @@
+func test():
+	var integer: int = 1
+	integer %= 0

+ 6 - 0
modules/gdscript/tests/scripts/runtime/errors/modulo_by_zero.out

@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/modulo_by_zero.gd
+>> 3
+>> Modulo by zero error in operator '%'.