diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-11-25 11:23:30 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-11-25 11:23:30 -0300 |
commit | cee1ebe3373d1ed9c87182edef49bd866126cceb (patch) | |
tree | 8de55dd8a8e0f92caf5090f0db7706bec7d3bbf9 | |
parent | 73c6ff659332d599e3faf20d87f0c898a3522a18 (diff) | |
download | lua-cee1ebe3373d1ed9c87182edef49bd866126cceb.tar.gz lua-cee1ebe3373d1ed9c87182edef49bd866126cceb.tar.bz2 lua-cee1ebe3373d1ed9c87182edef49bd866126cceb.zip |
File 'bugs' no longer tracked by git
The file 'bugs' reports bugs in several different versions
(corresponding to different branches in the repository), without
a clear division of "this bugs belongs to this version". So, it
doesn't make sense to track it along with one (or many) versions.
-rw-r--r-- | bugs | 4133 |
1 files changed, 0 insertions, 4133 deletions
@@ -1,4133 +0,0 @@ | |||
1 | --[=[ | ||
2 | ** lua.stx / llex.c | ||
3 | Tue 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 | ||
13 | Thu Jan 15 14:34:58 EDT 1998 | ||
14 | >> must include "stdlib.h" (for "exit()"). | ||
15 | |||
16 | ** lbuiltin.c / lobject.h | ||
17 | Thu Jan 15 14:34:58 EDT 1998 | ||
18 | >> MAX_WORD may be bigger than MAX_INT | ||
19 | (by lhf) | ||
20 | |||
21 | ** llex.c | ||
22 | Mon Jan 19 18:17:18 EDT 1998 | ||
23 | >> wrong line number (+1) in error report when file starts with "#..." | ||
24 | |||
25 | ** lstrlib.c | ||
26 | Tue 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 | ||
32 | Tue 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 | ||
36 | Wed Jan 28 14:48:12 EDT 1998 | ||
37 | >> tables can become full of "empty" slots, and keep growing without limits. | ||
38 | |||
39 | ** lstrlib.c | ||
40 | Mon Mar 9 15:26:09 EST 1998 | ||
41 | >> gsub('a', '(b?)%1*' ...) loops (because the capture is empty). | ||
42 | |||
43 | ** lstrlib.c | ||
44 | Mon 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 | ||
53 | Mon Sep 7 15:57:02 EST 1998 | ||
54 | >> function "luaL_argerror" prints wrong argument number (from a user's point | ||
55 | of view) when functions have upvalues. | ||
56 | |||
57 | ** lstrlib.c | ||
58 | Tue 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 | ||
63 | Fri Dec 18 11:22:55 EDT 1998 | ||
64 | >> "tonumber" goes crazy with negative numbers in other bases (not 10), | ||
65 | because "strtol" returns long, not unsigned long. | ||
66 | (by Visual C++) | ||
67 | |||
68 | ** lstrlib.c | ||
69 | Mon Jan 4 10:41:40 EDT 1999 | ||
70 | >> "format" does not check size of format item (such as "%00000...00000d"). | ||
71 | |||
72 | ** lapi.c | ||
73 | Wed Feb 3 14:40:21 EDT 1999 | ||
74 | >> getlocal cannot return the local itself, since lua_isstring and | ||
75 | lua_isnumber can modify it. | ||
76 | |||
77 | ** lstrlib.c | ||
78 | Thu 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 | ||
83 | Thu 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 | ||
93 | Fri 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 | ||
98 | Fri May 21 17:15:11 EST 1999 | ||
99 | >> foreach, foreachi, foreachvar points to function in stack when stack | ||
100 | can be reallocated. | ||
101 | (by tomas; since 3.2 beta) | ||
102 | |||
103 | ** lparser.c | ||
104 | Wed Jun 16 10:32:46 EST 1999 | ||
105 | >> cannot assign to unlimited variables, because it causes overflow in | ||
106 | the number of returns of a function. | ||
107 | (since 3.1) | ||
108 | |||
109 | |||
110 | |||
111 | ================================================================= | ||
112 | --- Version 3.2 | ||
113 | |||
114 | ** lmathlib.c | ||
115 | Wed 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 | ||
120 | Thu Sep 2 10:07:20 EST 1999 | ||
121 | >> in the (old) expression << ls->fs->f->consts[checkname(ls)] >>, checkname | ||
122 | could realloc f->consts. | ||
123 | (by Supratik Champati; since 3.2 beta) | ||
124 | |||
125 | ** lobject.c / lbuiltin.c | ||
126 | Wed 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 | ||
131 | Thu 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 | ||
136 | Wed 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 | ||
141 | Thu 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 | ||
146 | Thu 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 | ||
151 | Mon 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 | ||
156 | Mon 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 | |||
165 | Tested with full test suites (as locked in Mon Apr 24 14:23:11 EST 2000) | ||
166 | in 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 | ||
175 | Tue 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 | ||
180 | Fri 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 | ||
186 | Wed 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 | ||
192 | Tue Aug 29 15:56:05 EST 2000 | ||
193 | >> error message for `for' uses `while' | ||
194 | (since 4.0a; already corrected) | ||
195 | |||
196 | ** lgc.c | ||
197 | Tue 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 | ||
207 | Fri 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 | ||
212 | Mon 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 | ||
217 | Mon 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 | ||
222 | Wed 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 | ||
227 | Wed 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 | ||
233 | Thu 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 | ||
244 | Wed 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 | ||
249 | Fri 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 | ||
254 | Thu 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 | ||
259 | Fri 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 | ||
264 | Tue 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 | ||
269 | Tue 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 | ||
274 | Fri 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 | ||
279 | Wed 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 | ||
284 | Wed 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 | ||
296 | Fri 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 | ||
302 | Thu 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 | ||
307 | Fri 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 | ||
317 | Fri 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 | ||
322 | Thu 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) | ||
328 | Fri 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 | ||
333 | Thu 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 | |||
343 | Bug{ | ||
344 | what = [[lua_closethread exists only in the manual]], | ||
345 | report = [[by Nguyen Binh, 28/04/2003]], | ||
346 | patch = [[no patch; the manual is wrong]], | ||
347 | } | ||
348 | |||
349 | |||
350 | Bug{ | ||
351 | what = [[attempt to resume a running coroutine crashes Lua]], | ||
352 | example = [[ | ||
353 | function co_func (current_co) | ||
354 | coroutine.resume(co) | ||
355 | end | ||
356 | co = coroutine.create(co_func) | ||
357 | coroutine.resume(co) | ||
358 | coroutine.resume(co) --> seg. fault | ||
359 | ]], | ||
360 | report = [[by Alex Bilyk, 09/05/2003]], | ||
361 | patch = [[ | ||
362 | * ldo.c: | ||
363 | 325,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); | ||
368 | 329c328,329 | ||
369 | < else if (ci->state & CI_YIELD) { /* inside a yield? */ | ||
370 | --- | ||
371 | > else { /* inside a yield */ | ||
372 | > lua_assert(ci->state & CI_YIELD); | ||
373 | 344,345d343 | ||
374 | < else | ||
375 | < luaG_runerror(L, "cannot resume non-suspended coroutine"); | ||
376 | 351a350,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 | > | ||
386 | 355a363,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 | |||
397 | Bug{ | ||
398 | what = [[file:close cannot be called without a file. (results in seg fault)]], | ||
399 | example = [[ | ||
400 | > io.stdin.close() -- correct call shold be io.stdin:close() | ||
401 | ]], | ||
402 | report = [[by Tuomo Valkonen, 27/05/2003]], | ||
403 | patch = [[ | ||
404 | * liolib.c: | ||
405 | 161c161 | ||
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 | |||
413 | Bug{ | ||
414 | what = [[C functions also may have stacks larger than current top]], | ||
415 | example = [[ | ||
416 | Must recompile lua with a change in lua.c and with lua_assert defined: | ||
417 | * lua.c: | ||
418 | 381a382 | ||
419 | > lua_checkstack(l, 1000); | ||
420 | ]], | ||
421 | report = [[Alex Bilyk, 09/06/2003]], | ||
422 | patch = [[ | ||
423 | * lgc.c: | ||
424 | 247c247 | ||
425 | < if (!(ci->state & CI_C) && lim < ci->top) | ||
426 | --- | ||
427 | > if (lim < ci->top) | ||
428 | ]], | ||
429 | } | ||
430 | |||
431 | |||
432 | Bug{ | ||
433 | what = [[`pc' address is invalidated when a coroutine is suspended]], | ||
434 | example = [[ | ||
435 | function g(x) | ||
436 | coroutine.yield(x) | ||
437 | end | ||
438 | |||
439 | function f (i) | ||
440 | debug.sethook(print, "l") | ||
441 | for j=1,1000 do | ||
442 | g(i+j) | ||
443 | end | ||
444 | end | ||
445 | |||
446 | co = coroutine.wrap(f) | ||
447 | co(10) | ||
448 | pcall(co) | ||
449 | pcall(co) | ||
450 | ]], | ||
451 | report = [[Nick Trout, 07/07/2003]], | ||
452 | patch = [[ | ||
453 | * lvm.c: | ||
454 | 402,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; | ||
460 | 404a405 | ||
461 | > } | ||
462 | 405a407 | ||
463 | > L->ci->u.l.pc = &pc; | ||
464 | 676,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 | |||
474 | Bug{ | ||
475 | what = [[userdata to be collected still counts into new GC threshold, | ||
476 | increasing memory consumption]], | ||
477 | report = [[Roberto, 25/07/2003]], | ||
478 | example = [[ | ||
479 | a = newproxy(true) | ||
480 | getmetatable(a).__gc = function () end | ||
481 | for i=1,10000000 do | ||
482 | newproxy(a) | ||
483 | if math.mod(i, 10000) == 0 then print(gcinfo()) end | ||
484 | end | ||
485 | ]], | ||
486 | patch = [[ | ||
487 | * lgc.h: | ||
488 | 18c18 | ||
489 | < void luaC_separateudata (lua_State *L); | ||
490 | --- | ||
491 | > size_t luaC_separateudata (lua_State *L); | ||
492 | |||
493 | * lgc.c: | ||
494 | 113c113,114 | ||
495 | < void luaC_separateudata (lua_State *L) { | ||
496 | --- | ||
497 | > size_t luaC_separateudata (lua_State *L) { | ||
498 | > size_t deadmem = 0; | ||
499 | 127a129 | ||
500 | > deadmem += sizeudata(gcotou(curr)->uv.len); | ||
501 | 136a139 | ||
502 | > return deadmem; | ||
503 | 390c393 | ||
504 | < static void checkSizes (lua_State *L) { | ||
505 | --- | ||
506 | > static void checkSizes (lua_State *L, size_t deadmem) { | ||
507 | 400c403 | ||
508 | < G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ | ||
509 | --- | ||
510 | > G(L)->GCthreshold = 2*G(L)->nblocks - deadmem; /* new threshold */ | ||
511 | 454c457,458 | ||
512 | < static void mark (lua_State *L) { | ||
513 | --- | ||
514 | > static size_t mark (lua_State *L) { | ||
515 | > size_t deadmem; | ||
516 | 467c471 | ||
517 | < luaC_separateudata(L); /* separate userdata to be preserved */ | ||
518 | --- | ||
519 | > deadmem = luaC_separateudata(L); /* separate userdata to be preserved */ | ||
520 | 475a480 | ||
521 | > return deadmem; | ||
522 | 480c485 | ||
523 | < mark(L); | ||
524 | --- | ||
525 | > size_t deadmem = mark(L); | ||
526 | 482c487 | ||
527 | < checkSizes(L); | ||
528 | --- | ||
529 | > checkSizes(L, deadmem); | ||
530 | ]] | ||
531 | } | ||
532 | |||
533 | Bug{ | ||
534 | what=[[IBM AS400 (OS400) has sizeof(void *)==16, and a `%p' may generate | ||
535 | up to 60 characters in a `printf'. That causes a buffer overflow in | ||
536 | `tostring'.]], | ||
537 | |||
538 | report = [[David Burgess, 25/08/2003]], | ||
539 | |||
540 | example = [[print{}; (in an AS400 machine)]], | ||
541 | |||
542 | patch = [[ | ||
543 | * liolib.c: | ||
544 | 178c178 | ||
545 | < char buff[32]; | ||
546 | --- | ||
547 | > char buff[128]; | ||
548 | |||
549 | * lbaselib.c: | ||
550 | 327c327 | ||
551 | < char buff[64]; | ||
552 | --- | ||
553 | > char buff[128]; | ||
554 | ]] | ||
555 | } | ||
556 | |||
557 | |||
558 | Bug{ | ||
559 | what = [[syntax `local function' does not increment stack size]], | ||
560 | |||
561 | report = [[Rici Lake, 26/09/2003]], | ||
562 | |||
563 | example = [[ | ||
564 | -- must run this with precompiled code | ||
565 | local a,b,c | ||
566 | local function d () end | ||
567 | ]], | ||
568 | |||
569 | patch = [[ | ||
570 | * lparser.c: | ||
571 | 1143a1144 | ||
572 | > FuncState *fs = ls->fs; | ||
573 | 1145c1146,1147 | ||
574 | < init_exp(&v, VLOCAL, ls->fs->freereg++); | ||
575 | --- | ||
576 | > init_exp(&v, VLOCAL, fs->freereg); | ||
577 | > luaK_reserveregs(fs, 1); | ||
578 | 1148c1150,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 | |||
589 | Bug{ | ||
590 | |||
591 | what = [[count hook may be called without being set]], | ||
592 | |||
593 | report = [[Andreas Stenius, 06/10/2003]], | ||
594 | |||
595 | example = [[ | ||
596 | set 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, | ||
601 | but it is not wrong.) | ||
602 | ]], | ||
603 | |||
604 | patch = [[ | ||
605 | * lvm.c: | ||
606 | 69c69 | ||
607 | < if (mask > LUA_MASKLINE) { /* instruction-hook set? */ | ||
608 | --- | ||
609 | > if (mask & LUA_MASKCOUNT) { /* instruction-hook set? */ | ||
610 | ]], | ||
611 | |||
612 | } | ||
613 | |||
614 | |||
615 | Bug{ | ||
616 | |||
617 | what = [[`dofile' eats one return value when called without arguments]], | ||
618 | |||
619 | report = [[Frederico Abraham, 15/01/2004]], | ||
620 | |||
621 | example = [[ | ||
622 | a,b = dofile() --< here you enter `return 1,2,3 <eof>' | ||
623 | print(a,b) --> 2 3 (should be 1 and 2) | ||
624 | ]], | ||
625 | |||
626 | patch = [[ | ||
627 | * lbaselib.c: | ||
628 | 313a314 | ||
629 | > int n = lua_gettop(L); | ||
630 | 317c318 | ||
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 | |||
643 | Bug{ | ||
644 | what = [[string concatenation may cause arithmetic overflow, leading | ||
645 | to a buffer overflow]], | ||
646 | |||
647 | report = [[Rici Lake, 20/05/2004]], | ||
648 | |||
649 | example = [[ | ||
650 | longs = string.rep("\0", 2^25) | ||
651 | function catter(i) | ||
652 | return assert(loadstring( | ||
653 | string.format("return function(a) return a%s end", | ||
654 | string.rep("..a", i-1))))() | ||
655 | end | ||
656 | rep129 = catter(129) | ||
657 | rep129(longs) | ||
658 | ]], | ||
659 | |||
660 | patch = [[ | ||
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 | |||
688 | Bug{ | ||
689 | what = [[lua_getupvalue and setupvalue do not check for index too small]], | ||
690 | |||
691 | report = [[Mike Pall, ?/2004]], | ||
692 | |||
693 | example = [[debug.getupvalue(function() end, 0)]], | ||
694 | |||
695 | patch = [[ | ||
696 | * lapi.c | ||
697 | 941c941 | ||
698 | < if (n > f->c.nupvalues) return NULL; | ||
699 | --- | ||
700 | > if (!(1 <= n && n <= f->c.nupvalues)) return NULL; | ||
701 | 947c947 | ||
702 | < if (n > p->sizeupvalues) return NULL; | ||
703 | --- | ||
704 | > if (!(1 <= n && n <= p->sizeupvalues)) return NULL; | ||
705 | ]] | ||
706 | } | ||
707 | |||
708 | |||
709 | Bug{ | ||
710 | what = [[values holded in open upvalues of suspended threads may be | ||
711 | incorrectly collected]], | ||
712 | |||
713 | report = [[Spencer Schumann, 31/12/2004]], | ||
714 | |||
715 | example = [[ | ||
716 | local thread_id = 0 | ||
717 | local threads = {} | ||
718 | |||
719 | function fn(thread) | ||
720 | thread_id = thread_id + 1 | ||
721 | threads[thread_id] = function() | ||
722 | thread = nil | ||
723 | end | ||
724 | coroutine.yield() | ||
725 | end | ||
726 | |||
727 | while true do | ||
728 | local thread = coroutine.create(fn) | ||
729 | coroutine.resume(thread, thread) | ||
730 | end | ||
731 | ]], | ||
732 | |||
733 | patch = [[ | ||
734 | * lgc.c: | ||
735 | 221,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 | |||
747 | Bug{ | ||
748 | what = [[rawset/rawget do not ignore extra arguments]], | ||
749 | |||
750 | report = [[Romulo Bahiense, 11/03/2005]], | ||
751 | |||
752 | example = [[ | ||
753 | a = {} | ||
754 | rawset(a, 1, 2, 3) | ||
755 | print(a[1], a[2]) -- should be 2 and nil | ||
756 | ]], | ||
757 | |||
758 | patch = [[ | ||
759 | * lbaselib.c: | ||
760 | 175a176 | ||
761 | > lua_settop(L, 2); | ||
762 | 183a185 | ||
763 | > lua_settop(L, 3); | ||
764 | ]], | ||
765 | } | ||
766 | |||
767 | |||
768 | Bug{ | ||
769 | what = [[weak tables that survive one collection are never collected]], | ||
770 | |||
771 | report = [[Chromix, 02/01/2006]], | ||
772 | |||
773 | example = [[ | ||
774 | a = {} | ||
775 | print(gcinfo()) | ||
776 | for i = 1, 10000 do | ||
777 | a[i] = setmetatable({}, {__mode = "v"}) | ||
778 | end | ||
779 | collectgarbage() | ||
780 | a = nil | ||
781 | collectgarbage() | ||
782 | print(gcinfo()) | ||
783 | ]], | ||
784 | |||
785 | patch = [[ | ||
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 | |||
801 | Bug{ | ||
802 | what = [[Some "not not exp" may not result in boolean values]], | ||
803 | report = [[]], | ||
804 | since = [[4.0]], | ||
805 | example = [[ | ||
806 | -- should print false, but prints nil | ||
807 | print(not not (nil and 4)) | ||
808 | ]], | ||
809 | patch = [[]], | ||
810 | } | ||
811 | |||
812 | |||
813 | Bug{ | ||
814 | what = [[On some machines, closing a "piped file" (created with io.popen) | ||
815 | may crash Lua]], | ||
816 | report = [[]], | ||
817 | since = [[5.0]], | ||
818 | example = [[ | ||
819 | -- only on some machines | ||
820 | f = io.popen("ls") | ||
821 | f:close() | ||
822 | ]], | ||
823 | patch = [[]], | ||
824 | } | ||
825 | |||
826 | |||
827 | |||
828 | ----------------------------------------------------------------- | ||
829 | -- Lua 5.1 | ||
830 | |||
831 | Bug{ | ||
832 | what = [[In 16-bit machines, expressions and/or with numeric constants as the | ||
833 | right operand may result in weird values]], | ||
834 | |||
835 | report = [[Andreas Stenius/Kein-Hong Man, 15/03/2006]], | ||
836 | |||
837 | example = [[ | ||
838 | print(false or 0) -- on 16-bit machines | ||
839 | ]], | ||
840 | |||
841 | patch = [[ | ||
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 | |||
869 | Bug{ | ||
870 | what = [[luaL_checkudata may produce wrong error message]], | ||
871 | |||
872 | report = [[Greg Falcon, 21/03/2006]], | ||
873 | |||
874 | example = [[ | ||
875 | getmetatable(io.stdin).__gc() | ||
876 | --> bad argument #1 to '__gc' (FILE* expected, got table) | ||
877 | ]], | ||
878 | |||
879 | patch = [[ | ||
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 | |||
907 | Bug{ | ||
908 | what = [[ | ||
909 | In Windows, | ||
910 | when Lua is used in an application that also uses DirectX, | ||
911 | it may present an erractic behavior. | ||
912 | THIS IS NOT A LUA BUG! | ||
913 | The problem is that DirectX violates an ABI that Lua depends on.]], | ||
914 | |||
915 | patch = [[ | ||
916 | The simplest solution is to use DirectX with | ||
917 | the D3DCREATE_FPU_PRESERVE flag. | ||
918 | |||
919 | Otherwise, you can change the definition of lua_number2int, | ||
920 | in luaconf.h, to this one: | ||
921 | #define lua_number2int(i,d) __asm fld d __asm fistp i | ||
922 | ]], | ||
923 | |||
924 | } | ||
925 | |||
926 | |||
927 | Bug{ | ||
928 | what = [[option '%q' in string.format does not handle '\r' correctly.]], | ||
929 | |||
930 | example = [[ | ||
931 | local s = "a string with \r and \n and \r\n and \n\r" | ||
932 | local c = string.format("return %q", s) | ||
933 | assert(assert(loadstring(c))() == s) | ||
934 | ]], | ||
935 | |||
936 | patch = [[ | ||
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 | |||
954 | Bug{ | ||
955 | what = [[lua_dostring/lua_dofile should return any values returned | ||
956 | by the chunk]], | ||
957 | |||
958 | patch = [[ | ||
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 | |||
977 | Bug{ | ||
978 | |||
979 | what = [[garbage collector does not compensate enough for finalizers]], | ||
980 | |||
981 | patch = [[ | ||
982 | lgc.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 | |||
1005 | Bug{ | ||
1006 | |||
1007 | what = [[debug hooks may get wrong when mixed with coroutines]], | ||
1008 | |||
1009 | report = [[by Ivko Stanilov, 03/06/2006]], | ||
1010 | |||
1011 | example = [[ | ||
1012 | co = coroutine.create(function (a,b) | ||
1013 | coroutine.yield(a, b) | ||
1014 | return b, "end" | ||
1015 | end) | ||
1016 | |||
1017 | debug.sethook(co, function() end, "lcr") | ||
1018 | coroutine.resume(co, 100, 2000) | ||
1019 | coroutine.resume(co, 100, 2000) | ||
1020 | ]], | ||
1021 | |||
1022 | patch = [[ | ||
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 | |||
1048 | Bug{ | ||
1049 | what = [[list constructors have wrong limit]], | ||
1050 | |||
1051 | report = [[by Norman Ramsey, June 2006]], | ||
1052 | |||
1053 | since = "5.1", | ||
1054 | |||
1055 | example = [[ | ||
1056 | a = {} | ||
1057 | a[1] = "x={1" | ||
1058 | for i = 2, 2^20 do | ||
1059 | a[i] = 1 | ||
1060 | end | ||
1061 | a[#a + 1] = "}" | ||
1062 | s = table.concat(a, ",") | ||
1063 | assert(loadstring(s))() | ||
1064 | print(#x) | ||
1065 | ]], | ||
1066 | |||
1067 | patch = [[ | ||
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 | |||
1083 | Bug{ | ||
1084 | what = [[wrong message error in some cases involving closures]], | ||
1085 | |||
1086 | report = [[Shmuel Zeigerman, on 07/2006]], | ||
1087 | |||
1088 | since = "5.1", | ||
1089 | |||
1090 | example = [[ | ||
1091 | local Var | ||
1092 | local function main() | ||
1093 | NoSuchName (function() Var=0 end) | ||
1094 | end | ||
1095 | main() | ||
1096 | --> lua5.1: temp:3: attempt to call upvalue 'Var' (a nil value) | ||
1097 | ]], | ||
1098 | |||
1099 | patch = [[ | ||
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 | |||
1126 | Bug{ | ||
1127 | what = [[string.format("%") may read past the string]], | ||
1128 | report = [[Roberto, on 09/2006]], | ||
1129 | since = [[5.0]], | ||
1130 | example = [[print(string.format("%"))]], | ||
1131 | patch = [[ | ||
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 | |||
1145 | Bug{ | ||
1146 | what = [[os.date throws an error when result is the empty string]], | ||
1147 | report = [[]], | ||
1148 | since = [[4.0]], | ||
1149 | example = [[print(os.date(""))]], | ||
1150 | patch = [[ | ||
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 | |||
1180 | Bug{ | ||
1181 | what = [[setfenv accepts invalid 1st argument]], | ||
1182 | report = [[Doug Rogers, on 02/2007]], | ||
1183 | since = [[5.0]], | ||
1184 | example = [[setfenv(nil, {}) -- should throw an error]], | ||
1185 | patch = [[ | ||
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 | |||
1211 | Bug{ | ||
1212 | what = [[wrong code for arithmetic expressions in some specific scenarios]], | ||
1213 | report = [[Thierry Grellier, on 01/2007]], | ||
1214 | since = [[5.1]], | ||
1215 | example = [[ | ||
1216 | -- use a large number of names (almost 256) | ||
1217 | v1=1; v2=1; v3=1; v4=1; v5=1; v6=1; v7=1; v8=1; v9=1; | ||
1218 | v10=1; v11=1; v12=1; v13=1; v14=1; v15=1; v16=1; v17=1; | ||
1219 | v18=1; v19=1; v20=1; v21=1; v22=1; v23=1; v24=1; v25=1; | ||
1220 | v26=1; v27=1; v28=1; v29=1; v30=1; v31=1; v32=1; v33=1; | ||
1221 | v34=1; v35=1; v36=1; v37=1; v38=1; v39=1; v40=1; v41=1; | ||
1222 | v42=1; v43=1; v44=1; v45=1; v46=1; v47=1; v48=1; v49=1; | ||
1223 | v50=1; v51=1; v52=1; v53=1; v54=1; v55=1; v56=1; v57=1; | ||
1224 | v58=1; v59=1; v60=1; v61=1; v62=1; v63=1; v64=1; v65=1; | ||
1225 | v66=1; v67=1; v68=1; v69=1; v70=1; v71=1; v72=1; v73=1; | ||
1226 | v74=1; v75=1; v76=1; v77=1; v78=1; v79=1; v80=1; v81=1; | ||
1227 | v82=1; v83=1; v84=1; v85=1; v86=1; v87=1; v88=1; v89=1; | ||
1228 | v90=1; v91=1; v92=1; v93=1; v94=1; v95=1; v96=1; v97=1; | ||
1229 | v98=1; v99=1; v100=1; v101=1; v102=1; v103=1; v104=1; v105=1; | ||
1230 | v106=1; v107=1; v108=1; v109=1; v110=1; v111=1; v112=1; v113=1; | ||
1231 | v114=1; v115=1; v116=1; v117=1; v118=1; v119=1; v120=1; v121=1; | ||
1232 | v122=1; v123=1; v124=1; v125=1; v126=1; v127=1; v128=1; v129=1; | ||
1233 | v130=1; v131=1; v132=1; v133=1; v134=1; v135=1; v136=1; v137=1; | ||
1234 | v138=1; v139=1; v140=1; v141=1; v142=1; v143=1; v144=1; v145=1; | ||
1235 | v146=1; v147=1; v148=1; v149=1; v150=1; v151=1; v152=1; v153=1; | ||
1236 | v154=1; v155=1; v156=1; v157=1; v158=1; v159=1; v160=1; v161=1; | ||
1237 | v162=1; v163=1; v164=1; v165=1; v166=1; v167=1; v168=1; v169=1; | ||
1238 | v170=1; v171=1; v172=1; v173=1; v174=1; v175=1; v176=1; v177=1; | ||
1239 | v178=1; v179=1; v180=1; v181=1; v182=1; v183=1; v184=1; v185=1; | ||
1240 | v186=1; v187=1; v188=1; v189=1; v190=1; v191=1; v192=1; v193=1; | ||
1241 | v194=1; v195=1; v196=1; v197=1; v198=1; v199=1; v200=1; v201=1; | ||
1242 | v202=1; v203=1; v204=1; v205=1; v206=1; v207=1; v208=1; v209=1; | ||
1243 | v210=1; v211=1; v212=1; v213=1; v214=1; v215=1; v216=1; v217=1; | ||
1244 | v218=1; v219=1; v220=1; v221=1; v222=1; v223=1; v224=1; v225=1; | ||
1245 | v226=1; v227=1; v228=1; v229=1; v230=1; v231=1; v232=1; v233=1; | ||
1246 | v234=1; v235=1; v236=1; v237=1; v238=1; v239=1; v240=1; v241=1; | ||
1247 | v242=1; v243=1; v244=1; v245=1; v246=1; v247=1; v248=1; v249=1; | ||
1248 | v250=1; | ||
1249 | v251={k1 = 1}; | ||
1250 | v252=1; | ||
1251 | print(2 * v251.k1, v251.k1 * 2); -- 2 2, OK | ||
1252 | v253=1; | ||
1253 | print(2 * v251.k1, v251.k1 * 2); -- 1 2, ??? | ||
1254 | ]], | ||
1255 | patch = [[ | ||
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 | |||
1296 | Bug{ | ||
1297 | what = [[assignment of nil to parameter may be optimized away]], | ||
1298 | report = [[Thomas Lauer, on 03/2007]], | ||
1299 | since = [[5.1]], | ||
1300 | example = [[ | ||
1301 | function f (a) | ||
1302 | a=nil | ||
1303 | return a | ||
1304 | end | ||
1305 | |||
1306 | print(f("test")) | ||
1307 | ]], | ||
1308 | patch = [[ | ||
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 | |||
1345 | Bug{ | ||
1346 | what = [[__concat metamethod converts numbers to strings]], | ||
1347 | report = [[Paul Winwood, on 12/2006]], | ||
1348 | since = [[5.0]], | ||
1349 | example = [[ | ||
1350 | a = {} | ||
1351 | setmetatable(a, {__concat = function (a,b) print(type(a), type(b)) end}) | ||
1352 | a = 4 .. a | ||
1353 | ]], | ||
1354 | patch = [[ | ||
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 | |||
1375 | Bug{ | ||
1376 | what = [[As a library, loadlib.c should not access Lua internals | ||
1377 | (via lobject.h)]], | ||
1378 | report = [[Jérôme Vuarand, on 03/2007]], | ||
1379 | since = [[5.0]], | ||
1380 | example = [[the bug has no effect on external behavior]], | ||
1381 | patch = [[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 | |||
1390 | Bug{ | ||
1391 | what = [[Lua may close standard files, | ||
1392 | which then may be used by C]], | ||
1393 | report = [[David Manura/Ross Berteig, on 04/2007]], | ||
1394 | since = [[]], | ||
1395 | example = [[ | ||
1396 | io.close(io.stderr) | ||
1397 | -- in some systems, following attempts to write to 'stderr' may crash | ||
1398 | a = a + 1 | ||
1399 | ]], | ||
1400 | patch = [[ | ||
1401 | ]], | ||
1402 | } | ||
1403 | |||
1404 | Bug{ | ||
1405 | what = [[code generated for "-nil", "-true", and "-false" is wrong]], | ||
1406 | report = [[David Manura/Rici Lake, on 04/2007]], | ||
1407 | since = [[5.1]], | ||
1408 | example = [[print(-nil)]], | ||
1409 | patch = [[ | ||
1410 | lcode.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 | |||
1423 | Bug{ | ||
1424 | what = [[Count hook may be called without being set.]], | ||
1425 | report = [[Mike Pall, on 05/2007]], | ||
1426 | since = [[?]], | ||
1427 | example = [[]], | ||
1428 | patch = [[ | ||
1429 | lvm.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 | |||
1448 | Bug{ | ||
1449 | what = [[recursive coroutines may overflow C stack]], | ||
1450 | report = [[ , on ]], | ||
1451 | since = [[5.0]], | ||
1452 | example = [[ | ||
1453 | a = function(a) coroutine.wrap(a)(a) end | ||
1454 | a(a) | ||
1455 | ]], | ||
1456 | patch = [[The 'nCcalls' counter should be shared by all threads. | ||
1457 | (That is, it should be declared in the 'global_State' structure, | ||
1458 | not in 'lua_State'.) | ||
1459 | ]], | ||
1460 | } | ||
1461 | |||
1462 | Bug{ | ||
1463 | what = [[wrong error message in some concatenations]], | ||
1464 | report = [[Alex Davies, on 05/2007]], | ||
1465 | since = [[5.1.2]], | ||
1466 | example = [[a = nil; a = (1)..a]], | ||
1467 | patch = [[ | ||
1468 | ldebug.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 | |||
1483 | Bug{ | ||
1484 | what = [[Very small numbers all collide in the hash function. | ||
1485 | (This creates only performance problems; the behavoir is correct.)]], | ||
1486 | report = [[, on ]], | ||
1487 | since = [[5.0]], | ||
1488 | example = [[]], | ||
1489 | patch = [[ | ||
1490 | ltable.c: | ||
1491 | 87,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 | |||
1500 | Bug{ | ||
1501 | what = [[Too many variables in an assignment may cause a | ||
1502 | C stack overflow]], | ||
1503 | report = [[Mike Pall, on 07/2007]], | ||
1504 | since = [[5.0]], | ||
1505 | example = [[ | ||
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 | ]], | ||
1509 | patch = [[ | ||
1510 | lparser.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 | |||
1523 | Bug{ | ||
1524 | what = [[An error in a module loaded through the '-l' option | ||
1525 | shows no traceback]], | ||
1526 | report = [[David Manura, on 08/2007]], | ||
1527 | since = [[5.1]], | ||
1528 | example = [[lua -ltemp (assuming temp.lua has an error)]], | ||
1529 | patch = [[ | ||
1530 | lua.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 | |||
1541 | Bug{ | ||
1542 | what = [['gsub' may go wild when wrongly called without its third | ||
1543 | argument and with a large subject]], | ||
1544 | report = [[Florian Berger, on 10/2007]], | ||
1545 | since = [[5.1]], | ||
1546 | example = [[ | ||
1547 | x = string.rep('a', 10000) .. string.rep('b', 10000) | ||
1548 | print(#string.gsub(x, 'b')) | ||
1549 | ]], | ||
1550 | patch = [[ | ||
1551 | lstrlib.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 | |||
1572 | Bug{ | ||
1573 | what = [[table.remove removes last element of a table when given | ||
1574 | an out-of-bound index]], | ||
1575 | report = [[Patrick Donnelly, on 11/2007]], | ||
1576 | since = [[5.0]], | ||
1577 | example = [[ | ||
1578 | a = {1,2,3} | ||
1579 | table.remove(a, 4) | ||
1580 | print(a[3]) --> nil (should be 3) | ||
1581 | ]], | ||
1582 | patch = [[ | ||
1583 | ltablib.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 | |||
1597 | Bug{ | ||
1598 | what = [[lua_setfenv may crash if called over an invalid object]], | ||
1599 | report = [[Mike Pall, on 11/2007]], | ||
1600 | since = [[5.1]], | ||
1601 | example = [[ | ||
1602 | > debug.setfenv(3, {}) | ||
1603 | ]], | ||
1604 | patch = [[ | ||
1605 | lapi.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 | |||
1618 | Bug{ | ||
1619 | what = [[stand-alone interpreter shows incorrect error message | ||
1620 | when the "message" is a coroutine]], | ||
1621 | report = [[Patrick Donnelly, on 17/12/2007]], | ||
1622 | since = [[5.1]], | ||
1623 | example = [[> error(coroutine.create(function() end))]], | ||
1624 | patch = [[ | ||
1625 | lua.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 | |||
1639 | Bug{ | ||
1640 | what = [[debug.sethook/gethook may overflow the thread's stack]], | ||
1641 | report = [[Ivko Stanilov, on 2008/01/04]], | ||
1642 | since = [[5.1]], | ||
1643 | example = [[ | ||
1644 | a = coroutine.create(function() yield() end) | ||
1645 | coroutine.resume(a) | ||
1646 | debug.sethook(a) -- may overflow the stack of 'a' | ||
1647 | ]], | ||
1648 | patch = [[ | ||
1649 | ldblib.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 | |||
1691 | Bug{ | ||
1692 | what = [[LUAI_MAXCSTACK must be smaller than -LUA_REGISTRYINDEX]], | ||
1693 | report = [[Patrick Donnelly, on 2008/02/11]], | ||
1694 | since = [[5.1.3]], | ||
1695 | example = [[ | ||
1696 | j = 1e4 | ||
1697 | co = coroutine.create(function() | ||
1698 | t = {} | ||
1699 | for i = 1, j do t[i] = i end | ||
1700 | return unpack(t) | ||
1701 | end) | ||
1702 | print(coroutine.resume(co)) | ||
1703 | ]], | ||
1704 | patch = [[ | ||
1705 | luaconf.h: | ||
1706 | 443c443,444 | ||
1707 | < ** functions to consume unlimited stack space. | ||
1708 | --- | ||
1709 | > ** functions to consume unlimited stack space. (must be smaller than | ||
1710 | > ** -LUA_REGISTRYINDEX) | ||
1711 | 445,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 | |||
1719 | Bug{ | ||
1720 | what = [[coroutine.resume pushes element without ensuring stack size]], | ||
1721 | report = [[on 2008/02/11]], | ||
1722 | since = [[5.0]], | ||
1723 | example = [[(this bug cannot be detected without internal assertions)]], | ||
1724 | patch = [[ | ||
1725 | lbaselib.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 | |||
1738 | Bug{ | ||
1739 | what = [[lua_checkstack may have arithmetic overflow for large 'size']], | ||
1740 | report = [[Patrick Donnelly, on 2008/02/12]], | ||
1741 | since = [[5.0]], | ||
1742 | example = [[ | ||
1743 | print(unpack({1,2,3}, 0, 2^31-3)) | ||
1744 | ]], | ||
1745 | patch = [[ | ||
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 | |||
1770 | Bug{ | ||
1771 | what = [[unpack with maximum indices may crash due to arithmetic overflow]], | ||
1772 | report = [[Patrick Donnelly, on 2008/02/12]], | ||
1773 | since = [[5.1]], | ||
1774 | example = [[ | ||
1775 | print(unpack({1,2,3}, 2^31-1, 2^31-1)) | ||
1776 | ]], | ||
1777 | patch = [[ | ||
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 | |||
1799 | Bug{ | ||
1800 | what = [[The validator for precompiled code has several flaws that | ||
1801 | allow malicious binary code to crash the application]], | ||
1802 | report = [[Peter Cawley, on 2008/03/24]], | ||
1803 | since = [[5.0]], | ||
1804 | example = [[ | ||
1805 | a = string.dump(function()return;end) | ||
1806 | a = a:gsub(string.char(30,37,122,128), string.char(34,0,0), 1) | ||
1807 | loadstring(a)() | ||
1808 | ]], | ||
1809 | patch = [[ | ||
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 | |||
1856 | Bug{ | ||
1857 | what = [[maliciously crafted precompiled code can blow the C stack]], | ||
1858 | report = [[Greg Falcon, on 2008/03/25]], | ||
1859 | since = [[5.0]], | ||
1860 | example = [[ | ||
1861 | function 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) | ||
1875 | end | ||
1876 | for i=1,25 do print(i); crash(i) end | ||
1877 | ]], | ||
1878 | patch = [[ | ||
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 | |||
1902 | Bug{ | ||
1903 | what = [[code validator may reject (maliciously crafted) correct code]], | ||
1904 | report = [[Greg Falcon, on 2008/03/26]], | ||
1905 | since = [[5.0]], | ||
1906 | example = [[ | ||
1907 | z={} | ||
1908 | for i=1,27290 do z[i]='1,' end | ||
1909 | z = 'if 1+1==2 then local a={' .. table.concat(z) .. '} end' | ||
1910 | func = loadstring(z) | ||
1911 | print(loadstring(string.dump(func))) | ||
1912 | ]], | ||
1913 | patch = [[ | ||
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 | |||
1941 | Bug{ | ||
1942 | what = [[maliciously crafted precompiled code can inject invalid boolean | ||
1943 | values into Lua code]], | ||
1944 | report = [[Greg Falcon, on 2008/03/27]], | ||
1945 | since = [[5.0]], | ||
1946 | example = [[ | ||
1947 | maybe = string.dump(function() return ({[true]=true})[true] end) | ||
1948 | maybe = maybe:gsub('\1\1','\1\2') | ||
1949 | maybe = loadstring(maybe)() | ||
1950 | assert(type(maybe) == "boolean" and maybe ~= true and maybe ~= false) | ||
1951 | ]], | ||
1952 | patch = [[ | ||
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 | |||
1968 | Bug{ | ||
1969 | what = [['string.byte' gets confused with some out-of-range negative indices]], | ||
1970 | report = [[Mike Pall, on 2008/06/03]], | ||
1971 | since = [[5.1]], | ||
1972 | example = [[ | ||
1973 | print(string.byte("abc", -5)) --> 97 98 99 (should print nothing) | ||
1974 | ]], | ||
1975 | patch = [[ | ||
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 | |||
1992 | Bug{ | ||
1993 | what = [[user-requested GC step may loop forever]], | ||
1994 | report = [[Makoto Hamanaka, on 2008/07/01]], | ||
1995 | since = [[5.1]], | ||
1996 | example = [[ | ||
1997 | collectgarbage("setpause", 100) -- small value | ||
1998 | collectgarbage("setstepmul", 2000) -- large value | ||
1999 | collectgarbage("step",0) | ||
2000 | ]], | ||
2001 | patch = [[ | ||
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 | |||
2025 | Bug{ | ||
2026 | what = [['module' may change the environment of a C function]], | ||
2027 | report = [[Peter Cawley, on 2008/07/16]], | ||
2028 | since = [[5.1]], | ||
2029 | example = [[ | ||
2030 | pcall(module, "xuxu") | ||
2031 | assert(debug.getfenv(pcall) == xuxu) | ||
2032 | ]], | ||
2033 | patch = [[ | ||
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 | |||
2054 | Bug{ | ||
2055 | what = [[internal macro 'svalue' is wrong]], | ||
2056 | report = [[Martijn van Buul, on 2008/08/04]], | ||
2057 | since = [[5.1]], | ||
2058 | example = [[ | ||
2059 | /* in luaconf.h */ | ||
2060 | #define LUAI_USER_ALIGNMENT_T union { char b[32]; } | ||
2061 | ]], | ||
2062 | patch = [[ | ||
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 | |||
2077 | Bug{ | ||
2078 | what = [[malicious zero-length string in binary code may segfault Lua]], | ||
2079 | report = [[Peter Cawley, on 2008/09/01]], | ||
2080 | since = [[5.1]], | ||
2081 | example = [[ | ||
2082 | loadstring(('').dump(function()X''end):gsub('\2%z%z%zX','\0\0\0'))() | ||
2083 | ]], | ||
2084 | patch = [[ | ||
2085 | ]], | ||
2086 | } | ||
2087 | |||
2088 | |||
2089 | Bug{ | ||
2090 | what = [[wrong code generation for some particular boolean expressions]], | ||
2091 | report = [[Brian Kelley, on 2009/04/15]], | ||
2092 | since = [[5.0]], | ||
2093 | example = [[ | ||
2094 | print(((1 or false) and true) or false) --> 1 | ||
2095 | -- should be 'true' | ||
2096 | ]], | ||
2097 | patch = [[ | ||
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 | |||
2148 | Bug{ | ||
2149 | what = [['luaV_settable' may invalidate a reference to a table and try | ||
2150 | to reuse it]], | ||
2151 | report = [[Mark Feldman, on 2009/06/27]], | ||
2152 | since = [[5.0]], | ||
2153 | example = [[ | ||
2154 | grandparent = {} | ||
2155 | grandparent.__newindex = function(s,_,_) print(s) end | ||
2156 | |||
2157 | parent = {} | ||
2158 | parent.__newindex = parent | ||
2159 | setmetatable(parent, grandparent) | ||
2160 | |||
2161 | child = setmetatable({}, parent) | ||
2162 | child.foo = 10 --> (crash on some machines) | ||
2163 | ]], | ||
2164 | patch = [[ | ||
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 | |||
2189 | Bug{ | ||
2190 | what = [[smart use of varargs may create functions that return too | ||
2191 | many arguments and overflow the stack of C functions]], | ||
2192 | report = [[Patrick Donnelly, on 2008/12/10]], | ||
2193 | since = [[]], | ||
2194 | example = [[ | ||
2195 | local function lunpack(i, ...) | ||
2196 | if i == 0 then return ... | ||
2197 | else | ||
2198 | return lunpack(i-1, 1, ...) | ||
2199 | end | ||
2200 | end | ||
2201 | |||
2202 | Now, if C calls lunpack(n) with a huge n, it may end with | ||
2203 | too many values in its stack and confuse its stack indices. | ||
2204 | ]], | ||
2205 | patch = [[ | ||
2206 | ]], | ||
2207 | } | ||
2208 | |||
2209 | Bug{ | ||
2210 | what = [['debug.getfenv' does not check whether it has an argument]], | ||
2211 | report = [[Patrick Donnelly, 2009/07/30]], | ||
2212 | since = [[5.1]], | ||
2213 | example = [[debug.getfenv() -- should raise an error]], | ||
2214 | patch = [[ | ||
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 | |||
2228 | Bug{ | ||
2229 | what = [[GC may get stuck during a parser and avoids proper resizing of | ||
2230 | the string table, | ||
2231 | making its lists grow too much and degrading performance]], | ||
2232 | report = [[Sean Conner, 2009/11/10]], | ||
2233 | since = [[5.1]], | ||
2234 | example = [[See http://lua-users.org/lists/lua-l/2009-11/msg00463.html]], | ||
2235 | patch = [[ | ||
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 | |||
2253 | Bug{ | ||
2254 | what = [['string.format' may get buffer as an argument when there are | ||
2255 | missing arguments and format string is too long]], | ||
2256 | report = [[Roberto I., 2010/04/12]], | ||
2257 | since = [[5.0]], | ||
2258 | example = [[ | ||
2259 | x = string.rep("x", 10000) .. "%d" | ||
2260 | print(string.format(x)) -- gives wrong error message | ||
2261 | ]], | ||
2262 | patch = [[ | ||
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 | |||
2286 | Bug{ | ||
2287 | what = [['io.read(op, "*n")' may return garbage if second read fails]], | ||
2288 | report = [[Roberto I., 2010/04/12]], | ||
2289 | since = [[5.0]], | ||
2290 | example = [[ | ||
2291 | print(io.read("*n", "*n")) --<< enter "10 hi" | ||
2292 | --> file (0x884420) nil | ||
2293 | ]], | ||
2294 | patch = [[ | ||
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 | |||
2312 | Bug{ | ||
2313 | what = [[wrong code generation for some particular boolean expressions]], | ||
2314 | report = [[Thierry Van Elsuwe, 2011/01/20]], | ||
2315 | since = [[5.0]], | ||
2316 | example = [[ | ||
2317 | print((('hi' or true) and true) or true) | ||
2318 | --> hi (should be true) | ||
2319 | print(((nil and nil) or false) and true) | ||
2320 | --> nil (should be false) | ||
2321 | ]], | ||
2322 | patch = [[ | ||
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 | |||
2356 | Bug{ | ||
2357 | what = [[__newindex metamethod may not work if metatable is its own | ||
2358 | metatable]], | ||
2359 | report = [[Cuero Bugot, 2011/08/09]], | ||
2360 | since = [[5.1]], | ||
2361 | example = [[ | ||
2362 | meta={} | ||
2363 | setmetatable(meta, meta) | ||
2364 | meta.__newindex = function(t, key, value) print("set") end | ||
2365 | o = setmetatable({}, meta) | ||
2366 | o.x = 10 -- should print 'set' | ||
2367 | ]], | ||
2368 | patch = [[ | ||
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 | |||
2382 | Bug{ | ||
2383 | what = [[parser may collect a prototype while building it]], | ||
2384 | report = [[Ingo van Lil, 2011/10/13]], | ||
2385 | since = [[5.1.4 (caused by patch 5.1.4-6)]], | ||
2386 | example = nil, | ||
2387 | patch = [[ | ||
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 | |||
2405 | Bug{ | ||
2406 | what = [[When loading a file, | ||
2407 | Lua may call the reader function again after it returned end of input | ||
2408 | ]], | ||
2409 | report = [[Chris Howie, 2013/06/05]], | ||
2410 | since = [[5.1]], | ||
2411 | fix = [[5.2]], | ||
2412 | example = [[ | ||
2413 | load(function () print("called"); return nil end) | ||
2414 | --> called | ||
2415 | --> called (should be called only once!) | ||
2416 | ]], | ||
2417 | patch = [[ | ||
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 | |||
2459 | Bug{ | ||
2460 | what = [[memory hoarding when creating Lua hooks for coroutines]], | ||
2461 | report = [[Arseny Vakhrushev, 2012/01/16]], | ||
2462 | since = [[5.1]], | ||
2463 | fix = [[5.2.1]], | ||
2464 | example = [[ | ||
2465 | collectgarbage(); print(collectgarbage'count' * 1024) | ||
2466 | |||
2467 | for 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') | ||
2472 | end | ||
2473 | |||
2474 | collectgarbage(); print(collectgarbage'count' * 1024) | ||
2475 | -- value should back to near the original level | ||
2476 | ]], | ||
2477 | patch = [[ | ||
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 | |||
2532 | Bug{ | ||
2533 | what = [[Lexical gets confused with some combination of arithmetic | ||
2534 | operators and hexadecimal numbers]], | ||
2535 | report = [[Alexandra Barros, 2012/01/17]], | ||
2536 | since = [[5.2.0]], | ||
2537 | fix = [[5.2.1]], | ||
2538 | example = [[print(0xE+1)]], | ||
2539 | patch = [[ | ||
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 | |||
2569 | Bug{ | ||
2570 | what = [[Finalizers may call functions from a dynamic library after | ||
2571 | the library has been unloaded]], | ||
2572 | report = [[Josh Haberman, 2012/04/08]], | ||
2573 | since = [[5.1]], | ||
2574 | fix = [[5.2.1]], | ||
2575 | example = [[ | ||
2576 | local u = setmetatable({}, {__gc = function () foo() end}) | ||
2577 | local m = require 'mod' -- 'mod' may be any dynamic library written in C | ||
2578 | foo = m.foo -- 'foo' may be any function from 'mod' | ||
2579 | -- end program; it crashes | ||
2580 | ]], | ||
2581 | patch = [[ | ||
2582 | loadlib.c: | ||
2583 | 95c95 | ||
2584 | < #define LIBPREFIX "LOADLIB: " | ||
2585 | --- | ||
2586 | > #define CLIBS "_CLIBS" | ||
2587 | 251,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' */ | ||
2611 | 270a261,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 | > | ||
2622 | 272,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 | ||
2628 | 276,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 | > } | ||
2639 | 284,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 | > } | ||
2650 | 292c298 | ||
2651 | < lua_CFunction f = ll_sym(L, *reg, sym); | ||
2652 | --- | ||
2653 | > lua_CFunction f = ll_sym(L, reg, sym); | ||
2654 | 675,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 */ | ||
2661 | 678a686 | ||
2662 | > lua_setmetatable(L, -2); | ||
2663 | ]] | ||
2664 | } | ||
2665 | |||
2666 | Bug{ | ||
2667 | what = [[wrong handling of 'nCcalls' in coroutines]], | ||
2668 | report = [[Alexander Gavrilov, 2012/04/18]], | ||
2669 | since = [[5.2.0]], | ||
2670 | fix = [[5.2.1]], | ||
2671 | example = [[ | ||
2672 | coroutine.wrap(function() | ||
2673 | print(pcall(pcall,pcall,pcall,pcall,pcall,error,3)) | ||
2674 | end)() | ||
2675 | ]], | ||
2676 | patch = [[ | ||
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 | |||
2699 | Bug{ | ||
2700 | what = [[Internal Lua values may escape through the debug API]], | ||
2701 | report = [[Dan Tull, 2012/04/20]], | ||
2702 | since = [[5.1]], | ||
2703 | fix = [[5.2.1]], | ||
2704 | example = [[ | ||
2705 | -- for Lua 5.1 | ||
2706 | local firsttime = true | ||
2707 | local 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 | ||
2716 | end | ||
2717 | |||
2718 | print(load(foo)) -- prints some lines and then seg. fault. | ||
2719 | ]], | ||
2720 | patch = [[ | ||
2721 | ]] | ||
2722 | } | ||
2723 | |||
2724 | Bug{ | ||
2725 | what = [[Problems when yielding from debug hooks]], | ||
2726 | report = [[Erik Cassel, 2012/06/05]], | ||
2727 | since = [[5.2.0]], | ||
2728 | fix = [[5.2.1]], | ||
2729 | example = [[ | ||
2730 | Set, in C, a line hook that simply yields, | ||
2731 | and then call any Lua function. | ||
2732 | You get an infinite loop of yields. | ||
2733 | ]], | ||
2734 | patch = [[ | ||
2735 | ]] | ||
2736 | } | ||
2737 | |||
2738 | |||
2739 | ----------------------------------------------------------------- | ||
2740 | -- Lua 5.2.1 | ||
2741 | |||
2742 | Bug{ | ||
2743 | what = [[Some patterns can overflow the C stack, due to recursion]], | ||
2744 | report = [[Tim Starling, 2012/07/08]], | ||
2745 | since = [[2.5]], | ||
2746 | fix = [[5.2.2]], | ||
2747 | example = [[print(string.find(string.rep("a", 2^20), string.rep(".?", 2^20)))]], | ||
2748 | patch = [[ | ||
2749 | ]] | ||
2750 | } | ||
2751 | |||
2752 | |||
2753 | Bug{ | ||
2754 | what = [['pcall' may not restore previous error function when | ||
2755 | inside coroutines]], | ||
2756 | report = [[Alexander Gavrilov, 2012/06/12]], | ||
2757 | since = [[5.2.0]], | ||
2758 | fix = [[5.2.2]], | ||
2759 | example = [[ | ||
2760 | function errfunc(x) | ||
2761 | return 'errfunc' | ||
2762 | end | ||
2763 | |||
2764 | function 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!') | ||
2772 | end | ||
2773 | |||
2774 | coro = coroutine.wrap(function() | ||
2775 | print(xpcall(test, errfunc, false)) | ||
2776 | print(xpcall(test, errfunc, true)) | ||
2777 | print(xpcall(test, errfunc, false)) | ||
2778 | end) | ||
2779 | |||
2780 | coro() | ||
2781 | --> not yielding | ||
2782 | --> false errfunc | ||
2783 | --> yielding | ||
2784 | coro() | ||
2785 | --> false temp:12: fail! <<<< should be 'errfunc' too | ||
2786 | --> not yielding | ||
2787 | --> false errfunc | ||
2788 | ]], | ||
2789 | patch = [[ | ||
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 | |||
2808 | Bug{ | ||
2809 | what = [[Check for garbage collector in function calls does not cover | ||
2810 | all paths]], | ||
2811 | report = [[Roberto, 2012/08/15]], | ||
2812 | since = [[5.2.1]], | ||
2813 | fix = [[5.2.2]], | ||
2814 | example = [[ | ||
2815 | See <a href="http://lua-users.org/lists/lua-l/2012-08/msg00149.html"> | ||
2816 | http://lua-users.org/lists/lua-l/2012-08/msg00149.html</a> | ||
2817 | ]], | ||
2818 | patch = [[ | ||
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 | |||
2844 | Bug{ | ||
2845 | what = [[load/loadfile returns wrong result when given an environment | ||
2846 | for a binary chunk with no upvalues]], | ||
2847 | report = [[Vladimir Strakh, 2012/11/28]], | ||
2848 | since = [[5.2.0]], | ||
2849 | fix = [[5.2.2]], | ||
2850 | example = [[ | ||
2851 | f = load(string.dump(function () return 1 end), nil, "b", {}) | ||
2852 | print(type(f)) --> table (whould be a function) | ||
2853 | ]], | ||
2854 | patch = [[ | ||
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 | |||
2910 | Bug{ | ||
2911 | what = [[stack overflow in vararg functions with many fixed | ||
2912 | parameters called with few arguments]], | ||
2913 | report = [[云风, 2013/04/17]], | ||
2914 | since = [[5.1]], | ||
2915 | fix = [[5.2.3]], | ||
2916 | example = [[ | ||
2917 | function 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 | ||
2923 | end | ||
2924 | |||
2925 | f() -- seg. fault (on some machines) | ||
2926 | ]], | ||
2927 | patch = [[ | ||
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 | |||
2942 | Bug{ | ||
2943 | what = [[garbage collector can trigger too many times in recursive loops]], | ||
2944 | report = [[Roberto, 2013/04/25]], | ||
2945 | since = [[5.2.2]], | ||
2946 | fix = [[5.2.3]], | ||
2947 | example = [[ | ||
2948 | function f() f() end | ||
2949 | f() -- it takes too long before a "stack overflow" error | ||
2950 | ]], | ||
2951 | patch = [[ | ||
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 | -- [[]] | ||
2973 | Bug{ | ||
2974 | what = [[Wrong assert when reporting concatenation errors | ||
2975 | (manifests only when Lua is compiled in debug mode)]], | ||
2976 | report = [[Roberto, 2013/05/05]], | ||
2977 | since = [[?]], | ||
2978 | fix = [[5.2.3]], | ||
2979 | example = [[ | ||
2980 | -- only with Lua compiled in debug mode | ||
2981 | print({} .. 2) | ||
2982 | ]], | ||
2983 | patch = [[ | ||
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 | |||
2996 | Bug{ | ||
2997 | what = [[Wrong error message in some short-cut expressions]], | ||
2998 | report = [[Egor Skriptunoff, 2013/05/10]], | ||
2999 | since = [[5.0]], | ||
3000 | fix = [[5.2.3]], | ||
3001 | example = [[ | ||
3002 | > a,b,c = true,true,true | ||
3003 | > (a and b or c)('', '') | ||
3004 | stdin:1: attempt to call a boolean value (global 'c') | ||
3005 | |||
3006 | (It should be global 'b' instead of 'c'.) | ||
3007 | ]], | ||
3008 | patch = [[ | ||
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 | |||
3081 | Bug{ | ||
3082 | what = [[luac listings choke on long strings]], | ||
3083 | report = [[Ashwin Hirschi, 2013/07/03]], | ||
3084 | since = [[5.1.2]], | ||
3085 | fix = [[5.2.3]], | ||
3086 | example = [[ | ||
3087 | -- When you call 'luac -l' over this chunk, it chokes the output | ||
3088 | s="Lorem ipsum dolor sit amet, consectetur, " | ||
3089 | ]], | ||
3090 | patch = [[ | ||
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 | |||
3105 | Bug{ | ||
3106 | what = [[GC can collect a long string still in use during parser]], | ||
3107 | report = [[Roberto, 2013/08/30]], | ||
3108 | since = [[5.2]], | ||
3109 | fix = [[5.2.3]], | ||
3110 | example = [[This bug is very difficult to happen (and to reproduce), | ||
3111 | because it depends on the GC running in a very specific way when | ||
3112 | parsing a source code with long (larger than 40 characters) identifiers.]], | ||
3113 | patch = [[ | ||
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 | |||
3140 | Bug{ | ||
3141 | what = [[Call to macro 'luai_userstateclose' should be done only | ||
3142 | after the calls to __gc methods.]], | ||
3143 | report = [[Jean-Luc Jumpertz, 2013/09/02]], | ||
3144 | since = [[ ]], | ||
3145 | fix = nil, | ||
3146 | example = [[No example]], | ||
3147 | patch = [[ | ||
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 | |||
3178 | Bug{ | ||
3179 | what = [[Resuming the running coroutine makes it unyieldable]], | ||
3180 | report = [[Florian Nücke, 2013/10/28]], | ||
3181 | since = [[5.2]], | ||
3182 | fix = [[5.2.3]], | ||
3183 | example = [[ | ||
3184 | -- should print 'true' | ||
3185 | print(coroutine.resume(coroutine.create(function() | ||
3186 | coroutine.resume(coroutine.running()) | ||
3187 | coroutine.yield() | ||
3188 | end))) | ||
3189 | ]], | ||
3190 | patch = [[ | ||
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 | |||
3210 | Bug{ | ||
3211 | what = [[compiler can optimize away overflow check in 'table.unpack']], | ||
3212 | report = [[Paige DePol, 2014/03/30]], | ||
3213 | since = [[5.1 (at least)]], | ||
3214 | fix = nil, | ||
3215 | example = [[ | ||
3216 | > unpack({}, 0, 2^31 - 1) | ||
3217 | (segfaults on some platforms with some compiler options) | ||
3218 | ]], | ||
3219 | patch = [[ | ||
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 | |||
3243 | Bug{ | ||
3244 | what = [[Ephemeron table can wrongly collect entry with strong key]], | ||
3245 | report = [[Jörg Richter, 2014/08/22]], | ||
3246 | since = [[5.2]], | ||
3247 | fix = nil, | ||
3248 | example = [[ | ||
3249 | (This bug is very hard to reproduce, | ||
3250 | because it depends on a specific interleaving of | ||
3251 | events between the incremental collector and the program.) | ||
3252 | ]], | ||
3253 | patch = [[ | ||
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 | |||
3268 | Bug{ | ||
3269 | what = [[Chunk with too many lines can seg. fault]], | ||
3270 | report = [[Roberto, 2014/11/14]], | ||
3271 | since = [[5.1 (at least)]], | ||
3272 | fix = nil, | ||
3273 | example = [[ | ||
3274 | -- the cause of the bug is the use of an unitialized variable, so | ||
3275 | -- it cannot be reproduced reliably | ||
3276 | local s = string.rep("\n", 2^24) | ||
3277 | print(load(function () return s end)) | ||
3278 | ]], | ||
3279 | patch = [[ | ||
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 | |||
3296 | Bug{ | ||
3297 | what = [['string.format("%f")' can cause a buffer overflow | ||
3298 | (only when 'lua_Number' is long double!)]], | ||
3299 | report = [[Roberto, 2015/01/13]], | ||
3300 | since = [[5.3]], | ||
3301 | fix = nil, | ||
3302 | example = [[string.format("%.99f", 1e4000) -- when floats are long double]], | ||
3303 | patch = [[ | ||
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 | |||
3315 | Bug{ | ||
3316 | what = [['debug.getlocal' on a coroutine suspended in a hook | ||
3317 | can crash the interpreter]], | ||
3318 | report = [[云风, 2015/02/11]], | ||
3319 | since = [[5.2]], | ||
3320 | fix = nil, | ||
3321 | example = [[see http://lua-users.org/lists/lua-l/2015-02/msg00146.html]], | ||
3322 | patch = [[ | ||
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 | |||
3383 | Bug{ | ||
3384 | what = [[suspended '__le' metamethod can give wrong result]], | ||
3385 | report = [[Eric Zhong, 2015/04/07]], | ||
3386 | since = [[5.2]], | ||
3387 | fix = nil, | ||
3388 | |||
3389 | example = [[ | ||
3390 | mt = {__le = function (a,b) coroutine.yield("yield"); return a.x <= b.x end} | ||
3391 | t1 = setmetatable({x=1}, mt) | ||
3392 | t2 = {x=2} | ||
3393 | co = coroutine.wrap(function (a,b) return t2 <= t1 end) | ||
3394 | co() | ||
3395 | print(co()) --> true (should be false) | ||
3396 | ]], | ||
3397 | |||
3398 | patch = [[ | ||
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 | |||
3450 | Bug{ | ||
3451 | what = [[return hook may not see correct values for | ||
3452 | active local variables when function returns]], | ||
3453 | report = [[Philipp Janda/Peng Yi, 2015/05/19]], | ||
3454 | since = [[5.0]], | ||
3455 | fix = nil, | ||
3456 | example = [[ | ||
3457 | see messasge http://lua-users.org/lists/lua-l/2015-05/msg00376.html]], | ||
3458 | patch = [[ | ||
3459 | ]] | ||
3460 | } | ||
3461 | |||
3462 | |||
3463 | |||
3464 | ----------------------------------------------------------------- | ||
3465 | -- Lua 5.3.1 | ||
3466 | |||
3467 | Bug{ | ||
3468 | what = [['io.lines' does not check maximum number of options]], | ||
3469 | report = [[Patrick Donnell, 2015/07/10]], | ||
3470 | since = [[5.3.0]], | ||
3471 | fix = nil, | ||
3472 | example = [[ | ||
3473 | -- can segfault in some machines | ||
3474 | t ={}; for i = 1, 253 do t[i] = 1 end | ||
3475 | io.lines("someexistingfile", table.unpack(t))() | ||
3476 | ]], | ||
3477 | patch = [[ | ||
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 | |||
3503 | Bug{ | ||
3504 | what = [[Metatable may access its own dealocated field when | ||
3505 | it has a self reference in __newindex]], | ||
3506 | report = [[actboy168@gmail.com, 2016/01/01]], | ||
3507 | since = [[5.3.2]], | ||
3508 | fix = nil, | ||
3509 | example = [[ | ||
3510 | local mt = {} | ||
3511 | mt.__newindex = mt | ||
3512 | local t = setmetatable({}, mt) | ||
3513 | t[1] = 1 -- will segfault on some machines | ||
3514 | ]], | ||
3515 | patch = [[ | ||
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 | |||
3547 | Bug{ | ||
3548 | what = [[label between local definitions can mix-up their initializations]], | ||
3549 | report = [[Karel Tuma, 2016/03/01]], | ||
3550 | since = [[5.2]], | ||
3551 | fix = nil, | ||
3552 | example = [[ | ||
3553 | do | ||
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 | ||
3562 | end | ||
3563 | ]], | ||
3564 | patch = [[ | ||
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 | |||
3580 | Bug{ | ||
3581 | what = [['gmatch' iterator fails when called from a coroutine different | ||
3582 | from the one that created it]], | ||
3583 | report = [[Nagaev Boris, 2016/03/18]], | ||
3584 | since = [[5.3.2]], | ||
3585 | fix = nil, | ||
3586 | example = [[ | ||
3587 | local f = string.gmatch("1 2 3 4 5", "%d+") | ||
3588 | print(f()) --> 1 | ||
3589 | co = coroutine.wrap(f) | ||
3590 | print(co()) --> ??? (should be 2) | ||
3591 | ]], | ||
3592 | patch = [[ | ||
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 | |||
3611 | Bug{ | ||
3612 | what = [[expression list with four or more expressions in | ||
3613 | a 'for' loop can crash the interpreter]], | ||
3614 | report = [[Marco Schöpl, 2016/06/17]], | ||
3615 | since = [[5.2]], | ||
3616 | fix = nil, | ||
3617 | example = [[ | ||
3618 | -- the next loop will probably crash the interpreter | ||
3619 | repeat until load "for _ in _,_,_,_ do local function _() end" | ||
3620 | ]], | ||
3621 | patch = [[ | ||
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 | |||
3650 | Bug{ | ||
3651 | what = [[Checking a format for 'os.date' may read pass the format string]], | ||
3652 | report = [[Nagaev Boris, 2016/07/10]], | ||
3653 | since = [[5.3.3]], | ||
3654 | fix = nil, | ||
3655 | example = [[ | ||
3656 | This bug does not seem to happen with regular compilers. | ||
3657 | It needs an "interceptor" 'memcmp' function that continues | ||
3658 | reading memory after a difference is found.]], | ||
3659 | patch = [[ | ||
3660 | 2c2 | ||
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 $ | ||
3664 | 263c263,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 | |||
3673 | Bug{ | ||
3674 | what = [[Lua can generate wrong code in functions with too many constants]], | ||
3675 | report = [[Marco Schöpl, 2016/07/17]], | ||
3676 | since = [[5.3.3]], | ||
3677 | fix = nil, | ||
3678 | example = [[See http://lua-users.org/lists/lua-l/2016-07/msg00303.html]], | ||
3679 | patch = [[ | ||
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 | |||
3697 | Bug{ | ||
3698 | what = [[When a coroutine tries to resume a non-suspended coroutine, | ||
3699 | it can do some mess (and break C assertions) before detecting the error]], | ||
3700 | report = [[Marco Schöpl, 2016/07/20]], | ||
3701 | since = [[ ]], | ||
3702 | fix = nil, | ||
3703 | example = [[ | ||
3704 | -- with C assertions on | ||
3705 | A = coroutine.running() | ||
3706 | B = coroutine.create(function() coroutine.resume(A) end) | ||
3707 | coroutine.resume(B) | ||
3708 | |||
3709 | -- or | ||
3710 | A = coroutine.wrap(function() pcall(A, _) end) | ||
3711 | A() | ||
3712 | ]], | ||
3713 | patch = [[ | ||
3714 | ]] | ||
3715 | } | ||
3716 | |||
3717 | |||
3718 | ----------------------------------------------------------------- | ||
3719 | -- Lua 5.3.4 | ||
3720 | |||
3721 | |||
3722 | Bug{ | ||
3723 | what = [[Wrong code for a goto followed by a label inside an 'if']], | ||
3724 | report = [[云风, 2017/04/13]], | ||
3725 | since = [[5.2]], | ||
3726 | fix = nil, | ||
3727 | example = [[ | ||
3728 | -- should print 32323232..., but prints only '3' | ||
3729 | if true then | ||
3730 | goto LBL | ||
3731 | ::loop:: | ||
3732 | print(2) | ||
3733 | ::LBL:: | ||
3734 | print(3) | ||
3735 | goto loop | ||
3736 | end | ||
3737 | ]], | ||
3738 | patch = [[ | ||
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 | |||
3754 | Bug{ | ||
3755 | what = [[Lua crashes when building sequences with more than 2^30 elements.]], | ||
3756 | report = [[Viacheslav Usov, 2017/05/11]], | ||
3757 | since = [[ ]], | ||
3758 | fix = nil, | ||
3759 | example = [[ | ||
3760 | -- crashes if machine has enough memory | ||
3761 | local t = {} | ||
3762 | for i = 1, 0x7fffffff do | ||
3763 | t[i] = i | ||
3764 | end | ||
3765 | ]], | ||
3766 | patch = [[ | ||
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 | |||
3784 | Bug{ | ||
3785 | what = [[Table length computation overflows for sequences larger than | ||
3786 | 2^31 elements.]], | ||
3787 | report = [[Viacheslav Usov, 2017/05/12]], | ||
3788 | since = [[ ]], | ||
3789 | fix = nil, | ||
3790 | example = [[ | ||
3791 | -- on a machine with enough memory | ||
3792 | local t = {} | ||
3793 | for i = 1, 2147483681 do | ||
3794 | t[i] = i | ||
3795 | end | ||
3796 | print(#t) | ||
3797 | ]], | ||
3798 | patch = [[ | ||
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 | |||
3834 | Bug{ | ||
3835 | what = [[Lua does not check GC when creating error messages]], | ||
3836 | report = [[Viacheslav Usov, 2017/07/06]], | ||
3837 | since = [[5.3.2]], | ||
3838 | fix = nil, | ||
3839 | example = [[ | ||
3840 | function test() | ||
3841 | bob.joe.larry = 23 | ||
3842 | end | ||
3843 | |||
3844 | -- memory will grow steadly | ||
3845 | for i = 1, math.huge do | ||
3846 | pcall(test) | ||
3847 | if i % 100000 == 0 then | ||
3848 | io.write(collectgarbage'count'*1024, "\n") | ||
3849 | end | ||
3850 | end | ||
3851 | ]], | ||
3852 | patch = [[ | ||
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 | |||
3867 | Bug{ | ||
3868 | what = [[dead keys with nil values can stay in weak tables]], | ||
3869 | report = [[云风 Cloud Wu, 2017/08/15]], | ||
3870 | since = [[5.2]], | ||
3871 | fix = nil, | ||
3872 | example = [[ | ||
3873 | -- The following chunk, under a memory checker like valgrind, | ||
3874 | -- produces a memory access violation. | ||
3875 | |||
3876 | local a = setmetatable({}, {__mode = 'kv'}) | ||
3877 | |||
3878 | a['ABCDEFGHIJKLMNOPQRSTUVWXYZ' .. 'abcdefghijklmnopqrstuvwxyz'] = {} | ||
3879 | a[next(a)] = nil | ||
3880 | collectgarbage() | ||
3881 | print(a['BCDEFGHIJKLMNOPQRSTUVWXYZ' .. 'abcdefghijklmnopqrstuvwxyz']) | ||
3882 | ]], | ||
3883 | patch = [[ | ||
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 | |||
3901 | Bug{ | ||
3902 | what = [['lua_pushcclosure' should not call the garbage collector when | ||
3903 | 'n' is zero.]], | ||
3904 | report = [[Andrew Gierth, 2017/12/05]], | ||
3905 | since = [[5.3.3]], | ||
3906 | fix = nil, | ||
3907 | example = [[ ]], | ||
3908 | patch = [[ | ||
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 | |||
3934 | Bug{ | ||
3935 | what = [[memory-allocation error when resizing a table can leave it | ||
3936 | in an inconsistent state.]], | ||
3937 | report = [[Roberto, 2017/12/08]], | ||
3938 | since = [[5.0]], | ||
3939 | fix = nil, | ||
3940 | example = [[ | ||
3941 | local a = {x = 1, y = 1, z = 1} | ||
3942 | a[1] = 10 -- goes to the hash part (which has 4 slots) | ||
3943 | print(a[1]) --> 10 | ||
3944 | |||
3945 | -- assume that the 2nd memory allocation from now fails | ||
3946 | pcall(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... | ||
3952 | for k,v in pairs(a) do print(k,v) end | ||
3953 | ]], | ||
3954 | patch = [[ | ||
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 | |||
4001 | Bug{ | ||
4002 | what = [[Long brackets with a huge number of '=' overflow some | ||
4003 | internal buffer arithmetic]], | ||
4004 | report = [[Marco, 2018/12/12]], | ||
4005 | since = [[5.1]], | ||
4006 | fix = nil, | ||
4007 | example = [[ | ||
4008 | local eqs = string.rep("=", 0x3ffffffe) | ||
4009 | local code = "return [" .. eqs .. "[a]" .. eqs .. "]" | ||
4010 | print(#assert(load(code))()) | ||
4011 | ]], | ||
4012 | patch = [[ | ||
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 | |||
4093 | Bug{ | ||
4094 | what = [[joining an upvalue with itself can cause a use-after-free crash]], | ||
4095 | report = [[Fady Othman, 2019/01/10]], | ||
4096 | since = [[5.3]], | ||
4097 | fix = nil, | ||
4098 | example = [[ | ||
4099 | -- the next code may crash the machine | ||
4100 | f=load(function() end) | ||
4101 | interesting={} | ||
4102 | interesting[0]=string.rep("A",512) | ||
4103 | debug.upvaluejoin(f,1,f,1) | ||
4104 | ]], | ||
4105 | patch = [[ | ||
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 | --[=[ | ||
4122 | Bug{ | ||
4123 | what = [[ ]], | ||
4124 | report = [[ ]], | ||
4125 | since = [[ ]], | ||
4126 | fix = nil, | ||
4127 | example = [[ ]], | ||
4128 | patch = [[ | ||
4129 | ]] | ||
4130 | } | ||
4131 | ]=] | ||
4132 | |||
4133 | |||