summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
authorJuan Linietsky <juan@godotengine.org>2018-11-14 18:55:38 -0300
committerJuan Linietsky <juan@godotengine.org>2018-11-14 18:56:19 -0300
commitd2e642b2dc088486ac040c64dbc008dbf918f534 (patch)
tree899cfd7783cfb421975c223c911c67e1207c7ef8 /servers
parentc5656b7468e1d001658390d88ec6bb087bc51321 (diff)
Proper validation of out arguments in built-in shader functions, closes #16244
Diffstat (limited to 'servers')
-rw-r--r--servers/visual/shader_language.cpp41
-rw-r--r--servers/visual/shader_language.h8
2 files changed, 49 insertions, 0 deletions
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 3fe661090c..0783d91a59 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -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) {
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) {
+ //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)
*r_ret_type = builtin_func_defs[idx].rettype;
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index f07b1fade5..9277dfa2cf 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -333,6 +333,7 @@ public:
virtual DataType get_datatype() const { return datatype_cache; }
VariableNode() {
+
type = TYPE_VARIABLE;
datatype_cache = TYPE_VOID;
}
@@ -643,6 +644,12 @@ private:
const DataType args[MAX_ARGS];
};
+ struct BuiltinFuncOutArgs { //arguments used as out in built in funcions
+
+ const char *name;
+ int argument;
+ };
+
CompletionType completion_type;
int completion_line;
BlockNode *completion_block;
@@ -653,6 +660,7 @@ private:
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
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 _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);