Fix crash on signal/resume to dangling target

(cherry picked from commit 06b6cea62e)
This commit is contained in:
Pedro J. Estébanez 2018-11-25 12:38:12 +01:00 committed by Rémi Verschelde
parent a1b0e7b12c
commit 94476aba94
2 changed files with 19 additions and 31 deletions

View file

@ -256,7 +256,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
uint32_t alloca_size = 0;
GDScript *_class;
GDScript *script;
int ip = 0;
int line = _initial_line;
@ -267,7 +267,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
line = p_state->line;
ip = p_state->ip;
alloca_size = p_state->stack.size();
_class = p_state->_class;
script = p_state->script.ptr();
p_instance = p_state->instance;
defarg = p_state->defarg;
self = p_state->self;
@ -331,9 +331,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
} else {
self = p_instance->owner;
}
_class = p_instance->script.ptr();
script = p_instance->script.ptr();
} else {
_class = _script;
script = _script;
}
}
@ -358,7 +358,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
Variant *m_v; \
m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text); \
m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, stack, err_text); \
if (unlikely(!m_v)) \
OPCODE_BREAK;
@ -367,7 +367,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#define CHECK_SPACE(m_space)
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
Variant *m_v; \
m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text);
m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, stack, err_text);
#endif
@ -991,11 +991,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
gdfs->state.stack_size = _stack_size;
gdfs->state.self = self;
gdfs->state.alloca_size = alloca_size;
gdfs->state._class = _class;
gdfs->state.script = Ref<GDScript>(_script);
gdfs->state.ip = ip + ipofs;
gdfs->state.line = line;
gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : 0;
gdfs->state.script_id = _class->get_instance_id();
//gdfs->state.result_pos=ip+ipofs-1;
gdfs->state.defarg = defarg;
gdfs->state.instance = p_instance;
@ -1278,8 +1277,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
String err_file;
if (p_instance)
err_file = p_instance->script->path;
else if (_class)
err_file = _class->path;
else if (script)
err_file = script->path;
if (err_file == "")
err_file = "<built-in>";
String err_func = name;
@ -1484,17 +1483,14 @@ GDScriptFunction::~GDScriptFunction() {
Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
#ifdef DEBUG_ENABLED
if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
#ifdef DEBUG_ENABLED
ERR_EXPLAIN("Resumed after yield, but class instance is gone");
ERR_FAIL_V(Variant());
}
if (state.script_id && !ObjectDB::get_instance(state.script_id)) {
ERR_EXPLAIN("Resumed after yield, but script is gone");
ERR_FAIL_V(Variant());
}
#else
return Variant();
#endif
}
Variant arg;
r_error.error = Variant::CallError::CALL_OK;
@ -1564,9 +1560,6 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
//class instance gone?
if (state.instance_id && !ObjectDB::get_instance(state.instance_id))
return false;
//script gone?
if (state.script_id && !ObjectDB::get_instance(state.script_id))
return false;
}
return true;
@ -1575,17 +1568,14 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
Variant GDScriptFunctionState::resume(const Variant &p_arg) {
ERR_FAIL_COND_V(!function, Variant());
#ifdef DEBUG_ENABLED
if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) {
#ifdef DEBUG_ENABLED
ERR_EXPLAIN("Resumed after yield, but class instance is gone");
ERR_FAIL_V(Variant());
}
if (state.script_id && !ObjectDB::get_instance(state.script_id)) {
ERR_EXPLAIN("Resumed after yield, but script is gone");
ERR_FAIL_V(Variant());
}
#else
return Variant();
#endif
}
state.result = p_arg;
Variant::CallError err;

View file

@ -174,15 +174,13 @@ private:
public:
struct CallState {
ObjectID instance_id; //by debug only
ObjectID script_id;
ObjectID instance_id;
GDScriptInstance *instance;
Vector<uint8_t> stack;
int stack_size;
Variant self;
uint32_t alloca_size;
GDScript *_class;
Ref<GDScript> script;
int ip;
int line;
int defarg;