mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-20 01:11:18 +00:00
[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:
parent
e9af549195
commit
9348f7b89c
3 changed files with 20 additions and 12 deletions
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue