From 221f5da857035fc883c440f3d487d89377d2dca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mikrut?= Date: Sun, 15 Aug 2021 22:18:17 +0200 Subject: [PATCH] Fix crash when dividing by 0 in Vector2/3i --- core/variant/variant_op.cpp | 8 ++-- core/variant/variant_op.h | 96 +++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 4 deletions(-) diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp index 16c7428781..a245aff35b 100644 --- a/core/variant/variant_op.cpp +++ b/core/variant/variant_op.cpp @@ -171,7 +171,7 @@ void Variant::_register_variant_operators() { register_op>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::FLOAT); register_op>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::INT); - register_op>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::VECTOR2I); + register_op>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::VECTOR2I); register_op>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::FLOAT); register_op>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::INT); @@ -183,7 +183,7 @@ void Variant::_register_variant_operators() { register_op>(Variant::OP_DIVIDE, Variant::VECTOR3, Variant::FLOAT); register_op>(Variant::OP_DIVIDE, Variant::VECTOR3, Variant::INT); - register_op>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::VECTOR3I); + register_op>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::VECTOR3I); register_op>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::FLOAT); register_op>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::INT); @@ -195,10 +195,10 @@ void Variant::_register_variant_operators() { register_op>(Variant::OP_DIVIDE, Variant::COLOR, Variant::INT); register_op>(Variant::OP_MODULE, Variant::INT, Variant::INT); - register_op>(Variant::OP_MODULE, Variant::VECTOR2I, Variant::VECTOR2I); + register_op>(Variant::OP_MODULE, Variant::VECTOR2I, Variant::VECTOR2I); register_op>(Variant::OP_MODULE, Variant::VECTOR2I, Variant::INT); - register_op>(Variant::OP_MODULE, Variant::VECTOR3I, Variant::VECTOR3I); + register_op>(Variant::OP_MODULE, Variant::VECTOR3I, Variant::VECTOR3I); register_op>(Variant::OP_MODULE, Variant::VECTOR3I, Variant::INT); register_op(Variant::OP_MODULE, Variant::STRING, Variant::NIL); diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h index cbdd60f404..3c9f849a4f 100644 --- a/core/variant/variant_op.h +++ b/core/variant/variant_op.h @@ -168,6 +168,54 @@ public: static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } }; +template <> +class OperatorEvaluatorDivNZ { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector2i &a = *VariantGetInternalPtr::get_ptr(&p_left); + const Vector2i &b = *VariantGetInternalPtr::get_ptr(&p_right); + if (unlikely(b.x == 0 || b.y == 0)) { + r_valid = false; + *r_ret = "Division by zero error"; + return; + } + *r_ret = a / b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger::change(r_ret); + *VariantGetInternalPtr::get_ptr(r_ret) = *VariantGetInternalPtr::get_ptr(left) / *VariantGetInternalPtr::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg::encode(PtrToArg::convert(left) / PtrToArg::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } +}; + +template <> +class OperatorEvaluatorDivNZ { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector3i &a = *VariantGetInternalPtr::get_ptr(&p_left); + const Vector3i &b = *VariantGetInternalPtr::get_ptr(&p_right); + if (unlikely(b.x == 0 || b.y == 0 || b.z == 0)) { + r_valid = false; + *r_ret = "Division by zero error"; + return; + } + *r_ret = a / b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger::change(r_ret); + *VariantGetInternalPtr::get_ptr(r_ret) = *VariantGetInternalPtr::get_ptr(left) / *VariantGetInternalPtr::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg::encode(PtrToArg::convert(left) / PtrToArg::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } +}; + template class OperatorEvaluatorMod { public: @@ -209,6 +257,54 @@ public: static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } }; +template <> +class OperatorEvaluatorModNZ { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector2i &a = *VariantGetInternalPtr::get_ptr(&p_left); + const Vector2i &b = *VariantGetInternalPtr::get_ptr(&p_right); + if (unlikely(b.x == 0 || b.y == 0)) { + r_valid = false; + *r_ret = "Module by zero error"; + return; + } + *r_ret = a % b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger::change(r_ret); + *VariantGetInternalPtr::get_ptr(r_ret) = *VariantGetInternalPtr::get_ptr(left) % *VariantGetInternalPtr::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg::encode(PtrToArg::convert(left) / PtrToArg::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } +}; + +template <> +class OperatorEvaluatorModNZ { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector3i &a = *VariantGetInternalPtr::get_ptr(&p_left); + const Vector3i &b = *VariantGetInternalPtr::get_ptr(&p_right); + if (unlikely(b.x == 0 || b.y == 0 || b.z == 0)) { + r_valid = false; + *r_ret = "Module by zero error"; + return; + } + *r_ret = a % b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger::change(r_ret); + *VariantGetInternalPtr::get_ptr(r_ret) = *VariantGetInternalPtr::get_ptr(left) % *VariantGetInternalPtr::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg::encode(PtrToArg::convert(left) % PtrToArg::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo::VARIANT_TYPE; } +}; + template class OperatorEvaluatorNeg { public: