Proper validation of out arguments in built-in shader functions, closes #16244
This commit is contained in:
parent
c5656b7468
commit
d2e642b2dc
2 changed files with 49 additions and 0 deletions
|
@ -2037,6 +2037,12 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = {
|
||||||
|
//constructors
|
||||||
|
{ "modf", 1 },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type) {
|
bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type) {
|
||||||
|
|
||||||
ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, NULL);
|
ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, NULL);
|
||||||
|
@ -2080,6 +2086,41 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, OperatorNode *p
|
||||||
|
|
||||||
if (!fail) {
|
if (!fail) {
|
||||||
|
|
||||||
|
//make sure its not an out argument used in the wrong way
|
||||||
|
int outarg_idx = 0;
|
||||||
|
while (builtin_func_out_args[outarg_idx].name) {
|
||||||
|
|
||||||
|
if (String(name) == builtin_func_out_args[outarg_idx].name) {
|
||||||
|
int arg_idx = builtin_func_out_args[outarg_idx].argument;
|
||||||
|
|
||||||
|
if (arg_idx < argcount) {
|
||||||
|
|
||||||
|
if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE) {
|
||||||
|
_set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
StringName var_name = static_cast<const VariableNode *>(p_func->arguments[arg_idx + 1])->name;
|
||||||
|
|
||||||
|
const BlockNode *b = p_block;
|
||||||
|
bool valid = false;
|
||||||
|
while (b) {
|
||||||
|
if (b->variables.has(var_name)) {
|
||||||
|
valid = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
b = b->parent_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
_set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outarg_idx++;
|
||||||
|
}
|
||||||
|
|
||||||
if (r_ret_type)
|
if (r_ret_type)
|
||||||
*r_ret_type = builtin_func_defs[idx].rettype;
|
*r_ret_type = builtin_func_defs[idx].rettype;
|
||||||
|
|
||||||
|
|
|
@ -333,6 +333,7 @@ public:
|
||||||
virtual DataType get_datatype() const { return datatype_cache; }
|
virtual DataType get_datatype() const { return datatype_cache; }
|
||||||
|
|
||||||
VariableNode() {
|
VariableNode() {
|
||||||
|
|
||||||
type = TYPE_VARIABLE;
|
type = TYPE_VARIABLE;
|
||||||
datatype_cache = TYPE_VOID;
|
datatype_cache = TYPE_VOID;
|
||||||
}
|
}
|
||||||
|
@ -643,6 +644,12 @@ private:
|
||||||
const DataType args[MAX_ARGS];
|
const DataType args[MAX_ARGS];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BuiltinFuncOutArgs { //arguments used as out in built in funcions
|
||||||
|
|
||||||
|
const char *name;
|
||||||
|
int argument;
|
||||||
|
};
|
||||||
|
|
||||||
CompletionType completion_type;
|
CompletionType completion_type;
|
||||||
int completion_line;
|
int completion_line;
|
||||||
BlockNode *completion_block;
|
BlockNode *completion_block;
|
||||||
|
@ -653,6 +660,7 @@ private:
|
||||||
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
|
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
|
||||||
|
|
||||||
static const BuiltinFuncDef builtin_func_defs[];
|
static const BuiltinFuncDef builtin_func_defs[];
|
||||||
|
static const BuiltinFuncOutArgs builtin_func_out_args[];
|
||||||
bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
|
bool _validate_function_call(BlockNode *p_block, OperatorNode *p_func, DataType *r_ret_type);
|
||||||
|
|
||||||
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
|
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
|
||||||
|
|
Loading…
Reference in a new issue