aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto I <roberto@inf.puc-rio.br>2025-10-10 15:28:41 -0300
committerRoberto I <roberto@inf.puc-rio.br>2025-10-10 15:28:41 -0300
commit7a92f3f99a26d9e51be40b744ed4fab0b50ecaa5 (patch)
treed50948f6b4bebdd23a56ac00c96ee8c47c574d82
parent3347c9d32d4d91b6139bff475c78cf0c4796e2a7 (diff)
downloadlua-7a92f3f99a26d9e51be40b744ed4fab0b50ecaa5.tar.gz
lua-7a92f3f99a26d9e51be40b744ed4fab0b50ecaa5.tar.bz2
lua-7a92f3f99a26d9e51be40b744ed4fab0b50ecaa5.zip
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.
-rw-r--r--ldump.c22
-rw-r--r--lundump.c12
2 files changed, 19 insertions, 15 deletions
diff --git a/ldump.c b/ldump.c
index a75b20d2..57957889 100644
--- a/ldump.c
+++ b/ldump.c
@@ -132,27 +132,31 @@ static void dumpInteger (DumpState *D, lua_Integer x) {
132 132
133 133
134/* 134/*
135** Dump a String. First dump its "size": size==0 means NULL; 135** Dump a String. First dump its "size":
136** size==1 is followed by an index and means "reuse saved string with 136** size==0 is followed by an index and means "reuse saved string with
137** that index"; size>=2 is followed by the string contents with real 137** that index"; index==0 means NULL.
138** size==size-2 and means that string, which will be saved with 138** size>=1 is followed by the string contents with real size==size-1 and
139** the next available index. 139** means that string, which will be saved with the next available index.
140** The real size does not include the ending '\0' (which is not dumped),
141** so adding 1 to it cannot overflow a size_t.
140*/ 142*/
141static void dumpString (DumpState *D, TString *ts) { 143static void dumpString (DumpState *D, TString *ts) {
142 if (ts == NULL) 144 if (ts == NULL) {
143 dumpSize(D, 0); 145 dumpVarint(D, 0); /* will "reuse" NULL */
146 dumpVarint(D, 0); /* special index for NULL */
147 }
144 else { 148 else {
145 TValue idx; 149 TValue idx;
146 int tag = luaH_getstr(D->h, ts, &idx); 150 int tag = luaH_getstr(D->h, ts, &idx);
147 if (!tagisempty(tag)) { /* string already saved? */ 151 if (!tagisempty(tag)) { /* string already saved? */
148 dumpVarint(D, 1); /* reuse a saved string */ 152 dumpVarint(D, 0); /* reuse a saved string */
149 dumpVarint(D, l_castS2U(ivalue(&idx))); /* index of saved string */ 153 dumpVarint(D, l_castS2U(ivalue(&idx))); /* index of saved string */
150 } 154 }
151 else { /* must write and save the string */ 155 else { /* must write and save the string */
152 TValue key, value; /* to save the string in the hash */ 156 TValue key, value; /* to save the string in the hash */
153 size_t size; 157 size_t size;
154 const char *s = getlstr(ts, size); 158 const char *s = getlstr(ts, size);
155 dumpSize(D, size + 2); 159 dumpSize(D, size + 1);
156 dumpVector(D, s, size + 1); /* include ending '\0' */ 160 dumpVector(D, s, size + 1); /* include ending '\0' */
157 D->nstr++; /* one more saved string */ 161 D->nstr++; /* one more saved string */
158 setsvalue(D->L, &key, ts); /* the string is the key */ 162 setsvalue(D->L, &key, ts); /* the string is the key */
diff --git a/lundump.c b/lundump.c
index 74839af8..3b61cc8c 100644
--- a/lundump.c
+++ b/lundump.c
@@ -147,20 +147,20 @@ static void loadString (LoadState *S, Proto *p, TString **sl) {
147 TString *ts; 147 TString *ts;
148 TValue sv; 148 TValue sv;
149 size_t size = loadSize(S); 149 size_t size = loadSize(S);
150 if (size == 0) { /* no string? */ 150 if (size == 0) { /* previously saved string? */
151 lua_assert(*sl == NULL); /* must be prefilled */
152 return;
153 }
154 else if (size == 1) { /* previously saved string? */
155 lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */ 151 lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */
156 TValue stv; 152 TValue stv;
153 if (idx == 0) { /* no string? */
154 lua_assert(*sl == NULL); /* must be prefilled */
155 return;
156 }
157 if (novariant(luaH_getint(S->h, l_castU2S(idx), &stv)) != LUA_TSTRING) 157 if (novariant(luaH_getint(S->h, l_castU2S(idx), &stv)) != LUA_TSTRING)
158 error(S, "invalid string index"); 158 error(S, "invalid string index");
159 *sl = ts = tsvalue(&stv); /* get its value */ 159 *sl = ts = tsvalue(&stv); /* get its value */
160 luaC_objbarrier(L, p, ts); 160 luaC_objbarrier(L, p, ts);
161 return; /* do not save it again */ 161 return; /* do not save it again */
162 } 162 }
163 else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */ 163 else if ((size -= 1) <= LUAI_MAXSHORTLEN) { /* short string? */
164 char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */ 164 char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */
165 loadVector(S, buff, size + 1); /* load string into buffer */ 165 loadVector(S, buff, size + 1); /* load string into buffer */
166 *sl = ts = luaS_newlstr(L, buff, size); /* create string */ 166 *sl = ts = luaS_newlstr(L, buff, size); /* create string */