diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-12-27 11:02:25 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2007-12-27 11:02:25 -0200 |
| commit | f5ae26ec6c2eb69f03f316e59c1e1977c52c7c23 (patch) | |
| tree | b4c761dac7648caea2cc20f8ebc2dd5b27a3fa1e /bugs | |
| parent | 98194db4295726069137d13b8d24fca8cbf892b6 (diff) | |
| download | lua-f5ae26ec6c2eb69f03f316e59c1e1977c52c7c23.tar.gz lua-f5ae26ec6c2eb69f03f316e59c1e1977c52c7c23.tar.bz2 lua-f5ae26ec6c2eb69f03f316e59c1e1977c52c7c23.zip | |
official branch for Lua 5.1
Diffstat (limited to 'bugs')
| -rw-r--r-- | bugs | 1015 |
1 files changed, 0 insertions, 1015 deletions
| @@ -1,1015 +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 | |||
| 802 | ----------------------------------------------------------------- | ||
| 803 | -- Lua 5.1 | ||
| 804 | |||
| 805 | Bug{ | ||
| 806 | what = [[In 16-bit machines, expressions and/or with numeric constants as the | ||
| 807 | right operand may result in weird values]], | ||
| 808 | |||
| 809 | report = [[Andreas Stenius/Kein-Hong Man, 15/03/2006]], | ||
| 810 | |||
| 811 | example = [[ | ||
| 812 | print(false or 0) -- on 16-bit machines | ||
| 813 | ]], | ||
| 814 | |||
| 815 | patch = [[ | ||
| 816 | * lcode.c: | ||
| 817 | @@ -731,17 +731,15 @@ | ||
| 818 | case OPR_AND: { | ||
| 819 | lua_assert(e1->t == NO_JUMP); /* list must be closed */ | ||
| 820 | luaK_dischargevars(fs, e2); | ||
| 821 | - luaK_concat(fs, &e1->f, e2->f); | ||
| 822 | - e1->k = e2->k; e1->u.s.info = e2->u.s.info; | ||
| 823 | - e1->u.s.aux = e2->u.s.aux; e1->t = e2->t; | ||
| 824 | + luaK_concat(fs, &e2->f, e1->f); | ||
| 825 | + *e1 = *e2; | ||
| 826 | break; | ||
| 827 | } | ||
| 828 | case OPR_OR: { | ||
| 829 | lua_assert(e1->f == NO_JUMP); /* list must be closed */ | ||
| 830 | luaK_dischargevars(fs, e2); | ||
| 831 | - luaK_concat(fs, &e1->t, e2->t); | ||
| 832 | - e1->k = e2->k; e1->u.s.info = e2->u.s.info; | ||
| 833 | - e1->u.s.aux = e2->u.s.aux; e1->f = e2->f; | ||
| 834 | + luaK_concat(fs, &e2->t, e1->t); | ||
| 835 | + *e1 = *e2; | ||
| 836 | break; | ||
| 837 | } | ||
| 838 | ]], | ||
| 839 | |||
| 840 | } | ||
| 841 | |||
| 842 | |||
| 843 | Bug{ | ||
| 844 | what = [[luaL_checkudata may produce wrong error message]], | ||
| 845 | |||
| 846 | report = [[Greg Falcon, 21/03/2006]], | ||
| 847 | |||
| 848 | example = [[ | ||
| 849 | getmetatable(io.stdin).__gc() | ||
| 850 | --> bad argument #1 to '__gc' (FILE* expected, got table) | ||
| 851 | ]], | ||
| 852 | |||
| 853 | patch = [[ | ||
| 854 | * lauxlib.c: | ||
| 855 | @@ -123,11 +123,17 @@ | ||
| 856 | |||
| 857 | LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { | ||
| 858 | void *p = lua_touserdata(L, ud); | ||
| 859 | - lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ | ||
| 860 | - if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2)) | ||
| 861 | - luaL_typerror(L, ud, tname); | ||
| 862 | - lua_pop(L, 2); /* remove both metatables */ | ||
| 863 | - return p; | ||
| 864 | + if (p != NULL) { /* value is a userdata? */ | ||
| 865 | + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ | ||
| 866 | + lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ | ||
| 867 | + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ | ||
| 868 | + lua_pop(L, 2); /* remove both metatables */ | ||
| 869 | + return p; | ||
| 870 | + } | ||
| 871 | + } | ||
| 872 | + } | ||
| 873 | + luaL_typerror(L, ud, tname); /* else error */ | ||
| 874 | + return NULL; /* to avoid warnings */ | ||
| 875 | } | ||
| 876 | ]] | ||
| 877 | |||
| 878 | } | ||
| 879 | |||
| 880 | |||
| 881 | Bug{ | ||
| 882 | what = [[ | ||
| 883 | In Windows, | ||
| 884 | when Lua is used in an application that also uses DirectX, | ||
| 885 | it may present an erractic behavior. | ||
| 886 | THIS IS NOT A LUA BUG! | ||
| 887 | The problem is that DirectX violates an ABI that Lua depends on.]], | ||
| 888 | |||
| 889 | patch = [[ | ||
| 890 | The simplest solution is to use DirectX with | ||
| 891 | the D3DCREATE_FPU_PRESERVE flag. | ||
| 892 | |||
| 893 | Otherwise, you can change the definition of lua_number2int, | ||
| 894 | in luaconf.h, to this one: | ||
| 895 | #define lua_number2int(i,d) __asm fld d __asm fistp i | ||
| 896 | ]], | ||
| 897 | |||
| 898 | } | ||
| 899 | |||
| 900 | |||
| 901 | Bug{ | ||
| 902 | what = [[option '%q' in string.format does not handle '\r' correctly.]], | ||
| 903 | |||
| 904 | example = [[ | ||
| 905 | local s = "a string with \r and \n and \r\n and \n\r" | ||
| 906 | local c = string.format("return %q", s) | ||
| 907 | assert(assert(loadstring(c))() == s) | ||
| 908 | ]], | ||
| 909 | |||
| 910 | patch = [[ | ||
| 911 | * lstrlib.c: | ||
| 912 | @@ -703,6 +703,10 @@ | ||
| 913 | luaL_addchar(b, *s); | ||
| 914 | break; | ||
| 915 | } | ||
| 916 | + case '\r': { | ||
| 917 | + luaL_addlstring(b, "\\r", 2); | ||
| 918 | + break; | ||
| 919 | + } | ||
| 920 | case '\0': { | ||
| 921 | luaL_addlstring(b, "\\000", 4); | ||
| 922 | break; | ||
| 923 | ]], | ||
| 924 | |||
| 925 | } | ||
| 926 | |||
| 927 | |||
| 928 | Bug{ | ||
| 929 | what = [[lua_dostring/lua_dofile should return any values returned | ||
| 930 | by the chunk]], | ||
| 931 | |||
| 932 | patch = [[ | ||
| 933 | * lauxlib.h: | ||
| 934 | @@ -108,9 +108,11 @@ | ||
| 935 | |||
| 936 | #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) | ||
| 937 | |||
| 938 | -#define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, 0, 0)) | ||
| 939 | +#define luaL_dofile(L, fn) \ | ||
| 940 | + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) | ||
| 941 | |||
| 942 | -#define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, 0, 0))+#define luaL_dostring(L, s) \ | ||
| 943 | + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) | ||
| 944 | |||
| 945 | #define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) | ||
| 946 | ]], | ||
| 947 | |||
| 948 | } | ||
| 949 | |||
| 950 | |||
| 951 | Bug{ | ||
| 952 | |||
| 953 | what = [[garbage collector does not compensate enough for finalizers]], | ||
| 954 | |||
| 955 | patch = [[ | ||
| 956 | lgc.c: | ||
| 957 | @@ -322,4 +322,6 @@ | ||
| 958 | |||
| 959 | -static void propagateall (global_State *g) { | ||
| 960 | - while (g->gray) propagatemark(g); | ||
| 961 | +static size_t propagateall (global_State *g) { | ||
| 962 | + size_t m = 0; | ||
| 963 | + while (g->gray) m += propagatemark(g); | ||
| 964 | + return m; | ||
| 965 | } | ||
| 966 | @@ -542,3 +544,3 @@ | ||
| 967 | marktmu(g); /* mark `preserved' userdata */ | ||
| 968 | - propagateall(g); /* remark, to propagate `preserveness' */ | ||
| 969 | + udsize += propagateall(g); /* remark, to propagate `preserveness' */ | ||
| 970 | cleartable(g->weak); /* remove collected objects from weak tables */ | ||
| 971 | @@ -592,2 +594,4 @@ | ||
| 972 | GCTM(L); | ||
| 973 | + if (g->estimate > GCFINALIZECOST) | ||
| 974 | + g->estimate -= GCFINALIZECOST; | ||
| 975 | ]] | ||
| 976 | } | ||
| 977 | |||
| 978 | |||
| 979 | But{ | ||
| 980 | |||
| 981 | what = [[debug hooks may get wrong when mixed with coroutines]], | ||
| 982 | |||
| 983 | report = [[by Ivko Stanilov, 03/06/2006]], | ||
| 984 | |||
| 985 | example = [[ | ||
| 986 | co = coroutine.create(function (a,b) | ||
| 987 | coroutine.yield(a, b) | ||
| 988 | return b, "end" | ||
| 989 | end) | ||
| 990 | |||
| 991 | debug.sethook(co, function() end, "lcr") | ||
| 992 | coroutine.resume(co, 100, 2000) | ||
| 993 | coroutine.resume(co, 100, 2000) | ||
| 994 | ]], | ||
| 995 | |||
| 996 | patch = [[ | ||
| 997 | * ldo.c: | ||
| 998 | @@ -389,6 +389,7 @@ | ||
| 999 | return; | ||
| 1000 | } | ||
| 1001 | else { /* resuming from previous yield */ | ||
| 1002 | + L->status = 0; | ||
| 1003 | if (!f_isLua(ci)) { /* `common' yield? */ | ||
| 1004 | /* finish interrupted execution of `OP_CALL' */ | ||
| 1005 | lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || | ||
| 1006 | @@ -399,7 +400,6 @@ | ||
| 1007 | else /* yielded inside a hook: just continue its execution */ | ||
| 1008 | L->base = L->ci->base; | ||
| 1009 | } | ||
| 1010 | - L->status = 0; | ||
| 1011 | luaV_execute(L, cast_int(L->ci - L->base_ci)); | ||
| 1012 | } | ||
| 1013 | ]], | ||
| 1014 | |||
| 1015 | } | ||
