mirror of
https://github.com/lua/lua.git
synced 2026-01-26 07:37:58 +00:00
Change in dumping of NULL strings
When dumping a string, adding 2 to its size may overflow a size_t for external strings, which may not have a header. (Adding 1 is Ok, because all strings end with a '\0' not included in their size.) The new method for saving NULL strings code them as a repeated string, using the reserved index 0.
This commit is contained in:
parent
3347c9d32d
commit
7a92f3f99a
22
ldump.c
22
ldump.c
@ -132,27 +132,31 @@ static void dumpInteger (DumpState *D, lua_Integer x) {
|
||||
|
||||
|
||||
/*
|
||||
** Dump a String. First dump its "size": size==0 means NULL;
|
||||
** size==1 is followed by an index and means "reuse saved string with
|
||||
** that index"; size>=2 is followed by the string contents with real
|
||||
** size==size-2 and means that string, which will be saved with
|
||||
** the next available index.
|
||||
** Dump a String. First dump its "size":
|
||||
** size==0 is followed by an index and means "reuse saved string with
|
||||
** that index"; index==0 means NULL.
|
||||
** size>=1 is followed by the string contents with real size==size-1 and
|
||||
** means that string, which will be saved with the next available index.
|
||||
** The real size does not include the ending '\0' (which is not dumped),
|
||||
** so adding 1 to it cannot overflow a size_t.
|
||||
*/
|
||||
static void dumpString (DumpState *D, TString *ts) {
|
||||
if (ts == NULL)
|
||||
dumpSize(D, 0);
|
||||
if (ts == NULL) {
|
||||
dumpVarint(D, 0); /* will "reuse" NULL */
|
||||
dumpVarint(D, 0); /* special index for NULL */
|
||||
}
|
||||
else {
|
||||
TValue idx;
|
||||
int tag = luaH_getstr(D->h, ts, &idx);
|
||||
if (!tagisempty(tag)) { /* string already saved? */
|
||||
dumpVarint(D, 1); /* reuse a saved string */
|
||||
dumpVarint(D, 0); /* reuse a saved string */
|
||||
dumpVarint(D, l_castS2U(ivalue(&idx))); /* index of saved string */
|
||||
}
|
||||
else { /* must write and save the string */
|
||||
TValue key, value; /* to save the string in the hash */
|
||||
size_t size;
|
||||
const char *s = getlstr(ts, size);
|
||||
dumpSize(D, size + 2);
|
||||
dumpSize(D, size + 1);
|
||||
dumpVector(D, s, size + 1); /* include ending '\0' */
|
||||
D->nstr++; /* one more saved string */
|
||||
setsvalue(D->L, &key, ts); /* the string is the key */
|
||||
|
||||
12
lundump.c
12
lundump.c
@ -147,20 +147,20 @@ static void loadString (LoadState *S, Proto *p, TString **sl) {
|
||||
TString *ts;
|
||||
TValue sv;
|
||||
size_t size = loadSize(S);
|
||||
if (size == 0) { /* no string? */
|
||||
lua_assert(*sl == NULL); /* must be prefilled */
|
||||
return;
|
||||
}
|
||||
else if (size == 1) { /* previously saved string? */
|
||||
if (size == 0) { /* previously saved string? */
|
||||
lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */
|
||||
TValue stv;
|
||||
if (idx == 0) { /* no string? */
|
||||
lua_assert(*sl == NULL); /* must be prefilled */
|
||||
return;
|
||||
}
|
||||
if (novariant(luaH_getint(S->h, l_castU2S(idx), &stv)) != LUA_TSTRING)
|
||||
error(S, "invalid string index");
|
||||
*sl = ts = tsvalue(&stv); /* get its value */
|
||||
luaC_objbarrier(L, p, ts);
|
||||
return; /* do not save it again */
|
||||
}
|
||||
else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */
|
||||
else if ((size -= 1) <= LUAI_MAXSHORTLEN) { /* short string? */
|
||||
char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */
|
||||
loadVector(S, buff, size + 1); /* load string into buffer */
|
||||
*sl = ts = luaS_newlstr(L, buff, size); /* create string */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user