Prevent shader crash if invalid builtin used after array member accessor

This commit is contained in:
Yuri Roubinsky 2020-02-07 14:50:11 +03:00
parent 642de8e789
commit 3a70566b15
2 changed files with 34 additions and 12 deletions

View File

@ -2986,14 +2986,32 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
bool is_const = false; bool is_const = false;
int array_size = 0; int array_size = 0;
if (!_find_identifier(p_block, p_builtin_types, identifier, &data_type, &ident_type, &is_const, &array_size)) { if (p_block && p_block->block_tag != SubClassTag::TAG_GLOBAL) {
_set_error("Unknown identifier in expression: " + String(identifier)); int idx = 0;
return NULL; bool found = false;
}
if (ident_type == IDENTIFIER_FUNCTION) { while (builtin_func_defs[idx].name) {
_set_error("Can't use function as identifier: " + String(identifier)); if (builtin_func_defs[idx].tag == p_block->block_tag && builtin_func_defs[idx].name == identifier) {
return NULL; 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; Node *index_expression = NULL;
@ -3009,7 +3027,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (tk.type == TK_PERIOD) { if (tk.type == TK_PERIOD) {
completion_class = TAG_ARRAY; completion_class = TAG_ARRAY;
p_block->block_tag = SubClassTag::TAG_ARRAY;
call_expression = _parse_and_reduce_expression(p_block, p_builtin_types); call_expression = _parse_and_reduce_expression(p_block, p_builtin_types);
p_block->block_tag = SubClassTag::TAG_GLOBAL;
if (!call_expression) if (!call_expression)
return NULL; return NULL;
data_type = call_expression->get_datatype(); data_type = call_expression->get_datatype();

View File

@ -279,6 +279,11 @@ public:
ARGUMENT_QUALIFIER_INOUT, ARGUMENT_QUALIFIER_INOUT,
}; };
enum SubClassTag {
TAG_GLOBAL,
TAG_ARRAY,
};
struct Node { struct Node {
Node *next; Node *next;
@ -431,6 +436,7 @@ public:
}; };
int block_type; int block_type;
SubClassTag block_tag;
struct Variable { struct Variable {
DataType type; DataType type;
@ -449,6 +455,7 @@ public:
parent_function(NULL), parent_function(NULL),
parent_block(NULL), parent_block(NULL),
block_type(BLOCK_TYPE_STANDART), block_type(BLOCK_TYPE_STANDART),
block_tag(SubClassTag::TAG_GLOBAL),
single_statement(false) {} single_statement(false) {}
}; };
@ -713,11 +720,6 @@ private:
bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = NULL); bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = NULL);
bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL); bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL);
enum SubClassTag {
TAG_GLOBAL,
TAG_ARRAY,
};
struct BuiltinFuncDef { struct BuiltinFuncDef {
enum { MAX_ARGS = 5 }; enum { MAX_ARGS = 5 };
const char *name; const char *name;