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:
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;
|
** 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 */
|
||||||
|
|||||||
12
lundump.c
12
lundump.c
@@ -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_assert(*sl == NULL); /* must be prefilled */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (size == 1) { /* previously saved string? */
|
|
||||||
lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */
|
lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */
|
||||||
TValue stv;
|
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)
|
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 */
|
||||||
|
|||||||
Reference in New Issue
Block a user