mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
[gamecode] Add function PR_PushTempString
This "pushes" a temp string onto the callee's stack frame after removing it from the caller's stack frame. This is so builtins can pass auto-freed memory to called progs code. No checking is done, but mayhem is likely to ensue if a string is pushed that was allocated in an earlier frame.
This commit is contained in:
parent
9b0368039e
commit
f290b115a5
3 changed files with 44 additions and 1 deletions
|
@ -1286,6 +1286,17 @@ string_t PR_SetTempString(progs_t *pr, const char *s);
|
|||
*/
|
||||
string_t PR_AllocTempBlock (progs_t *pr, size_t size);
|
||||
|
||||
/** Push a temporary string to the callee stack frame
|
||||
|
||||
This is for when the temp string needs to be freed when the called function
|
||||
returns rather than the calling function. It is an error to push a non-temp
|
||||
string.
|
||||
|
||||
\param pr pointer to ::progs_t VM struct
|
||||
\param num string index of the temp string
|
||||
*/
|
||||
void PR_PushTempString (progs_t *pr, string_t num);
|
||||
|
||||
/** Make a temporary progs string that is the concatenation of two C strings.
|
||||
\param pr pointer to ::progs_t VM struct
|
||||
\param a C string
|
||||
|
@ -1733,6 +1744,7 @@ struct progs_s {
|
|||
///@{
|
||||
struct prstr_resources_s *pr_string_resources;
|
||||
strref_t *pr_xtstr;
|
||||
strref_t *pr_pushtstr;
|
||||
int float_promoted; ///< for PR_Sprintf
|
||||
///@}
|
||||
|
||||
|
|
|
@ -123,7 +123,8 @@ PR_PushFrame (progs_t *pr)
|
|||
frame->f = pr->pr_xfunction;
|
||||
frame->tstr = pr->pr_xtstr;
|
||||
|
||||
pr->pr_xtstr = 0;
|
||||
pr->pr_xtstr = pr->pr_pushtstr;
|
||||
pr->pr_pushtstr = 0;
|
||||
pr->pr_xfunction = 0;
|
||||
}
|
||||
|
||||
|
@ -137,6 +138,15 @@ PR_PopFrame (progs_t *pr)
|
|||
|
||||
if (pr->pr_xtstr)
|
||||
PR_FreeTempStrings (pr);
|
||||
// normally, this won't happen, but if a builtin pushed a temp string
|
||||
// when calling a function and the callee was another builtin that
|
||||
// did not call a progs function, then the push strings will still be
|
||||
// valid because PR_EnterFunction was never called
|
||||
if (pr->pr_pushtstr) {
|
||||
pr->pr_xtstr = pr->pr_pushtstr;
|
||||
pr->pr_pushtstr = 0;
|
||||
PR_FreeTempStrings (pr);
|
||||
}
|
||||
|
||||
// up stack
|
||||
frame = pr->pr_stack + --pr->pr_depth;
|
||||
|
|
|
@ -520,6 +520,27 @@ PR_AllocTempBlock (progs_t *pr, size_t size)
|
|||
return pr_settempstring (pr, res, pr_strmalloc (pr, size));
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
PR_PushTempString (progs_t *pr, string_t num)
|
||||
{
|
||||
prstr_resources_t *res = pr->pr_string_resources;
|
||||
strref_t *ref = get_strref (res, num);
|
||||
strref_t **temp_ref;
|
||||
|
||||
if (!ref || ref->type != str_temp) {
|
||||
PR_Error (pr, "attempt to push a non-temp string");
|
||||
}
|
||||
for (temp_ref = &pr->pr_xtstr; *temp_ref; temp_ref = &(*temp_ref)->next) {
|
||||
if (*temp_ref == ref) {
|
||||
*temp_ref = ref->next;
|
||||
ref->next = pr->pr_pushtstr;
|
||||
pr->pr_pushtstr = ref;
|
||||
return;
|
||||
}
|
||||
}
|
||||
PR_Error (pr, "attempt to push stale temp string");
|
||||
}
|
||||
|
||||
VISIBLE string_t
|
||||
PR_SetDynamicString (progs_t *pr, const char *s)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue