From 3a70566b15c094241f0df1731f8ad1b3e0d5dc0e Mon Sep 17 00:00:00 2001 From: Yuri Roubinsky Date: Fri, 7 Feb 2020 14:50:11 +0300 Subject: [PATCH] Prevent shader crash if invalid builtin used after array member accessor --- servers/visual/shader_language.cpp | 34 ++++++++++++++++++++++++------ servers/visual/shader_language.h | 12 ++++++----- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 14d2f6d0862..c144523a36f 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -2986,14 +2986,32 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons bool is_const = false; int array_size = 0; - if (!_find_identifier(p_block, p_builtin_types, identifier, &data_type, &ident_type, &is_const, &array_size)) { - _set_error("Unknown identifier in expression: " + String(identifier)); - return NULL; - } + if (p_block && p_block->block_tag != SubClassTag::TAG_GLOBAL) { + int idx = 0; + bool found = false; - if (ident_type == IDENTIFIER_FUNCTION) { - _set_error("Can't use function as identifier: " + String(identifier)); - return NULL; + while (builtin_func_defs[idx].name) { + if (builtin_func_defs[idx].tag == p_block->block_tag && builtin_func_defs[idx].name == identifier) { + found = true; + break; + } + idx++; + } + if (!found) { + _set_error("Unknown identifier in expression: " + String(identifier)); + return NULL; + } + } else { + + if (!_find_identifier(p_block, p_builtin_types, identifier, &data_type, &ident_type, &is_const, &array_size)) { + _set_error("Unknown identifier in expression: " + String(identifier)); + return NULL; + } + + if (ident_type == IDENTIFIER_FUNCTION) { + _set_error("Can't use function as identifier: " + String(identifier)); + return NULL; + } } Node *index_expression = NULL; @@ -3009,7 +3027,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (tk.type == TK_PERIOD) { completion_class = TAG_ARRAY; + p_block->block_tag = SubClassTag::TAG_ARRAY; call_expression = _parse_and_reduce_expression(p_block, p_builtin_types); + p_block->block_tag = SubClassTag::TAG_GLOBAL; if (!call_expression) return NULL; data_type = call_expression->get_datatype(); diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index e5c3c6852c9..f7b02ab70b2 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -279,6 +279,11 @@ public: ARGUMENT_QUALIFIER_INOUT, }; + enum SubClassTag { + TAG_GLOBAL, + TAG_ARRAY, + }; + struct Node { Node *next; @@ -431,6 +436,7 @@ public: }; int block_type; + SubClassTag block_tag; struct Variable { DataType type; @@ -449,6 +455,7 @@ public: parent_function(NULL), parent_block(NULL), block_type(BLOCK_TYPE_STANDART), + block_tag(SubClassTag::TAG_GLOBAL), single_statement(false) {} }; @@ -713,11 +720,6 @@ private: bool _validate_assign(Node *p_node, const Map &p_builtin_types, String *r_message = NULL); bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL); - enum SubClassTag { - TAG_GLOBAL, - TAG_ARRAY, - }; - struct BuiltinFuncDef { enum { MAX_ARGS = 5 }; const char *name;