From 474b17853469c44c978239c1694d06b137b8e342 Mon Sep 17 00:00:00 2001 From: Yuri Roubinsky Date: Thu, 25 Jun 2020 10:06:12 +0300 Subject: [PATCH] [3.2] Fix shader crash if pass const argument to 'out/inout' parameter --- servers/visual/shader_language.cpp | 66 +++++++++++++++++++++++++++++- servers/visual/shader_language.h | 1 + 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index f02d886bf8a..b400a6e03b2 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -883,6 +883,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, const Mapparent_block; } - + int function_index = -1; //test if function was parsed first for (int i = 0; i < shader->functions.size(); i++) { if (shader->functions[i].name == name) { @@ -2973,6 +2976,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons break; } } + function_index = i; break; } } @@ -2994,6 +2998,54 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } completion_class = TAG_GLOBAL; // reset sub-class + if (function_index >= 0) { + FunctionNode *call_function = shader->functions[function_index].function; + if (call_function) { + for (int i = 0; i < call_function->arguments.size(); i++) { + int argidx = i + 1; + if (argidx < func->arguments.size()) { + if (call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT) { + bool error = false; + Node *n = func->arguments[argidx]; + if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) { + error = true; + } else if (n->type == Node::TYPE_ARRAY) { + ArrayNode *an = static_cast(n); + if (an->call_expression != nullptr || an->is_const) { + error = true; + } + } else if (n->type == Node::TYPE_VARIABLE) { + VariableNode *vn = static_cast(n); + if (vn->is_const) { + error = true; + } else { + StringName varname = vn->name; + if (shader->constants.has(varname)) { + error = true; + } else if (shader->uniforms.has(varname)) { + error = true; + } else { + if (p_builtin_types.has(varname)) { + BuiltInInfo info = p_builtin_types[varname]; + if (info.constant) { + error = true; + } + } + } + } + } + if (error) { + _set_error(vformat("Constant value cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier))); + return nullptr; + } + } + } else { + break; + } + } + } + } + expr = func; } else { @@ -4729,6 +4781,18 @@ String ShaderLanguage::_get_shader_type_list(const Set &p_shader_types) return valid_types; } +String ShaderLanguage::_get_qualifier_str(ArgumentQualifier p_qualifier) const { + switch (p_qualifier) { + case ArgumentQualifier::ARGUMENT_QUALIFIER_IN: + return "in"; + case ArgumentQualifier::ARGUMENT_QUALIFIER_OUT: + return "out"; + case ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT: + return "inout"; + } + return ""; +} + Error ShaderLanguage::_validate_datatype(DataType p_type) { if (VisualServer::get_singleton()->is_low_end()) { bool invalid_type = false; diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 35f4a8b1b0f..f16369f869d 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -761,6 +761,7 @@ private: Node *_parse_and_reduce_expression(BlockNode *p_block, const Map &p_builtin_types); Error _parse_block(BlockNode *p_block, const Map &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); String _get_shader_type_list(const Set &p_shader_types) const; + String _get_qualifier_str(ArgumentQualifier p_qualifier) const; Error _parse_shader(const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types);