Merge pull request #31600 from Chaosus/shader_func_return_fix

Fix shader crash when users miss the return statement
This commit is contained in:
Yuri Roubinsky 2019-08-28 16:39:33 +03:00 committed by GitHub
commit 96ea1e6fb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 0 deletions

View file

@ -5141,6 +5141,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
if (err) if (err)
return err; return err;
if (func_node->return_type != DataType::TYPE_VOID) {
BlockNode *block = func_node->body;
if (_find_last_flow_op_in_block(block, FlowOperation::FLOW_OP_RETURN) != OK) {
_set_error("Expected at least one return statement in a non-void function.");
return ERR_PARSE_ERROR;
}
}
current_function = StringName(); current_function = StringName();
} }
} }
@ -5151,6 +5159,57 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return OK; return OK;
} }
Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op) {
bool found = false;
for (int i = p_flow->blocks.size() - 1; i >= 0; i--) {
if (p_flow->blocks[i]->type == Node::TYPE_BLOCK) {
BlockNode *last_block = (BlockNode *)p_flow->blocks[i];
if (_find_last_flow_op_in_block(last_block, p_op) == OK) {
found = true;
break;
}
}
}
if (found) {
return OK;
}
return FAILED;
}
Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op) {
bool found = false;
for (int i = p_block->statements.size() - 1; i >= 0; i--) {
if (p_block->statements[i]->type == Node::TYPE_CONTROL_FLOW) {
ControlFlowNode *flow = (ControlFlowNode *)p_block->statements[i];
if (flow->flow_op == p_op) {
found = true;
break;
} else {
if (_find_last_flow_op_in_op(flow, p_op) == OK) {
found = true;
break;
}
}
} else if (p_block->statements[i]->type == Node::TYPE_BLOCK) {
BlockNode *block = (BlockNode *)p_block->statements[i];
if (_find_last_flow_op_in_block(block, p_op) == OK) {
found = true;
break;
}
}
}
if (found) {
return OK;
}
return FAILED;
}
// skips over whitespace and /* */ and // comments // skips over whitespace and /* */ and // comments
static int _get_first_ident_pos(const String &p_code) { static int _get_first_ident_pos(const String &p_code) {

View file

@ -750,6 +750,9 @@ private:
Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false);
Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types); Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);
Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op);
public: public:
//static void get_keyword_list(ShaderType p_type,List<String> *p_keywords); //static void get_keyword_list(ShaderType p_type,List<String> *p_keywords);