[gamecode] Preserve the return pointer across calls

This required delaying the setting of the return pointer by call until
after the current pointer had been saved, and thus passing the desired
pointer into PR_CallFunction (which does have some advantages for C
functions calling progs functions, but some dangers too (should ensure a
128 byte (32 word) buffer when calling untrusted code (which is any,
really)).
This commit is contained in:
Bill Currie 2022-01-17 19:12:28 +09:00
parent e9af549195
commit 9348f7b89c
3 changed files with 20 additions and 12 deletions

View file

@ -175,10 +175,12 @@ void PR_ExecuteProgram (progs_t *pr, func_t fnum);
execute upon return of control to PR_ExecuteProgram().
\param pr pointer to ::progs_t VM struct
\param fnum number of the function to call
\param return_ptr pointer to location in which return values will be
written
\return true if \p fnum was a progs function, false if \p fnum was
a builtin
*/
int PR_CallFunction (progs_t *pr, func_t fnum);
int PR_CallFunction (progs_t *pr, func_t fnum, pr_type_t *return_ptr);
///@}
@ -1806,6 +1808,7 @@ typedef struct {
pr_uint_t stack_ptr; ///< data stack on entry to function
bfunction_t *func; ///< Calling function.
strref_t *tstr; ///< Linked list of temporary strings.
pr_type_t *return_ptr; ///< Saved return address
} prstack_t;
struct progs_s {

View file

@ -149,6 +149,7 @@ PR_PushFrame (progs_t *pr)
frame->bases = pr->pr_bases;
frame->func = pr->pr_xfunction;
frame->tstr = pr->pr_xtstr;
frame->return_ptr = pr->pr_return;
pr->pr_xtstr = pr->pr_pushtstr;
pr->pr_pushtstr = 0;
@ -180,6 +181,7 @@ PR_PopFrame (progs_t *pr)
// up stack
frame = pr->pr_stack + --pr->pr_depth;
pr->pr_return = frame->return_ptr;
pr->pr_xfunction = frame->func;
pr->pr_xstatement = frame->staddr;
pr->pr_xtstr = frame->tstr;
@ -419,7 +421,7 @@ error_handler (void *data)
}
VISIBLE int
PR_CallFunction (progs_t *pr, func_t fnum)
PR_CallFunction (progs_t *pr, func_t fnum, pr_type_t *return_ptr)
{
bfunction_t *f;
@ -432,10 +434,14 @@ PR_CallFunction (progs_t *pr, func_t fnum)
Sys_Printf ("Calling builtin %s @ %p\n",
PR_GetString (pr, f->descriptor->name), f->func);
}
pr_type_t *saved_return = pr->pr_return;
pr->pr_return = return_ptr;
f->func (pr);
pr->pr_return = saved_return;
return 0;
} else {
PR_EnterFunction (pr, f);
pr->pr_return = return_ptr;
return 1;
}
}
@ -1461,7 +1467,7 @@ op_rcall:
op_call:
pr->pr_xfunction->profile += profile - startprofile;
startprofile = profile;
PR_CallFunction (pr, OPA(uint));
PR_CallFunction (pr, OPA(uint), pr->pr_return);
st = pr->pr_statements + pr->pr_xstatement;
break;
case OP_DONE_v6p:
@ -3154,10 +3160,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth)
function = mm->func_var;
pr->pr_argc = 0;
// op_c specifies the location for the return value if any
pr->pr_return = op_c;
pr->pr_xfunction->profile += profile - startprofile;
startprofile = profile;
PR_CallFunction (pr, function);
PR_CallFunction (pr, function, op_c);
st = pr->pr_statements + pr->pr_xstatement;
break;
// 1 1010
@ -3466,7 +3471,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum)
}
int exitdepth = pr->pr_depth;
if (!PR_CallFunction (pr, fnum)) {
if (!PR_CallFunction (pr, fnum, pr->pr_return)) {
// called a builtin instead of progs code
goto exit_program;
}

View file

@ -1291,7 +1291,7 @@ rua___obj_forward (progs_t *pr)
P_PACKED (pr, pr_va_list_t, 3).count = argc;
P_PACKED (pr, pr_va_list_t, 3).list = PR_SetPointer (pr, argv);
PR_PushTempString (pr, args_block);
PR_CallFunction (pr, imp);
PR_CallFunction (pr, imp, pr->pr_return);
return;
}
//FIXME ditto
@ -1303,7 +1303,7 @@ rua___obj_forward (progs_t *pr)
P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel);
P_POINTER (pr, 2) = PR_SetPointer (pr, sel);
pr->pr_argc = 3;
PR_CallFunction (pr, imp);
PR_CallFunction (pr, imp, pr->pr_return);
return;
}
@ -1321,7 +1321,7 @@ rua___obj_forward (progs_t *pr)
P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel);
P_POINTER (pr, 2) = PR_SetTempString (pr, probj->msg->str);
pr->pr_argc = 3;
PR_CallFunction (pr, imp);
PR_CallFunction (pr, imp, pr->pr_return);
return;
}
@ -1437,7 +1437,7 @@ rua_obj_msg_sendv (progs_t *pr)
memcpy (&P_INT (pr, 2), params,
count * sizeof (pr_type_t) * pr->pr_param_size);
}
PR_CallFunction (pr, imp);
PR_CallFunction (pr, imp, pr->pr_return);
}
static void
@ -1544,7 +1544,7 @@ rua_obj_msgSend (progs_t *pr)
PR_GetString (pr, object_get_class_name (probj, self)),
PR_GetString (pr, probj->selector_names[_cmd->sel_id]));
PR_CallFunction (pr, imp);
PR_CallFunction (pr, imp, pr->pr_return);
}
static void
@ -1564,7 +1564,7 @@ rua_obj_msgSend_super (progs_t *pr)
}
pr->pr_params[0] = pr->pr_real_params[0];
P_POINTER (pr, 0) = super->self;
PR_CallFunction (pr, imp);
PR_CallFunction (pr, imp, pr->pr_return);
}
static void