瀏覽代碼

Fixed bug of long strings in binary chunks

When "undumping" a long string, the function 'loadVector' can call the
reader function, which can run the garbage collector, which can collect
the string being read. So, the string must be anchored during the call
to 'loadVector'.
Roberto Ierusalimschy 5 年之前
父節點
當前提交
6bc0f13505
共有 2 個文件被更改,包括 18 次插入1 次删除
  1. 3 0
      lundump.c
  2. 15 1
      testes/calls.lua

+ 3 - 0
lundump.c

@@ -120,7 +120,10 @@ static TString *loadStringN (LoadState *S, Proto *p) {
   }
   }
   else {  /* long string */
   else {  /* long string */
     ts = luaS_createlngstrobj(L, size);  /* create string */
     ts = luaS_createlngstrobj(L, size);  /* create string */
+    setsvalue2s(L, L->top, ts);  /* anchor it ('loadVector' can GC) */
+    luaD_inctop(L);
     loadVector(S, getstr(ts), size);  /* load directly in final place */
     loadVector(S, getstr(ts), size);  /* load directly in final place */
+    L->top--;  /* pop string */
   }
   }
   luaC_objbarrier(L, p, ts);
   luaC_objbarrier(L, p, ts);
   return ts;
   return ts;

+ 15 - 1
testes/calls.lua

@@ -317,6 +317,16 @@ f = load(string.dump(function () return 1 end), nil, "b", {})
 assert(type(f) == "function" and f() == 1)
 assert(type(f) == "function" and f() == 1)
 
 
 
 
+do   -- another bug (in 5.4.0)
+  -- loading a binary long string interrupted by GC cycles
+  local f = string.dump(function ()
+    return '01234567890123456789012345678901234567890123456789'
+  end)
+  f = load(read1(f))
+  assert(f() == '01234567890123456789012345678901234567890123456789')
+end
+
+
 x = string.dump(load("x = 1; return x"))
 x = string.dump(load("x = 1; return x"))
 a = assert(load(read1(x), nil, "b"))
 a = assert(load(read1(x), nil, "b"))
 assert(a() == 1 and _G.x == 1)
 assert(a() == 1 and _G.x == 1)
@@ -358,8 +368,12 @@ x = [[
    end
    end
   end
   end
 ]]
 ]]
+a = assert(load(read1(x), "read", "t"))
+assert(a()(2)(3)(10) == 15)
 
 
-a = assert(load(read1(x)))
+-- repeat the test loading a binary chunk
+x = string.dump(a)
+a = assert(load(read1(x), "read", "b"))
 assert(a()(2)(3)(10) == 15)
 assert(a()(2)(3)(10) == 15)