Prevent shader crash if invalid builtin used after array member accessor
(cherry picked from commit 3a70566b15
)
This commit is contained in:
parent
388adac947
commit
3b2490f19c
2 changed files with 34 additions and 12 deletions
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue