summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bugs4133
1 files changed, 0 insertions, 4133 deletions
diff --git a/bugs b/bugs
deleted file mode 100644
index 84cd3c2d..00000000
--- a/bugs
+++ /dev/null
@@ -1,4133 +0,0 @@
1--[=[
2** lua.stx / llex.c
3Tue Dec 2 10:45:48 EDT 1997
4>> BUG: "lastline" was not reset on function entry, so debug information
5>> started only in the 2nd line of a function.
6
7
8
9=================================================================
10--- Version 3.1 alpha
11
12** lua.c
13Thu Jan 15 14:34:58 EDT 1998
14>> must include "stdlib.h" (for "exit()").
15
16** lbuiltin.c / lobject.h
17Thu Jan 15 14:34:58 EDT 1998
18>> MAX_WORD may be bigger than MAX_INT
19(by lhf)
20
21** llex.c
22Mon Jan 19 18:17:18 EDT 1998
23>> wrong line number (+1) in error report when file starts with "#..."
24
25** lstrlib.c
26Tue Jan 27 15:27:49 EDT 1998
27>> formats like "%020d" were considered too big (3 digits); moreover,
28>> some sistems limit printf to at most 500 chars, so we can limit sizes
29>> to 2 digits (99).
30
31** lapi.c
32Tue Jan 27 17:12:36 EDT 1998
33>> "lua_getstring" may create a new string, so should check GC
34
35** lstring.c / ltable.c
36Wed Jan 28 14:48:12 EDT 1998
37>> tables can become full of "empty" slots, and keep growing without limits.
38
39** lstrlib.c
40Mon Mar 9 15:26:09 EST 1998
41>> gsub('a', '(b?)%1*' ...) loops (because the capture is empty).
42
43** lstrlib.c
44Mon May 18 19:20:00 EST 1998
45>> arguments for "format" 'x', 'X', 'o' and 'u' must be unsigned int.
46
47
48
49=================================================================
50--- Version 3.1
51
52** liolib.c / lauxlib.c
53Mon Sep 7 15:57:02 EST 1998
54>> function "luaL_argerror" prints wrong argument number (from a user's point
55of view) when functions have upvalues.
56
57** lstrlib.c
58Tue Nov 10 17:29:36 EDT 1998
59>> gsub/strfind do not check whether captures are properly finished.
60(by roberto/tomas)
61
62** lbuiltin.c
63Fri Dec 18 11:22:55 EDT 1998
64>> "tonumber" goes crazy with negative numbers in other bases (not 10),
65because "strtol" returns long, not unsigned long.
66(by Visual C++)
67
68** lstrlib.c
69Mon Jan 4 10:41:40 EDT 1999
70>> "format" does not check size of format item (such as "%00000...00000d").
71
72** lapi.c
73Wed Feb 3 14:40:21 EDT 1999
74>> getlocal cannot return the local itself, since lua_isstring and
75lua_isnumber can modify it.
76
77** lstrlib.c
78Thu Feb 4 17:08:50 EDT 1999
79>> format "%s" may break limit of "sprintf" on some machines.
80(by Marcelo Sales)
81
82** lzio.c
83Thu Mar 4 11:49:37 EST 1999
84>> file stream cannot call fread after EOF.
85(by lhf)
86
87
88
89=================================================================
90--- Version 3.2 (beta)
91
92** lstrlib.c
93Fri Apr 30 11:10:20 EST 1999
94>> '$' at end of pattern was matching regular '$', too.
95(by anna; since 2.5)
96
97** lbuiltin.c
98Fri May 21 17:15:11 EST 1999
99>> foreach, foreachi, foreachvar points to function in stack when stack
100can be reallocated.
101(by tomas; since 3.2 beta)
102
103** lparser.c
104Wed Jun 16 10:32:46 EST 1999
105>> cannot assign to unlimited variables, because it causes overflow in
106the number of returns of a function.
107(since 3.1)
108
109
110
111=================================================================
112--- Version 3.2
113
114** lmathlib.c
115Wed Aug 18 11:28:38 EST 1999
116>> random(0) and random(x,0) are wrong (0 is read as no argument!).
117(by Dave Bollinger; since 3.1)
118
119** lparser.c
120Thu Sep 2 10:07:20 EST 1999
121>> in the (old) expression << ls->fs->f->consts[checkname(ls)] >>, checkname
122could realloc f->consts.
123(by Supratik Champati; since 3.2 beta)
124
125** lobject.c / lbuiltin.c
126Wed Sep 8 17:41:54 EST 1999
127>> tonumber'e1' and tonumber(' ', x), for x!=10, gave 0 instead of nil.
128(since 3.1)
129
130** lstrlib.c
131Thu Nov 11 14:36:30 EDT 1999
132>> `strfind' does not handle \0 in plain search.
133(by Jon Kleiser; since 3.1)
134
135** lparser.c
136Wed Dec 29 16:05:43 EDT 1999
137>> return gives wrong line in debug information
138(by lhf; since 3.2 [at least])
139
140** ldo.c
141Thu Dec 30 16:39:33 EDT 1999
142>> cannot reopen stdin (for binary mode)
143(by lhf & roberto; since 3.1)
144
145** lapi.c
146Thu Mar 2 09:41:53 EST 2000
147>> lua_settable should check stack space (it could call a T.M.)
148(by lhf & celes; since 3.2; it was already fixed by fixed stack)
149
150** lparser.c
151Mon Apr 3 09:59:06 EST 2000
152>> '%' should be in expfollow
153(by Edgar Toernig; since 3.1; it was already fixed)
154
155** lbuiltin.c
156Mon Apr 3 10:05:05 EST 2000
157>> tostring() without arguments gives seg. fault.
158(by Edgar Toernig; since 3.0)
159
160
161
162=================================================================
163--- Version 4.0 alpha
164
165Tested with full test suites (as locked in Mon Apr 24 14:23:11 EST 2000)
166in the following platforms:
167* Linux - gcc, g++
168* AIX - gcc
169* Solaris - gcc, cc
170* IRIX - cc, cc-purify
171* Windows - Visual C++ (.c e .cpp, warning level=4)
172
173
174** lstrlib.c
175Tue May 2 15:27:58 EST 2000
176>> `strfind' gets wrong subject length when there is an offset
177(by Jon Kleiser; since 4.0a)
178
179** lparser.c
180Fri May 12 15:11:12 EST 2000
181>> first element in a list constructor is not adjusted to one value
182>> (e.g. «a = {gsub('a','a','')}»)
183(by Tomas; since 4.0a)
184
185** lparser.c
186Wed May 24 14:50:16 EST 2000
187>> record-constructor starting with an upvalue name gets an error
188>> (e.g. «local a; function f() x = {a=1} end»)
189(by Edgar Toernig; since 3.1)
190
191** lparser.c
192Tue Aug 29 15:56:05 EST 2000
193>> error message for `for' uses `while'
194(since 4.0a; already corrected)
195
196** lgc.c
197Tue Aug 29 15:57:41 EST 2000
198>> gc tag method for nil could call line hook
199(by ry; since ?)
200
201
202
203=================================================================
204--- Version 4.0 Beta
205
206** liolib.c
207Fri Sep 22 15:12:37 EST 2000
208>> `read("*w")' should return nil at EOF
209(by roberto; since 4.0b)
210
211** lvm.c
212Mon Sep 25 11:47:48 EST 2000
213>> lua_gettable does not get key from stack top
214(by Philip Yi; since 4.0b)
215
216** lgc.c
217Mon Sep 25 11:50:48 EST 2000
218>> GC may crash when checking locked C closures
219(by Philip Yi; since 4.0b)
220
221** lapi.c
222Wed Sep 27 09:50:19 EST 2000
223>> lua_tag should return LUA_NOTAG for non-valid indices
224(by Paul Hankin; since 4.0b)
225
226** llex.h / llex.c / lparser.c
227Wed Sep 27 13:39:45 EST 2000
228>> parser overwrites semantic information when looking ahead
229>> (e.g. «a = {print'foo'}»)
230(by Edgar Toernig; since 4.0b, deriving from previous bug)
231
232** liolib.c
233Thu Oct 26 10:50:46 EDT 2000
234>> in function `read_file', realloc() doesn't free the buffer if it can't
235>> allocate new memory
236(by Mauro Vezzosi; since 4.0b)
237
238
239
240=================================================================
241--- Version 4.0
242
243** lparser.c
244Wed Nov 29 09:51:44 EDT 2000
245>> parser does not accept a `;' after a `return'
246(by lhf; since 4.0b)
247
248** liolib.c
249Fri Dec 22 15:30:42 EDT 2000
250>> when `read' fails it must return nil (and not no value)
251(by cassino; since at least 3.1)
252
253** lstring.c/lapi.c
254Thu Feb 1 11:55:45 EDT 2001
255>> lua_pushuserdata(L, NULL) is buggy
256(by Edgar Toernig; since 4.0)
257
258** ldo.c
259Fri Feb 2 14:06:40 EDT 2001
260>> «while 1 dostring[[print('hello\n')]] end» never reclaims memory
261(by Andrew Paton; since 4.0b)
262
263** lbaselib.c
264Tue Feb 6 11:57:13 EDT 2001
265>> ESC (which starts precompiled code) in C is \33, not \27
266(by Edgar Toernig and lhf; since 4.0b)
267
268** lparser.c
269Tue Jul 10 16:59:18 EST 2001
270>> error message for `%a' gave wrong line number
271(by Leonardo Constantino; since 4.0)
272
273** lbaselib.c
274Fri Dec 21 15:21:05 EDT 2001
275>> seg. fault when rawget/rawset get extra arguments
276(by Eric Mauger; since 4.0b)
277
278** lvm.c
279Wed Jun 19 13:28:20 EST 2002
280>> line hook gets wrong `ar'
281(by Daniel C. Sinclair; since 4.0.b)
282
283** ldo.c
284Wed Jun 19 13:31:49 EST 2002
285>> `protectedparser' may run GC, and then collect `filename'
286>> (in function `parse_file')
287(by Alex Bilyk; since 4.0)
288
289
290
291
292=================================================================
293--- Version 5.0 alpha
294
295** lgc.c
296Fri Aug 30 13:49:14 EST 2002
297>> GC metamethod stored in a weak metatable being collected together with
298>> userdata may not be cleared properly
299(by Roberto; since 5.0a)
300
301** lapi.c
302Thu Nov 21 11:00:00 EST 2002
303>> ULONG_MAX>>10 may not fit into an int
304(by Jeff Petkau; since 4.0)
305
306** lparser.c
307Fri Dec 6 17:06:40 UTC 2002
308>> scope of generic for variables is not sound
309(by Gavin Wraith; since 5.0a)
310
311
312
313
314=================================================================
315--- Version 5.0 beta
316** lbaselib.c
317Fri Dec 20 09:53:19 UTC 2002
318>> `resume' was checking the wrong value for stack overflow
319(by Maik Zimmermann; since 5.0b)
320
321** ldo.c
322Thu Jan 23 11:29:06 UTC 2003
323>> error during garbage collection in luaD_protectedparser is not being
324>> protected
325(by Benoit Germain; since 5.0a)
326
327** ldo.c (and others)
328Fri Feb 28 14:20:33 EST 2003
329>> GC metamethod calls could mess C/Lua stack syncronization
330(by Roberto; since 5.0b)
331
332** lzio.h/zlio.c
333Thu Mar 20 11:40:12 EST 2003
334>> zio mixes a 255 as first char in a buffer with EOZ
335(by lhf; since 5.0a)
336
337
338
339--]=]
340-----------------------------------------------------------------
341-- Lua 5.0 (final)
342
343Bug{
344what = [[lua_closethread exists only in the manual]],
345report = [[by Nguyen Binh, 28/04/2003]],
346patch = [[no patch; the manual is wrong]],
347}
348
349
350Bug{
351what = [[attempt to resume a running coroutine crashes Lua]],
352example = [[
353function co_func (current_co)
354 coroutine.resume(co)
355end
356co = coroutine.create(co_func)
357coroutine.resume(co)
358coroutine.resume(co) --> seg. fault
359]],
360report = [[by Alex Bilyk, 09/05/2003]],
361patch = [[
362* ldo.c:
363325,326c325
364< if (nargs >= L->top - L->base)
365< luaG_runerror(L, "cannot resume dead coroutine");
366---
367> lua_assert(nargs < L->top - L->base);
368329c328,329
369< else if (ci->state & CI_YIELD) { /* inside a yield? */
370---
371> else { /* inside a yield */
372> lua_assert(ci->state & CI_YIELD);
373344,345d343
374< else
375< luaG_runerror(L, "cannot resume non-suspended coroutine");
376351a350,358
377> static int resume_error (lua_State *L, const char *msg) {
378> L->top = L->ci->base;
379> setsvalue2s(L->top, luaS_new(L, msg));
380> incr_top(L);
381> lua_unlock(L);
382> return LUA_ERRRUN;
383> }
384>
385>
386355a363,368
387> if (L->ci == L->base_ci) {
388> if (nargs >= L->top - L->base)
389> return resume_error(L, "cannot resume dead coroutine");
390> }
391> else if (!(L->ci->state & CI_YIELD)) /* not inside a yield? */
392> return resume_error(L, "cannot resume non-suspended coroutine");
393]],
394}
395
396
397Bug{
398what = [[file:close cannot be called without a file. (results in seg fault)]],
399example = [[
400> io.stdin.close() -- correct call shold be io.stdin:close()
401]],
402report = [[by Tuomo Valkonen, 27/05/2003]],
403patch = [[
404* liolib.c:
405161c161
406< if (lua_isnone(L, 1)) {
407---
408> if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE) {
409]], --}}
410}
411
412
413Bug{
414what = [[C functions also may have stacks larger than current top]],
415example = [[
416Must recompile lua with a change in lua.c and with lua_assert defined:
417* lua.c:
418381a382
419> lua_checkstack(l, 1000);
420]],
421report = [[Alex Bilyk, 09/06/2003]],
422patch = [[
423* lgc.c:
424247c247
425< if (!(ci->state & CI_C) && lim < ci->top)
426---
427> if (lim < ci->top)
428]],
429}
430
431
432Bug{
433what = [[`pc' address is invalidated when a coroutine is suspended]],
434example = [[
435function g(x)
436 coroutine.yield(x)
437end
438
439function f (i)
440 debug.sethook(print, "l")
441 for j=1,1000 do
442 g(i+j)
443 end
444end
445
446co = coroutine.wrap(f)
447co(10)
448pcall(co)
449pcall(co)
450]],
451report = [[Nick Trout, 07/07/2003]],
452patch = [[
453* lvm.c:
454402,403c402,403
455< L->ci->u.l.pc = &pc;
456< if (L->hookmask & LUA_MASKCALL)
457---
458> if (L->hookmask & LUA_MASKCALL) {
459> L->ci->u.l.pc = &pc;
460404a405
461> }
462405a407
463> L->ci->u.l.pc = &pc;
464676,678c678
465< lua_assert(ci->u.l.pc == &pc &&
466< ttisfunction(ci->base - 1) &&
467< (ci->state & CI_SAVEDPC));
468---
469> lua_assert(ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC));
470]]
471}
472
473
474Bug{
475what = [[userdata to be collected still counts into new GC threshold,
476increasing memory consumption]],
477report = [[Roberto, 25/07/2003]],
478example = [[
479a = newproxy(true)
480getmetatable(a).__gc = function () end
481for i=1,10000000 do
482 newproxy(a)
483 if math.mod(i, 10000) == 0 then print(gcinfo()) end
484end
485]],
486patch = [[
487* lgc.h:
48818c18
489< void luaC_separateudata (lua_State *L);
490---
491> size_t luaC_separateudata (lua_State *L);
492
493* lgc.c:
494113c113,114
495< void luaC_separateudata (lua_State *L) {
496---
497> size_t luaC_separateudata (lua_State *L) {
498> size_t deadmem = 0;
499127a129
500> deadmem += sizeudata(gcotou(curr)->uv.len);
501136a139
502> return deadmem;
503390c393
504< static void checkSizes (lua_State *L) {
505---
506> static void checkSizes (lua_State *L, size_t deadmem) {
507400c403
508< G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
509---
510> G(L)->GCthreshold = 2*G(L)->nblocks - deadmem; /* new threshold */
511454c457,458
512< static void mark (lua_State *L) {
513---
514> static size_t mark (lua_State *L) {
515> size_t deadmem;
516467c471
517< luaC_separateudata(L); /* separate userdata to be preserved */
518---
519> deadmem = luaC_separateudata(L); /* separate userdata to be preserved */
520475a480
521> return deadmem;
522480c485
523< mark(L);
524---
525> size_t deadmem = mark(L);
526482c487
527< checkSizes(L);
528---
529> checkSizes(L, deadmem);
530]]
531}
532
533Bug{
534what=[[IBM AS400 (OS400) has sizeof(void *)==16, and a `%p' may generate
535up to 60 characters in a `printf'. That causes a buffer overflow in
536`tostring'.]],
537
538report = [[David Burgess, 25/08/2003]],
539
540example = [[print{}; (in an AS400 machine)]],
541
542patch = [[
543* liolib.c:
544178c178
545< char buff[32];
546---
547> char buff[128];
548
549* lbaselib.c:
550327c327
551< char buff[64];
552---
553> char buff[128];
554]]
555}
556
557
558Bug{
559what = [[syntax `local function' does not increment stack size]],
560
561report = [[Rici Lake, 26/09/2003]],
562
563example = [[
564-- must run this with precompiled code
565local a,b,c
566local function d () end
567]],
568
569patch = [[
570* lparser.c:
5711143a1144
572> FuncState *fs = ls->fs;
5731145c1146,1147
574< init_exp(&v, VLOCAL, ls->fs->freereg++);
575---
576> init_exp(&v, VLOCAL, fs->freereg);
577> luaK_reserveregs(fs, 1);
5781148c1150,1152
579< luaK_storevar(ls->fs, &v, &b);
580---
581> luaK_storevar(fs, &v, &b);
582> /* debug information will only see the variable after this point! */
583> getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;
584]],
585
586}
587
588
589Bug{
590
591what = [[count hook may be called without being set]],
592
593report = [[Andreas Stenius, 06/10/2003]],
594
595example = [[
596set your hooks with
597
598 lua_sethook(L, my_hook, LUA_MASKLINE | LUA_MASKRET, 1);
599
600(It is weird to use a count > 0 without setting the count hook,
601but it is not wrong.)
602]],
603
604patch = [[
605* lvm.c:
60669c69
607< if (mask > LUA_MASKLINE) { /* instruction-hook set? */
608---
609> if (mask & LUA_MASKCOUNT) { /* instruction-hook set? */
610]],
611
612}
613
614
615Bug{
616
617what = [[`dofile' eats one return value when called without arguments]],
618
619report = [[Frederico Abraham, 15/01/2004]],
620
621example = [[
622a,b = dofile() --< here you enter `return 1,2,3 <eof>'
623print(a,b) --> 2 3 (should be 1 and 2)
624]],
625
626patch = [[
627* lbaselib.c:
628313a314
629> int n = lua_gettop(L);
630317c318
631< return lua_gettop(L) - 1;
632---
633> return lua_gettop(L) - n;
634]],
635
636}
637
638
639
640-----------------------------------------------------------------
641-- Lua 5.0.2
642
643Bug{
644what = [[string concatenation may cause arithmetic overflow, leading
645to a buffer overflow]],
646
647report = [[Rici Lake, 20/05/2004]],
648
649example = [[
650longs = string.rep("\0", 2^25)
651function catter(i)
652 return assert(loadstring(
653 string.format("return function(a) return a%s end",
654 string.rep("..a", i-1))))()
655end
656rep129 = catter(129)
657rep129(longs)
658]],
659
660patch = [[
661* lvm.c:
662@@ -321,15 +321,15 @@
663 luaG_concaterror(L, top-2, top-1);
664 } else if (tsvalue(top-1)->tsv.len > 0) { /* if len=0, do nothing */
665 /* at least two string values; get as many as possible */
666- lu_mem tl = cast(lu_mem, tsvalue(top-1)->tsv.len) +
667- cast(lu_mem, tsvalue(top-2)->tsv.len);
668+ size_t tl = tsvalue(top-1)->tsv.len;
669 char *buffer;
670 int i;
671- while (n < total && tostring(L, top-n-1)) { /* collect total length */
672- tl += tsvalue(top-n-1)->tsv.len;
673- n++;
674+ /* collect total length */
675+ for (n = 1; n < total && tostring(L, top-n-1); n++) {
676+ size_t l = tsvalue(top-n-1)->tsv.len;
677+ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
678+ tl += l;
679 }
680- if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");
681 buffer = luaZ_openspace(L, &G(L)->buff, tl);
682 tl = 0;
683 for (i=n; i>0; i--) { /* concat all strings */
684]]
685}
686
687
688Bug{
689what = [[lua_getupvalue and setupvalue do not check for index too small]],
690
691report = [[Mike Pall, ?/2004]],
692
693example = [[debug.getupvalue(function() end, 0)]],
694
695patch = [[
696* lapi.c
697941c941
698< if (n > f->c.nupvalues) return NULL;
699---
700> if (!(1 <= n && n <= f->c.nupvalues)) return NULL;
701947c947
702< if (n > p->sizeupvalues) return NULL;
703---
704> if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
705]]
706}
707
708
709Bug{
710what = [[values holded in open upvalues of suspended threads may be
711incorrectly collected]],
712
713report = [[Spencer Schumann, 31/12/2004]],
714
715example = [[
716local thread_id = 0
717local threads = {}
718
719function fn(thread)
720 thread_id = thread_id + 1
721 threads[thread_id] = function()
722 thread = nil
723 end
724 coroutine.yield()
725end
726
727while true do
728 local thread = coroutine.create(fn)
729 coroutine.resume(thread, thread)
730end
731]],
732
733patch = [[
734* lgc.c:
735221,224c221,222
736< if (!u->marked) {
737< markobject(st, &u->value);
738< u->marked = 1;
739< }
740---
741> markobject(st, u->v);
742> u->marked = 1;
743]],
744}
745
746
747Bug{
748what = [[rawset/rawget do not ignore extra arguments]],
749
750report = [[Romulo Bahiense, 11/03/2005]],
751
752example = [[
753a = {}
754rawset(a, 1, 2, 3)
755print(a[1], a[2]) -- should be 2 and nil
756]],
757
758patch = [[
759* lbaselib.c:
760175a176
761> lua_settop(L, 2);
762183a185
763> lua_settop(L, 3);
764]],
765}
766
767
768Bug{
769what = [[weak tables that survive one collection are never collected]],
770
771report = [[Chromix, 02/01/2006]],
772
773example = [[
774a = {}
775print(gcinfo())
776for i = 1, 10000 do
777 a[i] = setmetatable({}, {__mode = "v"})
778end
779collectgarbage()
780a = nil
781collectgarbage()
782print(gcinfo())
783]],
784
785patch = [[
786* lgc.c
787@@ -366,7 +366,7 @@
788 GCObject *curr;
789 int count = 0; /* number of collected items */
790 while ((curr = *p) != NULL) {
791- if (curr->gch.marked > limit) {
792+ if ((curr->gch.marked & ~(KEYWEAK | VALUEWEAK)) > limit) {
793 unmark(curr);
794 p = &curr->gch.next;
795 }
796]],
797
798}
799
800
801Bug{
802what = [[Some "not not exp" may not result in boolean values]],
803report = [[]],
804since = [[4.0]],
805example = [[
806-- should print false, but prints nil
807print(not not (nil and 4))
808]],
809patch = [[]],
810}
811
812
813Bug{
814what = [[On some machines, closing a "piped file" (created with io.popen)
815may crash Lua]],
816report = [[]],
817since = [[5.0]],
818example = [[
819-- only on some machines
820 f = io.popen("ls")
821 f:close()
822]],
823patch = [[]],
824}
825
826
827
828-----------------------------------------------------------------
829-- Lua 5.1
830
831Bug{
832what = [[In 16-bit machines, expressions and/or with numeric constants as the
833right operand may result in weird values]],
834
835report = [[Andreas Stenius/Kein-Hong Man, 15/03/2006]],
836
837example = [[
838print(false or 0) -- on 16-bit machines
839]],
840
841patch = [[
842* lcode.c:
843@@ -731,17 +731,15 @@
844 case OPR_AND: {
845 lua_assert(e1->t == NO_JUMP); /* list must be closed */
846 luaK_dischargevars(fs, e2);
847- luaK_concat(fs, &e1->f, e2->f);
848- e1->k = e2->k; e1->u.s.info = e2->u.s.info;
849- e1->u.s.aux = e2->u.s.aux; e1->t = e2->t;
850+ luaK_concat(fs, &e2->f, e1->f);
851+ *e1 = *e2;
852 break;
853 }
854 case OPR_OR: {
855 lua_assert(e1->f == NO_JUMP); /* list must be closed */
856 luaK_dischargevars(fs, e2);
857- luaK_concat(fs, &e1->t, e2->t);
858- e1->k = e2->k; e1->u.s.info = e2->u.s.info;
859- e1->u.s.aux = e2->u.s.aux; e1->f = e2->f;
860+ luaK_concat(fs, &e2->t, e1->t);
861+ *e1 = *e2;
862 break;
863 }
864]],
865
866}
867
868
869Bug{
870what = [[luaL_checkudata may produce wrong error message]],
871
872report = [[Greg Falcon, 21/03/2006]],
873
874example = [[
875getmetatable(io.stdin).__gc()
876 --> bad argument #1 to '__gc' (FILE* expected, got table)
877]],
878
879patch = [[
880* lauxlib.c:
881@@ -123,11 +123,17 @@
882
883 LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
884 void *p = lua_touserdata(L, ud);
885- lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
886- if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2))
887- luaL_typerror(L, ud, tname);
888- lua_pop(L, 2); /* remove both metatables */
889- return p;
890+ if (p != NULL) { /* value is a userdata? */
891+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
892+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
893+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
894+ lua_pop(L, 2); /* remove both metatables */
895+ return p;
896+ }
897+ }
898+ }
899+ luaL_typerror(L, ud, tname); /* else error */
900+ return NULL; /* to avoid warnings */
901 }
902]]
903
904}
905
906
907Bug{
908what = [[
909In Windows,
910when Lua is used in an application that also uses DirectX,
911it may present an erractic behavior.
912THIS IS NOT A LUA BUG!
913The problem is that DirectX violates an ABI that Lua depends on.]],
914
915patch = [[
916The simplest solution is to use DirectX with
917the D3DCREATE_FPU_PRESERVE flag.
918
919Otherwise, you can change the definition of lua_number2int,
920in luaconf.h, to this one:
921#define lua_number2int(i,d) __asm fld d __asm fistp i
922]],
923
924}
925
926
927Bug{
928what = [[option '%q' in string.format does not handle '\r' correctly.]],
929
930example = [[
931local s = "a string with \r and \n and \r\n and \n\r"
932local c = string.format("return %q", s)
933assert(assert(loadstring(c))() == s)
934]],
935
936patch = [[
937* lstrlib.c:
938@@ -703,6 +703,10 @@
939 luaL_addchar(b, *s);
940 break;
941 }
942+ case '\r': {
943+ luaL_addlstring(b, "\\r", 2);
944+ break;
945+ }
946 case '\0': {
947 luaL_addlstring(b, "\\000", 4);
948 break;
949]],
950
951}
952
953
954Bug{
955what = [[lua_dostring/lua_dofile should return any values returned
956by the chunk]],
957
958patch = [[
959* lauxlib.h:
960@@ -108,9 +108,11 @@
961
962 #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
963
964-#define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, 0, 0))
965+#define luaL_dofile(L, fn) \
966+ (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
967
968-#define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, 0, 0))+#define luaL_dostring(L, s) \
969+ (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
970
971 #define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
972]],
973
974}
975
976
977Bug{
978
979what = [[garbage collector does not compensate enough for finalizers]],
980
981patch = [[
982lgc.c:
983@@ -322,4 +322,6 @@
984
985-static void propagateall (global_State *g) {
986- while (g->gray) propagatemark(g);
987+static size_t propagateall (global_State *g) {
988+ size_t m = 0;
989+ while (g->gray) m += propagatemark(g);
990+ return m;
991 }
992@@ -542,3 +544,3 @@
993 marktmu(g); /* mark `preserved' userdata */
994- propagateall(g); /* remark, to propagate `preserveness' */
995+ udsize += propagateall(g); /* remark, to propagate `preserveness' */
996 cleartable(g->weak); /* remove collected objects from weak tables */
997@@ -592,2 +594,4 @@
998 GCTM(L);
999+ if (g->estimate > GCFINALIZECOST)
1000+ g->estimate -= GCFINALIZECOST;
1001]]
1002}
1003
1004
1005Bug{
1006
1007what = [[debug hooks may get wrong when mixed with coroutines]],
1008
1009report = [[by Ivko Stanilov, 03/06/2006]],
1010
1011example = [[
1012co = coroutine.create(function (a,b)
1013 coroutine.yield(a, b)
1014 return b, "end"
1015end)
1016
1017debug.sethook(co, function() end, "lcr")
1018coroutine.resume(co, 100, 2000)
1019coroutine.resume(co, 100, 2000)
1020]],
1021
1022patch = [[
1023* ldo.c:
1024@@ -389,6 +389,7 @@
1025 return;
1026 }
1027 else { /* resuming from previous yield */
1028+ L->status = 0;
1029 if (!f_isLua(ci)) { /* `common' yield? */
1030 /* finish interrupted execution of `OP_CALL' */
1031 lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
1032@@ -399,7 +400,6 @@
1033 else /* yielded inside a hook: just continue its execution */
1034 L->base = L->ci->base;
1035 }
1036- L->status = 0;
1037 luaV_execute(L, cast_int(L->ci - L->base_ci));
1038 }
1039]],
1040
1041}
1042
1043
1044
1045-----------------------------------------------------------------
1046-- Lua 5.1.1
1047
1048Bug{
1049what = [[list constructors have wrong limit]],
1050
1051report = [[by Norman Ramsey, June 2006]],
1052
1053since = "5.1",
1054
1055example = [[
1056a = {}
1057a[1] = "x={1"
1058for i = 2, 2^20 do
1059 a[i] = 1
1060end
1061a[#a + 1] = "}"
1062s = table.concat(a, ",")
1063assert(loadstring(s))()
1064print(#x)
1065]],
1066
1067patch = [[
1068* lparser.c:
1069@@ -489,7 +489,7 @@
1070
1071 static void listfield (LexState *ls, struct ConsControl *cc) {
1072 expr(ls, &cc->v);
1073- luaY_checklimit(ls->fs, cc->na, MAXARG_Bx, "items in a constructor");
1074+ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
1075 cc->na++;
1076 cc->tostore++;
1077 }
1078]],
1079
1080}
1081
1082
1083Bug{
1084what = [[wrong message error in some cases involving closures]],
1085
1086report = [[Shmuel Zeigerman, on 07/2006]],
1087
1088since = "5.1",
1089
1090example = [[
1091local Var
1092local function main()
1093 NoSuchName (function() Var=0 end)
1094end
1095main()
1096--> lua5.1: temp:3: attempt to call upvalue 'Var' (a nil value)
1097]],
1098
1099patch = [[
1100*ldebug.c:
1101@@ -435,14 +435,16 @@
1102 break;
1103 }
1104 case OP_CLOSURE: {
1105- int nup;
1106+ int nup, j;
1107 check(b < pt->sizep);
1108 nup = pt->p[b]->nups;
1109 check(pc + nup < pt->sizecode);
1110- for (; nup>0; nup--) {
1111- OpCode op1 = GET_OPCODE(pt->code[pc+nup]);
1112+ for (j = 1; j <= nup; j++) {
1113+ OpCode op1 = GET_OPCODE(pt->code[pc + j]);
1114 check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
1115 }
1116+ if (reg != NO_REG) /* tracing? */
1117+ pc += nup; /* do not 'execute' these pseudo-instructions */
1118 break;
1119 }
1120 case OP_VARARG: {
1121]],
1122
1123}
1124
1125
1126Bug{
1127what = [[string.format("%") may read past the string]],
1128report = [[Roberto, on 09/2006]],
1129since = [[5.0]],
1130example = [[print(string.format("%"))]],
1131patch = [[
1132*lstrlib.c:
1133@@ -723,7 +723,7 @@
1134
1135 static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { const char *p = strfrmt;
1136- while (strchr(FLAGS, *p)) p++; /* skip flags */
1137+ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
1138 if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
1139 luaL_error(L, "invalid format (repeated flags)");
1140 if (isdigit(uchar(*p))) p++; /* skip width */
1141]],
1142}
1143
1144
1145Bug{
1146what = [[os.date throws an error when result is the empty string]],
1147report = [[]],
1148since = [[4.0]],
1149example = [[print(os.date(""))]],
1150patch = [[
1151*loslib.c:
1152@@ -148,7 +148,18 @@
1153 else {
1154- char b[256];
1155- if (strftime(b, sizeof(b), s, stm))
1156- lua_pushstring(L, b);
1157- else
1158- return luaL_error(L, LUA_QL("date") " format too long");
1159+ char cc[3];
1160+ luaL_Buffer b;
1161+ cc[0] = '%'; cc[2] = '\0';
1162+ luaL_buffinit(L, &b);
1163+ for (; *s; s++) {
1164+ if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */
1165+ luaL_addchar(&b, *s);
1166+ else {
1167+ size_t reslen;
1168+ char buff[200]; /* should be big enough for any conversion result */
1169+ cc[1] = *(++s);
1170+ reslen = strftime(buff, sizeof(buff), cc, stm);
1171+ luaL_addlstring(&b, buff, reslen);
1172+ }
1173+ }
1174+ luaL_pushresult(&b);
1175 }
1176]],
1177}
1178
1179
1180Bug{
1181what = [[setfenv accepts invalid 1st argument]],
1182report = [[Doug Rogers, on 02/2007]],
1183since = [[5.0]],
1184example = [[setfenv(nil, {}) -- should throw an error]],
1185patch = [[
1186*lbaselib.c:
1187@@ -116,3 +116,3 @@
1188
1189-static void getfunc (lua_State *L) {
1190+static void getfunc (lua_State *L, int opt) {
1191 if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
1192@@ -120,3 +120,3 @@
1193 lua_Debug ar;
1194- int level = luaL_optint(L, 1, 1);
1195+ int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
1196 luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
1197@@ -133,3 +133,3 @@
1198 static int luaB_getfenv (lua_State *L) {
1199- getfunc(L);
1200+ getfunc(L, 1);
1201 if (lua_iscfunction(L, -1)) /* is a C function? */
1202@@ -144,3 +144,3 @@
1203 luaL_checktype(L, 2, LUA_TTABLE);
1204- getfunc(L);
1205+ getfunc(L, 0);
1206 lua_pushvalue(L, 2);
1207]],
1208}
1209
1210
1211Bug{
1212what = [[wrong code for arithmetic expressions in some specific scenarios]],
1213report = [[Thierry Grellier, on 01/2007]],
1214since = [[5.1]],
1215example = [[
1216-- use a large number of names (almost 256)
1217v1=1; v2=1; v3=1; v4=1; v5=1; v6=1; v7=1; v8=1; v9=1;
1218v10=1; v11=1; v12=1; v13=1; v14=1; v15=1; v16=1; v17=1;
1219v18=1; v19=1; v20=1; v21=1; v22=1; v23=1; v24=1; v25=1;
1220v26=1; v27=1; v28=1; v29=1; v30=1; v31=1; v32=1; v33=1;
1221v34=1; v35=1; v36=1; v37=1; v38=1; v39=1; v40=1; v41=1;
1222v42=1; v43=1; v44=1; v45=1; v46=1; v47=1; v48=1; v49=1;
1223v50=1; v51=1; v52=1; v53=1; v54=1; v55=1; v56=1; v57=1;
1224v58=1; v59=1; v60=1; v61=1; v62=1; v63=1; v64=1; v65=1;
1225v66=1; v67=1; v68=1; v69=1; v70=1; v71=1; v72=1; v73=1;
1226v74=1; v75=1; v76=1; v77=1; v78=1; v79=1; v80=1; v81=1;
1227v82=1; v83=1; v84=1; v85=1; v86=1; v87=1; v88=1; v89=1;
1228v90=1; v91=1; v92=1; v93=1; v94=1; v95=1; v96=1; v97=1;
1229v98=1; v99=1; v100=1; v101=1; v102=1; v103=1; v104=1; v105=1;
1230v106=1; v107=1; v108=1; v109=1; v110=1; v111=1; v112=1; v113=1;
1231v114=1; v115=1; v116=1; v117=1; v118=1; v119=1; v120=1; v121=1;
1232v122=1; v123=1; v124=1; v125=1; v126=1; v127=1; v128=1; v129=1;
1233v130=1; v131=1; v132=1; v133=1; v134=1; v135=1; v136=1; v137=1;
1234v138=1; v139=1; v140=1; v141=1; v142=1; v143=1; v144=1; v145=1;
1235v146=1; v147=1; v148=1; v149=1; v150=1; v151=1; v152=1; v153=1;
1236v154=1; v155=1; v156=1; v157=1; v158=1; v159=1; v160=1; v161=1;
1237v162=1; v163=1; v164=1; v165=1; v166=1; v167=1; v168=1; v169=1;
1238v170=1; v171=1; v172=1; v173=1; v174=1; v175=1; v176=1; v177=1;
1239v178=1; v179=1; v180=1; v181=1; v182=1; v183=1; v184=1; v185=1;
1240v186=1; v187=1; v188=1; v189=1; v190=1; v191=1; v192=1; v193=1;
1241v194=1; v195=1; v196=1; v197=1; v198=1; v199=1; v200=1; v201=1;
1242v202=1; v203=1; v204=1; v205=1; v206=1; v207=1; v208=1; v209=1;
1243v210=1; v211=1; v212=1; v213=1; v214=1; v215=1; v216=1; v217=1;
1244v218=1; v219=1; v220=1; v221=1; v222=1; v223=1; v224=1; v225=1;
1245v226=1; v227=1; v228=1; v229=1; v230=1; v231=1; v232=1; v233=1;
1246v234=1; v235=1; v236=1; v237=1; v238=1; v239=1; v240=1; v241=1;
1247v242=1; v243=1; v244=1; v245=1; v246=1; v247=1; v248=1; v249=1;
1248v250=1;
1249v251={k1 = 1};
1250v252=1;
1251print(2 * v251.k1, v251.k1 * 2); -- 2 2, OK
1252v253=1;
1253print(2 * v251.k1, v251.k1 * 2); -- 1 2, ???
1254]],
1255patch = [[
1256*lcode.c:
1257@@ -657,10 +657,16 @@
1258 if (constfolding(op, e1, e2))
1259 return;
1260 else {
1261- int o1 = luaK_exp2RK(fs, e1);
1262 int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
1263- freeexp(fs, e2);
1264- freeexp(fs, e1);
1265+ int o1 = luaK_exp2RK(fs, e1);
1266+ if (o1 > o2) {
1267+ freeexp(fs, e1);
1268+ freeexp(fs, e2);
1269+ }
1270+ else {
1271+ freeexp(fs, e2);
1272+ freeexp(fs, e1);
1273+ }
1274 e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
1275 e1->k = VRELOCABLE;
1276 }
1277@@ -718,10 +724,15 @@
1278 luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
1279 break;
1280 }
1281- default: {
1282+ case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
1283+ case OPR_MOD: case OPR_POW: {
1284 if (!isnumeral(v)) luaK_exp2RK(fs, v);
1285 break;
1286 }
1287+ default: {
1288+ luaK_exp2RK(fs, v);
1289+ break;
1290+ }
1291 }
1292 }
1293]],
1294}
1295
1296Bug{
1297what = [[assignment of nil to parameter may be optimized away]],
1298report = [[Thomas Lauer, on 03/2007]],
1299since = [[5.1]],
1300example = [[
1301function f (a)
1302 a=nil
1303 return a
1304end
1305
1306print(f("test"))
1307]],
1308patch = [[
1309*lcode.c:
1310@@ -35,16 +35,20 @@
1311 void luaK_nil (FuncState *fs, int from, int n) {
1312 Instruction *previous;
1313 if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
1314- if (fs->pc == 0) /* function start? */
1315- return; /* positions are already clean */
1316- previous = &fs->f->code[fs->pc-1];
1317- if (GET_OPCODE(*previous) == OP_LOADNIL) {
1318- int pfrom = GETARG_A(*previous);
1319- int pto = GETARG_B(*previous);
1320- if (pfrom <= from && from <= pto+1) { /* can connect both? */
1321- if (from+n-1 > pto)
1322- SETARG_B(*previous, from+n-1);
1323- return;
1324+ if (fs->pc == 0) { /* function start? */
1325+ if (from >= fs->nactvar)
1326+ return; /* positions are already clean */
1327+ }
1328+ else {
1329+ previous = &fs->f->code[fs->pc-1];
1330+ if (GET_OPCODE(*previous) == OP_LOADNIL) {
1331+ int pfrom = GETARG_A(*previous);
1332+ int pto = GETARG_B(*previous);
1333+ if (pfrom <= from && from <= pto+1) { /* can connect both? */
1334+ if (from+n-1 > pto)
1335+ SETARG_B(*previous, from+n-1);
1336+ return;
1337+ }
1338 }
1339 }
1340 }
1341]],
1342}
1343
1344
1345Bug{
1346what = [[__concat metamethod converts numbers to strings]],
1347report = [[Paul Winwood, on 12/2006]],
1348since = [[5.0]],
1349example = [[
1350a = {}
1351setmetatable(a, {__concat = function (a,b) print(type(a), type(b)) end})
1352a = 4 .. a
1353]],
1354patch = [[
1355*lvm.c:
1356@@ -281,10 +281,12 @@
1357 do {
1358 StkId top = L->base + last + 1;
1359 int n = 2; /* number of elements handled in this pass (at least 2) */
1360- if (!tostring(L, top-2) || !tostring(L, top-1)) {
1361+ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
1362 if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
1363 luaG_concaterror(L, top-2, top-1);
1364- } else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */
1365+ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */
1366+ (void)tostring(L, top - 2); /* result is first op (as string) */
1367+ else {
1368 /* at least two string values; get as many as possible */
1369 size_t tl = tsvalue(top-1)->len;
1370 char *buffer;
1371]],
1372}
1373
1374
1375Bug{
1376what = [[As a library, loadlib.c should not access Lua internals
1377(via lobject.h)]],
1378report = [[Jérôme Vuarand, on 03/2007]],
1379since = [[5.0]],
1380example = [[the bug has no effect on external behavior]],
1381patch = [[remove the '#include "lobject.h" and use
1382'lua_pushfstring' instead of 'luaO_pushfstring']],
1383}
1384
1385
1386
1387-----------------------------------------------------------------
1388-- Lua 5.1.2
1389
1390Bug{
1391what = [[Lua may close standard files,
1392which then may be used by C]],
1393report = [[David Manura/Ross Berteig, on 04/2007]],
1394since = [[]],
1395example = [[
1396io.close(io.stderr)
1397-- in some systems, following attempts to write to 'stderr' may crash
1398a = a + 1
1399]],
1400patch = [[
1401]],
1402}
1403
1404Bug{
1405what = [[code generated for "-nil", "-true", and "-false" is wrong]],
1406report = [[David Manura/Rici Lake, on 04/2007]],
1407since = [[5.1]],
1408example = [[print(-nil)]],
1409patch = [[
1410lcode.c:
1411@@ -699,7 +699,7 @@
1412 e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
1413 switch (op) {
1414 case OPR_MINUS: {
1415- if (e->k == VK)
1416+ if (!isnumeral(e))
1417 luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
1418 codearith(fs, OP_UNM, e, &e2);
1419 break;
1420]],
1421}
1422
1423Bug{
1424what = [[Count hook may be called without being set.]],
1425report = [[Mike Pall, on 05/2007]],
1426since = [[?]],
1427example = [[]],
1428patch = [[
1429lvm.c:
1430@@ -61,11 +61,9 @@
1431 lu_byte mask = L->hookmask;
1432 const Instruction *oldpc = L->savedpc;
1433 L->savedpc = pc;
1434- if (mask > LUA_MASKLINE) { /* instruction-hook set? */
1435- if (L->hookcount == 0) {
1436- resethookcount(L);
1437- luaD_callhook(L, LUA_HOOKCOUNT, -1);
1438- }
1439+ if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {
1440+ resethookcount(L);
1441+ luaD_callhook(L, LUA_HOOKCOUNT, -1);
1442 }
1443 if (mask & LUA_MASKLINE) {
1444 Proto *p = ci_func(L->ci)->l.p;
1445]],
1446}
1447
1448Bug{
1449what = [[recursive coroutines may overflow C stack]],
1450report = [[ , on ]],
1451since = [[5.0]],
1452example = [[
1453a = function(a) coroutine.wrap(a)(a) end
1454a(a)
1455]],
1456patch = [[The 'nCcalls' counter should be shared by all threads.
1457(That is, it should be declared in the 'global_State' structure,
1458not in 'lua_State'.)
1459]],
1460}
1461
1462Bug{
1463what = [[wrong error message in some concatenations]],
1464report = [[Alex Davies, on 05/2007]],
1465since = [[5.1.2]],
1466example = [[a = nil; a = (1)..a]],
1467patch = [[
1468ldebug.c:
1469@@ -563,8 +563,8 @@
1470
1471
1472 void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
1473- if (ttisstring(p1)) p1 = p2;
1474- lua_assert(!ttisstring(p1));
1475+ if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
1476+ lua_assert(!ttisstring(p1) && !ttisnumber(p1));
1477 luaG_typeerror(L, p1, "concatenate");
1478 }
1479
1480]],
1481}
1482
1483Bug{
1484what = [[Very small numbers all collide in the hash function.
1485(This creates only performance problems; the behavoir is correct.)]],
1486report = [[, on ]],
1487since = [[5.0]],
1488example = [[]],
1489patch = [[
1490ltable.c:
149187,88c87,88
1492< n += 1; /* normalize number (avoid -0) */
1493< lua_assert(sizeof(a) <= sizeof(n));
1494---
1495> if (luai_numeq(n, 0)) /* avoid problems with -0 */
1496> return gnode(t, 0);
1497]],
1498}
1499
1500Bug{
1501what = [[Too many variables in an assignment may cause a
1502C stack overflow]],
1503report = [[Mike Pall, on 07/2007]],
1504since = [[5.0]],
1505example = [[
1506$ ulimit -s 1024 # Reduce C stack to 1MB for quicker results
1507$ lua -e 'local s = "a,"; for i=1,18 do s = s..s end print(loadstring("local a;"..s.."a=nil", ""))'
1508]],
1509patch = [[
1510lparser.c:
1511@@ -938,6 +938,8 @@
1512 primaryexp(ls, &nv.v);
1513 if (nv.v.k == VLOCAL)
1514 check_conflict(ls, lh, &nv.v);
1515+ luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,
1516+ "variable names");
1517 assignment(ls, &nv, nvars+1);
1518 }
1519 else { /* assignment -> `=' explist1 */
1520]],
1521}
1522
1523Bug{
1524what = [[An error in a module loaded through the '-l' option
1525shows no traceback]],
1526report = [[David Manura, on 08/2007]],
1527since = [[5.1]],
1528example = [[lua -ltemp (assuming temp.lua has an error)]],
1529patch = [[
1530lua.c:
1531@@ -144,7 +144,7 @@
1532 static int dolibrary (lua_State *L, const char *name) {
1533 lua_getglobal(L, "require");
1534 lua_pushstring(L, name);
1535- return report(L, lua_pcall(L, 1, 0, 0));
1536+ return report(L, docall(L, 1, 1));
1537 }
1538]],
1539}
1540
1541Bug{
1542what = [['gsub' may go wild when wrongly called without its third
1543argument and with a large subject]],
1544report = [[Florian Berger, on 10/2007]],
1545since = [[5.1]],
1546example = [[
1547x = string.rep('a', 10000) .. string.rep('b', 10000)
1548print(#string.gsub(x, 'b'))
1549]],
1550patch = [[
1551lstrlib.c:
1552@@ -631,6 +631,2 @@
1553 }
1554- default: {
1555- luaL_argerror(L, 3, "string/function/table expected");
1556- return;
1557- }
1558 }
1559@@ -650,2 +646,3 @@
1560 const char *p = luaL_checkstring(L, 2);
1561+ int tr = lua_type(L, 3);
1562 int max_s = luaL_optint(L, 4, srcl+1);
1563@@ -655,2 +652,5 @@
1564 luaL_Buffer b;
1565+ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
1566+ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
1567+ "string/function/table expected");
1568 luaL_buffinit(L, &b);
1569]],
1570}
1571
1572Bug{
1573what = [[table.remove removes last element of a table when given
1574an out-of-bound index]],
1575report = [[Patrick Donnelly, on 11/2007]],
1576since = [[5.0]],
1577example = [[
1578a = {1,2,3}
1579table.remove(a, 4)
1580print(a[3]) --> nil (should be 3)
1581]],
1582patch = [[
1583ltablib.c:
1584@@ -118,7 +118,8 @@
1585 static int tremove (lua_State *L) {
1586 int e = aux_getn(L, 1);
1587 int pos = luaL_optint(L, 2, e);
1588- if (e == 0) return 0; /* table is `empty' */
1589+ if (!(1 <= pos && pos <= e)) /* position is outside bounds? */
1590+ return 0; /* nothing to remove */
1591 luaL_setn(L, 1, e - 1); /* t.n = n-1 */
1592 lua_rawgeti(L, 1, pos); /* result = t[pos] */
1593 for ( ;pos<e; pos++) {
1594]],
1595}
1596
1597Bug{
1598what = [[lua_setfenv may crash if called over an invalid object]],
1599report = [[Mike Pall, on 11/2007]],
1600since = [[5.1]],
1601example = [[
1602> debug.setfenv(3, {})
1603]],
1604patch = [[
1605lapi.c:
1606@@ -749,7 +749,7 @@
1607 res = 0;
1608 break;
1609 }
1610- luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
1611+ if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
1612 L->top--;
1613 lua_unlock(L);
1614 return res;
1615]],
1616}
1617
1618Bug{
1619what = [[stand-alone interpreter shows incorrect error message
1620when the "message" is a coroutine]],
1621report = [[Patrick Donnelly, on 17/12/2007]],
1622since = [[5.1]],
1623example = [[> error(coroutine.create(function() end))]],
1624patch = [[
1625lua.c:
1626@@ -74,6 +74,8 @@
1627
1628
1629 static int traceback (lua_State *L) {
1630+ if (!lua_isstring(L, 1)) /* 'message' not a string? */
1631+ return 1; /* keep it intact */
1632 lua_getfield(L, LUA_GLOBALSINDEX, "debug");
1633 if (!lua_istable(L, -1)) {
1634 lua_pop(L, 1);
1635
1636]],
1637}
1638
1639Bug{
1640what = [[debug.sethook/gethook may overflow the thread's stack]],
1641report = [[Ivko Stanilov, on 2008/01/04]],
1642since = [[5.1]],
1643example = [[
1644a = coroutine.create(function() yield() end)
1645coroutine.resume(a)
1646debug.sethook(a) -- may overflow the stack of 'a'
1647]],
1648patch = [[
1649ldblib.c:
1650@@ -268,12 +268,11 @@
1651 count = luaL_optint(L, arg+3, 0);
1652 func = hookf; mask = makemask(smask, count);
1653 }
1654- gethooktable(L1);
1655- lua_pushlightuserdata(L1, L1);
1656+ gethooktable(L);
1657+ lua_pushlightuserdata(L, L1);
1658 lua_pushvalue(L, arg+1);
1659- lua_xmove(L, L1, 1);
1660- lua_rawset(L1, -3); /* set new hook */
1661- lua_pop(L1, 1); /* remove hook table */
1662+ lua_rawset(L, -3); /* set new hook */
1663+ lua_pop(L, 1); /* remove hook table */
1664 lua_sethook(L1, func, mask, count); /* set hooks */
1665 return 0;
1666 }
1667@@ -288,11 +287,10 @@
1668 if (hook != NULL && hook != hookf) /* external hook? */
1669 lua_pushliteral(L, "external hook");
1670 else {
1671- gethooktable(L1);
1672- lua_pushlightuserdata(L1, L1);
1673- lua_rawget(L1, -2); /* get hook */
1674- lua_remove(L1, -2); /* remove hook table */
1675- lua_xmove(L1, L, 1);
1676+ gethooktable(L);
1677+ lua_pushlightuserdata(L, L1);
1678+ lua_rawget(L, -2); /* get hook */
1679+ lua_remove(L, -2); /* remove hook table */
1680 }
1681 lua_pushstring(L, unmakemask(mask, buff));
1682 lua_pushinteger(L, lua_gethookcount(L1));
1683]]
1684}
1685
1686
1687
1688-----------------------------------------------------------------
1689-- Lua 5.1.3
1690
1691Bug{
1692what = [[LUAI_MAXCSTACK must be smaller than -LUA_REGISTRYINDEX]],
1693report = [[Patrick Donnelly, on 2008/02/11]],
1694since = [[5.1.3]],
1695example = [[
1696j = 1e4
1697co = coroutine.create(function()
1698 t = {}
1699 for i = 1, j do t[i] = i end
1700 return unpack(t)
1701end)
1702print(coroutine.resume(co))
1703]],
1704patch = [[
1705luaconf.h:
1706443c443,444
1707< ** functions to consume unlimited stack space.
1708---
1709> ** functions to consume unlimited stack space. (must be smaller than
1710> ** -LUA_REGISTRYINDEX)
1711445,446c446
1712< #define LUAI_MCS_AUX ((int)(INT_MAX / (4*sizeof(LUA_NUMBER))))
1713< #define LUAI_MAXCSTACK (LUAI_MCS_AUX > SHRT_MAX ? SHRT_MAX : LUAI_MCS_AUX)
1714---
1715> #define LUAI_MAXCSTACK 8000
1716]],
1717}
1718
1719Bug{
1720what = [[coroutine.resume pushes element without ensuring stack size]],
1721report = [[on 2008/02/11]],
1722since = [[5.0]],
1723example = [[(this bug cannot be detected without internal assertions)]],
1724patch = [[
1725lbaselib.c:
1726@@ -526,7 +526,7 @@
1727 status = lua_resume(co, narg);
1728 if (status == 0 || status == LUA_YIELD) {
1729 int nres = lua_gettop(co);
1730- if (!lua_checkstack(L, nres))
1731+ if (!lua_checkstack(L, nres + 1))
1732 luaL_error(L, "too many results to resume");
1733 lua_xmove(co, L, nres); /* move yielded values */
1734 return nres;
1735]],
1736}
1737
1738Bug{
1739what = [[lua_checkstack may have arithmetic overflow for large 'size']],
1740report = [[Patrick Donnelly, on 2008/02/12]],
1741since = [[5.0]],
1742example = [[
1743print(unpack({1,2,3}, 0, 2^31-3))
1744]],
1745patch = [[
1746--- lapi.c 2008/01/03 15:20:39 2.55.1.3
1747+++ lapi.c 2008/02/14 16:05:21
1748@@ -93,15 +93,14 @@
1749
1750
1751 LUA_API int lua_checkstack (lua_State *L, int size) {
1752- int res;
1753+ int res = 1;
1754 lua_lock(L);
1755- if ((L->top - L->base + size) > LUAI_MAXCSTACK)
1756+ if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK)
1757 res = 0; /* stack overflow */
1758- else {
1759+ else if (size > 0) {
1760 luaD_checkstack(L, size);
1761 if (L->ci->top < L->top + size)
1762 L->ci->top = L->top + size;
1763- res = 1;
1764 }
1765 lua_unlock(L);
1766 return res;
1767]],
1768}
1769
1770Bug{
1771what = [[unpack with maximum indices may crash due to arithmetic overflow]],
1772report = [[Patrick Donnelly, on 2008/02/12]],
1773since = [[5.1]],
1774example = [[
1775print(unpack({1,2,3}, 2^31-1, 2^31-1))
1776]],
1777patch = [[
1778--- lbaselib.c 2008/02/11 16:24:24 1.191.1.5
1779+++ lbaselib.c 2008/02/14 16:10:25
1780@@ -344,10 +344,12 @@
1781 luaL_checktype(L, 1, LUA_TTABLE);
1782 i = luaL_optint(L, 2, 1);
1783 e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
1784+ if (i > e) return 0; /* empty range */
1785 n = e - i + 1; /* number of elements */
1786- if (n <= 0) return 0; /* empty range */
1787- luaL_checkstack(L, n, "table too big to unpack");
1788- for (; i<=e; i++) /* push arg[i...e] */
1789+ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
1790+ return luaL_error(L, "too many results to unpack");
1791+ lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
1792+ while (i++ < e) /* push arg[i + 1...e] */
1793 lua_rawgeti(L, 1, i);
1794 return n;
1795 }
1796]],
1797}
1798
1799Bug{
1800what = [[The validator for precompiled code has several flaws that
1801allow malicious binary code to crash the application]],
1802report = [[Peter Cawley, on 2008/03/24]],
1803since = [[5.0]],
1804example = [[
1805a = string.dump(function()return;end)
1806a = a:gsub(string.char(30,37,122,128), string.char(34,0,0), 1)
1807loadstring(a)()
1808]],
1809patch = [[
1810--- ldebug.c 2007/12/28 15:32:23 2.29.1.3
1811+++ ldebug.c 2008/04/04 15:15:40
1812@@ -275,12 +275,12 @@
1813
1814 static int precheck (const Proto *pt) {
1815 check(pt->maxstacksize <= MAXSTACK);
1816- lua_assert(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
1817- lua_assert(!(pt->is_vararg & VARARG_NEEDSARG) ||
1818+ check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
1819+ check(!(pt->is_vararg & VARARG_NEEDSARG) ||
1820 (pt->is_vararg & VARARG_HASARG));
1821 check(pt->sizeupvalues <= pt->nups);
1822 check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
1823- check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
1824+ check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
1825 return 1;
1826 }
1827
1828@@ -363,7 +363,11 @@
1829 }
1830 switch (op) {
1831 case OP_LOADBOOL: {
1832- check(c == 0 || pc+2 < pt->sizecode); /* check its jump */
1833+ if (c == 1) { /* does it jump? */
1834+ check(pc+2 < pt->sizecode); /* check its jump */
1835+ check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||
1836+ GETARG_C(pt->code[pc+1]) != 0);
1837+ }
1838 break;
1839 }
1840 case OP_LOADNIL: {
1841@@ -428,7 +432,10 @@
1842 }
1843 case OP_SETLIST: {
1844 if (b > 0) checkreg(pt, a + b);
1845- if (c == 0) pc++;
1846+ if (c == 0) {
1847+ pc++;
1848+ check(pc < pt->sizecode - 1);
1849+ }
1850 break;
1851 }
1852 case OP_CLOSURE: {
1853]],
1854}
1855
1856Bug{
1857what = [[maliciously crafted precompiled code can blow the C stack]],
1858report = [[Greg Falcon, on 2008/03/25]],
1859since = [[5.0]],
1860example = [[
1861function crash(depth)
1862 local init = '\27\76\117\97\81\0\1\4\4\4\8\0\7\0\0\0\61\115\116' ..
1863 '\100\105\110\0\1\0\0\0\1\0\0\0\0\0\0\2\2\0\0\0\36' ..
1864 '\0\0\0\30\0\128\0\0\0\0\0\1\0\0\0\0\0\0\0\1\0\0\0' ..
1865 '\1\0\0\0\0\0\0\2'
1866 local mid = '\1\0\0\0\30\0\128\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\0'
1867 local fin = '\0\0\0\0\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0' ..
1868 '\0\0\97\0\1\0\0\0\1\0\0\0\0\0\0\0'
1869 local lch = '\2\0\0\0\36\0\0\0\30\0\128\0\0\0\0\0\1\0\0\0\0\0\0' ..
1870 '\0\1\0\0\0\1\0\0\0\0\0\0\2'
1871 local rch = '\0\0\0\0\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0' ..
1872 '\0\0\97\0\1\0\0\0\1'
1873 for i=1,depth do lch,rch = lch..lch,rch..rch end
1874 loadstring(init .. lch .. mid .. rch .. fin)
1875end
1876for i=1,25 do print(i); crash(i) end
1877]],
1878patch = [[
1879--- lundump.c 2008/04/04 16:00:45 2.7.1.3
1880+++ lundump.c 2008/04/04 19:51:41 2.7.1.4
1881@@ -161,7 +161,9 @@
1882
1883 static Proto* LoadFunction(LoadState* S, TString* p)
1884 {
1885- Proto* f=luaF_newproto(S->L);
1886+ Proto* f;
1887+ if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
1888+ f=luaF_newproto(S->L);
1889 setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
1890 f->source=LoadString(S); if (f->source==NULL) f->source=p;
1891 f->linedefined=LoadInt(S);
1892@@ -175,6 +177,7 @@
1893 LoadDebug(S,f);
1894 IF (!luaG_checkcode(f), "bad code");
1895 S->L->top--;
1896+ S->L->nCcalls--;
1897 return f;
1898 }
1899]],
1900}
1901
1902Bug{
1903what = [[code validator may reject (maliciously crafted) correct code]],
1904report = [[Greg Falcon, on 2008/03/26]],
1905since = [[5.0]],
1906example = [[
1907z={}
1908for i=1,27290 do z[i]='1,' end
1909z = 'if 1+1==2 then local a={' .. table.concat(z) .. '} end'
1910func = loadstring(z)
1911print(loadstring(string.dump(func)))
1912]],
1913patch = [[
1914--- ldebug.c 2008/04/04 15:30:05 2.29.1.4
1915+++ ldebug.c 2008/04/04 15:47:10
1916@@ -346,9 +346,18 @@
1917 int dest = pc+1+b;
1918 check(0 <= dest && dest < pt->sizecode);
1919 if (dest > 0) {
1920- /* cannot jump to a setlist count */
1921- Instruction d = pt->code[dest-1];
1922- check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0));
1923+ int j;
1924+ /* check that it does not jump to a setlist count; this
1925+ is tricky, because the count from a previous setlist may
1926+ have the same value of an invalid setlist; so, we must
1927+ go all the way back to the first of them (if any) */
1928+ for (j = 0; j < dest; j++) {
1929+ Instruction d = pt->code[dest-1-j];
1930+ if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;
1931+ }
1932+ /* if 'j' is even, previous value is not a setlist (even if
1933+ it looks like one) */
1934+ check((j&1) == 0);
1935 }
1936 }
1937 break;
1938]],
1939}
1940
1941Bug{
1942what = [[maliciously crafted precompiled code can inject invalid boolean
1943values into Lua code]],
1944report = [[Greg Falcon, on 2008/03/27]],
1945since = [[5.0]],
1946example = [[
1947maybe = string.dump(function() return ({[true]=true})[true] end)
1948maybe = maybe:gsub('\1\1','\1\2')
1949maybe = loadstring(maybe)()
1950assert(type(maybe) == "boolean" and maybe ~= true and maybe ~= false)
1951]],
1952patch = [[
1953--- lundump.c 2008/01/18 16:39:11 2.7.1.2
1954+++ lundump.c 2008/04/04 15:50:39
1955@@ -115,7 +115,7 @@
1956 setnilvalue(o);
1957 break;
1958 case LUA_TBOOLEAN:
1959- setbvalue(o,LoadChar(S));
1960+ setbvalue(o,LoadChar(S)!=0);
1961 break;
1962 case LUA_TNUMBER:
1963 setnvalue(o,LoadNumber(S));
1964]],
1965}
1966
1967
1968Bug{
1969what = [['string.byte' gets confused with some out-of-range negative indices]],
1970report = [[Mike Pall, on 2008/06/03]],
1971since = [[5.1]],
1972example = [[
1973print(string.byte("abc", -5)) --> 97 98 99 (should print nothing)
1974]],
1975patch = [[
1976--- lstrlib.c 2007/12/28 15:32:23 1.132.1.3
1977+++ lstrlib.c 2008/07/05 11:53:42
1978@@ -35,7 +35,8 @@
1979
1980 static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
1981 /* relative string position: negative means back from end */
1982- return (pos>=0) ? pos : (ptrdiff_t)len+pos+1;
1983+ if (pos < 0) pos += (ptrdiff_t)len + 1;
1984+ return (pos >= 0) ? pos : 0;
1985 }
1986
1987
1988]],
1989}
1990
1991
1992Bug{
1993what = [[user-requested GC step may loop forever]],
1994report = [[Makoto Hamanaka, on 2008/07/01]],
1995since = [[5.1]],
1996example = [[
1997collectgarbage("setpause", 100) -- small value
1998collectgarbage("setstepmul", 2000) -- large value
1999collectgarbage("step",0)
2000]],
2001patch = [[
2002--- lapi.c 2008/02/14 16:46:39 2.55.1.4
2003+++ lapi.c 2008/07/04 18:34:48
2004@@ -929,10 +929,13 @@
2005 g->GCthreshold = g->totalbytes - a;
2006 else
2007 g->GCthreshold = 0;
2008- while (g->GCthreshold <= g->totalbytes)
2009+ while (g->GCthreshold <= g->totalbytes) {
2010 luaC_step(L);
2011- if (g->gcstate == GCSpause) /* end of cycle? */
2012- res = 1; /* signal it */
2013+ if (g->gcstate == GCSpause) { /* end of cycle? */
2014+ res = 1; /* signal it */
2015+ break;
2016+ }
2017+ }
2018 break;
2019 }
2020 case LUA_GCSETPAUSE: {
2021]],
2022}
2023
2024
2025Bug{
2026what = [['module' may change the environment of a C function]],
2027report = [[Peter Cawley, on 2008/07/16]],
2028since = [[5.1]],
2029example = [[
2030pcall(module, "xuxu")
2031assert(debug.getfenv(pcall) == xuxu)
2032]],
2033patch = [[
2034--- loadlib.c 2007/12/28 14:58:43 1.52.1.2
2035+++ loadlib.c 2008/08/05 19:39:00
2036@@ -506,8 +506,11 @@
2037
2038 static void setfenv (lua_State *L) {
2039 lua_Debug ar;
2040- lua_getstack(L, 1, &ar);
2041- lua_getinfo(L, "f", &ar);
2042+ if (lua_getstack(L, 1, &ar) == 0 ||
2043+ lua_getinfo(L, "f", &ar) == 0 || /* get calling function */
2044+ lua_iscfunction(L, -1))
2045+ luaL_error(L, "function " LUA_QL("module")
2046+ " not called from a Lua function");
2047 lua_pushvalue(L, -2);
2048 lua_setfenv(L, -2);
2049 lua_pop(L, 1);
2050]],
2051}
2052
2053
2054Bug{
2055what = [[internal macro 'svalue' is wrong]],
2056report = [[Martijn van Buul, on 2008/08/04]],
2057since = [[5.1]],
2058example = [[
2059/* in luaconf.h */
2060#define LUAI_USER_ALIGNMENT_T union { char b[32]; }
2061]],
2062patch = [[
2063--- lobject.h 2007/12/27 13:02:25 2.20.1.1
2064+++ lobject.h 2008/08/05 19:40:48
2065@@ -210,3 +210,3 @@
2066 #define getstr(ts) cast(const char *, (ts) + 1)
2067-#define svalue(o) getstr(tsvalue(o))
2068+#define svalue(o) getstr(rawtsvalue(o))
2069
2070]],
2071}
2072
2073
2074-----------------------------------------------------------------
2075-- Lua 5.1.4
2076
2077Bug{
2078what = [[malicious zero-length string in binary code may segfault Lua]],
2079report = [[Peter Cawley, on 2008/09/01]],
2080since = [[5.1]],
2081example = [[
2082loadstring(('').dump(function()X''end):gsub('\2%z%z%zX','\0\0\0'))()
2083]],
2084patch = [[
2085]],
2086}
2087
2088
2089Bug{
2090what = [[wrong code generation for some particular boolean expressions]],
2091report = [[Brian Kelley, on 2009/04/15]],
2092since = [[5.0]],
2093example = [[
2094print(((1 or false) and true) or false) --> 1
2095-- should be 'true'
2096]],
2097patch = [[
2098--- lcode.c 2007/12/28 15:32:23 2.25.1.3
2099+++ lcode.c 2009/06/15 14:07:34
2100@@ -544,15 +544,18 @@
2101 pc = NO_JUMP; /* always true; do nothing */
2102 break;
2103 }
2104- case VFALSE: {
2105- pc = luaK_jump(fs); /* always jump */
2106- break;
2107- }
2108 case VJMP: {
2109 invertjump(fs, e);
2110 pc = e->u.s.info;
2111 break;
2112 }
2113+ case VFALSE: {
2114+ if (!hasjumps(e)) {
2115+ pc = luaK_jump(fs); /* always jump */
2116+ break;
2117+ }
2118+ /* else go through */
2119+ }
2120 default: {
2121 pc = jumponcond(fs, e, 0);
2122 break;
2123@@ -572,14 +575,17 @@
2124 pc = NO_JUMP; /* always false; do nothing */
2125 break;
2126 }
2127- case VTRUE: {
2128- pc = luaK_jump(fs); /* always jump */
2129- break;
2130- }
2131 case VJMP: {
2132 pc = e->u.s.info;
2133 break;
2134 }
2135+ case VTRUE: {
2136+ if (!hasjumps(e)) {
2137+ pc = luaK_jump(fs); /* always jump */
2138+ break;
2139+ }
2140+ /* else go through */
2141+ }
2142 default: {
2143 pc = jumponcond(fs, e, 1);
2144 break;
2145]],
2146}
2147
2148Bug{
2149what = [['luaV_settable' may invalidate a reference to a table and try
2150to reuse it]],
2151report = [[Mark Feldman, on 2009/06/27]],
2152since = [[5.0]],
2153example = [[
2154grandparent = {}
2155grandparent.__newindex = function(s,_,_) print(s) end
2156
2157parent = {}
2158parent.__newindex = parent
2159setmetatable(parent, grandparent)
2160
2161child = setmetatable({}, parent)
2162child.foo = 10 --> (crash on some machines)
2163]],
2164patch = [[
2165--- lvm.c 2007/12/28 15:32:23 2.63.1.3
2166+++ lvm.c 2009/07/01 20:36:59
2167@@ -133,6 +133,7 @@
2168
2169 void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
2170 int loop;
2171+ TValue temp;
2172 for (loop = 0; loop < MAXTAGLOOP; loop++) {
2173 const TValue *tm;
2174 if (ttistable(t)) { /* `t' is a table? */
2175@@ -152,7 +153,9 @@
2176 callTM(L, tm, t, key, val);
2177 return;
2178 }
2179- t = tm; /* else repeat with `tm' */
2180+ /* else repeat with `tm' */
2181+ setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */
2182+ t = &temp;
2183 }
2184 luaG_runerror(L, "loop in settable");
2185 }
2186]],
2187}
2188
2189Bug{
2190what = [[smart use of varargs may create functions that return too
2191many arguments and overflow the stack of C functions]],
2192report = [[Patrick Donnelly, on 2008/12/10]],
2193since = [[]],
2194example = [[
2195local function lunpack(i, ...)
2196 if i == 0 then return ...
2197 else
2198 return lunpack(i-1, 1, ...)
2199 end
2200end
2201
2202Now, if C calls lunpack(n) with a huge n, it may end with
2203too many values in its stack and confuse its stack indices.
2204]],
2205patch = [[
2206]],
2207}
2208
2209Bug{
2210what = [['debug.getfenv' does not check whether it has an argument]],
2211report = [[Patrick Donnelly, 2009/07/30]],
2212since = [[5.1]],
2213example = [[debug.getfenv() -- should raise an error]],
2214patch = [[
2215--- ldblib.c 2008/01/21 13:11:21 1.104.1.3
2216+++ ldblib.c 2009/08/04 18:43:12
2217@@ -45,6 +45,7 @@
2218
2219
2220 static int db_getfenv (lua_State *L) {
2221+ luaL_checkany(L, 1);
2222 lua_getfenv(L, 1);
2223 return 1;
2224 }
2225]],
2226}
2227
2228Bug{
2229what = [[GC may get stuck during a parser and avoids proper resizing of
2230the string table,
2231making its lists grow too much and degrading performance]],
2232report = [[Sean Conner, 2009/11/10]],
2233since = [[5.1]],
2234example = [[See http://lua-users.org/lists/lua-l/2009-11/msg00463.html]],
2235patch = [[
2236--- llex.c 2007/12/27 13:02:25 2.20.1.1
2237+++ llex.c 2009/11/23 14:49:40
2238@@ -118,8 +118,10 @@
2239 lua_State *L = ls->L;
2240 TString *ts = luaS_newlstr(L, str, l);
2241 TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */
2242- if (ttisnil(o))
2243+ if (ttisnil(o)) {
2244 setbvalue(o, 1); /* make sure `str' will not be collected */
2245+ luaC_checkGC(L);
2246+ }
2247 return ts;
2248 }
2249
2250]]
2251}
2252
2253Bug{
2254what = [['string.format' may get buffer as an argument when there are
2255missing arguments and format string is too long]],
2256report = [[Roberto I., 2010/04/12]],
2257since = [[5.0]],
2258example = [[
2259x = string.rep("x", 10000) .. "%d"
2260print(string.format(x)) -- gives wrong error message
2261]],
2262patch = [[
2263--- lstrlib.c 2008/07/11 17:27:21 1.132.1.4
2264+++ lstrlib.c 2010/05/14 15:12:53
2265@@ -754,6 +754,7 @@
2266
2267
2268 static int str_format (lua_State *L) {
2269+ int top = lua_gettop(L);
2270 int arg = 1;
2271 size_t sfl;
2272 const char *strfrmt = luaL_checklstring(L, arg, &sfl);
2273@@ -768,7 +769,8 @@
2274 else { /* format item */
2275 char form[MAX_FORMAT]; /* to store the format (`%...') */
2276 char buff[MAX_ITEM]; /* to store the formatted item */
2277- arg++;
2278+ if (++arg > top)
2279+ luaL_argerror(L, arg, "no value");
2280 strfrmt = scanformat(L, strfrmt, form);
2281 switch (*strfrmt++) {
2282 case 'c': {
2283]]
2284}
2285
2286Bug{
2287what = [['io.read(op, "*n")' may return garbage if second read fails]],
2288report = [[Roberto I., 2010/04/12]],
2289since = [[5.0]],
2290example = [[
2291print(io.read("*n", "*n")) --<< enter "10 hi"
2292--> file (0x884420) nil
2293]],
2294patch = [[
2295--- liolib.c 2008/01/18 17:47:43 2.73.1.3
2296+++ liolib.c 2010/05/14 15:29:29
2297@@ -276,7 +276,10 @@
2298 lua_pushnumber(L, d);
2299 return 1;
2300 }
2301- else return 0; /* read fails */
2302+ else {
2303+ lua_pushnil(L); /* "result" to be removed */
2304+ return 0; /* read fails */
2305+ }
2306 }
2307
2308
2309]]
2310}
2311
2312Bug{
2313what = [[wrong code generation for some particular boolean expressions]],
2314report = [[Thierry Van Elsuwe, 2011/01/20]],
2315since = [[5.0]],
2316example = [[
2317print((('hi' or true) and true) or true)
2318--> hi (should be true)
2319print(((nil and nil) or false) and true)
2320--> nil (should be false)
2321]],
2322patch = [[
2323--- lcode.c 2009/06/15 14:12:25 2.25.1.4
2324+++ lcode.c 2011/01/31 14:44:25
2325@@ -549,13 +549,6 @@
2326 pc = e->u.s.info;
2327 break;
2328 }
2329- case VFALSE: {
2330- if (!hasjumps(e)) {
2331- pc = luaK_jump(fs); /* always jump */
2332- break;
2333- }
2334- /* else go through */
2335- }
2336 default: {
2337 pc = jumponcond(fs, e, 0);
2338 break;
2339@@ -579,13 +572,6 @@
2340 pc = e->u.s.info;
2341 break;
2342 }
2343- case VTRUE: {
2344- if (!hasjumps(e)) {
2345- pc = luaK_jump(fs); /* always jump */
2346- break;
2347- }
2348- /* else go through */
2349- }
2350 default: {
2351 pc = jumponcond(fs, e, 1);
2352 break;
2353]]
2354}
2355
2356Bug{
2357what = [[__newindex metamethod may not work if metatable is its own
2358metatable]],
2359report = [[Cuero Bugot, 2011/08/09]],
2360since = [[5.1]],
2361example = [[
2362meta={}
2363setmetatable(meta, meta)
2364meta.__newindex = function(t, key, value) print("set") end
2365o = setmetatable({}, meta)
2366o.x = 10 -- should print 'set'
2367]],
2368patch = [[
2369--- lvm.c 2009/07/01 21:10:33 2.63.1.4
2370+++ lvm.c 2011/08/17 20:36:28
2371@@ -142,6 +142,7 @@
2372 if (!ttisnil(oldval) || /* result is no nil? */
2373 (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
2374 setobj2t(L, oldval, val);
2375+ h->flags = 0;
2376 luaC_barriert(L, h, val);
2377 return;
2378 }
2379]]
2380}
2381
2382Bug{
2383what = [[parser may collect a prototype while building it]],
2384report = [[Ingo van Lil, 2011/10/13]],
2385since = [[5.1.4 (caused by patch 5.1.4-6)]],
2386example = nil,
2387patch = [[
2388--- lparser.c 2007/12/28 15:32:23 2.42.1.3
2389+++ lparser.c 2011/10/17 13:10:43
2390@@ -374,9 +374,9 @@
2391 lua_assert(luaG_checkcode(f));
2392 lua_assert(fs->bl == NULL);
2393 ls->fs = fs->prev;
2394- L->top -= 2; /* remove table and prototype from the stack */
2395 /* last token read was anchored in defunct function; must reanchor it */
2396 if (fs) anchor_token(ls);
2397+ L->top -= 2; /* remove table and prototype from the stack */
2398 }
2399
2400
2401]]
2402}
2403
2404
2405Bug{
2406what = [[When loading a file,
2407Lua may call the reader function again after it returned end of input
2408]],
2409report = [[Chris Howie, 2013/06/05]],
2410since = [[5.1]],
2411fix = [[5.2]],
2412example = [[
2413load(function () print("called"); return nil end)
2414--> called
2415--> called (should be called only once!)
2416]],
2417patch = [[
2418--- lzio.h 2007/12/27 13:02:25 1.21.1.1
2419+++ lzio.h 2013/07/04 13:55:59
2420@@ -59,6 +59,7 @@
2421 lua_Reader reader;
2422 void* data; /* additional data */
2423 lua_State *L; /* Lua state (for reader) */
2424+ int eoz; /* true if reader has no more data */
2425 };
2426
2427
2428--- lzio.c 2007/12/27 13:02:25 1.31.1.1
2429+++ lzio.c 2013/07/04 13:53:06
2430@@ -22,10 +22,14 @@
2431 size_t size;
2432 lua_State *L = z->L;
2433 const char *buff;
2434+ if (z->eoz) return EOZ;
2435 lua_unlock(L);
2436 buff = z->reader(L, z->data, &size);
2437 lua_lock(L);
2438- if (buff == NULL || size == 0) return EOZ;
2439+ if (buff == NULL || size == 0) {
2440+ z->eoz = 1; /* avoid calling reader function next time */
2441+ return EOZ;
2442+ }
2443 z->n = size - 1;
2444 z->p = buff;
2445 return char2int(*(z->p++));
2446@@ -51,6 +55,7 @@
2447 z->data = data;
2448 z->n = 0;
2449 z->p = NULL;
2450+ z->eoz = 0;
2451 }
2452]]
2453}
2454
2455
2456-----------------------------------------------------------------
2457-- Lua 5.2.0
2458
2459Bug{
2460what = [[memory hoarding when creating Lua hooks for coroutines]],
2461report = [[Arseny Vakhrushev, 2012/01/16]],
2462since = [[5.1]],
2463fix = [[5.2.1]],
2464example = [[
2465collectgarbage(); print(collectgarbage'count' * 1024)
2466
2467for i = 1, 100 do
2468 local co = coroutine.create(function () end)
2469 local x = {}
2470 for j=1,1000 do x[j] = j end
2471 debug.sethook(co, function () return x end, 'l')
2472end
2473
2474collectgarbage(); print(collectgarbage'count' * 1024)
2475-- value should back to near the original level
2476]],
2477patch = [[
2478-- For 5.2
2479
2480--- ldblib.c 2011/10/24 14:54:05 1.131
2481+++ ldblib.c 2012/01/18 02:36:59
2482@@ -253,14 +253,15 @@
2483 }
2484
2485
2486-#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY);
2487+#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)
2488
2489
2490 static void hookf (lua_State *L, lua_Debug *ar) {
2491 static const char *const hooknames[] =
2492 {"call", "return", "line", "count", "tail call"};
2493 gethooktable(L);
2494- lua_rawgetp(L, -1, L);
2495+ lua_pushthread(L);
2496+ lua_rawget(L, -2);
2497 if (lua_isfunction(L, -1)) {
2498 lua_pushstring(L, hooknames[(int)ar->event]);
2499 if (ar->currentline >= 0)
2500@@ -306,10 +307,15 @@
2501 count = luaL_optint(L, arg+3, 0);
2502 func = hookf; mask = makemask(smask, count);
2503 }
2504- gethooktable(L);
2505+ if (gethooktable(L) == 0) { /* creating hook table? */
2506+ lua_pushstring(L, "k");
2507+ lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */
2508+ lua_pushvalue(L, -1);
2509+ lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
2510+ }
2511+ lua_pushthread(L1); lua_xmove(L1, L, 1);
2512 lua_pushvalue(L, arg+1);
2513- lua_rawsetp(L, -2, L1); /* set new hook */
2514- lua_pop(L, 1); /* remove hook table */
2515+ lua_rawset(L, -3); /* set new hook */
2516 lua_sethook(L1, func, mask, count); /* set hooks */
2517 return 0;
2518 }
2519@@ -325,7 +331,8 @@
2520 lua_pushliteral(L, "external hook");
2521 else {
2522 gethooktable(L);
2523- lua_rawgetp(L, -1, L1); /* get hook */
2524+ lua_pushthread(L1); lua_xmove(L1, L, 1);
2525+ lua_rawget(L, -2); /* get hook */
2526 lua_remove(L, -2); /* remove hook table */
2527 }
2528 lua_pushstring(L, unmakemask(mask, buff));
2529]]
2530}
2531
2532Bug{
2533what = [[Lexical gets confused with some combination of arithmetic
2534operators and hexadecimal numbers]],
2535report = [[Alexandra Barros, 2012/01/17]],
2536since = [[5.2.0]],
2537fix = [[5.2.1]],
2538example = [[print(0xE+1)]],
2539patch = [[
2540--- llex.c 2011/11/30 12:43:51 2.59
2541+++ llex.c 2012/01/20 18:22:50
2542@@ -223,12 +223,19 @@
2543
2544 /* LUA_NUMBER */
2545 static void read_numeral (LexState *ls, SemInfo *seminfo) {
2546+ const char *expo = "Ee";
2547+ int first = ls->current;
2548 lua_assert(lisdigit(ls->current));
2549- do {
2550- save_and_next(ls);
2551- if (check_next(ls, "EePp")) /* exponent part? */
2552+ save_and_next(ls);
2553+ if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */
2554+ expo = "Pp";
2555+ for (;;) {
2556+ if (check_next(ls, expo)) /* exponent part? */
2557 check_next(ls, "+-"); /* optional exponent sign */
2558- } while (lislalnum(ls->current) || ls->current == '.');
2559+ if (lisxdigit(ls->current) || ls->current == '.')
2560+ save_and_next(ls);
2561+ else break;
2562+ }
2563 save(ls, '\0');
2564 buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
2565 if (!buff2d(ls->buff, &seminfo->r)) /* format error? */
2566]]
2567}
2568
2569Bug{
2570what = [[Finalizers may call functions from a dynamic library after
2571the library has been unloaded]],
2572report = [[Josh Haberman, 2012/04/08]],
2573since = [[5.1]],
2574fix = [[5.2.1]],
2575example = [[
2576local u = setmetatable({}, {__gc = function () foo() end})
2577local m = require 'mod' -- 'mod' may be any dynamic library written in C
2578foo = m.foo -- 'foo' may be any function from 'mod'
2579-- end program; it crashes
2580]],
2581patch = [[
2582loadlib.c:
258395c95
2584< #define LIBPREFIX "LOADLIB: "
2585---
2586> #define CLIBS "_CLIBS"
2587251,266c251,256
2588<
2589< static void **ll_register (lua_State *L, const char *path) {
2590< void **plib;
2591< lua_pushfstring(L, "%s%s", LIBPREFIX, path);
2592< lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */
2593< if (!lua_isnil(L, -1)) /* is there an entry? */
2594< plib = (void **)lua_touserdata(L, -1);
2595< else { /* no entry yet; create one */
2596< lua_pop(L, 1); /* remove result from gettable */
2597< plib = (void **)lua_newuserdata(L, sizeof(const void *));
2598< *plib = NULL;
2599< luaL_setmetatable(L, "_LOADLIB");
2600< lua_pushfstring(L, "%s%s", LIBPREFIX, path);
2601< lua_pushvalue(L, -2);
2602< lua_settable(L, LUA_REGISTRYINDEX);
2603< }
2604---
2605> static void *ll_checkclib (lua_State *L, const char *path) {
2606> void *plib;
2607> lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
2608> lua_getfield(L, -1, path);
2609> plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */
2610> lua_pop(L, 2); /* pop CLIBS table and 'plib' */
2611270a261,270
2612> static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
2613> lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
2614> lua_pushlightuserdata(L, plib);
2615> lua_pushvalue(L, -1);
2616> lua_setfield(L, -3, path); /* CLIBS[path] = plib */
2617> lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
2618> lua_pop(L, 1); /* pop CLIBS table */
2619> }
2620>
2621>
2622272,273c272,273
2623< ** __gc tag method: calls library's `ll_unloadlib' function with the lib
2624< ** handle
2625---
2626> ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
2627> ** handles in list CLIBS
2628276,278c276,281
2629< void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
2630< if (*lib) ll_unloadlib(*lib);
2631< *lib = NULL; /* mark library as closed */
2632---
2633> int n = luaL_len(L, 1);
2634> for (; n >= 1; n--) { /* for each handle, in reverse order */
2635> lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */
2636> ll_unloadlib(lua_touserdata(L, -1));
2637> lua_pop(L, 1); /* pop handle */
2638> }
2639284,286c287,292
2640< void **reg = ll_register(L, path);
2641< if (*reg == NULL) *reg = ll_load(L, path, *sym == '*');
2642< if (*reg == NULL) return ERRLIB; /* unable to load library */
2643---
2644> void *reg = ll_checkclib(L, path); /* check loaded C libraries */
2645> if (reg == NULL) { /* must load library? */
2646> reg = ll_load(L, path, *sym == '*');
2647> if (reg == NULL) return ERRLIB; /* unable to load library */
2648> ll_addtoclib(L, path, reg);
2649> }
2650292c298
2651< lua_CFunction f = ll_sym(L, *reg, sym);
2652---
2653> lua_CFunction f = ll_sym(L, reg, sym);
2654675,676c681,683
2655< /* create new type _LOADLIB */
2656< luaL_newmetatable(L, "_LOADLIB");
2657---
2658> /* create table CLIBS to keep track of loaded C libraries */
2659> luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
2660> lua_createtable(L, 0, 1); /* metatable for CLIBS */
2661678a686
2662> lua_setmetatable(L, -2);
2663]]
2664}
2665
2666Bug{
2667what = [[wrong handling of 'nCcalls' in coroutines]],
2668report = [[Alexander Gavrilov, 2012/04/18]],
2669since = [[5.2.0]],
2670fix = [[5.2.1]],
2671example = [[
2672coroutine.wrap(function()
2673 print(pcall(pcall,pcall,pcall,pcall,pcall,error,3))
2674end)()
2675]],
2676patch = [[
2677--- ldo.c 2011/11/29 15:55:08 2.102
2678+++ ldo.c 2012/04/26 20:38:32
2679@@ -402,8 +402,6 @@
2680 int n;
2681 lua_assert(ci->u.c.k != NULL); /* must have a continuation */
2682 lua_assert(L->nny == 0);
2683- /* finish 'luaD_call' */
2684- L->nCcalls--;
2685 /* finish 'lua_callk' */
2686 adjustresults(L, ci->nresults);
2687 /* call continuation function */
2688@@ -513,7 +511,6 @@
2689 api_checknelems(L, n);
2690 firstArg = L->top - n; /* yield results come from continuation */
2691 }
2692- L->nCcalls--; /* finish 'luaD_call' */
2693 luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
2694 }
2695 unroll(L, NULL);
2696]]
2697}
2698
2699Bug{
2700what = [[Internal Lua values may escape through the debug API]],
2701report = [[Dan Tull, 2012/04/20]],
2702since = [[5.1]],
2703fix = [[5.2.1]],
2704example = [[
2705-- for Lua 5.1
2706local firsttime = true
2707local function foo ()
2708 if firsttime then
2709 firsttime = false
2710 return "a = 1"
2711 else
2712 for i = 1, 10 do
2713 print(debug.getlocal(2, i))
2714 end
2715 end
2716end
2717
2718print(load(foo)) -- prints some lines and then seg. fault.
2719]],
2720patch = [[
2721]]
2722}
2723
2724Bug{
2725what = [[Problems when yielding from debug hooks]],
2726report = [[Erik Cassel, 2012/06/05]],
2727since = [[5.2.0]],
2728fix = [[5.2.1]],
2729example = [[
2730Set, in C, a line hook that simply yields,
2731and then call any Lua function.
2732You get an infinite loop of yields.
2733]],
2734patch = [[
2735]]
2736}
2737
2738
2739-----------------------------------------------------------------
2740-- Lua 5.2.1
2741
2742Bug{
2743what = [[Some patterns can overflow the C stack, due to recursion]],
2744report = [[Tim Starling, 2012/07/08]],
2745since = [[2.5]],
2746fix = [[5.2.2]],
2747example = [[print(string.find(string.rep("a", 2^20), string.rep(".?", 2^20)))]],
2748patch = [[
2749]]
2750}
2751
2752
2753Bug{
2754what = [['pcall' may not restore previous error function when
2755inside coroutines]],
2756report = [[Alexander Gavrilov, 2012/06/12]],
2757since = [[5.2.0]],
2758fix = [[5.2.2]],
2759example = [[
2760function errfunc(x)
2761 return 'errfunc'
2762end
2763
2764function test(do_yield)
2765 print(do_yield and "yielding" or "not yielding")
2766 pcall(function() -- this pcall sets errfunc back to none
2767 if do_yield then
2768 coroutine.yield() -- stops errfunc from being restored
2769 end
2770 end)
2771 error('fail!')
2772end
2773
2774coro = coroutine.wrap(function()
2775 print(xpcall(test, errfunc, false))
2776 print(xpcall(test, errfunc, true))
2777 print(xpcall(test, errfunc, false))
2778end)
2779
2780coro()
2781--> not yielding
2782--> false errfunc
2783--> yielding
2784coro()
2785--> false temp:12: fail! <<<< should be 'errfunc' too
2786--> not yielding
2787--> false errfunc
2788]],
2789patch = [[
2790--- ldo.c 2012/08/28 18:30:45 2.107
2791+++ ldo.c 2012/09/23 15:49:55
2792@@ -403,7 +403,11 @@
2793 int n;
2794 lua_assert(ci->u.c.k != NULL); /* must have a continuation */
2795 lua_assert(L->nny == 0);
2796- /* finish 'lua_callk' */
2797+ if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */
2798+ ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */
2799+ L->errfunc = ci->u.c.old_errfunc;
2800+ }
2801+ /* finish 'lua_callk'/'lua_pcall' */
2802 adjustresults(L, ci->nresults);
2803 /* call continuation function */
2804 if (!(ci->callstatus & CIST_STAT)) /* no call status? */
2805]]
2806}
2807
2808Bug{
2809what = [[Check for garbage collector in function calls does not cover
2810all paths]],
2811report = [[Roberto, 2012/08/15]],
2812since = [[5.2.1]],
2813fix = [[5.2.2]],
2814example = [[
2815See <a href="http://lua-users.org/lists/lua-l/2012-08/msg00149.html">
2816http://lua-users.org/lists/lua-l/2012-08/msg00149.html</a>
2817]],
2818patch = [[
2819@@ -311,6 +311,7 @@
2820 ci->top = L->top + LUA_MINSTACK;
2821 lua_assert(ci->top <= L->stack_last);
2822 ci->callstatus = 0;
2823+ luaC_checkGC(L); /* stack grow uses memory */
2824 if (L->hookmask & LUA_MASKCALL)
2825 luaD_hook(L, LUA_HOOKCALL, -1);
2826 lua_unlock(L);
2827@@ -338,6 +339,7 @@
2828 ci->u.l.savedpc = p->code; /* starting point */
2829 ci->callstatus = CIST_LUA;
2830 L->top = ci->top;
2831+ luaC_checkGC(L); /* stack grow uses memory */
2832 if (L->hookmask & LUA_MASKCALL)
2833 callhook(L, ci);
2834 return 0;
2835@@ -393,7 +395,6 @@
2836 luaV_execute(L); /* call it */
2837 if (!allowyield) L->nny--;
2838 L->nCcalls--;
2839- luaC_checkGC(L);
2840 }
2841]]
2842}
2843
2844Bug{
2845what = [[load/loadfile returns wrong result when given an environment
2846for a binary chunk with no upvalues]],
2847report = [[Vladimir Strakh, 2012/11/28]],
2848since = [[5.2.0]],
2849fix = [[5.2.2]],
2850example = [[
2851f = load(string.dump(function () return 1 end), nil, "b", {})
2852print(type(f)) --> table (whould be a function)
2853]],
2854patch = [[
2855--- lbaselib.c 2012/04/27 14:13:19 1.274
2856+++ lbaselib.c 2012/12/03 20:08:15
2857@@ -244,5 +244,11 @@
2858
2859-static int load_aux (lua_State *L, int status) {
2860- if (status == LUA_OK)
2861+static int load_aux (lua_State *L, int status, int envidx) {
2862+ if (status == LUA_OK) {
2863+ if (envidx != 0) { /* 'env' parameter? */
2864+ lua_pushvalue(L, envidx); /* environment for loaded function */
2865+ if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
2866+ lua_pop(L, 1); /* remove 'env' if not used by previous call */
2867+ }
2868 return 1;
2869+ }
2870 else {
2871@@ -258,9 +264,5 @@
2872 const char *mode = luaL_optstring(L, 2, NULL);
2873- int env = !lua_isnone(L, 3); /* 'env' parameter? */
2874+ int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
2875 int status = luaL_loadfilex(L, fname, mode);
2876- if (status == LUA_OK && env) { /* 'env' parameter? */
2877- lua_pushvalue(L, 3);
2878- lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */
2879- }
2880- return load_aux(L, status);
2881+ return load_aux(L, status, env);
2882 }
2883@@ -309,5 +311,5 @@
2884 size_t l;
2885- int top = lua_gettop(L);
2886 const char *s = lua_tolstring(L, 1, &l);
2887 const char *mode = luaL_optstring(L, 3, "bt");
2888+ int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
2889 if (s != NULL) { /* loading a string? */
2890@@ -322,7 +324,3 @@
2891 }
2892- if (status == LUA_OK && top >= 4) { /* is there an 'env' argument */
2893- lua_pushvalue(L, 4); /* environment for loaded function */
2894- lua_setupvalue(L, -2, 1); /* set it as 1st upvalue */
2895- }
2896- return load_aux(L, status);
2897+ return load_aux(L, status, env);
2898 }
2899]]
2900}
2901
2902
2903
2904
2905
2906-----------------------------------------------------------------
2907-- Lua 5.2.2
2908
2909
2910Bug{
2911what = [[stack overflow in vararg functions with many fixed
2912parameters called with few arguments]],
2913report = [[云风, 2013/04/17]],
2914since = [[5.1]],
2915fix = [[5.2.3]],
2916example = [[
2917function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
2918 p11, p12, p13, p14, p15, p16, p17, p18, p19, p20,
2919 p21, p22, p23, p24, p25, p26, p27, p28, p29, p30,
2920 p31, p32, p33, p34, p35, p36, p37, p38, p39, p40,
2921 p41, p42, p43, p44, p45, p46, p48, p49, p50, ...)
2922 local a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14
2923end
2924
2925f() -- seg. fault (on some machines)
2926]],
2927patch = [[
2928--- ldo.c 2012/10/01 14:05:04 2.108
2929+++ ldo.c 2013/04/19 20:56:06
2930@@ -324,7 +324,7 @@
2931 case LUA_TLCL: { /* Lua function: prepare its call */
2932 StkId base;
2933 Proto *p = clLvalue(func)->p;
2934- luaD_checkstack(L, p->maxstacksize);
2935+ luaD_checkstack(L, p->maxstacksize + p->numparams);
2936 func = restorestack(L, funcr);
2937 n = cast_int(L->top - func) - 1; /* number of real arguments */
2938 for (; n < p->numparams; n++)
2939]],
2940}
2941
2942Bug{
2943what = [[garbage collector can trigger too many times in recursive loops]],
2944report = [[Roberto, 2013/04/25]],
2945since = [[5.2.2]],
2946fix = [[5.2.3]],
2947example = [[
2948function f() f() end
2949f() -- it takes too long before a "stack overflow" error
2950]],
2951patch = [[
2952--- lgc.c 2013/04/12 18:48:47 2.140.1.1
2953+++ lgc.c 2013/04/25 21:30:20
2954@@ -495,2 +495,3 @@
2955 static lu_mem traversestack (global_State *g, lua_State *th) {
2956+ int n = 0;
2957 StkId o = th->stack;
2958@@ -505,3 +506,9 @@
2959 }
2960- return sizeof(lua_State) + sizeof(TValue) * th->stacksize;
2961+ else { /* count call infos to compute size */
2962+ CallInfo *ci;
2963+ for (ci = &th->base_ci; ci != th->ci; ci = ci->next)
2964+ n++;
2965+ }
2966+ return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
2967+ sizeof(CallInfo) * n;
2968 }
2969]]
2970}
2971
2972-- [[]]
2973Bug{
2974what = [[Wrong assert when reporting concatenation errors
2975(manifests only when Lua is compiled in debug mode)]],
2976report = [[Roberto, 2013/05/05]],
2977since = [[?]],
2978fix = [[5.2.3]],
2979example = [[
2980-- only with Lua compiled in debug mode
2981print({} .. 2)
2982]],
2983patch = [[
2984--- ldebug.c 2013/04/12 18:48:47 2.90.1.1
2985+++ ldebug.c 2013/05/05 14:38:30
2986@@ -519,5 +519,5 @@
2987 l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
2988 if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
2989- lua_assert(!ttisstring(p1) && !ttisnumber(p2));
2990+ lua_assert(!ttisstring(p1) && !ttisnumber(p1));
2991 luaG_typeerror(L, p1, "concatenate");
2992 }
2993]]
2994}
2995
2996Bug{
2997what = [[Wrong error message in some short-cut expressions]],
2998report = [[Egor Skriptunoff, 2013/05/10]],
2999since = [[5.0]],
3000fix = [[5.2.3]],
3001example = [[
3002> a,b,c = true,true,true
3003> (a and b or c)('', '')
3004stdin:1: attempt to call a boolean value (global 'c')
3005
3006 (It should be global 'b' instead of 'c'.)
3007]],
3008patch = [[
3009--- ldebug.c 2013/05/06 17:20:22 2.90.1.2
3010+++ ldebug.c 2013/05/14 19:52:48
3011@@ -327,12 +327,20 @@
3012 }
3013
3014
3015+static int filterpc (int pc, int jmptarget) {
3016+ if (pc < jmptarget) /* is code conditional (inside a jump)? */
3017+ return -1; /* cannot know who sets that register */
3018+ else return pc; /* current position sets that register */
3019+}
3020+
3021+
3022 /*
3023 ** try to find last instruction before 'lastpc' that modified register 'reg'
3024 */
3025 static int findsetreg (Proto *p, int lastpc, int reg) {
3026 int pc;
3027 int setreg = -1; /* keep last instruction that changed 'reg' */
3028+ int jmptarget = 0; /* any code before this address is conditional */
3029 for (pc = 0; pc < lastpc; pc++) {
3030 Instruction i = p->code[pc];
3031 OpCode op = GET_OPCODE(i);
3032@@ -341,33 +349,38 @@
3033 case OP_LOADNIL: {
3034 int b = GETARG_B(i);
3035 if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */
3036- setreg = pc;
3037+ setreg = filterpc(pc, jmptarget);
3038 break;
3039 }
3040 case OP_TFORCALL: {
3041- if (reg >= a + 2) setreg = pc; /* affect all regs above its base */
3042+ if (reg >= a + 2) /* affect all regs above its base */
3043+ setreg = filterpc(pc, jmptarget);
3044 break;
3045 }
3046 case OP_CALL:
3047 case OP_TAILCALL: {
3048- if (reg >= a) setreg = pc; /* affect all registers above base */
3049+ if (reg >= a) /* affect all registers above base */
3050+ setreg = filterpc(pc, jmptarget);
3051 break;
3052 }
3053 case OP_JMP: {
3054 int b = GETARG_sBx(i);
3055 int dest = pc + 1 + b;
3056 /* jump is forward and do not skip `lastpc'? */
3057- if (pc < dest && dest <= lastpc)
3058- pc += b; /* do the jump */
3059+ if (pc < dest && dest <= lastpc) {
3060+ if (dest > jmptarget)
3061+ jmptarget = dest; /* update 'jmptarget' */
3062+ }
3063 break;
3064 }
3065 case OP_TEST: {
3066- if (reg == a) setreg = pc; /* jumped code can change 'a' */
3067+ if (reg == a) /* jumped code can change 'a' */
3068+ setreg = filterpc(pc, jmptarget);
3069 break;
3070 }
3071 default:
3072 if (testAMode(op) && reg == a) /* any instruction that set A */
3073- setreg = pc;
3074+ setreg = filterpc(pc, jmptarget);
3075 break;
3076 }
3077 }
3078]]
3079}
3080
3081Bug{
3082what = [[luac listings choke on long strings]],
3083report = [[Ashwin Hirschi, 2013/07/03]],
3084since = [[5.1.2]],
3085fix = [[5.2.3]],
3086example = [[
3087-- When you call 'luac -l' over this chunk, it chokes the output
3088s="Lorem ipsum dolor sit amet, consectetur, "
3089]],
3090patch = [[
3091--- luac.c 2011-11-29 15:46:33 -0200 1.69
3092+++ luac.c 2013-07-03 21:26:01 -0300
3093@@ -251,7 +251,7 @@
3094 static void PrintConstant(const Proto* f, int i)
3095 {
3096 const TValue* o=&f->k[i];
3097- switch (ttype(o))
3098+ switch (ttypenv(o))
3099 {
3100 case LUA_TNIL:
3101 printf("nil");
3102]]
3103}
3104
3105Bug{
3106what = [[GC can collect a long string still in use during parser]],
3107report = [[Roberto, 2013/08/30]],
3108since = [[5.2]],
3109fix = [[5.2.3]],
3110example = [[This bug is very difficult to happen (and to reproduce),
3111because it depends on the GC running in a very specific way when
3112parsing a source code with long (larger than 40 characters) identifiers.]],
3113patch = [[
3114--- ltable.h 2013/04/12 18:48:47 2.16.1.1
3115+++ ltable.h 2013/08/30 15:34:24
3116@@ -18,4 +18,8 @@
3117 #define invalidateTMcache(t) ((t)->flags = 0)
3118
3119+/* returns the key, given the value of a table entry */
3120+#define keyfromval(v) \
3121+ (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val))))
3122+
3123
3124 LUAI_FUNC const TValue *luaH_getint (Table *t, int key);
3125
3126--- llex.c 2013/04/12 18:48:47 2.63.1.1
3127+++ llex.c 2013/08/30 15:34:59
3128@@ -134,4 +134,7 @@
3129 luaC_checkGC(L);
3130 }
3131+ else { /* string already present */
3132+ ts = rawtsvalue(keyfromval(o)); /* re-use value previously stored */
3133+ }
3134 L->top--; /* remove string from stack */
3135 return ts;
3136]]
3137}
3138
3139
3140Bug{
3141what = [[Call to macro 'luai_userstateclose' should be done only
3142after the calls to __gc methods.]],
3143report = [[Jean-Luc Jumpertz, 2013/09/02]],
3144since = [[ ]],
3145fix = nil,
3146example = [[No example]],
3147patch = [[
3148--- lstate.c 2013/04/12 18:48:47 2.99.1.1
3149+++ lstate.c 2013/11/08 17:39:57
3150@@ -194,2 +194,4 @@
3151 g->gcrunning = 1; /* allow gc */
3152+ g->version = lua_version(NULL);
3153+ luai_userstateopen(L);
3154 }
3155@@ -224,2 +226,4 @@
3156 luaC_freeallobjects(L); /* collect all objects */
3157+ if (g->version) /* closing a fully built state? */
3158+ luai_userstateclose(L);
3159 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
3160@@ -289,3 +293,3 @@
3161 g->panic = NULL;
3162- g->version = lua_version(NULL);
3163+ g->version = NULL;
3164 g->gcstate = GCSpause;
3165@@ -308,4 +312,2 @@
3166 }
3167- else
3168- luai_userstateopen(L);
3169 return L;
3170@@ -317,3 +319,2 @@
3171 lua_lock(L);
3172- luai_userstateclose(L);
3173 close_state(L);
3174]]
3175}
3176
3177
3178Bug{
3179what = [[Resuming the running coroutine makes it unyieldable]],
3180report = [[Florian Nücke, 2013/10/28]],
3181since = [[5.2]],
3182fix = [[5.2.3]],
3183example = [[
3184-- should print 'true'
3185print(coroutine.resume(coroutine.create(function()
3186 coroutine.resume(coroutine.running())
3187 coroutine.yield()
3188end)))
3189]],
3190patch = [[
3191--- ldo.c 2013/04/19 21:03:23 2.108.1.2
3192+++ ldo.c 2013/11/08 18:20:57
3193@@ -536,2 +536,3 @@
3194 int status;
3195+ int oldnny = L->nny; /* save 'nny' */
3196 lua_lock(L);
3197@@ -557,3 +558,3 @@
3198 }
3199- L->nny = 1; /* do not allow yields */
3200+ L->nny = oldnny; /* restore 'nny' */
3201 L->nCcalls--;
3202]]
3203}
3204
3205
3206
3207-----------------------------------------------------------------
3208-- Lua 5.2.3
3209
3210Bug{
3211what = [[compiler can optimize away overflow check in 'table.unpack']],
3212report = [[Paige DePol, 2014/03/30]],
3213since = [[5.1 (at least)]],
3214fix = nil,
3215example = [[
3216> unpack({}, 0, 2^31 - 1)
3217(segfaults on some platforms with some compiler options)
3218]],
3219patch = [[
3220--- ltablib.c 2013/04/12 18:48:47 1.65.1.1
3221+++ ltablib.c 2014/05/07 16:32:55 1.65.1.2
3222@@ -134,13 +135,14 @@
3223
3224
3225 static int unpack (lua_State *L) {
3226- int i, e, n;
3227+ int i, e;
3228+ unsigned int n;
3229 luaL_checktype(L, 1, LUA_TTABLE);
3230 i = luaL_optint(L, 2, 1);
3231 e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1));
3232 if (i > e) return 0; /* empty range */
3233- n = e - i + 1; /* number of elements */
3234- if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
3235+ n = (unsigned int)e - (unsigned int)i; /* number of elements minus 1 */
3236+ if (n > (INT_MAX - 10) || !lua_checkstack(L, ++n))
3237 return luaL_error(L, "too many results to unpack");
3238 lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
3239 while (i++ < e) /* push arg[i + 1...e] */
3240]]
3241}
3242
3243Bug{
3244what = [[Ephemeron table can wrongly collect entry with strong key]],
3245report = [[Jörg Richter, 2014/08/22]],
3246since = [[5.2]],
3247fix = nil,
3248example = [[
3249(This bug is very hard to reproduce,
3250because it depends on a specific interleaving of
3251events between the incremental collector and the program.)
3252]],
3253patch = [[
3254--- lgc.c 2013/04/26 18:22:05 2.140.1.2
3255+++ lgc.c 2014/09/01 13:24:33
3256@@ -403,7 +403,7 @@
3257 reallymarkobject(g, gcvalue(gval(n))); /* mark it now */
3258 }
3259 }
3260- if (prop)
3261+ if (g->gcstate != GCSatomic || prop)
3262 linktable(h, &g->ephemeron); /* have to propagate again */
3263 else if (hasclears) /* does table have white keys? */
3264 linktable(h, &g->allweak); /* may have to clean white keys */
3265]]
3266}
3267
3268Bug{
3269what = [[Chunk with too many lines can seg. fault]],
3270report = [[Roberto, 2014/11/14]],
3271since = [[5.1 (at least)]],
3272fix = nil,
3273example = [[
3274-- the cause of the bug is the use of an unitialized variable, so
3275-- it cannot be reproduced reliably
3276local s = string.rep("\n", 2^24)
3277print(load(function () return s end))
3278]],
3279patch = [[
3280--- llex.c 2013/08/30 15:49:41 2.63.1.2
3281+++ llex.c 2015/02/09 17:05:31
3282@@ -153,5 +153,5 @@
3283 next(ls); /* skip `\n\r' or `\r\n' */
3284 if (++ls->linenumber >= MAX_INT)
3285- luaX_syntaxerror(ls, "chunk has too many lines");
3286+ lexerror(ls, "chunk has too many lines", 0);
3287 }
3288
3289]]
3290}
3291
3292
3293-----------------------------------------------------------------
3294-- Lua 5.3.0
3295
3296Bug{
3297what = [['string.format("%f")' can cause a buffer overflow
3298(only when 'lua_Number' is long double!)]],
3299report = [[Roberto, 2015/01/13]],
3300since = [[5.3]],
3301fix = nil,
3302example = [[string.format("%.99f", 1e4000) -- when floats are long double]],
3303patch = [[
3304--- lstrlib.c 2014/12/11 14:03:07 1.221
3305+++ lstrlib.c 2015/02/23 19:01:42
3306@@ -800,3 +800,4 @@
3307 /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
3308-#define MAX_ITEM 512
3309+#define MAX_ITEM \
3310+ (sizeof(lua_Number) <= 4 ? 150 : sizeof(lua_Number) <= 8 ? 450 : 5050)
3311
3312]]
3313}
3314
3315Bug{
3316what = [['debug.getlocal' on a coroutine suspended in a hook
3317can crash the interpreter]],
3318report = [[云风, 2015/02/11]],
3319since = [[5.2]],
3320fix = nil,
3321example = [[see http://lua-users.org/lists/lua-l/2015-02/msg00146.html]],
3322patch = [[
3323--- ldebug.c 2015/01/02 12:52:22 2.110
3324+++ ldebug.c 2015/02/13 16:03:23
3325@@ -49,4 +49,14 @@
3326
3327
3328+static void swapextra (lua_State *L) {
3329+ if (L->status == LUA_YIELD) {
3330+ CallInfo *ci = L->ci; /* get function that yielded */
3331+ StkId temp = ci->func; /* exchange its 'func' and 'extra' values */
3332+ ci->func = restorestack(L, ci->extra);
3333+ ci->extra = savestack(L, temp);
3334+ }
3335+}
3336+
3337+
3338 /*
3339 ** this function can be called asynchronous (e.g. during a signal)
3340@@ -145,4 +155,5 @@
3341 const char *name;
3342 lua_lock(L);
3343+ swapextra(L);
3344 if (ar == NULL) { /* information about non-active function? */
3345 if (!isLfunction(L->top - 1)) /* not a Lua function? */
3346@@ -159,4 +170,5 @@
3347 }
3348 }
3349+ swapextra(L);
3350 lua_unlock(L);
3351 return name;
3352@@ -166,10 +178,13 @@
3353 LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
3354 StkId pos = 0; /* to avoid warnings */
3355- const char *name = findlocal(L, ar->i_ci, n, &pos);
3356+ const char *name;
3357 lua_lock(L);
3358+ swapextra(L);
3359+ name = findlocal(L, ar->i_ci, n, &pos);
3360 if (name) {
3361 setobjs2s(L, pos, L->top - 1);
3362 L->top--; /* pop value */
3363 }
3364+ swapextra(L);
3365 lua_unlock(L);
3366 return name;
3367@@ -271,4 +286,5 @@
3368 StkId func;
3369 lua_lock(L);
3370+ swapextra(L);
3371 if (*what == '>') {
3372 ci = NULL;
3373@@ -289,4 +305,5 @@
3374 api_incr_top(L);
3375 }
3376+ swapextra(L);
3377 if (strchr(what, 'L'))
3378 collectvalidlines(L, cl);
3379]]
3380}
3381
3382
3383Bug{
3384what = [[suspended '__le' metamethod can give wrong result]],
3385report = [[Eric Zhong, 2015/04/07]],
3386since = [[5.2]],
3387fix = nil,
3388
3389example = [[
3390mt = {__le = function (a,b) coroutine.yield("yield"); return a.x <= b.x end}
3391t1 = setmetatable({x=1}, mt)
3392t2 = {x=2}
3393co = coroutine.wrap(function (a,b) return t2 <= t1 end)
3394co()
3395print(co()) --> true (should be false)
3396]],
3397
3398patch = [[
3399--- lstate.h 2014/10/30 18:53:28 2.119
3400+++ lstate.h 2015/04/13 15:58:40
3401@@ -94,6 +94,7 @@
3402 #define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
3403 #define CIST_TAIL (1<<5) /* call was tail called */
3404 #define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
3405+#define CIST_LEQ (1<<7) /* using __lt for __le */
3406
3407 #define isLua(ci) ((ci)->callstatus & CIST_LUA)
3408
3409--- lvm.c 2014/12/27 20:30:38 2.232
3410+++ lvm.c 2015/04/13 15:51:30
3411@@ -292,9 +292,14 @@
3412 return l_strcmp(tsvalue(l), tsvalue(r)) <= 0;
3413 else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try 'le' */
3414 return res;
3415- else if ((res = luaT_callorderTM(L, r, l, TM_LT)) < 0) /* else try 'lt' */
3416- luaG_ordererror(L, l, r);
3417- return !res;
3418+ else { /* try 'lt': */
3419+ L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */
3420+ res = luaT_callorderTM(L, r, l, TM_LT);
3421+ L->ci->callstatus ^= CIST_LEQ; /* clear mark */
3422+ if (res < 0)
3423+ luaG_ordererror(L, l, r);
3424+ return !res; /* result is negated */
3425+ }
3426 }
3427
3428
3429@@ -553,11 +558,11 @@
3430 case OP_LE: case OP_LT: case OP_EQ: {
3431 int res = !l_isfalse(L->top - 1);
3432 L->top--;
3433- /* metamethod should not be called when operand is K */
3434- lua_assert(!ISK(GETARG_B(inst)));
3435- if (op == OP_LE && /* "<=" using "<" instead? */
3436- ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE)))
3437- res = !res; /* invert result */
3438+ if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */
3439+ lua_assert(op == OP_LE);
3440+ ci->callstatus ^= CIST_LEQ; /* clear mark */
3441+ res = !res; /* negate result */
3442+ }
3443 lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
3444 if (res != GETARG_A(inst)) /* condition failed? */
3445 ci->u.l.savedpc++; /* skip jump instruction */
3446]]
3447}
3448
3449
3450Bug{
3451what = [[return hook may not see correct values for
3452 active local variables when function returns]],
3453report = [[Philipp Janda/Peng Yi, 2015/05/19]],
3454since = [[5.0]],
3455fix = nil,
3456example = [[
3457see messasge http://lua-users.org/lists/lua-l/2015-05/msg00376.html]],
3458patch = [[
3459]]
3460}
3461
3462
3463
3464-----------------------------------------------------------------
3465-- Lua 5.3.1
3466
3467Bug{
3468what = [['io.lines' does not check maximum number of options]],
3469report = [[Patrick Donnell, 2015/07/10]],
3470since = [[5.3.0]],
3471fix = nil,
3472example = [[
3473-- can segfault in some machines
3474t ={}; for i = 1, 253 do t[i] = 1 end
3475io.lines("someexistingfile", table.unpack(t))()
3476]],
3477patch = [[
3478--- liolib.c 2015/07/07 17:03:34 2.146
3479+++ liolib.c 2015/07/15 14:40:28 2.147
3480@@ -318,8 +318,15 @@
3481 static int io_readline (lua_State *L);
3482
3483
3484+/*
3485+** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
3486+** in the limit for upvalues of a closure)
3487+*/
3488+#define MAXARGLINE 250
3489+
3490 static void aux_lines (lua_State *L, int toclose) {
3491 int n = lua_gettop(L) - 1; /* number of arguments to read */
3492+ luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
3493 lua_pushinteger(L, n); /* number of arguments to read */
3494 lua_pushboolean(L, toclose); /* close/not close file when finished */
3495 lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */
3496]]
3497}
3498
3499
3500-----------------------------------------------------------------
3501-- Lua 5.3.2
3502
3503Bug{
3504what = [[Metatable may access its own dealocated field when
3505it has a self reference in __newindex]],
3506report = [[actboy168@gmail.com, 2016/01/01]],
3507since = [[5.3.2]],
3508fix = nil,
3509example = [[
3510local mt = {}
3511mt.__newindex = mt
3512local t = setmetatable({}, mt)
3513t[1] = 1 -- will segfault on some machines
3514]],
3515patch = [[
3516--- lvm.c 2015/11/23 11:30:45 2.265
3517+++ lvm.c 2016/01/01 14:34:12
3518@@ -190,18 +190,19 @@
3519 for (loop = 0; loop < MAXTAGLOOP; loop++) {
3520 const TValue *tm;
3521 if (oldval != NULL) {
3522- lua_assert(ttistable(t) && ttisnil(oldval));
3523+ Table *h = hvalue(t); /* save 't' table */
3524+ lua_assert(ttisnil(oldval));
3525 /* must check the metamethod */
3526- if ((tm = fasttm(L, hvalue(t)->metatable, TM_NEWINDEX)) == NULL &&
3527+ if ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
3528 /* no metamethod; is there a previous entry in the table? */
3529 (oldval != luaO_nilobject ||
3530 /* no previous entry; must create one. (The next test is
3531 always true; we only need the assignment.) */
3532- (oldval = luaH_newkey(L, hvalue(t), key), 1))) {
3533+ (oldval = luaH_newkey(L, h, key), 1))) {
3534 /* no metamethod and (now) there is an entry with given key */
3535 setobj2t(L, cast(TValue *, oldval), val);
3536- invalidateTMcache(hvalue(t));
3537- luaC_barrierback(L, hvalue(t), val);
3538+ invalidateTMcache(h);
3539+ luaC_barrierback(L, h, val);
3540 return;
3541 }
3542 /* else will try the metamethod */
3543]]
3544}
3545
3546
3547Bug{
3548what = [[label between local definitions can mix-up their initializations]],
3549report = [[Karel Tuma, 2016/03/01]],
3550since = [[5.2]],
3551fix = nil,
3552example = [[
3553do
3554 local k = 0
3555 local x
3556 ::foo::
3557 local y -- should be reset to nil after goto, but it is not
3558 assert(not y)
3559 y = true
3560 k = k + 1
3561 if k < 2 then goto foo end
3562end
3563]],
3564patch = [[
3565--- lparser.c 2015/11/02 16:09:30 2.149
3566+++ lparser.c 2016/03/03 12:03:37
3567@@ -1226,7 +1226,7 @@
3568 checkrepeated(fs, ll, label); /* check for repeated labels */
3569 checknext(ls, TK_DBCOLON); /* skip double colon */
3570 /* create new entry for this label */
3571- l = newlabelentry(ls, ll, label, line, fs->pc);
3572+ l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs));
3573 skipnoopstat(ls); /* skip other no-op statements */
3574 if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */
3575 /* assume that locals are already out of scope */
3576]]
3577}
3578
3579
3580Bug{
3581what = [['gmatch' iterator fails when called from a coroutine different
3582from the one that created it]],
3583report = [[Nagaev Boris, 2016/03/18]],
3584since = [[5.3.2]],
3585fix = nil,
3586example = [[
3587local f = string.gmatch("1 2 3 4 5", "%d+")
3588print(f()) --> 1
3589co = coroutine.wrap(f)
3590print(co()) --> ??? (should be 2)
3591]],
3592patch = [[
3593--- lstrlib.c 2015/11/25 16:28:17 1.239
3594+++ lstrlib.c 2016/04/11 15:29:41
3595@@ -688,6 +688,7 @@
3596 static int gmatch_aux (lua_State *L) {
3597 GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
3598 const char *src;
3599+ gm->ms.L = L;
3600 for (src = gm->src; src <= gm->ms.src_end; src++) {
3601 const char *e;
3602 reprepstate(&gm->ms);
3603]]
3604}
3605
3606
3607-----------------------------------------------------------------
3608-- Lua 5.3.3
3609
3610
3611Bug{
3612what = [[expression list with four or more expressions in
3613a 'for' loop can crash the interpreter]],
3614report = [[Marco Schöpl, 2016/06/17]],
3615since = [[5.2]],
3616fix = nil,
3617example = [[
3618-- the next loop will probably crash the interpreter
3619repeat until load "for _ in _,_,_,_ do local function _() end"
3620]],
3621patch = [[
3622--- lparser.c 2016/05/13 19:10:16 2.153
3623+++ lparser.c 2016/06/17 19:52:48
3624@@ -323,6 +323,8 @@
3625 luaK_nil(fs, reg, extra);
3626 }
3627 }
3628+ if (nexps > nvars)
3629+ ls->fs->freereg -= nexps - nvars; /* remove extra values */
3630 }
3631
3632
3633@@ -1160,11 +1162,8 @@
3634 int nexps;
3635 checknext(ls, '=');
3636 nexps = explist(ls, &e);
3637- if (nexps != nvars) {
3638+ if (nexps != nvars)
3639 adjust_assign(ls, nvars, nexps, &e);
3640- if (nexps > nvars)
3641- ls->fs->freereg -= nexps - nvars; /* remove extra values */
3642- }
3643 else {
3644 luaK_setoneret(ls->fs, &e); /* close last expression */
3645 luaK_storevar(ls->fs, &lh->v, &e);
3646]]
3647}
3648
3649
3650Bug{
3651what = [[Checking a format for 'os.date' may read pass the format string]],
3652report = [[Nagaev Boris, 2016/07/10]],
3653since = [[5.3.3]],
3654fix = nil,
3655example = [[
3656This bug does not seem to happen with regular compilers.
3657It needs an "interceptor" 'memcmp' function that continues
3658reading memory after a difference is found.]],
3659patch = [[
36602c2
3661< ** $Id: bugs,v 1.160 2018/05/24 20:25:14 roberto Exp roberto $
3662---
3663> ** $Id: bugs,v 1.160 2018/05/24 20:25:14 roberto Exp roberto $
3664263c263,264
3665< for (option = LUA_STRFTIMEOPTIONS; *option != '\0'; option += oplen) {
3666---
3667> int convlen = (int)strlen(conv);
3668> for (option = LUA_STRFTIMEOPTIONS; *option != '\0' && oplen <= convlen; option += oplen) {
3669]]
3670}
3671
3672
3673Bug{
3674what = [[Lua can generate wrong code in functions with too many constants]],
3675report = [[Marco Schöpl, 2016/07/17]],
3676since = [[5.3.3]],
3677fix = nil,
3678example = [[See http://lua-users.org/lists/lua-l/2016-07/msg00303.html]],
3679patch = [[
3680--- lcode.c 2016/06/20 19:12:46 2.110
3681+++ lcode.c 2016/07/18 15:43:41
3682@@ -1018,8 +1018,8 @@
3683 */
3684 static void codebinexpval (FuncState *fs, OpCode op,
3685 expdesc *e1, expdesc *e2, int line) {
3686- int rk1 = luaK_exp2RK(fs, e1); /* both operands are "RK" */
3687- int rk2 = luaK_exp2RK(fs, e2);
3688+ int rk2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */
3689+ int rk1 = luaK_exp2RK(fs, e1);
3690 freeexps(fs, e1, e2);
3691 e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); /* generate opcode */
3692 e1->k = VRELOCABLE; /* all those operations are relocatable */
3693]]
3694}
3695
3696
3697Bug{
3698what = [[When a coroutine tries to resume a non-suspended coroutine,
3699it can do some mess (and break C assertions) before detecting the error]],
3700report = [[Marco Schöpl, 2016/07/20]],
3701since = [[ ]],
3702fix = nil,
3703example = [[
3704-- with C assertions on
3705A = coroutine.running()
3706B = coroutine.create(function() coroutine.resume(A) end)
3707coroutine.resume(B)
3708
3709-- or
3710A = coroutine.wrap(function() pcall(A, _) end)
3711A()
3712]],
3713patch = [[
3714]]
3715}
3716
3717
3718-----------------------------------------------------------------
3719-- Lua 5.3.4
3720
3721
3722Bug{
3723what = [[Wrong code for a goto followed by a label inside an 'if']],
3724report = [[云风, 2017/04/13]],
3725since = [[5.2]],
3726fix = nil,
3727example = [[
3728-- should print 32323232..., but prints only '3'
3729if true then
3730 goto LBL
3731 ::loop::
3732 print(2)
3733 ::LBL::
3734 print(3)
3735 goto loop
3736end
3737]],
3738patch = [[
3739--- lparser.c 2017/04/19 17:20:42 2.155.1.1
3740+++ lparser.c 2017/04/29 18:11:40 2.155.1.2
3741@@ -1392,7 +1392,7 @@
3742 luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */
3743 enterblock(fs, &bl, 0); /* must enter block before 'goto' */
3744 gotostat(ls, v.t); /* handle goto/break */
3745- skipnoopstat(ls); /* skip other no-op statements */
3746+ while (testnext(ls, ';')) {} /* skip semicolons */
3747 if (block_follow(ls, 0)) { /* 'goto' is the entire block? */
3748 leaveblock(fs);
3749 return; /* and that is it */
3750]]
3751}
3752
3753
3754Bug{
3755what = [[Lua crashes when building sequences with more than 2^30 elements.]],
3756report = [[Viacheslav Usov, 2017/05/11]],
3757since = [[ ]],
3758fix = nil,
3759example = [[
3760-- crashes if machine has enough memory
3761local t = {}
3762for i = 1, 0x7fffffff do
3763 t[i] = i
3764end
3765]],
3766patch = [[
3767--- ltable.c 2017/04/19 17:20:42 2.118.1.1
3768+++ ltable.c 2018/05/24 18:34:38
3769@@ -223,7 +223,9 @@
3770 unsigned int na = 0; /* number of elements to go to array part */
3771 unsigned int optimal = 0; /* optimal size for array part */
3772 /* loop while keys can fill more than half of total size */
3773- for (i = 0, twotoi = 1; *pna > twotoi / 2; i++, twotoi *= 2) {
3774+ for (i = 0, twotoi = 1;
3775+ twotoi > 0 && *pna > twotoi / 2;
3776+ i++, twotoi *= 2) {
3777 if (nums[i] > 0) {
3778 a += nums[i];
3779 if (a > twotoi/2) { /* more than half elements present? */
3780]]
3781}
3782
3783
3784Bug{
3785what = [[Table length computation overflows for sequences larger than
37862^31 elements.]],
3787report = [[Viacheslav Usov, 2017/05/12]],
3788since = [[ ]],
3789fix = nil,
3790example = [[
3791-- on a machine with enough memory
3792local t = {}
3793for i = 1, 2147483681 do
3794 t[i] = i
3795end
3796print(#t)
3797]],
3798patch = [[
3799--- ltable.h 2017/04/19 17:20:42 2.23.1.1
3800+++ ltable.h 2018/05/24 19:31:50
3801@@ -56,3 +56,3 @@
3802 LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
3803-LUAI_FUNC int luaH_getn (Table *t);
3804+LUAI_FUNC lua_Unsigned luaH_getn (Table *t);
3805
3806--- ltable.c 2018/05/24 19:22:37 2.118.1.2
3807+++ ltable.c 2018/05/24 19:25:05
3808@@ -614,4 +614,4 @@
3809
3810-static int unbound_search (Table *t, unsigned int j) {
3811- unsigned int i = j; /* i is zero or a present index */
3812+static lua_Unsigned unbound_search (Table *t, lua_Unsigned j) {
3813+ lua_Unsigned i = j; /* i is zero or a present index */
3814 j++;
3815@@ -620,3 +620,3 @@
3816 i = j;
3817- if (j > cast(unsigned int, MAX_INT)/2) { /* overflow? */
3818+ if (j > l_castS2U(LUA_MAXINTEGER) / 2) { /* overflow? */
3819 /* table was built with bad purposes: resort to linear search */
3820@@ -630,3 +630,3 @@
3821 while (j - i > 1) {
3822- unsigned int m = (i+j)/2;
3823+ lua_Unsigned m = (i+j)/2;
3824 if (ttisnil(luaH_getint(t, m))) j = m;
3825@@ -642,3 +642,3 @@
3826 */
3827-int luaH_getn (Table *t) {
3828+lua_Unsigned luaH_getn (Table *t) {
3829 unsigned int j = t->sizearray;
3830]]
3831}
3832
3833
3834Bug{
3835what = [[Lua does not check GC when creating error messages]],
3836report = [[Viacheslav Usov, 2017/07/06]],
3837since = [[5.3.2]],
3838fix = nil,
3839example = [[
3840function test()
3841 bob.joe.larry = 23
3842end
3843
3844-- memory will grow steadly
3845for i = 1, math.huge do
3846 pcall(test)
3847 if i % 100000 == 0 then
3848 io.write(collectgarbage'count'*1024, "\n")
3849 end
3850end
3851]],
3852patch = [[
3853--- ldebug.c 2017/04/19 17:20:42 2.121.1.1
3854+++ ldebug.c 2017/07/10 17:08:39
3855@@ -653,6 +653,7 @@
3856 CallInfo *ci = L->ci;
3857 const char *msg;
3858 va_list argp;
3859+ luaC_checkGC(L); /* error message uses memory */
3860 va_start(argp, fmt);
3861 msg = luaO_pushvfstring(L, fmt, argp); /* format message */
3862 va_end(argp);
3863]]
3864}
3865
3866
3867Bug{
3868what = [[dead keys with nil values can stay in weak tables]],
3869report = [[云风 Cloud Wu, 2017/08/15]],
3870since = [[5.2]],
3871fix = nil,
3872example = [[
3873-- The following chunk, under a memory checker like valgrind,
3874-- produces a memory access violation.
3875
3876local a = setmetatable({}, {__mode = 'kv'})
3877
3878a['ABCDEFGHIJKLMNOPQRSTUVWXYZ' .. 'abcdefghijklmnopqrstuvwxyz'] = {}
3879a[next(a)] = nil
3880collectgarbage()
3881print(a['BCDEFGHIJKLMNOPQRSTUVWXYZ' .. 'abcdefghijklmnopqrstuvwxyz'])
3882]],
3883patch = [[
3884--- lgc.c 2016/12/22 13:08:50 2.215
3885+++ lgc.c 2017/08/31 16:08:23
3886@@ -643,8 +643,9 @@
3887 for (n = gnode(h, 0); n < limit; n++) {
3888 if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) {
3889 setnilvalue(gval(n)); /* remove value ... */
3890- removeentry(n); /* and remove entry from table */
3891 }
3892+ if (ttisnil(gval(n))) /* is entry empty? */
3893+ removeentry(n); /* remove entry from table */
3894 }
3895 }
3896 }
3897]]
3898}
3899
3900
3901Bug{
3902what = [['lua_pushcclosure' should not call the garbage collector when
3903'n' is zero.]],
3904report = [[Andrew Gierth, 2017/12/05]],
3905since = [[5.3.3]],
3906fix = nil,
3907example = [[ ]],
3908patch = [[
3909--- lapi.c 2017/04/19 17:13:00 2.259.1.1
3910+++ lapi.c 2017/12/06 18:14:45
3911@@ -533,6 +533,7 @@
3912 lua_lock(L);
3913 if (n == 0) {
3914 setfvalue(L->top, fn);
3915+ api_incr_top(L);
3916 }
3917 else {
3918 CClosure *cl;
3919@@ -546,9 +547,9 @@
3920 /* does not need barrier because closure is white */
3921 }
3922 setclCvalue(L, L->top, cl);
3923+ api_incr_top(L);
3924+ luaC_checkGC(L);
3925 }
3926- api_incr_top(L);
3927- luaC_checkGC(L);
3928 lua_unlock(L);
3929 }
3930]]
3931}
3932
3933
3934Bug{
3935what = [[memory-allocation error when resizing a table can leave it
3936in an inconsistent state.]],
3937report = [[Roberto, 2017/12/08]],
3938since = [[5.0]],
3939fix = nil,
3940example = [[
3941local a = {x = 1, y = 1, z = 1}
3942a[1] = 10 -- goes to the hash part (which has 4 slots)
3943print(a[1]) --> 10
3944
3945-- assume that the 2nd memory allocation from now fails
3946pcall(rawset, a, 2, 20) -- forces a rehash
3947
3948-- a[1] now exists both in the array part (because the array part
3949-- grew) and in the hash part (because the allocation of the hash
3950-- part failed, keeping it as it was).
3951-- This makes the following traversal goes forever...
3952for k,v in pairs(a) do print(k,v) end
3953]],
3954patch = [[
3955--- ltable.c 2018/05/24 19:39:05 2.118.1.3
3956+++ ltable.c 2018/06/04 16:00:25
3957@@ -332,17 +332,34 @@
3958 }
3959
3960
3961+typedef struct {
3962+ Table *t;
3963+ unsigned int nhsize;
3964+} AuxsetnodeT;
3965+
3966+
3967+static void auxsetnode (lua_State *L, void *ud) {
3968+ AuxsetnodeT *asn = cast(AuxsetnodeT *, ud);
3969+ setnodevector(L, asn->t, asn->nhsize);
3970+}
3971+
3972+
3973 void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
3974 unsigned int nhsize) {
3975 unsigned int i;
3976 int j;
3977+ AuxsetnodeT asn;
3978 unsigned int oldasize = t->sizearray;
3979 int oldhsize = allocsizenode(t);
3980 Node *nold = t->node; /* save old hash ... */
3981 if (nasize > oldasize) /* array part must grow? */
3982 setarrayvector(L, t, nasize);
3983 /* create new hash part with appropriate size */
3984- setnodevector(L, t, nhsize);
3985+ asn.t = t; asn.nhsize = nhsize;
3986+ if (luaD_rawrunprotected(L, auxsetnode, &asn) != LUA_OK) { /* mem. error? */
3987+ setarrayvector(L, t, oldasize); /* array back to its original size */
3988+ luaD_throw(L, LUA_ERRMEM); /* rethrow memory error */
3989+ }
3990 if (nasize < oldasize) { /* array part must shrink? */
3991 t->sizearray = nasize;
3992 /* re-insert elements from vanishing slice */
3993]]
3994}
3995
3996
3997
3998-----------------------------------------------------------------
3999-- Lua 5.3.5
4000
4001Bug{
4002what = [[Long brackets with a huge number of '=' overflow some
4003internal buffer arithmetic]],
4004report = [[Marco, 2018/12/12]],
4005since = [[5.1]],
4006fix = nil,
4007example = [[
4008local eqs = string.rep("=", 0x3ffffffe)
4009local code = "return [" .. eqs .. "[a]" .. eqs .. "]"
4010print(#assert(load(code))())
4011]],
4012patch = [[
4013--- a/llex.c
4014+++ b/llex.c
4015@@ -244,12 +244,12 @@
4016
4017
4018 /*
4019-** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return
4020-** its number of '='s; otherwise, return a negative number (-1 iff there
4021-** are no '='s after initial bracket)
4022+** reads a sequence '[=*[' or ']=*]', leaving the last bracket.
4023+** If sequence is well formed, return its number of '='s + 2; otherwise,
4024+** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...').
4025 */
4026-static int skip_sep (LexState *ls) {
4027- int count = 0;
4028+static size_t skip_sep (LexState *ls) {
4029+ size_t count = 0;
4030 int s = ls->current;
4031 lua_assert(s == '[' || s == ']');
4032 save_and_next(ls);
4033@@ -257,11 +257,14 @@
4034 save_and_next(ls);
4035 count++;
4036 }
4037- return (ls->current == s) ? count : (-count) - 1;
4038+ return (ls->current == s) ? count + 2
4039+ : (count == 0) ? 1
4040+ : 0;
4041+
4042 }
4043
4044
4045-static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
4046+static void read_long_string (LexState *ls, SemInfo *seminfo, size_t sep) {
4047 int line = ls->linenumber; /* initial line (for error message) */
4048 save_and_next(ls); /* skip 2nd '[' */
4049 if (currIsNewline(ls)) /* string starts with a newline? */
4050@@ -295,8 +298,8 @@
4051 }
4052 } endloop:
4053 if (seminfo)
4054- seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
4055- luaZ_bufflen(ls->buff) - 2*(2 + sep));
4056+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + sep,
4057+ luaZ_bufflen(ls->buff) - 2 * sep);
4058 }
4059
4060
4061@@ -444,9 +447,9 @@
4062 /* else is a comment */
4063 next(ls);
4064 if (ls->current == '[') { /* long comment? */
4065- int sep = skip_sep(ls);
4066+ size_t sep = skip_sep(ls);
4067 luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */
4068- if (sep >= 0) {
4069+ if (sep >= 2) {
4070 read_long_string(ls, NULL, sep); /* skip long comment */
4071 luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */
4072 break;
4073@@ -458,12 +461,12 @@
4074 break;
4075 }
4076 case '[': { /* long string or simply '[' */
4077- int sep = skip_sep(ls);
4078- if (sep >= 0) {
4079+ size_t sep = skip_sep(ls);
4080+ if (sep >= 2) {
4081 read_long_string(ls, seminfo, sep);
4082 return TK_STRING;
4083 }
4084- else if (sep != -1) /* '[=...' missing second bracket */
4085+ else if (sep == 0) /* '[=...' missing second bracket */
4086 lexerror(ls, "invalid long string delimiter", TK_STRING);
4087 return '[';
4088 }
4089]]
4090}
4091
4092
4093Bug{
4094what = [[joining an upvalue with itself can cause a use-after-free crash]],
4095report = [[Fady Othman, 2019/01/10]],
4096since = [[5.3]],
4097fix = nil,
4098example = [[
4099-- the next code may crash the machine
4100f=load(function() end)
4101interesting={}
4102interesting[0]=string.rep("A",512)
4103debug.upvaluejoin(f,1,f,1)
4104]],
4105patch = [[
4106--- a/lapi.c
4107+++ b/lapi.c
4108@@ -1289,6 +1289,8 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
4109 LClosure *f1;
4110 UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
4111 UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
4112+ if (*up1 == *up2)
4113+ return;
4114 luaC_upvdeccount(L, *up1);
4115 *up1 = *up2;
4116 (*up1)->refcount++;
4117]]
4118}
4119
4120
4121--[=[
4122Bug{
4123what = [[ ]],
4124report = [[ ]],
4125since = [[ ]],
4126fix = nil,
4127example = [[ ]],
4128patch = [[
4129]]
4130}
4131]=]
4132
4133