From 9348f7b89ca30bc7441ad8c5d19b53ebd7d7a51b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 19:12:28 +0900 Subject: [PATCH] [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)). --- include/QF/progs.h | 5 ++++- libs/gamecode/pr_exec.c | 15 ++++++++++----- libs/ruamoko/rua_obj.c | 12 ++++++------ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index d2a923743..634eb38a0 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -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 { diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 90296c153..a8585fc2b 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -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; } diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index aab7b4c0f..22a8b98e7 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -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