From ce265d95750913f1a1a9634d41c4f5be2dcafb1c Mon Sep 17 00:00:00 2001 From: Chaosus Date: Mon, 5 Aug 2024 22:36:55 +0300 Subject: [PATCH] Fix crash when division by zero/modulo by zero happen on vectors --- modules/gdscript/gdscript_byte_codegen.cpp | 57 ++++++++++++++++++- .../errors/op_by_zero/division_by_zero_int.gd | 3 + .../op_by_zero/division_by_zero_int.out | 6 ++ .../op_by_zero/division_by_zero_vector2i.gd | 3 + .../op_by_zero/division_by_zero_vector2i.out | 6 ++ .../op_by_zero/division_by_zero_vector3i.gd | 3 + .../op_by_zero/division_by_zero_vector3i.out | 6 ++ .../op_by_zero/division_by_zero_vector4i.gd | 3 + .../op_by_zero/division_by_zero_vector4i.out | 6 ++ .../errors/op_by_zero/modulo_by_zero_int.gd | 3 + .../errors/op_by_zero/modulo_by_zero_int.out | 6 ++ .../op_by_zero/modulo_by_zero_vector2i.gd | 3 + .../op_by_zero/modulo_by_zero_vector2i.out | 6 ++ .../op_by_zero/modulo_by_zero_vector3i.gd | 3 + .../op_by_zero/modulo_by_zero_vector3i.out | 6 ++ .../op_by_zero/modulo_by_zero_vector4i.gd | 3 + .../op_by_zero/modulo_by_zero_vector4i.out | 6 ++ 17 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_int.gd create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_int.out create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector2i.gd create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector2i.out create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector3i.gd create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector3i.out create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector4i.gd create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector4i.out create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_int.gd create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_int.out create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector2i.gd create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector2i.out create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector3i.gd create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector3i.out create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector4i.gd create mode 100644 modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector4i.out diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 4cda3d30375..d4eb1f6e838 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -585,8 +585,61 @@ 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) { - // 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)) { + // Avoid validated evaluator for modulo and division when operands are int or integer vector, since there's no check for division by zero. + bool valid = HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand); + if (valid && (p_operator == Variant::OP_DIVIDE || p_operator == Variant::OP_MODULE)) { + switch (p_left_operand.type.builtin_type) { + case Variant::INT: + switch (p_right_operand.type.builtin_type) { + case Variant::INT: + valid = false; + break; + default: + break; + } + break; + case Variant::VECTOR2I: + switch (p_right_operand.type.builtin_type) { + case Variant::INT: + valid = false; + break; + case Variant::VECTOR2I: + valid = false; + break; + default: + break; + } + break; + case Variant::VECTOR3I: + switch (p_right_operand.type.builtin_type) { + case Variant::INT: + valid = false; + break; + case Variant::VECTOR3I: + valid = false; + break; + default: + break; + } + break; + case Variant::VECTOR4I: + switch (p_right_operand.type.builtin_type) { + case Variant::INT: + valid = false; + break; + case Variant::VECTOR4I: + valid = false; + break; + default: + break; + } + break; + default: + break; + } + } + + if (valid) { 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 temp_type = temporaries[p_target.address].type; diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_int.gd b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_int.gd new file mode 100644 index 00000000000..585639851ad --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_int.gd @@ -0,0 +1,3 @@ +func test(): + var integer = 1 + integer /= 0 diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_int.out b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_int.out new file mode 100644 index 00000000000..d861def4a10 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_int.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/op_by_zero/division_by_zero_int.gd +>> 3 +>> Division by zero error in operator '/'. diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector2i.gd b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector2i.gd new file mode 100644 index 00000000000..103374165fb --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector2i.gd @@ -0,0 +1,3 @@ +func test(): + var vec2i = Vector2i(1, 1) + vec2i /= Vector2i(0, 0) diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector2i.out b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector2i.out new file mode 100644 index 00000000000..36168577c96 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector2i.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/op_by_zero/division_by_zero_vector2i.gd +>> 3 +>> Division by zero error in operator '/'. diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector3i.gd b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector3i.gd new file mode 100644 index 00000000000..4cc21afd258 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector3i.gd @@ -0,0 +1,3 @@ +func test(): + var vec3i = Vector3i(1, 1, 1) + vec3i /= Vector3i(0, 0, 0) diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector3i.out b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector3i.out new file mode 100644 index 00000000000..8a26ffec6bf --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector3i.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/op_by_zero/division_by_zero_vector3i.gd +>> 3 +>> Division by zero error in operator '/'. diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector4i.gd b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector4i.gd new file mode 100644 index 00000000000..0a670ea7da2 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector4i.gd @@ -0,0 +1,3 @@ +func test(): + var vec4i = Vector4i(1, 1, 1, 1) + vec4i /= Vector4i(0, 0, 0, 0) diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector4i.out b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector4i.out new file mode 100644 index 00000000000..e84cd85faff --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/division_by_zero_vector4i.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/op_by_zero/division_by_zero_vector4i.gd +>> 3 +>> Division by zero error in operator '/'. diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_int.gd b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_int.gd new file mode 100644 index 00000000000..bcef3c5f1eb --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_int.gd @@ -0,0 +1,3 @@ +func test(): + var integer = 1 + integer %= 0 diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_int.out b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_int.out new file mode 100644 index 00000000000..5600da84f58 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_int.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/op_by_zero/modulo_by_zero_int.gd +>> 3 +>> Modulo by zero error in operator '%'. diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector2i.gd b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector2i.gd new file mode 100644 index 00000000000..b6165d3b661 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector2i.gd @@ -0,0 +1,3 @@ +func test(): + var vec2i = Vector2i(1, 1) + vec2i %= Vector2i(0, 0) diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector2i.out b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector2i.out new file mode 100644 index 00000000000..8da3ce9f92c --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector2i.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/op_by_zero/modulo_by_zero_vector2i.gd +>> 3 +>> Modulo by zero error in operator '%'. diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector3i.gd b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector3i.gd new file mode 100644 index 00000000000..a2f0b3fde35 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector3i.gd @@ -0,0 +1,3 @@ +func test(): + var vec3i = Vector3i(1, 1, 1) + vec3i %= Vector3i(0, 0, 0) diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector3i.out b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector3i.out new file mode 100644 index 00000000000..51d6269158a --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector3i.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/op_by_zero/modulo_by_zero_vector3i.gd +>> 3 +>> Modulo by zero error in operator '%'. diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector4i.gd b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector4i.gd new file mode 100644 index 00000000000..b611b5aef7a --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector4i.gd @@ -0,0 +1,3 @@ +func test(): + var vec4i = Vector4i(1, 1, 1, 1) + vec4i %= Vector4i(0, 0, 0, 0) diff --git a/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector4i.out b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector4i.out new file mode 100644 index 00000000000..f7d953089a1 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/errors/op_by_zero/modulo_by_zero_vector4i.out @@ -0,0 +1,6 @@ +GDTEST_RUNTIME_ERROR +>> SCRIPT ERROR +>> on function: test() +>> runtime/errors/op_by_zero/modulo_by_zero_vector4i.gd +>> 3 +>> Modulo by zero error in operator '%'.