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:
Roberto I
2025-10-10 15:28:41 -03:00
parent 3347c9d32d
commit 7a92f3f99a
2 changed files with 19 additions and 15 deletions

22
ldump.c
View File

@@ -132,27 +132,31 @@ static void dumpInteger (DumpState *D, lua_Integer x) {
/* /*
** Dump a String. First dump its "size": size==0 means NULL; ** Dump a String. First dump its "size":
** size==1 is followed by an index and means "reuse saved string with ** size==0 is followed by an index and means "reuse saved string with
** that index"; size>=2 is followed by the string contents with real ** that index"; index==0 means NULL.
** size==size-2 and means that string, which will be saved with ** size>=1 is followed by the string contents with real size==size-1 and
** the next available index. ** 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) { static void dumpString (DumpState *D, TString *ts) {
if (ts == NULL) if (ts == NULL) {
dumpSize(D, 0); dumpVarint(D, 0); /* will "reuse" NULL */
dumpVarint(D, 0); /* special index for NULL */
}
else { else {
TValue idx; TValue idx;
int tag = luaH_getstr(D->h, ts, &idx); int tag = luaH_getstr(D->h, ts, &idx);
if (!tagisempty(tag)) { /* string already saved? */ 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 */ dumpVarint(D, l_castS2U(ivalue(&idx))); /* index of saved string */
} }
else { /* must write and save the string */ else { /* must write and save the string */
TValue key, value; /* to save the string in the hash */ TValue key, value; /* to save the string in the hash */
size_t size; size_t size;
const char *s = getlstr(ts, size); const char *s = getlstr(ts, size);
dumpSize(D, size + 2); dumpSize(D, size + 1);
dumpVector(D, s, size + 1); /* include ending '\0' */ dumpVector(D, s, size + 1); /* include ending '\0' */
D->nstr++; /* one more saved string */ D->nstr++; /* one more saved string */
setsvalue(D->L, &key, ts); /* the string is the key */ setsvalue(D->L, &key, ts); /* the string is the key */

View File

@@ -147,20 +147,20 @@ static void loadString (LoadState *S, Proto *p, TString **sl) {
TString *ts; TString *ts;
TValue sv; TValue sv;
size_t size = loadSize(S); size_t size = loadSize(S);
if (size == 0) { /* no 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 */ lua_assert(*sl == NULL); /* must be prefilled */
return; return;
} }
else if (size == 1) { /* previously saved string? */
lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */
TValue stv;
if (novariant(luaH_getint(S->h, l_castU2S(idx), &stv)) != LUA_TSTRING) if (novariant(luaH_getint(S->h, l_castU2S(idx), &stv)) != LUA_TSTRING)
error(S, "invalid string index"); error(S, "invalid string index");
*sl = ts = tsvalue(&stv); /* get its value */ *sl = ts = tsvalue(&stv); /* get its value */
luaC_objbarrier(L, p, ts); luaC_objbarrier(L, p, ts);
return; /* do not save it again */ 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' */ char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */
loadVector(S, buff, size + 1); /* load string into buffer */ loadVector(S, buff, size + 1); /* load string into buffer */
*sl = ts = luaS_newlstr(L, buff, size); /* create string */ *sl = ts = luaS_newlstr(L, buff, size); /* create string */