Fix shader crash when passing array.length to functions
and similar cases
This commit is contained in:
parent
0e1f4628f4
commit
7c07ae4c50
2 changed files with 50 additions and 65 deletions
|
@ -930,7 +930,6 @@ void ShaderLanguage::clear() {
|
||||||
error_set = false;
|
error_set = false;
|
||||||
error_str = "";
|
error_str = "";
|
||||||
last_const = false;
|
last_const = false;
|
||||||
pass_array = false;
|
|
||||||
while (nodes) {
|
while (nodes) {
|
||||||
Node *n = nodes;
|
Node *n = nodes;
|
||||||
nodes = nodes->next;
|
nodes = nodes->next;
|
||||||
|
@ -2387,10 +2386,13 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
|
||||||
failed_builtin = true;
|
failed_builtin = true;
|
||||||
bool fail = false;
|
bool fail = false;
|
||||||
for (int i = 0; i < argcount; i++) {
|
for (int i = 0; i < argcount; i++) {
|
||||||
if (p_func->arguments[i + 1]->type == Node::TYPE_ARRAY && !static_cast<const ArrayNode *>(p_func->arguments[i + 1])->is_indexed()) {
|
if (p_func->arguments[i + 1]->type == Node::TYPE_ARRAY) {
|
||||||
|
const ArrayNode *anode = static_cast<const ArrayNode *>(p_func->arguments[i + 1]);
|
||||||
|
if (anode->call_expression == nullptr && !anode->is_indexed()) {
|
||||||
fail = true;
|
fail = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) {
|
if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) {
|
||||||
//all good, but needs implicit conversion later
|
//all good, but needs implicit conversion later
|
||||||
} else if (args[i] != builtin_func_defs[idx].args[i]) {
|
} else if (args[i] != builtin_func_defs[idx].args[i]) {
|
||||||
|
@ -4007,9 +4009,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
|
||||||
if (!is_token_variable_datatype(tk.type)) {
|
if (!is_token_variable_datatype(tk.type)) {
|
||||||
_set_tkpos(prev_pos);
|
_set_tkpos(prev_pos);
|
||||||
|
|
||||||
pass_array = true;
|
|
||||||
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
|
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
|
||||||
pass_array = false;
|
|
||||||
|
|
||||||
if (!n) {
|
if (!n) {
|
||||||
_set_error("Invalid data type for array");
|
_set_error("Invalid data type for array");
|
||||||
|
@ -4099,7 +4099,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_compare_datatypes(p_type, p_struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
|
if (!_compare_datatypes(p_type, p_struct_name, 0, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4347,9 +4347,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
||||||
|
|
||||||
int carg = -1;
|
int carg = -1;
|
||||||
|
|
||||||
pass_array = true;
|
|
||||||
bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg);
|
bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg);
|
||||||
pass_array = false;
|
|
||||||
|
|
||||||
// Check if block has a variable with the same name as function to prevent shader crash.
|
// Check if block has a variable with the same name as function to prevent shader crash.
|
||||||
ShaderLanguage::BlockNode *bnode = p_block;
|
ShaderLanguage::BlockNode *bnode = p_block;
|
||||||
|
@ -4601,14 +4599,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
||||||
Node *assign_expression = nullptr;
|
Node *assign_expression = nullptr;
|
||||||
|
|
||||||
if (array_size > 0) {
|
if (array_size > 0) {
|
||||||
if (!pass_array) {
|
prepos = _get_tkpos();
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
|
|
||||||
if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD && tk.type != TK_OP_ASSIGN) {
|
|
||||||
_set_error("Expected '[','.' or '='");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tk.type == TK_OP_ASSIGN) {
|
if (tk.type == TK_OP_ASSIGN) {
|
||||||
if (is_const) {
|
if (is_const) {
|
||||||
_set_error("Constants cannot be modified.");
|
_set_error("Constants cannot be modified.");
|
||||||
|
@ -4627,7 +4620,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
data_type = call_expression->get_datatype();
|
data_type = call_expression->get_datatype();
|
||||||
} else { // indexing
|
} else if (tk.type == TK_BRACKET_OPEN) { // indexing
|
||||||
index_expression = _parse_and_reduce_expression(p_block, p_function_info);
|
index_expression = _parse_and_reduce_expression(p_block, p_function_info);
|
||||||
if (!index_expression) {
|
if (!index_expression) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -4656,7 +4649,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
||||||
_set_error("Expected ']'");
|
_set_error("Expected ']'");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
_set_tkpos(prepos);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayNode *arrname = alloc_node<ArrayNode>();
|
ArrayNode *arrname = alloc_node<ArrayNode>();
|
||||||
|
@ -5081,10 +5075,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
|
||||||
}
|
}
|
||||||
mn->index_expression = index_expression;
|
mn->index_expression = index_expression;
|
||||||
} else {
|
} else {
|
||||||
if (!pass_array) {
|
|
||||||
_set_error("Expected '[','.' or '='");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
_set_tkpos(prev_pos);
|
_set_tkpos(prev_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6027,9 +6017,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
|
||||||
|
|
||||||
if (tk.type == TK_IDENTIFIER) { // a function call array initialization
|
if (tk.type == TK_IDENTIFIER) { // a function call array initialization
|
||||||
_set_tkpos(prev_pos);
|
_set_tkpos(prev_pos);
|
||||||
pass_array = true;
|
|
||||||
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
|
Node *n = _parse_and_reduce_expression(p_block, p_function_info);
|
||||||
pass_array = false;
|
|
||||||
|
|
||||||
if (!n) {
|
if (!n) {
|
||||||
_set_error("Expected correct array initializer!");
|
_set_error("Expected correct array initializer!");
|
||||||
|
@ -6754,12 +6742,10 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
|
||||||
} else {
|
} else {
|
||||||
_set_tkpos(pos); //rollback, wants expression
|
_set_tkpos(pos); //rollback, wants expression
|
||||||
|
|
||||||
pass_array = true;
|
|
||||||
Node *expr = _parse_and_reduce_expression(p_block, p_function_info);
|
Node *expr = _parse_and_reduce_expression(p_block, p_function_info);
|
||||||
if (!expr) {
|
if (!expr) {
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
pass_array = false;
|
|
||||||
|
|
||||||
if (b->parent_function->return_type != expr->get_datatype() || b->parent_function->return_array_size != expr->get_array_size() || return_struct_name != expr->get_datatype_name()) {
|
if (b->parent_function->return_type != expr->get_datatype() || b->parent_function->return_array_size != expr->get_array_size() || return_struct_name != expr->get_datatype_name()) {
|
||||||
_set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
|
_set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
|
||||||
|
|
|
@ -876,7 +876,6 @@ private:
|
||||||
|
|
||||||
StringName current_function;
|
StringName current_function;
|
||||||
bool last_const = false;
|
bool last_const = false;
|
||||||
bool pass_array = false;
|
|
||||||
StringName last_name;
|
StringName last_name;
|
||||||
|
|
||||||
VaryingFunctionNames varying_function_names;
|
VaryingFunctionNames varying_function_names;
|
||||||
|
|
Loading…
Reference in a new issue