1
0
Fork 0
forked from fte/fteqw

Fix up some issues with buffer stuff.

This commit is contained in:
Shpoike 2023-10-30 04:29:48 +00:00
parent b133a4defb
commit ee36f33522
4 changed files with 71 additions and 30 deletions

View file

@ -8484,6 +8484,11 @@ qboolean CSQC_Init (qboolean anycsqc, const char *csprogsname, unsigned int chec
memset(csqcent, 0, sizeof(*csqcent)*maxcsqcentities); //clear the server->csqc entity translations.
if (csqc_isdarkplaces)
CSQC_FindGlobals(true);
else
CSQC_FindGlobals(false);
for (i = 0; i < csqcprogs->numprogs; i++)
{
func_t f = PR_FindFunction (csqcprogs, "init", i);
@ -8495,11 +8500,6 @@ qboolean CSQC_Init (qboolean anycsqc, const char *csprogsname, unsigned int chec
}
}
if (csqc_isdarkplaces)
CSQC_FindGlobals(true);
else
CSQC_FindGlobals(false);
csqcentsize = PR_InitEnts(csqcprogs, pr_csqc_maxedicts.value);
//world edict becomes readonly

View file

@ -49,6 +49,8 @@ void PF_buf_shutdown(pubprogfuncs_t *prinst);
void skel_info_f(void);
void skel_generateragdoll_f(void);
void *PR_PointerToNative_Resize(pubprogfuncs_t *inst, pint_t ptr, size_t offset, size_t datasize); //dangerous version
void *PR_PointerToNative_MoInvalidate(pubprogfuncs_t *inst, pint_t ptr, size_t offset, size_t datasize); //safer faily version.
#ifdef __SSE2__
#include "xmmintrin.h"
@ -2040,20 +2042,26 @@ void QCBUILTIN PF_memfree (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa
}
void QCBUILTIN PF_memcpy (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int dst = G_INT(OFS_PARM0);
int src = G_INT(OFS_PARM1);
int qcdst = G_INT(OFS_PARM0);
int qcsrc = G_INT(OFS_PARM1);
int size = G_INT(OFS_PARM2);
if (size < 0 || size > prinst->stringtablesize)
int srcoffset = (prinst->callargc>3)?G_INT(OFS_PARM3):0;
int dstoffset = (prinst->callargc>4)?G_INT(OFS_PARM4):0;
if (size < 0)
PR_BIError(prinst, "PF_memcpy: invalid size\n");
else if (dst < 0 || dst+size > prinst->stringtablesize)
PR_BIError(prinst, "PF_memcpy: invalid dest\n");
else if (src < 0 || src+size > prinst->stringtablesize)
PR_BIError(prinst, "PF_memcpy: invalid source\n");
else
memmove(prinst->stringtable + dst, prinst->stringtable + src, size);
else if (size)
{
void *dst = PR_PointerToNative_Resize(prinst, qcdst, dstoffset, size);
void *src = PR_PointerToNative_MoInvalidate(prinst, qcsrc, srcoffset, size);
if (!dst)
PR_BIError(prinst, "PF_memcpy: invalid dest\n");
else if (!src)
PR_BIError(prinst, "PF_memcpy: invalid source\n");
else
memmove(dst, src, size);
}
}
void *PR_PointerToNative_Resize(pubprogfuncs_t *inst, pint_t ptr, size_t offset, size_t datasize);
void QCBUILTIN PF_memfill8 (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int dst = G_INT(OFS_PARM0);
@ -2077,6 +2085,7 @@ void QCBUILTIN PF_memptradd (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
PR_BIError(prinst, "PF_memptradd: non-integer offset\n");
if (ofs & 3)
PR_BIError(prinst, "PF_memptradd: offset is not 32-bit aligned.\n"); //allows for other implementations to provide this with eg pointers expressed as 16.16 with 18-bit segments/allocations.
//cannot work with tempstrings/createbuffer
if (((unsigned int)ofs & 0x80000000) && ofs!=0)
PR_BIError(prinst, "PF_memptradd: special pointers cannot be offset.\n");
@ -3136,28 +3145,32 @@ void QCBUILTIN PF_fputs (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals
void QCBUILTIN PF_fwrite (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX;
int ptr = G_INT(OFS_PARM1);
int qcptr = G_INT(OFS_PARM1);
int size = G_INT(OFS_PARM2);
if (ptr < 0 || size < 0 || ptr+size >= prinst->stringtablesize)
int srcoffset = (prinst->callargc>3)?G_INT(OFS_PARM3):0;
const void *ptr = PR_PointerToNative_MoInvalidate(prinst, qcptr, srcoffset, size);
if (!ptr)
{
PR_BIError(prinst, "PF_fwrite: invalid ptr / size\n");
return;
}
G_INT(OFS_RETURN) = PF_fwrite_internal (prinst, fnum, prinst->stringtable + ptr, size);
G_INT(OFS_RETURN) = PF_fwrite_internal (prinst, fnum, ptr, size);
}
void QCBUILTIN PF_fread (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX;
int ptr = G_INT(OFS_PARM1);
int qcptr = G_INT(OFS_PARM1);
int size = G_INT(OFS_PARM2);
if (ptr <= 0 || size < 0 || (unsigned)ptr+(unsigned)size >= (unsigned)prinst->stringtablesize)
int dstoffset = (prinst->callargc>3)?G_INT(OFS_PARM3):0;
void *ptr = PR_PointerToNative_Resize(prinst, qcptr, dstoffset, size);
if (!ptr)
{
PR_BIError(prinst, "PF_fread: invalid ptr / size\n");
return;
}
G_INT(OFS_RETURN) = PF_fread_internal (prinst, fnum, prinst->stringtable + ptr, size);
G_INT(OFS_RETURN) = PF_fread_internal (prinst, fnum, ptr, size);
}
void QCBUILTIN PF_fseek (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -5723,13 +5736,15 @@ void QCBUILTIN PF_digest_ptr (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
const char *hashtype = PR_GetStringOfs(prinst, OFS_PARM0);
int qcptr = G_INT(OFS_PARM1);
int size = G_INT(OFS_PARM2);
if (qcptr < 0 || qcptr+size >= prinst->stringtablesize)
int offset = (prinst->callargc>3)?G_INT(OFS_PARM3):0;
const void *input = PR_PointerToNative_MoInvalidate(prinst, qcptr, offset, size); //make sure the input is a valid qc pointer.
if (!input)
{
PR_BIError(prinst, "PF_digest_ptr: invalid dest\n");
PR_BIError(prinst, "PF_digest_ptr: invalid pointer\n");
G_INT(OFS_RETURN) = 0;
return;
}
PF_digest_internal(prinst, pr_globals, hashtype, prinst->stringtable + qcptr, size);
PF_digest_internal(prinst, pr_globals, hashtype, input, size);
}
void QCBUILTIN PF_base64encode (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -5746,7 +5761,7 @@ void QCBUILTIN PF_base64decode (pubprogfuncs_t *prinst, struct globalvars_s *pr_
const unsigned char *s = PR_GetStringOfs(prinst, OFS_PARM0); //grab the input string
size_t bytes = Base64_DecodeBlock(s, NULL, NULL, 0); //figure out how long the output needs to be
qbyte *ptr = prinst->AddressableAlloc(prinst, bytes); //grab some qc memory
bytes = Base64_DecodeBlock(s, NULL, NULL, bytes); //decode it.
bytes = Base64_DecodeBlock(s, NULL, ptr, bytes); //decode it.
ptr[bytes] = 0; //make sure its null terminated or whatever.
G_INT(OFS_RETURN) = (char*)ptr - prinst->stringtable; //let the qc know where it is.

View file

@ -1109,7 +1109,7 @@ eval_t *PR_GetWriteTempStringPtr(progfuncs_t *progfuncs, string_t str, size_t of
return NULL;
}
//returns null for invalid accesses.
//returns null for invalid accesses. WARNING: invalidates any other pointers to the same tempstring so use this before getting any read pointers (or strings!).
void *PR_PointerToNative_Resize(pubprogfuncs_t *inst, pint_t ptr, size_t offset, size_t datasize)
{
progfuncs_t *progfuncs = (progfuncs_t*)inst;
@ -1149,6 +1149,32 @@ void *PR_PointerToNative_Resize(pubprogfuncs_t *inst, pint_t ptr, size_t offset,
}
return NULL;
}
void *PR_PointerToNative_MoInvalidate(pubprogfuncs_t *inst, pint_t ptr, size_t offset, size_t datasize)
{
progfuncs_t *progfuncs = (progfuncs_t*)inst;
if (((unsigned int)ptr & STRING_SPECMASK) == STRING_TEMP)
{ //buffer. these auto-upsize.
unsigned int i = ptr & ~STRING_SPECMASK;
tempstr_t *temp;
if (i < prinst.maxtempstrings && (temp=prinst.tempstrings[i]))
{
if (datasize > temp->size || offset >= temp->size-datasize)
{ //access is beyond the current size. we're not allowed to break any other pointers though, so just fail and let the caller handle that.
return NULL; //gotta have a cut-off point somewhere.
}
return (eval_t*)(temp->value + offset);
}
return NULL; //nothing not allocated.
}
else
{ //regular pointer
offset += ptr;
if (datasize > inst->stringtablesize || offset >= inst->stringtablesize-datasize || !offset)
return NULL; //can't autoresize these. just fail.
return inst->stringtable + ptr;
}
return NULL;
}
void QCBUILTIN PF_memgetval (pubprogfuncs_t *inst, struct globalvars_s *globals)
{

View file

@ -11596,8 +11596,8 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"fclose", PF_fclose, 0, 0, 0, 111, "void(filestream fhandle)"}, // (FRIK_FILE)
{"fgets", PF_fgets, 0, 0, 0, 112, D("string(filestream fhandle)", "Reads a single line out of the file. The new line character is not returned as part of the string. Returns the null string on EOF (use if not(string) to easily test for this, which distinguishes it from the empty string which is returned if the line being read is blank")}, // (FRIK_FILE)
{"fputs", PF_fputs, 0, 0, 0, 113, D("void(filestream fhandle, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7)", "Writes the given string(s) into the file. For compatibility with fgets, you should ensure that the string is terminated with a \\n - this will not otherwise be done for you. It is up to the engine whether dos or unix line endings are actually written.")}, // (FRIK_FILE)
{"fread", PF_fread, 0, 0, 0, 0, D("int(filestream fhandle, void *ptr, int size)", "Reads binary data out of the file. Returns truncated lengths if the read exceeds the length of the file.")},
{"fwrite", PF_fwrite, 0, 0, 0, 0, D("int(filestream fhandle, void *ptr, int size)", "Writes binary data out of the file.")},
{"fread", PF_fread, 0, 0, 0, 0, D("int(filestream fhandle, void *ptr, int size, optional int offset)", "Reads binary data out of the file. Returns truncated lengths if the read exceeds the length of the file.")},
{"fwrite", PF_fwrite, 0, 0, 0, 0, D("int(filestream fhandle, void *ptr, int size, optional int offset)", "Writes binary data out of the file.")},
{"fseek", PF_fseek, 0, 0, 0, 0, D("#define ftell fseek //c compat\nint(filestream fhandle, optional int newoffset)", "Changes the current position of the file, if specified. Returns prior position, in bytes.")},
{"fsize", PF_fsize, 0, 0, 0, 0, D("int(filestream fhandle, optional int newsize)", "Reports the total size of the file, in bytes. Can also be used to truncate/extend the file")},
{"strlen", PF_strlen, 0, 0, 0, 114, "float(string s)"}, // (FRIK_FILE)
@ -12016,7 +12016,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"memalloc", PF_memalloc, 0, 0, 0, 384, D("__variant*(int size)", "Allocate an arbitary block of memory")},
{"memfree", PF_memfree, 0, 0, 0, 385, D("void(__variant *ptr)", "Frees a block of memory that was allocated with memfree")},
{"memcpy", PF_memcpy, 0, 0, 0, 386, D("void(__variant *dst, __variant *src, int size)", "Copys memory from one location to another")},
{"memcpy", PF_memcpy, 0, 0, 0, 386, D("void(__variant *dst, __variant *src, int size, optional int dstoffset, int srcoffset)", "Copys memory from one location to another")},
{"memfill8", PF_memfill8, 0, 0, 0, 387, D("void(__variant *dst, int val, int size, optional int offset)", "Sets an entire block of memory to a specified value. Pretty much always 0.")},
{"memgetval", PF_memgetval, 0, 0, 0, 388, D("__variant(__variant *dst, float ofs)", "Looks up the 32bit value stored at a pointer-with-offset.")},
{"memsetval", PF_memsetval, 0, 0, 0, 389, D("void(__variant *dst, float ofs, __variant val)", "Changes the 32bit value stored at the specified pointer-with-offset.")},
@ -12325,7 +12325,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"crypto_getmyidfp",PF_Fixme, 0, 0, 0, 637, "DEP string(float addr)" STUB},
// {"CL_RotateMoves", PF_Fixme, 0, 0, 0, 638, D("void(vector anglechange)", "Rewrites the input log history to rotate all unacknowledged frames according to the angle delta specified.")},
{"digest_hex", PF_digest_hex, 0, 0, 0, 639, "string(string digest, string data, ...)"},
{"digest_ptr", PF_digest_ptr, 0, 0, 0, 0, D("string(string digest, void *data, int length)", "Calculates the digest of a single contiguous block of memory (including nulls) using the specified hash function.")},
{"digest_ptr", PF_digest_ptr, 0, 0, 0, 0, D("string(string digest, void *data, int length, optional int offset)", "Calculates the digest of a single contiguous block of memory (including nulls) using the specified hash function.")},
{"V_CalcRefdef", PF_Fixme, 0, 0, 0, 640, "DEP void(entity e, float flags)" STUB},
{"crypto_getmyidstatus",PF_Fixme, 0, 0, 0, 641, "DEP float(float i)" STUB},
{"coverage", PF_Fixme, 0, 0, 0, 642, "DEP void()" STUB},