Browse Source

Proper validation of out arguments in built-in shader functions, closes #16244

Juan Linietsky 6 years ago
parent
commit
d2e642b2dc
2 changed files with 49 additions and 0 deletions
  1. 41 0
      servers/visual/shader_language.cpp
  2. 8 0
      servers/visual/shader_language.h

+ 41 - 0
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;
 

+ 8 - 0
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);