*fixed some crash and hanging with invalid expression and routine.

This commit is contained in:
Wang Renxin 2019-02-03 00:19:38 +08:00
parent 67353d1da8
commit 3630e237f5
2 changed files with 62 additions and 26 deletions

View File

@ -1,3 +1,6 @@
Feb. 2 2019
Fixed some crash and hanging with invalid expression and routine, thanks to siraben for pointing it out
Dec. 31 2018 Dec. 31 2018
Fixed a wrong scope processing bug when resetting interpreter Fixed a wrong scope processing bug when resetting interpreter

View File

@ -3757,6 +3757,9 @@ static int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val
running = s->running_context; running = s->running_context;
ast = *l; ast = *l;
if(!ast) {
_handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, s->source_file, DON(ast), MB_FUNC_ERR, _error, result);
}
c = (_object_t*)ast->data; c = (_object_t*)ast->data;
#ifdef MB_PREFER_SPEED #ifdef MB_PREFER_SPEED
if(c->is_const) { if(c->is_const) {
@ -3795,8 +3798,10 @@ static int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val
ast = ast->next; ast = ast->next;
_ls_pushback(optr, _exp_assign); _ls_pushback(optr, _exp_assign);
while( while(
!(c->type == _DT_FUNC && strcmp(c->data.func->name, _DUMMY_ASSIGN_CHAR) == 0) || c &&
!(((_object_t*)(_ls_back(optr)->data))->type == _DT_FUNC && strcmp(((_object_t*)(_ls_back(optr)->data))->data.func->name, _DUMMY_ASSIGN_CHAR) == 0)) { (!(c->type == _DT_FUNC && strcmp(c->data.func->name, _DUMMY_ASSIGN_CHAR) == 0) ||
!(((_object_t*)(_ls_back(optr)->data))->type == _DT_FUNC && strcmp(((_object_t*)(_ls_back(optr)->data))->data.func->name, _DUMMY_ASSIGN_CHAR) == 0))
) {
if(!hack) { if(!hack) {
if(_IS_FUNC(c, _core_open_bracket)) { if(_IS_FUNC(c, _core_open_bracket)) {
++bracket_count; ++bracket_count;
@ -3869,7 +3874,7 @@ _array:
f++; f++;
} }
} else if(c->type == _DT_FUNC) { } else if(c->type == _DT_FUNC) {
ast = ast->prev; if(ast) ast = ast->prev;
if(_IS_UNARY_FUNC(c)) { if(_IS_UNARY_FUNC(c)) {
#ifdef MB_ENABLE_STACK_TRACE #ifdef MB_ENABLE_STACK_TRACE
_ls_pushback(s->stack_frames, c->data.func->name); _ls_pushback(s->stack_frames, c->data.func->name);
@ -3930,6 +3935,8 @@ _routine:
_object_t* obj = 0; _object_t* obj = 0;
_ls_node_t* fn = 0; _ls_node_t* fn = 0;
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
if(!ast)
break;
ast = ast->prev; ast = ast->prev;
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
calling = s->calling; calling = s->calling;
@ -4122,7 +4129,7 @@ _var:
if(running->calc_depth != _INFINITY_CALC_DEPTH) if(running->calc_depth != _INFINITY_CALC_DEPTH)
running->calc_depth--; running->calc_depth--;
if(ast && (running->calc_depth == _INFINITY_CALC_DEPTH || running->calc_depth)) { if(ast && (running->calc_depth == _INFINITY_CALC_DEPTH || running->calc_depth)) {
c = (_object_t*)ast->data; c = ast ? (_object_t*)ast->data : 0;
if(c->type == _DT_FUNC && !_is_operator(c->data.func->pointer) && !_is_flow(c->data.func->pointer)) { if(c->type == _DT_FUNC && !_is_operator(c->data.func->pointer) && !_is_flow(c->data.func->pointer)) {
_ls_foreach(opnd, _remove_source_object); _ls_foreach(opnd, _remove_source_object);
@ -4138,15 +4145,15 @@ _var:
switch(pri) { switch(pri) {
case '<': case '<':
_ls_pushback(optr, c); _ls_pushback(optr, c);
c = (_object_t*)ast->data; c = ast ? (_object_t*)ast->data : 0;
ast = ast->next; if(ast) ast = ast->next;
f = 0; f = 0;
break; break;
case '=': case '=':
x = (_object_t*)_ls_popback(optr); x = (_object_t*)_ls_popback(optr);
c = (_object_t*)ast->data; c = ast ? (_object_t*)ast->data : 0;
ast = ast->next; if(ast) ast = ast->next;
break; break;
case '>': case '>':
@ -4539,6 +4546,11 @@ static int _eval_script_routine(mb_interpreter_t* s, _ls_node_t** l, mb_value_t*
do { do {
result = _execute_statement(s, l, true); result = _execute_statement(s, l, true);
if(ast == *l) {
_handle_error_now(s, SE_RN_INVALID_EXPRESSION, s->last_error_file, result);
goto _exit;
}
ast = *l; ast = *l;
if(result == MB_SUB_RETURN) { if(result == MB_SUB_RETURN) {
result = MB_FUNC_OK; result = MB_FUNC_OK;
@ -5822,7 +5834,9 @@ static int _parse_char(mb_interpreter_t* s, const char* str, int n, int pos, uns
if(str) { if(str) {
#ifdef MB_ENABLE_UNICODE_ID #ifdef MB_ENABLE_UNICODE_ID
if(n == 1) if(n == 0)
result = MB_FUNC_ERR;
else if(n == 1)
c = *str; c = *str;
else else
memcpy(&uc, str, n); memcpy(&uc, str, n);
@ -8675,7 +8689,7 @@ static bool_t _is_valid_class_accessor_following_routine(mb_interpreter_t* s, _v
if(out) *out = 0; if(out) *out = 0;
if(_is_accessor_char(*var->name) && (ast && ast->prev && _IS_FUNC(ast->prev->data, _core_close_bracket)) && running->intermediate_value.type == MB_DT_CLASS) { if(_is_accessor_char(*var->name) && (ast && ast->prev && ast->prev != s->ast && _IS_FUNC(ast->prev->data, _core_close_bracket)) && running->intermediate_value.type == MB_DT_CLASS) {
_class_t* instance = (_class_t*)running->intermediate_value.value.instance; _class_t* instance = (_class_t*)running->intermediate_value.value.instance;
_ls_node_t* fn = _search_identifier_in_class(s, instance, var->name + 1, 0, 0); _ls_node_t* fn = _search_identifier_in_class(s, instance, var->name + 1, 0, 0);
result = true; result = true;
@ -10345,7 +10359,8 @@ static int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl) {
switch(itn->type) { switch(itn->type) {
case _DT_VAR: case _DT_VAR:
result = _internal_object_to_public_value(itn->data.variable->data, pbl); if(itn->data.variable)
result = _internal_object_to_public_value(itn->data.variable->data, pbl);
break; break;
case _DT_NIL: case _DT_NIL:
@ -10581,7 +10596,7 @@ static void _destroy_var_arg(void* data, void* extra, _gc_t* gc) {
static void _destroy_edge_objects(mb_interpreter_t* s) { static void _destroy_edge_objects(mb_interpreter_t* s) {
if(!s) return; if(!s) return;
_ls_foreach(s->edge_destroy_objects, _destroy_object); _LS_FOREACH(s->edge_destroy_objects, _destroy_object, _try_clear_intermediate_value, s);
_ls_clear(s->edge_destroy_objects); _ls_clear(s->edge_destroy_objects);
} }
@ -11045,7 +11060,7 @@ _retry:
if(result != MB_FUNC_OK && result != MB_FUNC_SUSPEND && result != MB_SUB_RETURN) if(result != MB_FUNC_OK && result != MB_FUNC_SUSPEND && result != MB_SUB_RETURN)
goto _exit; goto _exit;
if(ast) { if(ast && ast != s->ast) {
obj = DON(ast); obj = DON(ast);
if(!obj) { if(!obj) {
/* Do nothing */ /* Do nothing */
@ -11108,14 +11123,16 @@ _exit:
end_of_ast = true; end_of_ast = true;
} }
do { if(ast == s->ast) {
*l = ast->next;
} else {
int ret = _stepped(s, ast); int ret = _stepped(s, ast);
if(result == MB_FUNC_OK) if(result == MB_FUNC_OK)
result = ret; result = ret;
if(end_of_ast && ast && ast->next) /* May be changed when stepping */ if(end_of_ast && ast && ast->next) /* May be changed when stepping */
*l = ast->next; *l = ast->next;
} while(0); }
return result; return result;
} }
@ -12158,7 +12175,7 @@ int mb_close(struct mb_interpreter_t** s) {
_close_core_lib(*s); _close_core_lib(*s);
ast = (*s)->ast; ast = (*s)->ast;
_ls_foreach(ast, _destroy_object); _LS_FOREACH(ast, _destroy_object, _try_clear_intermediate_value, *s);
_ls_destroy(ast); _ls_destroy(ast);
_ls_destroy((*s)->sub_stack); _ls_destroy((*s)->sub_stack);
@ -12252,7 +12269,7 @@ int mb_reset(struct mb_interpreter_t** s, bool_t clrf) {
memset(&(running->intermediate_value), 0, sizeof(mb_value_t)); memset(&(running->intermediate_value), 0, sizeof(mb_value_t));
ast = (*s)->ast; ast = (*s)->ast;
_ls_foreach(ast, _destroy_object); _LS_FOREACH(ast, _destroy_object, _try_clear_intermediate_value, *s);
_ls_clear(ast); _ls_clear(ast);
_ls_clear((*s)->sub_stack); _ls_clear((*s)->sub_stack);
@ -12507,6 +12524,11 @@ int mb_attempt_func_begin(struct mb_interpreter_t* s, void** l) {
_ls_pushback(s->multiline_enabled, (void*)(intptr_t)false); _ls_pushback(s->multiline_enabled, (void*)(intptr_t)false);
#endif /* _MULTILINE_STATEMENT */ #endif /* _MULTILINE_STATEMENT */
ast = (_ls_node_t*)*l; ast = (_ls_node_t*)*l;
if(!ast) {
result = MB_FUNC_ERR;
goto _exit;
}
obj = (_object_t*)ast->data; obj = (_object_t*)ast->data;
if(!(obj->type == _DT_FUNC)) { if(!(obj->type == _DT_FUNC)) {
#if _MULTILINE_STATEMENT #if _MULTILINE_STATEMENT
@ -14024,8 +14046,9 @@ int mb_dispose_value(struct mb_interpreter_t* s, mb_value_t val) {
goto _exit; goto _exit;
} }
if(val.type == MB_DT_STRING) if(val.type == MB_DT_STRING) {
safe_free(val.value.string); safe_free(val.value.string);
}
_assign_public_value(s, &val, 0, false); _assign_public_value(s, &val, 0, false);
@ -14350,7 +14373,13 @@ int mb_run(struct mb_interpreter_t* s, bool_t clear_parser) {
} }
do { do {
_ls_node_t* p = ast;
result = _execute_statement(s, &ast, true); result = _execute_statement(s, &ast, true);
if(ast == p) {
_handle_error_now(s, SE_RN_INVALID_EXPRESSION, s->last_error_file, result);
goto _exit;
}
if(result != MB_FUNC_OK && result != MB_SUB_RETURN) { if(result != MB_FUNC_OK && result != MB_SUB_RETURN) {
if(result != MB_FUNC_SUSPEND) { if(result != MB_FUNC_SUSPEND) {
if(result >= MB_EXTENDED_ABORT) if(result >= MB_EXTENDED_ABORT)
@ -16095,7 +16124,7 @@ static int _core_do(mb_interpreter_t* s, void** l) {
_loop_begin: _loop_begin:
ast = loop_begin_node; ast = loop_begin_node;
obj = (_object_t*)ast->data; obj = ast ? (_object_t*)ast->data : 0;
while(obj && !_IS_FUNC(obj, _core_until)) { while(obj && !_IS_FUNC(obj, _core_until)) {
result = _execute_statement(s, &ast, true); result = _execute_statement(s, &ast, true);
if(result == MB_LOOP_BREAK) { /* EXIT */ if(result == MB_LOOP_BREAK) { /* EXIT */
@ -16416,7 +16445,7 @@ static int _core_def(mb_interpreter_t* s, void** l) {
if(s->has_run) if(s->has_run)
goto _skip; goto _skip;
obj = (_object_t*)ast->data; obj = ast ? (_object_t*)ast->data : 0;
if(!_IS_ROUTINE(obj)) { if(!_IS_ROUTINE(obj)) {
_handle_error_on_obj(s, SE_RN_ROUTINE_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_ROUTINE_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result);
} }
@ -16431,7 +16460,7 @@ static int _core_def(mb_interpreter_t* s, void** l) {
} }
ast = ast->next; ast = ast->next;
obj = (_object_t*)ast->data; obj = (_object_t*)ast->data;
while(!_IS_FUNC(obj, _core_close_bracket)) { while(obj && !_IS_FUNC(obj, _core_close_bracket)) {
if(obj->type == _DT_VAR) { if(obj->type == _DT_VAR) {
var = obj->data.variable; var = obj->data.variable;
rnode = _search_identifier_in_scope_chain(s, routine->func.basic.scope, var->name, _PATHING_NONE, 0, 0); rnode = _search_identifier_in_scope_chain(s, routine->func.basic.scope, var->name, _PATHING_NONE, 0, 0);
@ -16451,15 +16480,15 @@ static int _core_def(mb_interpreter_t* s, void** l) {
} }
ast = ast->next; ast = ast->next;
obj = (_object_t*)ast->data; obj = ast ? (_object_t*)ast->data : 0;
} }
ast = ast->next; if(ast) ast = ast->next;
routine->func.basic.entry = ast; routine->func.basic.entry = ast;
_skip: _skip:
_skip_to(s, &ast, _core_enddef, _DT_INVALID); _skip_to(s, &ast, _core_enddef, _DT_INVALID);
ast = ast->next; if(ast) ast = ast->next;
_exit: _exit:
*l = ast; *l = ast;
@ -17002,6 +17031,10 @@ static int _core_end(mb_interpreter_t* s, void** l) {
mb_assert(s && l); mb_assert(s && l);
mb_check(mb_attempt_func_begin(s, l));
mb_check(mb_attempt_func_end(s, l));
result = MB_FUNC_END; result = MB_FUNC_END;
return result; return result;
@ -18147,10 +18180,10 @@ static int _std_print(mb_interpreter_t* s, void** l) {
++s->no_eat_comma_mark; ++s->no_eat_comma_mark;
ast = (_ls_node_t*)*l; ast = (_ls_node_t*)*l;
ast = ast->next; if(!ast || !ast->next || !ast->next->data) {
if(!ast || !ast->data) {
_handle_error_on_obj(s, SE_RN_SYNTAX_ERROR, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_SYNTAX_ERROR, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result);
} }
ast = ast->next;
obj = (_object_t*)ast->data; obj = (_object_t*)ast->data;
do { do {