Просмотр исходного кода

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.
Roberto I 3 месяцев назад
Родитель
Сommit
7a92f3f99a
2 измененных файлов с 19 добавлено и 15 удалено
  1. 13 9
      ldump.c
  2. 6 6
      lundump.c

+ 13 - 9
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 */

+ 6 - 6
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 */