123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510 |
- --[=[
- ** lua.stx / llex.c
- Tue Dec 2 10:45:48 EDT 1997
- >> BUG: "lastline" was not reset on function entry, so debug information
- >> started only in the 2nd line of a function.
- =================================================================
- --- Version 3.1 alpha
- ** lua.c
- Thu Jan 15 14:34:58 EDT 1998
- >> must include "stdlib.h" (for "exit()").
- ** lbuiltin.c / lobject.h
- Thu Jan 15 14:34:58 EDT 1998
- >> MAX_WORD may be bigger than MAX_INT
- (by lhf)
- ** llex.c
- Mon Jan 19 18:17:18 EDT 1998
- >> wrong line number (+1) in error report when file starts with "#..."
- ** lstrlib.c
- Tue Jan 27 15:27:49 EDT 1998
- >> formats like "%020d" were considered too big (3 digits); moreover,
- >> some sistems limit printf to at most 500 chars, so we can limit sizes
- >> to 2 digits (99).
- ** lapi.c
- Tue Jan 27 17:12:36 EDT 1998
- >> "lua_getstring" may create a new string, so should check GC
- ** lstring.c / ltable.c
- Wed Jan 28 14:48:12 EDT 1998
- >> tables can become full of "empty" slots, and keep growing without limits.
- ** lstrlib.c
- Mon Mar 9 15:26:09 EST 1998
- >> gsub('a', '(b?)%1*' ...) loops (because the capture is empty).
- ** lstrlib.c
- Mon May 18 19:20:00 EST 1998
- >> arguments for "format" 'x', 'X', 'o' and 'u' must be unsigned int.
- =================================================================
- --- Version 3.1
- ** liolib.c / lauxlib.c
- Mon Sep 7 15:57:02 EST 1998
- >> function "luaL_argerror" prints wrong argument number (from a user's point
- of view) when functions have upvalues.
- ** lstrlib.c
- Tue Nov 10 17:29:36 EDT 1998
- >> gsub/strfind do not check whether captures are properly finished.
- (by roberto/tomas)
- ** lbuiltin.c
- Fri Dec 18 11:22:55 EDT 1998
- >> "tonumber" goes crazy with negative numbers in other bases (not 10),
- because "strtol" returns long, not unsigned long.
- (by Visual C++)
- ** lstrlib.c
- Mon Jan 4 10:41:40 EDT 1999
- >> "format" does not check size of format item (such as "%00000...00000d").
- ** lapi.c
- Wed Feb 3 14:40:21 EDT 1999
- >> getlocal cannot return the local itself, since lua_isstring and
- lua_isnumber can modify it.
- ** lstrlib.c
- Thu Feb 4 17:08:50 EDT 1999
- >> format "%s" may break limit of "sprintf" on some machines.
- (by Marcelo Sales)
- ** lzio.c
- Thu Mar 4 11:49:37 EST 1999
- >> file stream cannot call fread after EOF.
- (by lhf)
- =================================================================
- --- Version 3.2 (beta)
- ** lstrlib.c
- Fri Apr 30 11:10:20 EST 1999
- >> '$' at end of pattern was matching regular '$', too.
- (by anna; since 2.5)
- ** lbuiltin.c
- Fri May 21 17:15:11 EST 1999
- >> foreach, foreachi, foreachvar points to function in stack when stack
- can be reallocated.
- (by tomas; since 3.2 beta)
- ** lparser.c
- Wed Jun 16 10:32:46 EST 1999
- >> cannot assign to unlimited variables, because it causes overflow in
- the number of returns of a function.
- (since 3.1)
- =================================================================
- --- Version 3.2
- ** lmathlib.c
- Wed Aug 18 11:28:38 EST 1999
- >> random(0) and random(x,0) are wrong (0 is read as no argument!).
- (by Dave Bollinger; since 3.1)
- ** lparser.c
- Thu Sep 2 10:07:20 EST 1999
- >> in the (old) expression << ls->fs->f->consts[checkname(ls)] >>, checkname
- could realloc f->consts.
- (by Supratik Champati; since 3.2 beta)
- ** lobject.c / lbuiltin.c
- Wed Sep 8 17:41:54 EST 1999
- >> tonumber'e1' and tonumber(' ', x), for x!=10, gave 0 instead of nil.
- (since 3.1)
- ** lstrlib.c
- Thu Nov 11 14:36:30 EDT 1999
- >> `strfind' does not handle \0 in plain search.
- (by Jon Kleiser; since 3.1)
- ** lparser.c
- Wed Dec 29 16:05:43 EDT 1999
- >> return gives wrong line in debug information
- (by lhf; since 3.2 [at least])
- ** ldo.c
- Thu Dec 30 16:39:33 EDT 1999
- >> cannot reopen stdin (for binary mode)
- (by lhf & roberto; since 3.1)
- ** lapi.c
- Thu Mar 2 09:41:53 EST 2000
- >> lua_settable should check stack space (it could call a T.M.)
- (by lhf & celes; since 3.2; it was already fixed by fixed stack)
- ** lparser.c
- Mon Apr 3 09:59:06 EST 2000
- >> '%' should be in expfollow
- (by Edgar Toernig; since 3.1; it was already fixed)
- ** lbuiltin.c
- Mon Apr 3 10:05:05 EST 2000
- >> tostring() without arguments gives seg. fault.
- (by Edgar Toernig; since 3.0)
- =================================================================
- --- Version 4.0 alpha
- Tested with full test suites (as locked in Mon Apr 24 14:23:11 EST 2000)
- in the following platforms:
- * Linux - gcc, g++
- * AIX - gcc
- * Solaris - gcc, cc
- * IRIX - cc, cc-purify
- * Windows - Visual C++ (.c e .cpp, warning level=4)
- ** lstrlib.c
- Tue May 2 15:27:58 EST 2000
- >> `strfind' gets wrong subject length when there is an offset
- (by Jon Kleiser; since 4.0a)
- ** lparser.c
- Fri May 12 15:11:12 EST 2000
- >> first element in a list constructor is not adjusted to one value
- >> (e.g. «a = {gsub('a','a','')}»)
- (by Tomas; since 4.0a)
- ** lparser.c
- Wed May 24 14:50:16 EST 2000
- >> record-constructor starting with an upvalue name gets an error
- >> (e.g. «local a; function f() x = {a=1} end»)
- (by Edgar Toernig; since 3.1)
- ** lparser.c
- Tue Aug 29 15:56:05 EST 2000
- >> error message for `for' uses `while'
- (since 4.0a; already corrected)
- ** lgc.c
- Tue Aug 29 15:57:41 EST 2000
- >> gc tag method for nil could call line hook
- (by ry; since ?)
- =================================================================
- --- Version 4.0 Beta
- ** liolib.c
- Fri Sep 22 15:12:37 EST 2000
- >> `read("*w")' should return nil at EOF
- (by roberto; since 4.0b)
- ** lvm.c
- Mon Sep 25 11:47:48 EST 2000
- >> lua_gettable does not get key from stack top
- (by Philip Yi; since 4.0b)
- ** lgc.c
- Mon Sep 25 11:50:48 EST 2000
- >> GC may crash when checking locked C closures
- (by Philip Yi; since 4.0b)
- ** lapi.c
- Wed Sep 27 09:50:19 EST 2000
- >> lua_tag should return LUA_NOTAG for non-valid indices
- (by Paul Hankin; since 4.0b)
- ** llex.h / llex.c / lparser.c
- Wed Sep 27 13:39:45 EST 2000
- >> parser overwrites semantic information when looking ahead
- >> (e.g. «a = {print'foo'}»)
- (by Edgar Toernig; since 4.0b, deriving from previous bug)
- ** liolib.c
- Thu Oct 26 10:50:46 EDT 2000
- >> in function `read_file', realloc() doesn't free the buffer if it can't
- >> allocate new memory
- (by Mauro Vezzosi; since 4.0b)
- =================================================================
- --- Version 4.0
- ** lparser.c
- Wed Nov 29 09:51:44 EDT 2000
- >> parser does not accept a `;' after a `return'
- (by lhf; since 4.0b)
- ** liolib.c
- Fri Dec 22 15:30:42 EDT 2000
- >> when `read' fails it must return nil (and not no value)
- (by cassino; since at least 3.1)
- ** lstring.c/lapi.c
- Thu Feb 1 11:55:45 EDT 2001
- >> lua_pushuserdata(L, NULL) is buggy
- (by Edgar Toernig; since 4.0)
- ** ldo.c
- Fri Feb 2 14:06:40 EDT 2001
- >> «while 1 dostring[[print('hello\n')]] end» never reclaims memory
- (by Andrew Paton; since 4.0b)
- ** lbaselib.c
- Tue Feb 6 11:57:13 EDT 2001
- >> ESC (which starts precompiled code) in C is \33, not \27
- (by Edgar Toernig and lhf; since 4.0b)
- ** lparser.c
- Tue Jul 10 16:59:18 EST 2001
- >> error message for `%a' gave wrong line number
- (by Leonardo Constantino; since 4.0)
- ** lbaselib.c
- Fri Dec 21 15:21:05 EDT 2001
- >> seg. fault when rawget/rawset get extra arguments
- (by Eric Mauger; since 4.0b)
- ** lvm.c
- Wed Jun 19 13:28:20 EST 2002
- >> line hook gets wrong `ar'
- (by Daniel C. Sinclair; since 4.0.b)
- ** ldo.c
- Wed Jun 19 13:31:49 EST 2002
- >> `protectedparser' may run GC, and then collect `filename'
- >> (in function `parse_file')
- (by Alex Bilyk; since 4.0)
- =================================================================
- --- Version 5.0 alpha
- ** lgc.c
- Fri Aug 30 13:49:14 EST 2002
- >> GC metamethod stored in a weak metatable being collected together with
- >> userdata may not be cleared properly
- (by Roberto; since 5.0a)
- ** lapi.c
- Thu Nov 21 11:00:00 EST 2002
- >> ULONG_MAX>>10 may not fit into an int
- (by Jeff Petkau; since 4.0)
- ** lparser.c
- Fri Dec 6 17:06:40 UTC 2002
- >> scope of generic for variables is not sound
- (by Gavin Wraith; since 5.0a)
- =================================================================
- --- Version 5.0 beta
- ** lbaselib.c
- Fri Dec 20 09:53:19 UTC 2002
- >> `resume' was checking the wrong value for stack overflow
- (by Maik Zimmermann; since 5.0b)
- ** ldo.c
- Thu Jan 23 11:29:06 UTC 2003
- >> error during garbage collection in luaD_protectedparser is not being
- >> protected
- (by Benoit Germain; since 5.0a)
- ** ldo.c (and others)
- Fri Feb 28 14:20:33 EST 2003
- >> GC metamethod calls could mess C/Lua stack syncronization
- (by Roberto; since 5.0b)
- ** lzio.h/zlio.c
- Thu Mar 20 11:40:12 EST 2003
- >> zio mixes a 255 as first char in a buffer with EOZ
- (by lhf; since 5.0a)
- --]=]
- -----------------------------------------------------------------
- -- Lua 5.0 (final)
- Bug{
- what = [[lua_closethread exists only in the manual]],
- report = [[by Nguyen Binh, 28/04/2003]],
- patch = [[no patch; the manual is wrong]],
- }
- Bug{
- what = [[attempt to resume a running coroutine crashes Lua]],
- example = [[
- function co_func (current_co)
- coroutine.resume(co)
- end
- co = coroutine.create(co_func)
- coroutine.resume(co)
- coroutine.resume(co) --> seg. fault
- ]],
- report = [[by Alex Bilyk, 09/05/2003]],
- patch = [[
- * ldo.c:
- 325,326c325
- < if (nargs >= L->top - L->base)
- < luaG_runerror(L, "cannot resume dead coroutine");
- ---
- > lua_assert(nargs < L->top - L->base);
- 329c328,329
- < else if (ci->state & CI_YIELD) { /* inside a yield? */
- ---
- > else { /* inside a yield */
- > lua_assert(ci->state & CI_YIELD);
- 344,345d343
- < else
- < luaG_runerror(L, "cannot resume non-suspended coroutine");
- 351a350,358
- > static int resume_error (lua_State *L, const char *msg) {
- > L->top = L->ci->base;
- > setsvalue2s(L->top, luaS_new(L, msg));
- > incr_top(L);
- > lua_unlock(L);
- > return LUA_ERRRUN;
- > }
- >
- >
- 355a363,368
- > if (L->ci == L->base_ci) {
- > if (nargs >= L->top - L->base)
- > return resume_error(L, "cannot resume dead coroutine");
- > }
- > else if (!(L->ci->state & CI_YIELD)) /* not inside a yield? */
- > return resume_error(L, "cannot resume non-suspended coroutine");
- ]],
- }
- Bug{
- what = [[file:close cannot be called without a file. (results in seg fault)]],
- example = [[
- > io.stdin.close() -- correct call shold be io.stdin:close()
- ]],
- report = [[by Tuomo Valkonen, 27/05/2003]],
- patch = [[
- * liolib.c:
- 161c161
- < if (lua_isnone(L, 1)) {
- ---
- > if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE) {
- ]], --}}
- }
- Bug{
- what = [[C functions also may have stacks larger than current top]],
- example = [[
- Must recompile lua with a change in lua.c and with lua_assert defined:
- * lua.c:
- 381a382
- > lua_checkstack(l, 1000);
- ]],
- report = [[Alex Bilyk, 09/06/2003]],
- patch = [[
- * lgc.c:
- 247c247
- < if (!(ci->state & CI_C) && lim < ci->top)
- ---
- > if (lim < ci->top)
- ]],
- }
- Bug{
- what = [[`pc' address is invalidated when a coroutine is suspended]],
- example = [[
- function g(x)
- coroutine.yield(x)
- end
- function f (i)
- debug.sethook(print, "l")
- for j=1,1000 do
- g(i+j)
- end
- end
- co = coroutine.wrap(f)
- co(10)
- pcall(co)
- pcall(co)
- ]],
- report = [[Nick Trout, 07/07/2003]],
- patch = [[
- * lvm.c:
- 402,403c402,403
- < L->ci->u.l.pc = &pc;
- < if (L->hookmask & LUA_MASKCALL)
- ---
- > if (L->hookmask & LUA_MASKCALL) {
- > L->ci->u.l.pc = &pc;
- 404a405
- > }
- 405a407
- > L->ci->u.l.pc = &pc;
- 676,678c678
- < lua_assert(ci->u.l.pc == &pc &&
- < ttisfunction(ci->base - 1) &&
- < (ci->state & CI_SAVEDPC));
- ---
- > lua_assert(ttisfunction(ci->base - 1) && (ci->state & CI_SAVEDPC));
- ]]
- }
- Bug{
- what = [[userdata to be collected still counts into new GC threshold,
- increasing memory consumption]],
- report = [[Roberto, 25/07/2003]],
- example = [[
- a = newproxy(true)
- getmetatable(a).__gc = function () end
- for i=1,10000000 do
- newproxy(a)
- if math.mod(i, 10000) == 0 then print(gcinfo()) end
- end
- ]],
- patch = [[
- * lgc.h:
- 18c18
- < void luaC_separateudata (lua_State *L);
- ---
- > size_t luaC_separateudata (lua_State *L);
- * lgc.c:
- 113c113,114
- < void luaC_separateudata (lua_State *L) {
- ---
- > size_t luaC_separateudata (lua_State *L) {
- > size_t deadmem = 0;
- 127a129
- > deadmem += sizeudata(gcotou(curr)->uv.len);
- 136a139
- > return deadmem;
- 390c393
- < static void checkSizes (lua_State *L) {
- ---
- > static void checkSizes (lua_State *L, size_t deadmem) {
- 400c403
- < G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
- ---
- > G(L)->GCthreshold = 2*G(L)->nblocks - deadmem; /* new threshold */
- 454c457,458
- < static void mark (lua_State *L) {
- ---
- > static size_t mark (lua_State *L) {
- > size_t deadmem;
- 467c471
- < luaC_separateudata(L); /* separate userdata to be preserved */
- ---
- > deadmem = luaC_separateudata(L); /* separate userdata to be preserved */
- 475a480
- > return deadmem;
- 480c485
- < mark(L);
- ---
- > size_t deadmem = mark(L);
- 482c487
- < checkSizes(L);
- ---
- > checkSizes(L, deadmem);
- ]]
- }
- Bug{
- what=[[IBM AS400 (OS400) has sizeof(void *)==16, and a `%p' may generate
- up to 60 characters in a `printf'. That causes a buffer overflow in
- `tostring'.]],
- report = [[David Burgess, 25/08/2003]],
- example = [[print{}; (in an AS400 machine)]],
- patch = [[
- * liolib.c:
- 178c178
- < char buff[32];
- ---
- > char buff[128];
- * lbaselib.c:
- 327c327
- < char buff[64];
- ---
- > char buff[128];
- ]]
- }
- Bug{
- what = [[syntax `local function' does not increment stack size]],
- report = [[Rici Lake, 26/09/2003]],
- example = [[
- -- must run this with precompiled code
- local a,b,c
- local function d () end
- ]],
- patch = [[
- * lparser.c:
- 1143a1144
- > FuncState *fs = ls->fs;
- 1145c1146,1147
- < init_exp(&v, VLOCAL, ls->fs->freereg++);
- ---
- > init_exp(&v, VLOCAL, fs->freereg);
- > luaK_reserveregs(fs, 1);
- 1148c1150,1152
- < luaK_storevar(ls->fs, &v, &b);
- ---
- > luaK_storevar(fs, &v, &b);
- > /* debug information will only see the variable after this point! */
- > getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;
- ]],
- }
- Bug{
- what = [[count hook may be called without being set]],
- report = [[Andreas Stenius, 06/10/2003]],
- example = [[
- set your hooks with
- lua_sethook(L, my_hook, LUA_MASKLINE | LUA_MASKRET, 1);
- (It is weird to use a count > 0 without setting the count hook,
- but it is not wrong.)
- ]],
- patch = [[
- * lvm.c:
- 69c69
- < if (mask > LUA_MASKLINE) { /* instruction-hook set? */
- ---
- > if (mask & LUA_MASKCOUNT) { /* instruction-hook set? */
- ]],
- }
- Bug{
- what = [[`dofile' eats one return value when called without arguments]],
- report = [[Frederico Abraham, 15/01/2004]],
- example = [[
- a,b = dofile() --< here you enter `return 1,2,3 <eof>'
- print(a,b) --> 2 3 (should be 1 and 2)
- ]],
- patch = [[
- * lbaselib.c:
- 313a314
- > int n = lua_gettop(L);
- 317c318
- < return lua_gettop(L) - 1;
- ---
- > return lua_gettop(L) - n;
- ]],
- }
- -----------------------------------------------------------------
- -- Lua 5.0.2
- Bug{
- what = [[string concatenation may cause arithmetic overflow, leading
- to a buffer overflow]],
- report = [[Rici Lake, 20/05/2004]],
- example = [[
- longs = string.rep("\0", 2^25)
- function catter(i)
- return assert(loadstring(
- string.format("return function(a) return a%s end",
- string.rep("..a", i-1))))()
- end
- rep129 = catter(129)
- rep129(longs)
- ]],
- patch = [[
- * lvm.c:
- @@ -321,15 +321,15 @@
- luaG_concaterror(L, top-2, top-1);
- } else if (tsvalue(top-1)->tsv.len > 0) { /* if len=0, do nothing */
- /* at least two string values; get as many as possible */
- - lu_mem tl = cast(lu_mem, tsvalue(top-1)->tsv.len) +
- - cast(lu_mem, tsvalue(top-2)->tsv.len);
- + size_t tl = tsvalue(top-1)->tsv.len;
- char *buffer;
- int i;
- - while (n < total && tostring(L, top-n-1)) { /* collect total length */
- - tl += tsvalue(top-n-1)->tsv.len;
- - n++;
- + /* collect total length */
- + for (n = 1; n < total && tostring(L, top-n-1); n++) {
- + size_t l = tsvalue(top-n-1)->tsv.len;
- + if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow");
- + tl += l;
- }
- - if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");
- buffer = luaZ_openspace(L, &G(L)->buff, tl);
- tl = 0;
- for (i=n; i>0; i--) { /* concat all strings */
- ]]
- }
- Bug{
- what = [[lua_getupvalue and setupvalue do not check for index too small]],
- report = [[Mike Pall, ?/2004]],
- example = [[debug.getupvalue(function() end, 0)]],
- patch = [[
- * lapi.c
- 941c941
- < if (n > f->c.nupvalues) return NULL;
- ---
- > if (!(1 <= n && n <= f->c.nupvalues)) return NULL;
- 947c947
- < if (n > p->sizeupvalues) return NULL;
- ---
- > if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
- ]]
- }
- Bug{
- what = [[values holded in open upvalues of suspended threads may be
- incorrectly collected]],
- report = [[Spencer Schumann, 31/12/2004]],
- example = [[
- local thread_id = 0
- local threads = {}
- function fn(thread)
- thread_id = thread_id + 1
- threads[thread_id] = function()
- thread = nil
- end
- coroutine.yield()
- end
- while true do
- local thread = coroutine.create(fn)
- coroutine.resume(thread, thread)
- end
- ]],
- patch = [[
- * lgc.c:
- 221,224c221,222
- < if (!u->marked) {
- < markobject(st, &u->value);
- < u->marked = 1;
- < }
- ---
- > markobject(st, u->v);
- > u->marked = 1;
- ]],
- }
- Bug{
- what = [[rawset/rawget do not ignore extra arguments]],
- report = [[Romulo Bahiense, 11/03/2005]],
- example = [[
- a = {}
- rawset(a, 1, 2, 3)
- print(a[1], a[2]) -- should be 2 and nil
- ]],
- patch = [[
- * lbaselib.c:
- 175a176
- > lua_settop(L, 2);
- 183a185
- > lua_settop(L, 3);
- ]],
- }
- Bug{
- what = [[weak tables that survive one collection are never collected]],
- report = [[Chromix, 02/01/2006]],
- example = [[
- a = {}
- print(gcinfo())
- for i = 1, 10000 do
- a[i] = setmetatable({}, {__mode = "v"})
- end
- collectgarbage()
- a = nil
- collectgarbage()
- print(gcinfo())
- ]],
- patch = [[
- * lgc.c
- @@ -366,7 +366,7 @@
- GCObject *curr;
- int count = 0; /* number of collected items */
- while ((curr = *p) != NULL) {
- - if (curr->gch.marked > limit) {
- + if ((curr->gch.marked & ~(KEYWEAK | VALUEWEAK)) > limit) {
- unmark(curr);
- p = &curr->gch.next;
- }
- ]],
- }
- Bug{
- what = [[Some "not not exp" may not result in boolean values]],
- report = [[]],
- since = [[4.0]],
- example = [[
- -- should print false, but prints nil
- print(not not (nil and 4))
- ]],
- patch = [[]],
- }
- Bug{
- what = [[On some machines, closing a "piped file" (created with io.popen)
- may crash Lua]],
- report = [[]],
- since = [[5.0]],
- example = [[
- -- only on some machines
- f = io.popen("ls")
- f:close()
- ]],
- patch = [[]],
- }
- -----------------------------------------------------------------
- -- Lua 5.1
- Bug{
- what = [[In 16-bit machines, expressions and/or with numeric constants as the
- right operand may result in weird values]],
- report = [[Andreas Stenius/Kein-Hong Man, 15/03/2006]],
- example = [[
- print(false or 0) -- on 16-bit machines
- ]],
- patch = [[
- * lcode.c:
- @@ -731,17 +731,15 @@
- case OPR_AND: {
- lua_assert(e1->t == NO_JUMP); /* list must be closed */
- luaK_dischargevars(fs, e2);
- - luaK_concat(fs, &e1->f, e2->f);
- - e1->k = e2->k; e1->u.s.info = e2->u.s.info;
- - e1->u.s.aux = e2->u.s.aux; e1->t = e2->t;
- + luaK_concat(fs, &e2->f, e1->f);
- + *e1 = *e2;
- break;
- }
- case OPR_OR: {
- lua_assert(e1->f == NO_JUMP); /* list must be closed */
- luaK_dischargevars(fs, e2);
- - luaK_concat(fs, &e1->t, e2->t);
- - e1->k = e2->k; e1->u.s.info = e2->u.s.info;
- - e1->u.s.aux = e2->u.s.aux; e1->f = e2->f;
- + luaK_concat(fs, &e2->t, e1->t);
- + *e1 = *e2;
- break;
- }
- ]],
- }
- Bug{
- what = [[luaL_checkudata may produce wrong error message]],
- report = [[Greg Falcon, 21/03/2006]],
- example = [[
- getmetatable(io.stdin).__gc()
- --> bad argument #1 to '__gc' (FILE* expected, got table)
- ]],
- patch = [[
- * lauxlib.c:
- @@ -123,11 +123,17 @@
- LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
- void *p = lua_touserdata(L, ud);
- - lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
- - if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2))
- - luaL_typerror(L, ud, tname);
- - lua_pop(L, 2); /* remove both metatables */
- - return p;
- + if (p != NULL) { /* value is a userdata? */
- + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
- + lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
- + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
- + lua_pop(L, 2); /* remove both metatables */
- + return p;
- + }
- + }
- + }
- + luaL_typerror(L, ud, tname); /* else error */
- + return NULL; /* to avoid warnings */
- }
- ]]
- }
- Bug{
- what = [[
- In Windows,
- when Lua is used in an application that also uses DirectX,
- it may present an erractic behavior.
- THIS IS NOT A LUA BUG!
- The problem is that DirectX violates an ABI that Lua depends on.]],
- patch = [[
- The simplest solution is to use DirectX with
- the D3DCREATE_FPU_PRESERVE flag.
- Otherwise, you can change the definition of lua_number2int,
- in luaconf.h, to this one:
- #define lua_number2int(i,d) __asm fld d __asm fistp i
- ]],
- }
- Bug{
- what = [[option '%q' in string.format does not handle '\r' correctly.]],
- example = [[
- local s = "a string with \r and \n and \r\n and \n\r"
- local c = string.format("return %q", s)
- assert(assert(loadstring(c))() == s)
- ]],
- patch = [[
- * lstrlib.c:
- @@ -703,6 +703,10 @@
- luaL_addchar(b, *s);
- break;
- }
- + case '\r': {
- + luaL_addlstring(b, "\\r", 2);
- + break;
- + }
- case '\0': {
- luaL_addlstring(b, "\\000", 4);
- break;
- ]],
- }
- Bug{
- what = [[lua_dostring/lua_dofile should return any values returned
- by the chunk]],
- patch = [[
- * lauxlib.h:
- @@ -108,9 +108,11 @@
- #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
- -#define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, 0, 0))
- +#define luaL_dofile(L, fn) \
- + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
- -#define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, 0, 0))+#define luaL_dostring(L, s) \
- + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
- #define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
- ]],
- }
- Bug{
- what = [[garbage collector does not compensate enough for finalizers]],
- patch = [[
- lgc.c:
- @@ -322,4 +322,6 @@
- -static void propagateall (global_State *g) {
- - while (g->gray) propagatemark(g);
- +static size_t propagateall (global_State *g) {
- + size_t m = 0;
- + while (g->gray) m += propagatemark(g);
- + return m;
- }
- @@ -542,3 +544,3 @@
- marktmu(g); /* mark `preserved' userdata */
- - propagateall(g); /* remark, to propagate `preserveness' */
- + udsize += propagateall(g); /* remark, to propagate `preserveness' */
- cleartable(g->weak); /* remove collected objects from weak tables */
- @@ -592,2 +594,4 @@
- GCTM(L);
- + if (g->estimate > GCFINALIZECOST)
- + g->estimate -= GCFINALIZECOST;
- ]]
- }
- Bug{
- what = [[debug hooks may get wrong when mixed with coroutines]],
- report = [[by Ivko Stanilov, 03/06/2006]],
- example = [[
- co = coroutine.create(function (a,b)
- coroutine.yield(a, b)
- return b, "end"
- end)
- debug.sethook(co, function() end, "lcr")
- coroutine.resume(co, 100, 2000)
- coroutine.resume(co, 100, 2000)
- ]],
- patch = [[
- * ldo.c:
- @@ -389,6 +389,7 @@
- return;
- }
- else { /* resuming from previous yield */
- + L->status = 0;
- if (!f_isLua(ci)) { /* `common' yield? */
- /* finish interrupted execution of `OP_CALL' */
- lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
- @@ -399,7 +400,6 @@
- else /* yielded inside a hook: just continue its execution */
- L->base = L->ci->base;
- }
- - L->status = 0;
- luaV_execute(L, cast_int(L->ci - L->base_ci));
- }
- ]],
- }
- -----------------------------------------------------------------
- -- Lua 5.1.1
- Bug{
- what = [[list constructors have wrong limit]],
- report = [[by Norman Ramsey, June 2006]],
- since = "5.1",
- example = [[
- a = {}
- a[1] = "x={1"
- for i = 2, 2^20 do
- a[i] = 1
- end
- a[#a + 1] = "}"
- s = table.concat(a, ",")
- assert(loadstring(s))()
- print(#x)
- ]],
- patch = [[
- * lparser.c:
- @@ -489,7 +489,7 @@
- static void listfield (LexState *ls, struct ConsControl *cc) {
- expr(ls, &cc->v);
- - luaY_checklimit(ls->fs, cc->na, MAXARG_Bx, "items in a constructor");
- + luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
- cc->na++;
- cc->tostore++;
- }
- ]],
- }
- Bug{
- what = [[wrong message error in some cases involving closures]],
- report = [[Shmuel Zeigerman, on 07/2006]],
- since = "5.1",
- example = [[
- local Var
- local function main()
- NoSuchName (function() Var=0 end)
- end
- main()
- --> lua5.1: temp:3: attempt to call upvalue 'Var' (a nil value)
- ]],
- patch = [[
- *ldebug.c:
- @@ -435,14 +435,16 @@
- break;
- }
- case OP_CLOSURE: {
- - int nup;
- + int nup, j;
- check(b < pt->sizep);
- nup = pt->p[b]->nups;
- check(pc + nup < pt->sizecode);
- - for (; nup>0; nup--) {
- - OpCode op1 = GET_OPCODE(pt->code[pc+nup]);
- + for (j = 1; j <= nup; j++) {
- + OpCode op1 = GET_OPCODE(pt->code[pc + j]);
- check(op1 == OP_GETUPVAL || op1 == OP_MOVE);
- }
- + if (reg != NO_REG) /* tracing? */
- + pc += nup; /* do not 'execute' these pseudo-instructions */
- break;
- }
- case OP_VARARG: {
- ]],
- }
- Bug{
- what = [[string.format("%") may read past the string]],
- report = [[Roberto, on 09/2006]],
- since = [[5.0]],
- example = [[print(string.format("%"))]],
- patch = [[
- *lstrlib.c:
- @@ -723,7 +723,7 @@
- static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { const char *p = strfrmt;
- - while (strchr(FLAGS, *p)) p++; /* skip flags */
- + while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
- if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
- luaL_error(L, "invalid format (repeated flags)");
- if (isdigit(uchar(*p))) p++; /* skip width */
- ]],
- }
- Bug{
- what = [[os.date throws an error when result is the empty string]],
- report = [[]],
- since = [[4.0]],
- example = [[print(os.date(""))]],
- patch = [[
- *loslib.c:
- @@ -148,7 +148,18 @@
- else {
- - char b[256];
- - if (strftime(b, sizeof(b), s, stm))
- - lua_pushstring(L, b);
- - else
- - return luaL_error(L, LUA_QL("date") " format too long");
- + char cc[3];
- + luaL_Buffer b;
- + cc[0] = '%'; cc[2] = '\0';
- + luaL_buffinit(L, &b);
- + for (; *s; s++) {
- + if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */
- + luaL_addchar(&b, *s);
- + else {
- + size_t reslen;
- + char buff[200]; /* should be big enough for any conversion result */
- + cc[1] = *(++s);
- + reslen = strftime(buff, sizeof(buff), cc, stm);
- + luaL_addlstring(&b, buff, reslen);
- + }
- + }
- + luaL_pushresult(&b);
- }
- ]],
- }
- Bug{
- what = [[setfenv accepts invalid 1st argument]],
- report = [[Doug Rogers, on 02/2007]],
- since = [[5.0]],
- example = [[setfenv(nil, {}) -- should throw an error]],
- patch = [[
- *lbaselib.c:
- @@ -116,3 +116,3 @@
- -static void getfunc (lua_State *L) {
- +static void getfunc (lua_State *L, int opt) {
- if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
- @@ -120,3 +120,3 @@
- lua_Debug ar;
- - int level = luaL_optint(L, 1, 1);
- + int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
- luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
- @@ -133,3 +133,3 @@
- static int luaB_getfenv (lua_State *L) {
- - getfunc(L);
- + getfunc(L, 1);
- if (lua_iscfunction(L, -1)) /* is a C function? */
- @@ -144,3 +144,3 @@
- luaL_checktype(L, 2, LUA_TTABLE);
- - getfunc(L);
- + getfunc(L, 0);
- lua_pushvalue(L, 2);
- ]],
- }
- Bug{
- what = [[wrong code for arithmetic expressions in some specific scenarios]],
- report = [[Thierry Grellier, on 01/2007]],
- since = [[5.1]],
- example = [[
- -- use a large number of names (almost 256)
- v1=1; v2=1; v3=1; v4=1; v5=1; v6=1; v7=1; v8=1; v9=1;
- v10=1; v11=1; v12=1; v13=1; v14=1; v15=1; v16=1; v17=1;
- v18=1; v19=1; v20=1; v21=1; v22=1; v23=1; v24=1; v25=1;
- v26=1; v27=1; v28=1; v29=1; v30=1; v31=1; v32=1; v33=1;
- v34=1; v35=1; v36=1; v37=1; v38=1; v39=1; v40=1; v41=1;
- v42=1; v43=1; v44=1; v45=1; v46=1; v47=1; v48=1; v49=1;
- v50=1; v51=1; v52=1; v53=1; v54=1; v55=1; v56=1; v57=1;
- v58=1; v59=1; v60=1; v61=1; v62=1; v63=1; v64=1; v65=1;
- v66=1; v67=1; v68=1; v69=1; v70=1; v71=1; v72=1; v73=1;
- v74=1; v75=1; v76=1; v77=1; v78=1; v79=1; v80=1; v81=1;
- v82=1; v83=1; v84=1; v85=1; v86=1; v87=1; v88=1; v89=1;
- v90=1; v91=1; v92=1; v93=1; v94=1; v95=1; v96=1; v97=1;
- v98=1; v99=1; v100=1; v101=1; v102=1; v103=1; v104=1; v105=1;
- v106=1; v107=1; v108=1; v109=1; v110=1; v111=1; v112=1; v113=1;
- v114=1; v115=1; v116=1; v117=1; v118=1; v119=1; v120=1; v121=1;
- v122=1; v123=1; v124=1; v125=1; v126=1; v127=1; v128=1; v129=1;
- v130=1; v131=1; v132=1; v133=1; v134=1; v135=1; v136=1; v137=1;
- v138=1; v139=1; v140=1; v141=1; v142=1; v143=1; v144=1; v145=1;
- v146=1; v147=1; v148=1; v149=1; v150=1; v151=1; v152=1; v153=1;
- v154=1; v155=1; v156=1; v157=1; v158=1; v159=1; v160=1; v161=1;
- v162=1; v163=1; v164=1; v165=1; v166=1; v167=1; v168=1; v169=1;
- v170=1; v171=1; v172=1; v173=1; v174=1; v175=1; v176=1; v177=1;
- v178=1; v179=1; v180=1; v181=1; v182=1; v183=1; v184=1; v185=1;
- v186=1; v187=1; v188=1; v189=1; v190=1; v191=1; v192=1; v193=1;
- v194=1; v195=1; v196=1; v197=1; v198=1; v199=1; v200=1; v201=1;
- v202=1; v203=1; v204=1; v205=1; v206=1; v207=1; v208=1; v209=1;
- v210=1; v211=1; v212=1; v213=1; v214=1; v215=1; v216=1; v217=1;
- v218=1; v219=1; v220=1; v221=1; v222=1; v223=1; v224=1; v225=1;
- v226=1; v227=1; v228=1; v229=1; v230=1; v231=1; v232=1; v233=1;
- v234=1; v235=1; v236=1; v237=1; v238=1; v239=1; v240=1; v241=1;
- v242=1; v243=1; v244=1; v245=1; v246=1; v247=1; v248=1; v249=1;
- v250=1;
- v251={k1 = 1};
- v252=1;
- print(2 * v251.k1, v251.k1 * 2); -- 2 2, OK
- v253=1;
- print(2 * v251.k1, v251.k1 * 2); -- 1 2, ???
- ]],
- patch = [[
- *lcode.c:
- @@ -657,10 +657,16 @@
- if (constfolding(op, e1, e2))
- return;
- else {
- - int o1 = luaK_exp2RK(fs, e1);
- int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
- - freeexp(fs, e2);
- - freeexp(fs, e1);
- + int o1 = luaK_exp2RK(fs, e1);
- + if (o1 > o2) {
- + freeexp(fs, e1);
- + freeexp(fs, e2);
- + }
- + else {
- + freeexp(fs, e2);
- + freeexp(fs, e1);
- + }
- e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);
- e1->k = VRELOCABLE;
- }
- @@ -718,10 +724,15 @@
- luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
- break;
- }
- - default: {
- + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
- + case OPR_MOD: case OPR_POW: {
- if (!isnumeral(v)) luaK_exp2RK(fs, v);
- break;
- }
- + default: {
- + luaK_exp2RK(fs, v);
- + break;
- + }
- }
- }
- ]],
- }
- Bug{
- what = [[assignment of nil to parameter may be optimized away]],
- report = [[Thomas Lauer, on 03/2007]],
- since = [[5.1]],
- example = [[
- function f (a)
- a=nil
- return a
- end
- print(f("test"))
- ]],
- patch = [[
- *lcode.c:
- @@ -35,16 +35,20 @@
- void luaK_nil (FuncState *fs, int from, int n) {
- Instruction *previous;
- if (fs->pc > fs->lasttarget) { /* no jumps to current position? */
- - if (fs->pc == 0) /* function start? */
- - return; /* positions are already clean */
- - previous = &fs->f->code[fs->pc-1];
- - if (GET_OPCODE(*previous) == OP_LOADNIL) {
- - int pfrom = GETARG_A(*previous);
- - int pto = GETARG_B(*previous);
- - if (pfrom <= from && from <= pto+1) { /* can connect both? */
- - if (from+n-1 > pto)
- - SETARG_B(*previous, from+n-1);
- - return;
- + if (fs->pc == 0) { /* function start? */
- + if (from >= fs->nactvar)
- + return; /* positions are already clean */
- + }
- + else {
- + previous = &fs->f->code[fs->pc-1];
- + if (GET_OPCODE(*previous) == OP_LOADNIL) {
- + int pfrom = GETARG_A(*previous);
- + int pto = GETARG_B(*previous);
- + if (pfrom <= from && from <= pto+1) { /* can connect both? */
- + if (from+n-1 > pto)
- + SETARG_B(*previous, from+n-1);
- + return;
- + }
- }
- }
- }
- ]],
- }
- Bug{
- what = [[__concat metamethod converts numbers to strings]],
- report = [[Paul Winwood, on 12/2006]],
- since = [[5.0]],
- example = [[
- a = {}
- setmetatable(a, {__concat = function (a,b) print(type(a), type(b)) end})
- a = 4 .. a
- ]],
- patch = [[
- *lvm.c:
- @@ -281,10 +281,12 @@
- do {
- StkId top = L->base + last + 1;
- int n = 2; /* number of elements handled in this pass (at least 2) */
- - if (!tostring(L, top-2) || !tostring(L, top-1)) {
- + if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
- if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
- luaG_concaterror(L, top-2, top-1);
- - } else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */
- + } else if (tsvalue(top-1)->len == 0) /* second op is empty? */
- + (void)tostring(L, top - 2); /* result is first op (as string) */
- + else {
- /* at least two string values; get as many as possible */
- size_t tl = tsvalue(top-1)->len;
- char *buffer;
- ]],
- }
- Bug{
- what = [[As a library, loadlib.c should not access Lua internals
- (via lobject.h)]],
- report = [[Jérôme Vuarand, on 03/2007]],
- since = [[5.0]],
- example = [[the bug has no effect on external behavior]],
- patch = [[remove the '#include "lobject.h" and use
- 'lua_pushfstring' instead of 'luaO_pushfstring']],
- }
- -----------------------------------------------------------------
- -- Lua 5.1.2
- Bug{
- what = [[Lua may close standard files,
- which then may be used by C]],
- report = [[David Manura/Ross Berteig, on 04/2007]],
- since = [[]],
- example = [[
- io.close(io.stderr)
- -- in some systems, following attempts to write to 'stderr' may crash
- a = a + 1
- ]],
- patch = [[
- ]],
- }
- Bug{
- what = [[code generated for "-nil", "-true", and "-false" is wrong]],
- report = [[David Manura/Rici Lake, on 04/2007]],
- since = [[5.1]],
- example = [[print(-nil)]],
- patch = [[
- lcode.c:
- @@ -699,7 +699,7 @@
- e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
- switch (op) {
- case OPR_MINUS: {
- - if (e->k == VK)
- + if (!isnumeral(e))
- luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */
- codearith(fs, OP_UNM, e, &e2);
- break;
- ]],
- }
- Bug{
- what = [[Count hook may be called without being set.]],
- report = [[Mike Pall, on 05/2007]],
- since = [[?]],
- example = [[]],
- patch = [[
- lvm.c:
- @@ -61,11 +61,9 @@
- lu_byte mask = L->hookmask;
- const Instruction *oldpc = L->savedpc;
- L->savedpc = pc;
- - if (mask > LUA_MASKLINE) { /* instruction-hook set? */
- - if (L->hookcount == 0) {
- - resethookcount(L);
- - luaD_callhook(L, LUA_HOOKCOUNT, -1);
- - }
- + if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {
- + resethookcount(L);
- + luaD_callhook(L, LUA_HOOKCOUNT, -1);
- }
- if (mask & LUA_MASKLINE) {
- Proto *p = ci_func(L->ci)->l.p;
- ]],
- }
- Bug{
- what = [[recursive coroutines may overflow C stack]],
- report = [[ , on ]],
- since = [[5.0]],
- example = [[
- a = function(a) coroutine.wrap(a)(a) end
- a(a)
- ]],
- patch = [[The 'nCcalls' counter should be shared by all threads.
- (That is, it should be declared in the 'global_State' structure,
- not in 'lua_State'.)
- ]],
- }
- Bug{
- what = [[wrong error message in some concatenations]],
- report = [[Alex Davies, on 05/2007]],
- since = [[5.1.2]],
- example = [[a = nil; a = (1)..a]],
- patch = [[
- ldebug.c:
- @@ -563,8 +563,8 @@
- void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
- - if (ttisstring(p1)) p1 = p2;
- - lua_assert(!ttisstring(p1));
- + if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
- + lua_assert(!ttisstring(p1) && !ttisnumber(p1));
- luaG_typeerror(L, p1, "concatenate");
- }
- ]],
- }
- Bug{
- what = [[Very small numbers all collide in the hash function.
- (This creates only performance problems; the behavoir is correct.)]],
- report = [[, on ]],
- since = [[5.0]],
- example = [[]],
- patch = [[
- ltable.c:
- 87,88c87,88
- < n += 1; /* normalize number (avoid -0) */
- < lua_assert(sizeof(a) <= sizeof(n));
- ---
- > if (luai_numeq(n, 0)) /* avoid problems with -0 */
- > return gnode(t, 0);
- ]],
- }
- Bug{
- what = [[Too many variables in an assignment may cause a
- C stack overflow]],
- report = [[Mike Pall, on 07/2007]],
- since = [[5.0]],
- example = [[
- $ ulimit -s 1024 # Reduce C stack to 1MB for quicker results
- $ lua -e 'local s = "a,"; for i=1,18 do s = s..s end print(loadstring("local a;"..s.."a=nil", ""))'
- ]],
- patch = [[
- lparser.c:
- @@ -938,6 +938,8 @@
- primaryexp(ls, &nv.v);
- if (nv.v.k == VLOCAL)
- check_conflict(ls, lh, &nv.v);
- + luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,
- + "variable names");
- assignment(ls, &nv, nvars+1);
- }
- else { /* assignment -> `=' explist1 */
- ]],
- }
- Bug{
- what = [[An error in a module loaded through the '-l' option
- shows no traceback]],
- report = [[David Manura, on 08/2007]],
- since = [[5.1]],
- example = [[lua -ltemp (assuming temp.lua has an error)]],
- patch = [[
- lua.c:
- @@ -144,7 +144,7 @@
- static int dolibrary (lua_State *L, const char *name) {
- lua_getglobal(L, "require");
- lua_pushstring(L, name);
- - return report(L, lua_pcall(L, 1, 0, 0));
- + return report(L, docall(L, 1, 1));
- }
- ]],
- }
- Bug{
- what = [['gsub' may go wild when wrongly called without its third
- argument and with a large subject]],
- report = [[Florian Berger, on 10/2007]],
- since = [[5.1]],
- example = [[
- x = string.rep('a', 10000) .. string.rep('b', 10000)
- print(#string.gsub(x, 'b'))
- ]],
- patch = [[
- lstrlib.c:
- @@ -631,6 +631,2 @@
- }
- - default: {
- - luaL_argerror(L, 3, "string/function/table expected");
- - return;
- - }
- }
- @@ -650,2 +646,3 @@
- const char *p = luaL_checkstring(L, 2);
- + int tr = lua_type(L, 3);
- int max_s = luaL_optint(L, 4, srcl+1);
- @@ -655,2 +652,5 @@
- luaL_Buffer b;
- + luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
- + tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
- + "string/function/table expected");
- luaL_buffinit(L, &b);
- ]],
- }
- Bug{
- what = [[table.remove removes last element of a table when given
- an out-of-bound index]],
- report = [[Patrick Donnelly, on 11/2007]],
- since = [[5.0]],
- example = [[
- a = {1,2,3}
- table.remove(a, 4)
- print(a[3]) --> nil (should be 3)
- ]],
- patch = [[
- ltablib.c:
- @@ -118,7 +118,8 @@
- static int tremove (lua_State *L) {
- int e = aux_getn(L, 1);
- int pos = luaL_optint(L, 2, e);
- - if (e == 0) return 0; /* table is `empty' */
- + if (!(1 <= pos && pos <= e)) /* position is outside bounds? */
- + return 0; /* nothing to remove */
- luaL_setn(L, 1, e - 1); /* t.n = n-1 */
- lua_rawgeti(L, 1, pos); /* result = t[pos] */
- for ( ;pos<e; pos++) {
- ]],
- }
- Bug{
- what = [[lua_setfenv may crash if called over an invalid object]],
- report = [[Mike Pall, on 11/2007]],
- since = [[5.1]],
- example = [[
- > debug.setfenv(3, {})
- ]],
- patch = [[
- lapi.c:
- @@ -749,7 +749,7 @@
- res = 0;
- break;
- }
- - luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
- + if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
- L->top--;
- lua_unlock(L);
- return res;
- ]],
- }
- Bug{
- what = [[stand-alone interpreter shows incorrect error message
- when the "message" is a coroutine]],
- report = [[Patrick Donnelly, on 17/12/2007]],
- since = [[5.1]],
- example = [[> error(coroutine.create(function() end))]],
- patch = [[
- lua.c:
- @@ -74,6 +74,8 @@
-
-
- static int traceback (lua_State *L) {
- + if (!lua_isstring(L, 1)) /* 'message' not a string? */
- + return 1; /* keep it intact */
- lua_getfield(L, LUA_GLOBALSINDEX, "debug");
- if (!lua_istable(L, -1)) {
- lua_pop(L, 1);
- ]],
- }
- Bug{
- what = [[debug.sethook/gethook may overflow the thread's stack]],
- report = [[Ivko Stanilov, on 2008/01/04]],
- since = [[5.1]],
- example = [[
- a = coroutine.create(function() yield() end)
- coroutine.resume(a)
- debug.sethook(a) -- may overflow the stack of 'a'
- ]],
- patch = [[
- ldblib.c:
- @@ -268,12 +268,11 @@
- count = luaL_optint(L, arg+3, 0);
- func = hookf; mask = makemask(smask, count);
- }
- - gethooktable(L1);
- - lua_pushlightuserdata(L1, L1);
- + gethooktable(L);
- + lua_pushlightuserdata(L, L1);
- lua_pushvalue(L, arg+1);
- - lua_xmove(L, L1, 1);
- - lua_rawset(L1, -3); /* set new hook */
- - lua_pop(L1, 1); /* remove hook table */
- + lua_rawset(L, -3); /* set new hook */
- + lua_pop(L, 1); /* remove hook table */
- lua_sethook(L1, func, mask, count); /* set hooks */
- return 0;
- }
- @@ -288,11 +287,10 @@
- if (hook != NULL && hook != hookf) /* external hook? */
- lua_pushliteral(L, "external hook");
- else {
- - gethooktable(L1);
- - lua_pushlightuserdata(L1, L1);
- - lua_rawget(L1, -2); /* get hook */
- - lua_remove(L1, -2); /* remove hook table */
- - lua_xmove(L1, L, 1);
- + gethooktable(L);
- + lua_pushlightuserdata(L, L1);
- + lua_rawget(L, -2); /* get hook */
- + lua_remove(L, -2); /* remove hook table */
- }
- lua_pushstring(L, unmakemask(mask, buff));
- lua_pushinteger(L, lua_gethookcount(L1));
- ]]
- }
- -----------------------------------------------------------------
- -- Lua 5.1.3
- Bug{
- what = [[LUAI_MAXCSTACK must be smaller than -LUA_REGISTRYINDEX]],
- report = [[Patrick Donnelly, on 2008/02/11]],
- since = [[5.1.3]],
- example = [[
- j = 1e4
- co = coroutine.create(function()
- t = {}
- for i = 1, j do t[i] = i end
- return unpack(t)
- end)
- print(coroutine.resume(co))
- ]],
- patch = [[
- luaconf.h:
- 443c443,444
- < ** functions to consume unlimited stack space.
- ---
- > ** functions to consume unlimited stack space. (must be smaller than
- > ** -LUA_REGISTRYINDEX)
- 445,446c446
- < #define LUAI_MCS_AUX ((int)(INT_MAX / (4*sizeof(LUA_NUMBER))))
- < #define LUAI_MAXCSTACK (LUAI_MCS_AUX > SHRT_MAX ? SHRT_MAX : LUAI_MCS_AUX)
- ---
- > #define LUAI_MAXCSTACK 8000
- ]],
- }
- Bug{
- what = [[coroutine.resume pushes element without ensuring stack size]],
- report = [[on 2008/02/11]],
- since = [[5.0]],
- example = [[(this bug cannot be detected without internal assertions)]],
- patch = [[
- lbaselib.c:
- @@ -526,7 +526,7 @@
- status = lua_resume(co, narg);
- if (status == 0 || status == LUA_YIELD) {
- int nres = lua_gettop(co);
- - if (!lua_checkstack(L, nres))
- + if (!lua_checkstack(L, nres + 1))
- luaL_error(L, "too many results to resume");
- lua_xmove(co, L, nres); /* move yielded values */
- return nres;
- ]],
- }
- Bug{
- what = [[lua_checkstack may have arithmetic overflow for large 'size']],
- report = [[Patrick Donnelly, on 2008/02/12]],
- since = [[5.0]],
- example = [[
- print(unpack({1,2,3}, 0, 2^31-3))
- ]],
- patch = [[
- --- lapi.c 2008/01/03 15:20:39 2.55.1.3
- +++ lapi.c 2008/02/14 16:05:21
- @@ -93,15 +93,14 @@
-
-
- LUA_API int lua_checkstack (lua_State *L, int size) {
- - int res;
- + int res = 1;
- lua_lock(L);
- - if ((L->top - L->base + size) > LUAI_MAXCSTACK)
- + if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK)
- res = 0; /* stack overflow */
- - else {
- + else if (size > 0) {
- luaD_checkstack(L, size);
- if (L->ci->top < L->top + size)
- L->ci->top = L->top + size;
- - res = 1;
- }
- lua_unlock(L);
- return res;
- ]],
- }
- Bug{
- what = [[unpack with maximum indices may crash due to arithmetic overflow]],
- report = [[Patrick Donnelly, on 2008/02/12]],
- since = [[5.1]],
- example = [[
- print(unpack({1,2,3}, 2^31-1, 2^31-1))
- ]],
- patch = [[
- --- lbaselib.c 2008/02/11 16:24:24 1.191.1.5
- +++ lbaselib.c 2008/02/14 16:10:25
- @@ -344,10 +344,12 @@
- luaL_checktype(L, 1, LUA_TTABLE);
- i = luaL_optint(L, 2, 1);
- e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
- + if (i > e) return 0; /* empty range */
- n = e - i + 1; /* number of elements */
- - if (n <= 0) return 0; /* empty range */
- - luaL_checkstack(L, n, "table too big to unpack");
- - for (; i<=e; i++) /* push arg[i...e] */
- + if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
- + return luaL_error(L, "too many results to unpack");
- + lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
- + while (i++ < e) /* push arg[i + 1...e] */
- lua_rawgeti(L, 1, i);
- return n;
- }
- ]],
- }
- Bug{
- what = [[The validator for precompiled code has several flaws that
- allow malicious binary code to crash the application]],
- report = [[Peter Cawley, on 2008/03/24]],
- since = [[5.0]],
- example = [[
- a = string.dump(function()return;end)
- a = a:gsub(string.char(30,37,122,128), string.char(34,0,0), 1)
- loadstring(a)()
- ]],
- patch = [[
- --- ldebug.c 2007/12/28 15:32:23 2.29.1.3
- +++ ldebug.c 2008/04/04 15:15:40
- @@ -275,12 +275,12 @@
-
- static int precheck (const Proto *pt) {
- check(pt->maxstacksize <= MAXSTACK);
- - lua_assert(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
- - lua_assert(!(pt->is_vararg & VARARG_NEEDSARG) ||
- + check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);
- + check(!(pt->is_vararg & VARARG_NEEDSARG) ||
- (pt->is_vararg & VARARG_HASARG));
- check(pt->sizeupvalues <= pt->nups);
- check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
- - check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
- + check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
- return 1;
- }
-
- @@ -363,7 +363,11 @@
- }
- switch (op) {
- case OP_LOADBOOL: {
- - check(c == 0 || pc+2 < pt->sizecode); /* check its jump */
- + if (c == 1) { /* does it jump? */
- + check(pc+2 < pt->sizecode); /* check its jump */
- + check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||
- + GETARG_C(pt->code[pc+1]) != 0);
- + }
- break;
- }
- case OP_LOADNIL: {
- @@ -428,7 +432,10 @@
- }
- case OP_SETLIST: {
- if (b > 0) checkreg(pt, a + b);
- - if (c == 0) pc++;
- + if (c == 0) {
- + pc++;
- + check(pc < pt->sizecode - 1);
- + }
- break;
- }
- case OP_CLOSURE: {
- ]],
- }
- Bug{
- what = [[maliciously crafted precompiled code can blow the C stack]],
- report = [[Greg Falcon, on 2008/03/25]],
- since = [[5.0]],
- example = [[
- function crash(depth)
- local init = '\27\76\117\97\81\0\1\4\4\4\8\0\7\0\0\0\61\115\116' ..
- '\100\105\110\0\1\0\0\0\1\0\0\0\0\0\0\2\2\0\0\0\36' ..
- '\0\0\0\30\0\128\0\0\0\0\0\1\0\0\0\0\0\0\0\1\0\0\0' ..
- '\1\0\0\0\0\0\0\2'
- 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'
- 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' ..
- '\0\0\97\0\1\0\0\0\1\0\0\0\0\0\0\0'
- 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' ..
- '\0\1\0\0\0\1\0\0\0\0\0\0\2'
- 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' ..
- '\0\0\97\0\1\0\0\0\1'
- for i=1,depth do lch,rch = lch..lch,rch..rch end
- loadstring(init .. lch .. mid .. rch .. fin)
- end
- for i=1,25 do print(i); crash(i) end
- ]],
- patch = [[
- --- lundump.c 2008/04/04 16:00:45 2.7.1.3
- +++ lundump.c 2008/04/04 19:51:41 2.7.1.4
- @@ -161,7 +161,9 @@
-
- static Proto* LoadFunction(LoadState* S, TString* p)
- {
- - Proto* f=luaF_newproto(S->L);
- + Proto* f;
- + if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
- + f=luaF_newproto(S->L);
- setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
- f->source=LoadString(S); if (f->source==NULL) f->source=p;
- f->linedefined=LoadInt(S);
- @@ -175,6 +177,7 @@
- LoadDebug(S,f);
- IF (!luaG_checkcode(f), "bad code");
- S->L->top--;
- + S->L->nCcalls--;
- return f;
- }
- ]],
- }
- Bug{
- what = [[code validator may reject (maliciously crafted) correct code]],
- report = [[Greg Falcon, on 2008/03/26]],
- since = [[5.0]],
- example = [[
- z={}
- for i=1,27290 do z[i]='1,' end
- z = 'if 1+1==2 then local a={' .. table.concat(z) .. '} end'
- func = loadstring(z)
- print(loadstring(string.dump(func)))
- ]],
- patch = [[
- --- ldebug.c 2008/04/04 15:30:05 2.29.1.4
- +++ ldebug.c 2008/04/04 15:47:10
- @@ -346,9 +346,18 @@
- int dest = pc+1+b;
- check(0 <= dest && dest < pt->sizecode);
- if (dest > 0) {
- - /* cannot jump to a setlist count */
- - Instruction d = pt->code[dest-1];
- - check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0));
- + int j;
- + /* check that it does not jump to a setlist count; this
- + is tricky, because the count from a previous setlist may
- + have the same value of an invalid setlist; so, we must
- + go all the way back to the first of them (if any) */
- + for (j = 0; j < dest; j++) {
- + Instruction d = pt->code[dest-1-j];
- + if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;
- + }
- + /* if 'j' is even, previous value is not a setlist (even if
- + it looks like one) */
- + check((j&1) == 0);
- }
- }
- break;
- ]],
- }
- Bug{
- what = [[maliciously crafted precompiled code can inject invalid boolean
- values into Lua code]],
- report = [[Greg Falcon, on 2008/03/27]],
- since = [[5.0]],
- example = [[
- maybe = string.dump(function() return ({[true]=true})[true] end)
- maybe = maybe:gsub('\1\1','\1\2')
- maybe = loadstring(maybe)()
- assert(type(maybe) == "boolean" and maybe ~= true and maybe ~= false)
- ]],
- patch = [[
- --- lundump.c 2008/01/18 16:39:11 2.7.1.2
- +++ lundump.c 2008/04/04 15:50:39
- @@ -115,7 +115,7 @@
- setnilvalue(o);
- break;
- case LUA_TBOOLEAN:
- - setbvalue(o,LoadChar(S));
- + setbvalue(o,LoadChar(S)!=0);
- break;
- case LUA_TNUMBER:
- setnvalue(o,LoadNumber(S));
- ]],
- }
- Bug{
- what = [['string.byte' gets confused with some out-of-range negative indices]],
- report = [[Mike Pall, on 2008/06/03]],
- since = [[5.1]],
- example = [[
- print(string.byte("abc", -5)) --> 97 98 99 (should print nothing)
- ]],
- patch = [[
- --- lstrlib.c 2007/12/28 15:32:23 1.132.1.3
- +++ lstrlib.c 2008/07/05 11:53:42
- @@ -35,7 +35,8 @@
-
- static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
- /* relative string position: negative means back from end */
- - return (pos>=0) ? pos : (ptrdiff_t)len+pos+1;
- + if (pos < 0) pos += (ptrdiff_t)len + 1;
- + return (pos >= 0) ? pos : 0;
- }
-
-
- ]],
- }
- Bug{
- what = [[user-requested GC step may loop forever]],
- report = [[Makoto Hamanaka, on 2008/07/01]],
- since = [[5.1]],
- example = [[
- collectgarbage("setpause", 100) -- small value
- collectgarbage("setstepmul", 2000) -- large value
- collectgarbage("step",0)
- ]],
- patch = [[
- --- lapi.c 2008/02/14 16:46:39 2.55.1.4
- +++ lapi.c 2008/07/04 18:34:48
- @@ -929,10 +929,13 @@
- g->GCthreshold = g->totalbytes - a;
- else
- g->GCthreshold = 0;
- - while (g->GCthreshold <= g->totalbytes)
- + while (g->GCthreshold <= g->totalbytes) {
- luaC_step(L);
- - if (g->gcstate == GCSpause) /* end of cycle? */
- - res = 1; /* signal it */
- + if (g->gcstate == GCSpause) { /* end of cycle? */
- + res = 1; /* signal it */
- + break;
- + }
- + }
- break;
- }
- case LUA_GCSETPAUSE: {
- ]],
- }
- Bug{
- what = [['module' may change the environment of a C function]],
- report = [[Peter Cawley, on 2008/07/16]],
- since = [[5.1]],
- example = [[
- pcall(module, "xuxu")
- assert(debug.getfenv(pcall) == xuxu)
- ]],
- patch = [[
- --- loadlib.c 2007/12/28 14:58:43 1.52.1.2
- +++ loadlib.c 2008/08/05 19:39:00
- @@ -506,8 +506,11 @@
-
- static void setfenv (lua_State *L) {
- lua_Debug ar;
- - lua_getstack(L, 1, &ar);
- - lua_getinfo(L, "f", &ar);
- + if (lua_getstack(L, 1, &ar) == 0 ||
- + lua_getinfo(L, "f", &ar) == 0 || /* get calling function */
- + lua_iscfunction(L, -1))
- + luaL_error(L, "function " LUA_QL("module")
- + " not called from a Lua function");
- lua_pushvalue(L, -2);
- lua_setfenv(L, -2);
- lua_pop(L, 1);
- ]],
- }
- Bug{
- what = [[internal macro 'svalue' is wrong]],
- report = [[Martijn van Buul, on 2008/08/04]],
- since = [[5.1]],
- example = [[
- /* in luaconf.h */
- #define LUAI_USER_ALIGNMENT_T union { char b[32]; }
- ]],
- patch = [[
- --- lobject.h 2007/12/27 13:02:25 2.20.1.1
- +++ lobject.h 2008/08/05 19:40:48
- @@ -210,3 +210,3 @@
- #define getstr(ts) cast(const char *, (ts) + 1)
- -#define svalue(o) getstr(tsvalue(o))
- +#define svalue(o) getstr(rawtsvalue(o))
-
- ]],
- }
- -----------------------------------------------------------------
- -- Lua 5.1.4
- Bug{
- what = [[malicious zero-length string in binary code may segfault Lua]],
- report = [[Peter Cawley, on 2008/09/01]],
- since = [[5.1]],
- example = [[
- loadstring(('').dump(function()X''end):gsub('\2%z%z%zX','\0\0\0'))()
- ]],
- patch = [[
- ]],
- }
- Bug{
- what = [[wrong code generation for some particular boolean expressions]],
- report = [[Brian Kelley, on 2009/04/15]],
- since = [[5.0]],
- example = [[
- print(((1 or false) and true) or false) --> 1
- -- should be 'true'
- ]],
- patch = [[
- --- lcode.c 2007/12/28 15:32:23 2.25.1.3
- +++ lcode.c 2009/06/15 14:07:34
- @@ -544,15 +544,18 @@
- pc = NO_JUMP; /* always true; do nothing */
- break;
- }
- - case VFALSE: {
- - pc = luaK_jump(fs); /* always jump */
- - break;
- - }
- case VJMP: {
- invertjump(fs, e);
- pc = e->u.s.info;
- break;
- }
- + case VFALSE: {
- + if (!hasjumps(e)) {
- + pc = luaK_jump(fs); /* always jump */
- + break;
- + }
- + /* else go through */
- + }
- default: {
- pc = jumponcond(fs, e, 0);
- break;
- @@ -572,14 +575,17 @@
- pc = NO_JUMP; /* always false; do nothing */
- break;
- }
- - case VTRUE: {
- - pc = luaK_jump(fs); /* always jump */
- - break;
- - }
- case VJMP: {
- pc = e->u.s.info;
- break;
- }
- + case VTRUE: {
- + if (!hasjumps(e)) {
- + pc = luaK_jump(fs); /* always jump */
- + break;
- + }
- + /* else go through */
- + }
- default: {
- pc = jumponcond(fs, e, 1);
- break;
- ]],
- }
- Bug{
- what = [['luaV_settable' may invalidate a reference to a table and try
- to reuse it]],
- report = [[Mark Feldman, on 2009/06/27]],
- since = [[5.0]],
- example = [[
- grandparent = {}
- grandparent.__newindex = function(s,_,_) print(s) end
- parent = {}
- parent.__newindex = parent
- setmetatable(parent, grandparent)
- child = setmetatable({}, parent)
- child.foo = 10 --> (crash on some machines)
- ]],
- patch = [[
- --- lvm.c 2007/12/28 15:32:23 2.63.1.3
- +++ lvm.c 2009/07/01 20:36:59
- @@ -133,6 +133,7 @@
-
- void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
- int loop;
- + TValue temp;
- for (loop = 0; loop < MAXTAGLOOP; loop++) {
- const TValue *tm;
- if (ttistable(t)) { /* `t' is a table? */
- @@ -152,7 +153,9 @@
- callTM(L, tm, t, key, val);
- return;
- }
- - t = tm; /* else repeat with `tm' */
- + /* else repeat with `tm' */
- + setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */
- + t = &temp;
- }
- luaG_runerror(L, "loop in settable");
- }
- ]],
- }
- Bug{
- what = [[smart use of varargs may create functions that return too
- many arguments and overflow the stack of C functions]],
- report = [[Patrick Donnelly, on 2008/12/10]],
- since = [[]],
- example = [[
- local function lunpack(i, ...)
- if i == 0 then return ...
- else
- return lunpack(i-1, 1, ...)
- end
- end
- Now, if C calls lunpack(n) with a huge n, it may end with
- too many values in its stack and confuse its stack indices.
- ]],
- patch = [[
- ]],
- }
- Bug{
- what = [['debug.getfenv' does not check whether it has an argument]],
- report = [[Patrick Donnelly, 2009/07/30]],
- since = [[5.1]],
- example = [[debug.getfenv() -- should raise an error]],
- patch = [[
- --- ldblib.c 2008/01/21 13:11:21 1.104.1.3
- +++ ldblib.c 2009/08/04 18:43:12
- @@ -45,6 +45,7 @@
-
-
- static int db_getfenv (lua_State *L) {
- + luaL_checkany(L, 1);
- lua_getfenv(L, 1);
- return 1;
- }
- ]],
- }
- Bug{
- what = [[GC may get stuck during a parser and avoids proper resizing of
- the string table,
- making its lists grow too much and degrading performance]],
- report = [[Sean Conner, 2009/11/10]],
- since = [[5.1]],
- example = [[See http://lua-users.org/lists/lua-l/2009-11/msg00463.html]],
- patch = [[
- --- llex.c 2007/12/27 13:02:25 2.20.1.1
- +++ llex.c 2009/11/23 14:49:40
- @@ -118,8 +118,10 @@
- lua_State *L = ls->L;
- TString *ts = luaS_newlstr(L, str, l);
- TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */
- - if (ttisnil(o))
- + if (ttisnil(o)) {
- setbvalue(o, 1); /* make sure `str' will not be collected */
- + luaC_checkGC(L);
- + }
- return ts;
- }
-
- ]]
- }
- Bug{
- what = [['string.format' may get buffer as an argument when there are
- missing arguments and format string is too long]],
- report = [[Roberto I., 2010/04/12]],
- since = [[5.0]],
- example = [[
- x = string.rep("x", 10000) .. "%d"
- print(string.format(x)) -- gives wrong error message
- ]],
- patch = [[
- --- lstrlib.c 2008/07/11 17:27:21 1.132.1.4
- +++ lstrlib.c 2010/05/14 15:12:53
- @@ -754,6 +754,7 @@
-
-
- static int str_format (lua_State *L) {
- + int top = lua_gettop(L);
- int arg = 1;
- size_t sfl;
- const char *strfrmt = luaL_checklstring(L, arg, &sfl);
- @@ -768,7 +769,8 @@
- else { /* format item */
- char form[MAX_FORMAT]; /* to store the format (`%...') */
- char buff[MAX_ITEM]; /* to store the formatted item */
- - arg++;
- + if (++arg > top)
- + luaL_argerror(L, arg, "no value");
- strfrmt = scanformat(L, strfrmt, form);
- switch (*strfrmt++) {
- case 'c': {
- ]]
- }
- Bug{
- what = [['io.read(op, "*n")' may return garbage if second read fails]],
- report = [[Roberto I., 2010/04/12]],
- since = [[5.0]],
- example = [[
- print(io.read("*n", "*n")) --<< enter "10 hi"
- --> file (0x884420) nil
- ]],
- patch = [[
- --- liolib.c 2008/01/18 17:47:43 2.73.1.3
- +++ liolib.c 2010/05/14 15:29:29
- @@ -276,7 +276,10 @@
- lua_pushnumber(L, d);
- return 1;
- }
- - else return 0; /* read fails */
- + else {
- + lua_pushnil(L); /* "result" to be removed */
- + return 0; /* read fails */
- + }
- }
-
-
- ]]
- }
- Bug{
- what = [[wrong code generation for some particular boolean expressions]],
- report = [[Thierry Van Elsuwe, 2011/01/20]],
- since = [[5.0]],
- example = [[
- print((('hi' or true) and true) or true)
- --> hi (should be true)
- print(((nil and nil) or false) and true)
- --> nil (should be false)
- ]],
- patch = [[
- --- lcode.c 2009/06/15 14:12:25 2.25.1.4
- +++ lcode.c 2011/01/31 14:44:25
- @@ -549,13 +549,6 @@
- pc = e->u.s.info;
- break;
- }
- - case VFALSE: {
- - if (!hasjumps(e)) {
- - pc = luaK_jump(fs); /* always jump */
- - break;
- - }
- - /* else go through */
- - }
- default: {
- pc = jumponcond(fs, e, 0);
- break;
- @@ -579,13 +572,6 @@
- pc = e->u.s.info;
- break;
- }
- - case VTRUE: {
- - if (!hasjumps(e)) {
- - pc = luaK_jump(fs); /* always jump */
- - break;
- - }
- - /* else go through */
- - }
- default: {
- pc = jumponcond(fs, e, 1);
- break;
- ]]
- }
- Bug{
- what = [[__newindex metamethod may not work if metatable is its own
- metatable]],
- report = [[Cuero Bugot, 2011/08/09]],
- since = [[5.1]],
- example = [[
- meta={}
- setmetatable(meta, meta)
- meta.__newindex = function(t, key, value) print("set") end
- o = setmetatable({}, meta)
- o.x = 10 -- should print 'set'
- ]],
- patch = [[
- --- lvm.c 2009/07/01 21:10:33 2.63.1.4
- +++ lvm.c 2011/08/17 20:36:28
- @@ -142,6 +142,7 @@
- if (!ttisnil(oldval) || /* result is no nil? */
- (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
- setobj2t(L, oldval, val);
- + h->flags = 0;
- luaC_barriert(L, h, val);
- return;
- }
- ]]
- }
- Bug{
- what = [[parser may collect a prototype while building it]],
- report = [[Ingo van Lil, 2011/10/13]],
- since = [[5.1.4 (caused by patch 5.1.4-6)]],
- example = nil,
- patch = [[
- --- lparser.c 2007/12/28 15:32:23 2.42.1.3
- +++ lparser.c 2011/10/17 13:10:43
- @@ -374,9 +374,9 @@
- lua_assert(luaG_checkcode(f));
- lua_assert(fs->bl == NULL);
- ls->fs = fs->prev;
- - L->top -= 2; /* remove table and prototype from the stack */
- /* last token read was anchored in defunct function; must reanchor it */
- if (fs) anchor_token(ls);
- + L->top -= 2; /* remove table and prototype from the stack */
- }
-
-
- ]]
- }
- Bug{
- what = [[When loading a file,
- Lua may call the reader function again after it returned end of input
- ]],
- report = [[Chris Howie, 2013/06/05]],
- since = [[5.1]],
- fix = [[5.2]],
- example = [[
- load(function () print("called"); return nil end)
- --> called
- --> called (should be called only once!)
- ]],
- patch = [[
- --- lzio.h 2007/12/27 13:02:25 1.21.1.1
- +++ lzio.h 2013/07/04 13:55:59
- @@ -59,6 +59,7 @@
- lua_Reader reader;
- void* data; /* additional data */
- lua_State *L; /* Lua state (for reader) */
- + int eoz; /* true if reader has no more data */
- };
- --- lzio.c 2007/12/27 13:02:25 1.31.1.1
- +++ lzio.c 2013/07/04 13:53:06
- @@ -22,10 +22,14 @@
- size_t size;
- lua_State *L = z->L;
- const char *buff;
- + if (z->eoz) return EOZ;
- lua_unlock(L);
- buff = z->reader(L, z->data, &size);
- lua_lock(L);
- - if (buff == NULL || size == 0) return EOZ;
- + if (buff == NULL || size == 0) {
- + z->eoz = 1; /* avoid calling reader function next time */
- + return EOZ;
- + }
- z->n = size - 1;
- z->p = buff;
- return char2int(*(z->p++));
- @@ -51,6 +55,7 @@
- z->data = data;
- z->n = 0;
- z->p = NULL;
- + z->eoz = 0;
- }
- ]]
- }
- -----------------------------------------------------------------
- -- Lua 5.2.0
- Bug{
- what = [[memory hoarding when creating Lua hooks for coroutines]],
- report = [[Arseny Vakhrushev, 2012/01/16]],
- since = [[5.1]],
- fix = [[5.2.1]],
- example = [[
- collectgarbage(); print(collectgarbage'count' * 1024)
- for i = 1, 100 do
- local co = coroutine.create(function () end)
- local x = {}
- for j=1,1000 do x[j] = j end
- debug.sethook(co, function () return x end, 'l')
- end
- collectgarbage(); print(collectgarbage'count' * 1024)
- -- value should back to near the original level
- ]],
- patch = [[
- -- For 5.2
- --- ldblib.c 2011/10/24 14:54:05 1.131
- +++ ldblib.c 2012/01/18 02:36:59
- @@ -253,14 +253,15 @@
- }
-
-
- -#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY);
- +#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)
-
-
- static void hookf (lua_State *L, lua_Debug *ar) {
- static const char *const hooknames[] =
- {"call", "return", "line", "count", "tail call"};
- gethooktable(L);
- - lua_rawgetp(L, -1, L);
- + lua_pushthread(L);
- + lua_rawget(L, -2);
- if (lua_isfunction(L, -1)) {
- lua_pushstring(L, hooknames[(int)ar->event]);
- if (ar->currentline >= 0)
- @@ -306,10 +307,15 @@
- count = luaL_optint(L, arg+3, 0);
- func = hookf; mask = makemask(smask, count);
- }
- - gethooktable(L);
- + if (gethooktable(L) == 0) { /* creating hook table? */
- + lua_pushstring(L, "k");
- + lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */
- + lua_pushvalue(L, -1);
- + lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */
- + }
- + lua_pushthread(L1); lua_xmove(L1, L, 1);
- lua_pushvalue(L, arg+1);
- - lua_rawsetp(L, -2, L1); /* set new hook */
- - lua_pop(L, 1); /* remove hook table */
- + lua_rawset(L, -3); /* set new hook */
- lua_sethook(L1, func, mask, count); /* set hooks */
- return 0;
- }
- @@ -325,7 +331,8 @@
- lua_pushliteral(L, "external hook");
- else {
- gethooktable(L);
- - lua_rawgetp(L, -1, L1); /* get hook */
- + lua_pushthread(L1); lua_xmove(L1, L, 1);
- + lua_rawget(L, -2); /* get hook */
- lua_remove(L, -2); /* remove hook table */
- }
- lua_pushstring(L, unmakemask(mask, buff));
- ]]
- }
- Bug{
- what = [[Lexical gets confused with some combination of arithmetic
- operators and hexadecimal numbers]],
- report = [[Alexandra Barros, 2012/01/17]],
- since = [[5.2.0]],
- fix = [[5.2.1]],
- example = [[print(0xE+1)]],
- patch = [[
- --- llex.c 2011/11/30 12:43:51 2.59
- +++ llex.c 2012/01/20 18:22:50
- @@ -223,12 +223,19 @@
- /* LUA_NUMBER */
- static void read_numeral (LexState *ls, SemInfo *seminfo) {
- + const char *expo = "Ee";
- + int first = ls->current;
- lua_assert(lisdigit(ls->current));
- - do {
- - save_and_next(ls);
- - if (check_next(ls, "EePp")) /* exponent part? */
- + save_and_next(ls);
- + if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */
- + expo = "Pp";
- + for (;;) {
- + if (check_next(ls, expo)) /* exponent part? */
- check_next(ls, "+-"); /* optional exponent sign */
- - } while (lislalnum(ls->current) || ls->current == '.');
- + if (lisxdigit(ls->current) || ls->current == '.')
- + save_and_next(ls);
- + else break;
- + }
- save(ls, '\0');
- buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
- if (!buff2d(ls->buff, &seminfo->r)) /* format error? */
- ]]
- }
- Bug{
- what = [[Finalizers may call functions from a dynamic library after
- the library has been unloaded]],
- report = [[Josh Haberman, 2012/04/08]],
- since = [[5.1]],
- fix = [[5.2.1]],
- example = [[
- local u = setmetatable({}, {__gc = function () foo() end})
- local m = require 'mod' -- 'mod' may be any dynamic library written in C
- foo = m.foo -- 'foo' may be any function from 'mod'
- -- end program; it crashes
- ]],
- patch = [[
- loadlib.c:
- 95c95
- < #define LIBPREFIX "LOADLIB: "
- ---
- > #define CLIBS "_CLIBS"
- 251,266c251,256
- <
- < static void **ll_register (lua_State *L, const char *path) {
- < void **plib;
- < lua_pushfstring(L, "%s%s", LIBPREFIX, path);
- < lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */
- < if (!lua_isnil(L, -1)) /* is there an entry? */
- < plib = (void **)lua_touserdata(L, -1);
- < else { /* no entry yet; create one */
- < lua_pop(L, 1); /* remove result from gettable */
- < plib = (void **)lua_newuserdata(L, sizeof(const void *));
- < *plib = NULL;
- < luaL_setmetatable(L, "_LOADLIB");
- < lua_pushfstring(L, "%s%s", LIBPREFIX, path);
- < lua_pushvalue(L, -2);
- < lua_settable(L, LUA_REGISTRYINDEX);
- < }
- ---
- > static void *ll_checkclib (lua_State *L, const char *path) {
- > void *plib;
- > lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
- > lua_getfield(L, -1, path);
- > plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */
- > lua_pop(L, 2); /* pop CLIBS table and 'plib' */
- 270a261,270
- > static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
- > lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
- > lua_pushlightuserdata(L, plib);
- > lua_pushvalue(L, -1);
- > lua_setfield(L, -3, path); /* CLIBS[path] = plib */
- > lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
- > lua_pop(L, 1); /* pop CLIBS table */
- > }
- >
- >
- 272,273c272,273
- < ** __gc tag method: calls library's `ll_unloadlib' function with the lib
- < ** handle
- ---
- > ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
- > ** handles in list CLIBS
- 276,278c276,281
- < void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
- < if (*lib) ll_unloadlib(*lib);
- < *lib = NULL; /* mark library as closed */
- ---
- > int n = luaL_len(L, 1);
- > for (; n >= 1; n--) { /* for each handle, in reverse order */
- > lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */
- > ll_unloadlib(lua_touserdata(L, -1));
- > lua_pop(L, 1); /* pop handle */
- > }
- 284,286c287,292
- < void **reg = ll_register(L, path);
- < if (*reg == NULL) *reg = ll_load(L, path, *sym == '*');
- < if (*reg == NULL) return ERRLIB; /* unable to load library */
- ---
- > void *reg = ll_checkclib(L, path); /* check loaded C libraries */
- > if (reg == NULL) { /* must load library? */
- > reg = ll_load(L, path, *sym == '*');
- > if (reg == NULL) return ERRLIB; /* unable to load library */
- > ll_addtoclib(L, path, reg);
- > }
- 292c298
- < lua_CFunction f = ll_sym(L, *reg, sym);
- ---
- > lua_CFunction f = ll_sym(L, reg, sym);
- 675,676c681,683
- < /* create new type _LOADLIB */
- < luaL_newmetatable(L, "_LOADLIB");
- ---
- > /* create table CLIBS to keep track of loaded C libraries */
- > luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
- > lua_createtable(L, 0, 1); /* metatable for CLIBS */
- 678a686
- > lua_setmetatable(L, -2);
- ]]
- }
- Bug{
- what = [[wrong handling of 'nCcalls' in coroutines]],
- report = [[Alexander Gavrilov, 2012/04/18]],
- since = [[5.2.0]],
- fix = [[5.2.1]],
- example = [[
- coroutine.wrap(function()
- print(pcall(pcall,pcall,pcall,pcall,pcall,error,3))
- end)()
- ]],
- patch = [[
- --- ldo.c 2011/11/29 15:55:08 2.102
- +++ ldo.c 2012/04/26 20:38:32
- @@ -402,8 +402,6 @@
- int n;
- lua_assert(ci->u.c.k != NULL); /* must have a continuation */
- lua_assert(L->nny == 0);
- - /* finish 'luaD_call' */
- - L->nCcalls--;
- /* finish 'lua_callk' */
- adjustresults(L, ci->nresults);
- /* call continuation function */
- @@ -513,7 +511,6 @@
- api_checknelems(L, n);
- firstArg = L->top - n; /* yield results come from continuation */
- }
- - L->nCcalls--; /* finish 'luaD_call' */
- luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
- }
- unroll(L, NULL);
- ]]
- }
- Bug{
- what = [[Internal Lua values may escape through the debug API]],
- report = [[Dan Tull, 2012/04/20]],
- since = [[5.1]],
- fix = [[5.2.1]],
- example = [[
- -- for Lua 5.1
- local firsttime = true
- local function foo ()
- if firsttime then
- firsttime = false
- return "a = 1"
- else
- for i = 1, 10 do
- print(debug.getlocal(2, i))
- end
- end
- end
- print(load(foo)) -- prints some lines and then seg. fault.
- ]],
- patch = [[
- ]]
- }
- Bug{
- what = [[Problems when yielding from debug hooks]],
- report = [[Erik Cassel, 2012/06/05]],
- since = [[5.2.0]],
- fix = [[5.2.1]],
- example = [[
- Set, in C, a line hook that simply yields,
- and then call any Lua function.
- You get an infinite loop of yields.
- ]],
- patch = [[
- ]]
- }
- -----------------------------------------------------------------
- -- Lua 5.2.1
- Bug{
- what = [[Some patterns can overflow the C stack, due to recursion]],
- report = [[Tim Starling, 2012/07/08]],
- since = [[2.5]],
- fix = [[5.2.2]],
- example = [[print(string.find(string.rep("a", 2^20), string.rep(".?", 2^20)))]],
- patch = [[
- ]]
- }
- Bug{
- what = [['pcall' may not restore previous error function when
- inside coroutines]],
- report = [[Alexander Gavrilov, 2012/06/12]],
- since = [[5.2.0]],
- fix = [[5.2.2]],
- example = [[
- function errfunc(x)
- return 'errfunc'
- end
- function test(do_yield)
- print(do_yield and "yielding" or "not yielding")
- pcall(function() -- this pcall sets errfunc back to none
- if do_yield then
- coroutine.yield() -- stops errfunc from being restored
- end
- end)
- error('fail!')
- end
- coro = coroutine.wrap(function()
- print(xpcall(test, errfunc, false))
- print(xpcall(test, errfunc, true))
- print(xpcall(test, errfunc, false))
- end)
- coro()
- --> not yielding
- --> false errfunc
- --> yielding
- coro()
- --> false temp:12: fail! <<<< should be 'errfunc' too
- --> not yielding
- --> false errfunc
- ]],
- patch = [[
- --- ldo.c 2012/08/28 18:30:45 2.107
- +++ ldo.c 2012/09/23 15:49:55
- @@ -403,7 +403,11 @@
- int n;
- lua_assert(ci->u.c.k != NULL); /* must have a continuation */
- lua_assert(L->nny == 0);
- - /* finish 'lua_callk' */
- + if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */
- + ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */
- + L->errfunc = ci->u.c.old_errfunc;
- + }
- + /* finish 'lua_callk'/'lua_pcall' */
- adjustresults(L, ci->nresults);
- /* call continuation function */
- if (!(ci->callstatus & CIST_STAT)) /* no call status? */
- ]]
- }
- Bug{
- what = [[Check for garbage collector in function calls does not cover
- all paths]],
- report = [[Roberto, 2012/08/15]],
- since = [[5.2.1]],
- fix = [[5.2.2]],
- example = [[
- See <a href="http://lua-users.org/lists/lua-l/2012-08/msg00149.html">
- http://lua-users.org/lists/lua-l/2012-08/msg00149.html</a>
- ]],
- patch = [[
- @@ -311,6 +311,7 @@
- ci->top = L->top + LUA_MINSTACK;
- lua_assert(ci->top <= L->stack_last);
- ci->callstatus = 0;
- + luaC_checkGC(L); /* stack grow uses memory */
- if (L->hookmask & LUA_MASKCALL)
- luaD_hook(L, LUA_HOOKCALL, -1);
- lua_unlock(L);
- @@ -338,6 +339,7 @@
- ci->u.l.savedpc = p->code; /* starting point */
- ci->callstatus = CIST_LUA;
- L->top = ci->top;
- + luaC_checkGC(L); /* stack grow uses memory */
- if (L->hookmask & LUA_MASKCALL)
- callhook(L, ci);
- return 0;
- @@ -393,7 +395,6 @@
- luaV_execute(L); /* call it */
- if (!allowyield) L->nny--;
- L->nCcalls--;
- - luaC_checkGC(L);
- }
- ]]
- }
- Bug{
- what = [[load/loadfile returns wrong result when given an environment
- for a binary chunk with no upvalues]],
- report = [[Vladimir Strakh, 2012/11/28]],
- since = [[5.2.0]],
- fix = [[5.2.2]],
- example = [[
- f = load(string.dump(function () return 1 end), nil, "b", {})
- print(type(f)) --> table (whould be a function)
- ]],
- patch = [[
- --- lbaselib.c 2012/04/27 14:13:19 1.274
- +++ lbaselib.c 2012/12/03 20:08:15
- @@ -244,5 +244,11 @@
-
- -static int load_aux (lua_State *L, int status) {
- - if (status == LUA_OK)
- +static int load_aux (lua_State *L, int status, int envidx) {
- + if (status == LUA_OK) {
- + if (envidx != 0) { /* 'env' parameter? */
- + lua_pushvalue(L, envidx); /* environment for loaded function */
- + if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
- + lua_pop(L, 1); /* remove 'env' if not used by previous call */
- + }
- return 1;
- + }
- else {
- @@ -258,9 +264,5 @@
- const char *mode = luaL_optstring(L, 2, NULL);
- - int env = !lua_isnone(L, 3); /* 'env' parameter? */
- + int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
- int status = luaL_loadfilex(L, fname, mode);
- - if (status == LUA_OK && env) { /* 'env' parameter? */
- - lua_pushvalue(L, 3);
- - lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */
- - }
- - return load_aux(L, status);
- + return load_aux(L, status, env);
- }
- @@ -309,5 +311,5 @@
- size_t l;
- - int top = lua_gettop(L);
- const char *s = lua_tolstring(L, 1, &l);
- const char *mode = luaL_optstring(L, 3, "bt");
- + int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
- if (s != NULL) { /* loading a string? */
- @@ -322,7 +324,3 @@
- }
- - if (status == LUA_OK && top >= 4) { /* is there an 'env' argument */
- - lua_pushvalue(L, 4); /* environment for loaded function */
- - lua_setupvalue(L, -2, 1); /* set it as 1st upvalue */
- - }
- - return load_aux(L, status);
- + return load_aux(L, status, env);
- }
- ]]
- }
- -----------------------------------------------------------------
- -- Lua 5.2.2
- Bug{
- what = [[stack overflow in vararg functions with many fixed
- parameters called with few arguments]],
- report = [[云风, 2013/04/17]],
- since = [[5.1]],
- fix = [[5.2.3]],
- example = [[
- function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
- p11, p12, p13, p14, p15, p16, p17, p18, p19, p20,
- p21, p22, p23, p24, p25, p26, p27, p28, p29, p30,
- p31, p32, p33, p34, p35, p36, p37, p38, p39, p40,
- p41, p42, p43, p44, p45, p46, p48, p49, p50, ...)
- local a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14
- end
- f() -- seg. fault (on some machines)
- ]],
- patch = [[
- --- ldo.c 2012/10/01 14:05:04 2.108
- +++ ldo.c 2013/04/19 20:56:06
- @@ -324,7 +324,7 @@
- case LUA_TLCL: { /* Lua function: prepare its call */
- StkId base;
- Proto *p = clLvalue(func)->p;
- - luaD_checkstack(L, p->maxstacksize);
- + luaD_checkstack(L, p->maxstacksize + p->numparams);
- func = restorestack(L, funcr);
- n = cast_int(L->top - func) - 1; /* number of real arguments */
- for (; n < p->numparams; n++)
- ]],
- }
- Bug{
- what = [[garbage collector can trigger too many times in recursive loops]],
- report = [[Roberto, 2013/04/25]],
- since = [[5.2.2]],
- fix = [[5.2.3]],
- example = [[
- function f() f() end
- f() -- it takes too long before a "stack overflow" error
- ]],
- patch = [[
- --- lgc.c 2013/04/12 18:48:47 2.140.1.1
- +++ lgc.c 2013/04/25 21:30:20
- @@ -495,2 +495,3 @@
- static lu_mem traversestack (global_State *g, lua_State *th) {
- + int n = 0;
- StkId o = th->stack;
- @@ -505,3 +506,9 @@
- }
- - return sizeof(lua_State) + sizeof(TValue) * th->stacksize;
- + else { /* count call infos to compute size */
- + CallInfo *ci;
- + for (ci = &th->base_ci; ci != th->ci; ci = ci->next)
- + n++;
- + }
- + return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
- + sizeof(CallInfo) * n;
- }
- ]]
- }
- -- [[]]
- Bug{
- what = [[Wrong assert when reporting concatenation errors
- (manifests only when Lua is compiled in debug mode)]],
- report = [[Roberto, 2013/05/05]],
- since = [[?]],
- fix = [[5.2.3]],
- example = [[
- -- only with Lua compiled in debug mode
- print({} .. 2)
- ]],
- patch = [[
- --- ldebug.c 2013/04/12 18:48:47 2.90.1.1
- +++ ldebug.c 2013/05/05 14:38:30
- @@ -519,5 +519,5 @@
- l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
- if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
- - lua_assert(!ttisstring(p1) && !ttisnumber(p2));
- + lua_assert(!ttisstring(p1) && !ttisnumber(p1));
- luaG_typeerror(L, p1, "concatenate");
- }
- ]]
- }
- Bug{
- what = [[Wrong error message in some short-cut expressions]],
- report = [[Egor Skriptunoff, 2013/05/10]],
- since = [[5.0]],
- fix = [[5.2.3]],
- example = [[
- > a,b,c = true,true,true
- > (a and b or c)('', '')
- stdin:1: attempt to call a boolean value (global 'c')
- (It should be global 'b' instead of 'c'.)
- ]],
- patch = [[
- --- ldebug.c 2013/05/06 17:20:22 2.90.1.2
- +++ ldebug.c 2013/05/14 19:52:48
- @@ -327,12 +327,20 @@
- }
-
-
- +static int filterpc (int pc, int jmptarget) {
- + if (pc < jmptarget) /* is code conditional (inside a jump)? */
- + return -1; /* cannot know who sets that register */
- + else return pc; /* current position sets that register */
- +}
- +
- +
- /*
- ** try to find last instruction before 'lastpc' that modified register 'reg'
- */
- static int findsetreg (Proto *p, int lastpc, int reg) {
- int pc;
- int setreg = -1; /* keep last instruction that changed 'reg' */
- + int jmptarget = 0; /* any code before this address is conditional */
- for (pc = 0; pc < lastpc; pc++) {
- Instruction i = p->code[pc];
- OpCode op = GET_OPCODE(i);
- @@ -341,33 +349,38 @@
- case OP_LOADNIL: {
- int b = GETARG_B(i);
- if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */
- - setreg = pc;
- + setreg = filterpc(pc, jmptarget);
- break;
- }
- case OP_TFORCALL: {
- - if (reg >= a + 2) setreg = pc; /* affect all regs above its base */
- + if (reg >= a + 2) /* affect all regs above its base */
- + setreg = filterpc(pc, jmptarget);
- break;
- }
- case OP_CALL:
- case OP_TAILCALL: {
- - if (reg >= a) setreg = pc; /* affect all registers above base */
- + if (reg >= a) /* affect all registers above base */
- + setreg = filterpc(pc, jmptarget);
- break;
- }
- case OP_JMP: {
- int b = GETARG_sBx(i);
- int dest = pc + 1 + b;
- /* jump is forward and do not skip `lastpc'? */
- - if (pc < dest && dest <= lastpc)
- - pc += b; /* do the jump */
- + if (pc < dest && dest <= lastpc) {
- + if (dest > jmptarget)
- + jmptarget = dest; /* update 'jmptarget' */
- + }
- break;
- }
- case OP_TEST: {
- - if (reg == a) setreg = pc; /* jumped code can change 'a' */
- + if (reg == a) /* jumped code can change 'a' */
- + setreg = filterpc(pc, jmptarget);
- break;
- }
- default:
- if (testAMode(op) && reg == a) /* any instruction that set A */
- - setreg = pc;
- + setreg = filterpc(pc, jmptarget);
- break;
- }
- }
- ]]
- }
- Bug{
- what = [[luac listings choke on long strings]],
- report = [[Ashwin Hirschi, 2013/07/03]],
- since = [[5.1.2]],
- fix = [[5.2.3]],
- example = [[
- -- When you call 'luac -l' over this chunk, it chokes the output
- s="Lorem ipsum dolor sit amet, consectetur, "
- ]],
- patch = [[
- --- luac.c 2011-11-29 15:46:33 -0200 1.69
- +++ luac.c 2013-07-03 21:26:01 -0300
- @@ -251,7 +251,7 @@
- static void PrintConstant(const Proto* f, int i)
- {
- const TValue* o=&f->k[i];
- - switch (ttype(o))
- + switch (ttypenv(o))
- {
- case LUA_TNIL:
- printf("nil");
- ]]
- }
- Bug{
- what = [[GC can collect a long string still in use during parser]],
- report = [[Roberto, 2013/08/30]],
- since = [[5.2]],
- fix = [[5.2.3]],
- example = [[This bug is very difficult to happen (and to reproduce),
- because it depends on the GC running in a very specific way when
- parsing a source code with long (larger than 40 characters) identifiers.]],
- patch = [[
- --- ltable.h 2013/04/12 18:48:47 2.16.1.1
- +++ ltable.h 2013/08/30 15:34:24
- @@ -18,4 +18,8 @@
- #define invalidateTMcache(t) ((t)->flags = 0)
-
- +/* returns the key, given the value of a table entry */
- +#define keyfromval(v) \
- + (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val))))
- +
-
- LUAI_FUNC const TValue *luaH_getint (Table *t, int key);
- --- llex.c 2013/04/12 18:48:47 2.63.1.1
- +++ llex.c 2013/08/30 15:34:59
- @@ -134,4 +134,7 @@
- luaC_checkGC(L);
- }
- + else { /* string already present */
- + ts = rawtsvalue(keyfromval(o)); /* re-use value previously stored */
- + }
- L->top--; /* remove string from stack */
- return ts;
- ]]
- }
- Bug{
- what = [[Call to macro 'luai_userstateclose' should be done only
- after the calls to __gc methods.]],
- report = [[Jean-Luc Jumpertz, 2013/09/02]],
- since = [[ ]],
- fix = nil,
- example = [[No example]],
- patch = [[
- --- lstate.c 2013/04/12 18:48:47 2.99.1.1
- +++ lstate.c 2013/11/08 17:39:57
- @@ -194,2 +194,4 @@
- g->gcrunning = 1; /* allow gc */
- + g->version = lua_version(NULL);
- + luai_userstateopen(L);
- }
- @@ -224,2 +226,4 @@
- luaC_freeallobjects(L); /* collect all objects */
- + if (g->version) /* closing a fully built state? */
- + luai_userstateclose(L);
- luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
- @@ -289,3 +293,3 @@
- g->panic = NULL;
- - g->version = lua_version(NULL);
- + g->version = NULL;
- g->gcstate = GCSpause;
- @@ -308,4 +312,2 @@
- }
- - else
- - luai_userstateopen(L);
- return L;
- @@ -317,3 +319,2 @@
- lua_lock(L);
- - luai_userstateclose(L);
- close_state(L);
- ]]
- }
- Bug{
- what = [[Resuming the running coroutine makes it unyieldable]],
- report = [[Florian Nücke, 2013/10/28]],
- since = [[5.2]],
- fix = [[5.2.3]],
- example = [[
- -- should print 'true'
- print(coroutine.resume(coroutine.create(function()
- coroutine.resume(coroutine.running())
- coroutine.yield()
- end)))
- ]],
- patch = [[
- --- ldo.c 2013/04/19 21:03:23 2.108.1.2
- +++ ldo.c 2013/11/08 18:20:57
- @@ -536,2 +536,3 @@
- int status;
- + int oldnny = L->nny; /* save 'nny' */
- lua_lock(L);
- @@ -557,3 +558,3 @@
- }
- - L->nny = 1; /* do not allow yields */
- + L->nny = oldnny; /* restore 'nny' */
- L->nCcalls--;
- ]]
- }
- -----------------------------------------------------------------
- -- Lua 5.2.3
- Bug{
- what = [[compiler can optimize away overflow check in 'table.unpack']],
- report = [[Paige DePol, 2014/03/30]],
- since = [[5.1 (at least)]],
- fix = nil,
- example = [[
- > unpack({}, 0, 2^31 - 1)
- (segfaults on some platforms with some compiler options)
- ]],
- patch = [[
- --- ltablib.c 2013/04/12 18:48:47 1.65.1.1
- +++ ltablib.c 2014/05/07 16:32:55 1.65.1.2
- @@ -134,13 +135,14 @@
-
-
- static int unpack (lua_State *L) {
- - int i, e, n;
- + int i, e;
- + unsigned int n;
- luaL_checktype(L, 1, LUA_TTABLE);
- i = luaL_optint(L, 2, 1);
- e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1));
- if (i > e) return 0; /* empty range */
- - n = e - i + 1; /* number of elements */
- - if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */
- + n = (unsigned int)e - (unsigned int)i; /* number of elements minus 1 */
- + if (n > (INT_MAX - 10) || !lua_checkstack(L, ++n))
- return luaL_error(L, "too many results to unpack");
- lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */
- while (i++ < e) /* push arg[i + 1...e] */
- ]]
- }
- Bug{
- what = [[Ephemeron table can wrongly collect entry with strong key]],
- report = [[Jörg Richter, 2014/08/22]],
- since = [[5.2]],
- fix = nil,
- example = [[
- (This bug is very hard to reproduce,
- because it depends on a specific interleaving of
- events between the incremental collector and the program.)
- ]],
- patch = [[
- --- lgc.c 2013/04/26 18:22:05 2.140.1.2
- +++ lgc.c 2014/09/01 13:24:33
- @@ -403,7 +403,7 @@
- reallymarkobject(g, gcvalue(gval(n))); /* mark it now */
- }
- }
- - if (prop)
- + if (g->gcstate != GCSatomic || prop)
- linktable(h, &g->ephemeron); /* have to propagate again */
- else if (hasclears) /* does table have white keys? */
- linktable(h, &g->allweak); /* may have to clean white keys */
- ]]
- }
- Bug{
- what = [[Chunk with too many lines can seg. fault]],
- report = [[Roberto, 2014/11/14]],
- since = [[5.1 (at least)]],
- fix = nil,
- example = [[
- -- the cause of the bug is the use of an unitialized variable, so
- -- it cannot be reproduced reliably
- local s = string.rep("\n", 2^24)
- print(load(function () return s end))
- ]],
- patch = [[
- --- llex.c 2013/08/30 15:49:41 2.63.1.2
- +++ llex.c 2015/02/09 17:05:31
- @@ -153,5 +153,5 @@
- next(ls); /* skip `\n\r' or `\r\n' */
- if (++ls->linenumber >= MAX_INT)
- - luaX_syntaxerror(ls, "chunk has too many lines");
- + lexerror(ls, "chunk has too many lines", 0);
- }
-
- ]]
- }
- -----------------------------------------------------------------
- -- Lua 5.3.0
- Bug{
- what = [['string.format("%f")' can cause a buffer overflow
- (only when 'lua_Number' is long double!)]],
- report = [[Roberto, 2015/01/13]],
- since = [[5.3]],
- fix = nil,
- example = [[string.format("%.99f", 1e4000) -- when floats are long double]],
- patch = [[
- --- lstrlib.c 2014/12/11 14:03:07 1.221
- +++ lstrlib.c 2015/02/23 19:01:42
- @@ -800,3 +800,4 @@
- /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
- -#define MAX_ITEM 512
- +#define MAX_ITEM \
- + (sizeof(lua_Number) <= 4 ? 150 : sizeof(lua_Number) <= 8 ? 450 : 5050)
-
- ]]
- }
- Bug{
- what = [['debug.getlocal' on a coroutine suspended in a hook
- can crash the interpreter]],
- report = [[云风, 2015/02/11]],
- since = [[5.2]],
- fix = nil,
- example = [[see http://lua-users.org/lists/lua-l/2015-02/msg00146.html]],
- patch = [[
- --- ldebug.c 2015/01/02 12:52:22 2.110
- +++ ldebug.c 2015/02/13 16:03:23
- @@ -49,4 +49,14 @@
-
-
- +static void swapextra (lua_State *L) {
- + if (L->status == LUA_YIELD) {
- + CallInfo *ci = L->ci; /* get function that yielded */
- + StkId temp = ci->func; /* exchange its 'func' and 'extra' values */
- + ci->func = restorestack(L, ci->extra);
- + ci->extra = savestack(L, temp);
- + }
- +}
- +
- +
- /*
- ** this function can be called asynchronous (e.g. during a signal)
- @@ -145,4 +155,5 @@
- const char *name;
- lua_lock(L);
- + swapextra(L);
- if (ar == NULL) { /* information about non-active function? */
- if (!isLfunction(L->top - 1)) /* not a Lua function? */
- @@ -159,4 +170,5 @@
- }
- }
- + swapextra(L);
- lua_unlock(L);
- return name;
- @@ -166,10 +178,13 @@
- LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
- StkId pos = 0; /* to avoid warnings */
- - const char *name = findlocal(L, ar->i_ci, n, &pos);
- + const char *name;
- lua_lock(L);
- + swapextra(L);
- + name = findlocal(L, ar->i_ci, n, &pos);
- if (name) {
- setobjs2s(L, pos, L->top - 1);
- L->top--; /* pop value */
- }
- + swapextra(L);
- lua_unlock(L);
- return name;
- @@ -271,4 +286,5 @@
- StkId func;
- lua_lock(L);
- + swapextra(L);
- if (*what == '>') {
- ci = NULL;
- @@ -289,4 +305,5 @@
- api_incr_top(L);
- }
- + swapextra(L);
- if (strchr(what, 'L'))
- collectvalidlines(L, cl);
- ]]
- }
- Bug{
- what = [[suspended '__le' metamethod can give wrong result]],
- report = [[Eric Zhong, 2015/04/07]],
- since = [[5.2]],
- fix = nil,
- example = [[
- mt = {__le = function (a,b) coroutine.yield("yield"); return a.x <= b.x end}
- t1 = setmetatable({x=1}, mt)
- t2 = {x=2}
- co = coroutine.wrap(function (a,b) return t2 <= t1 end)
- co()
- print(co()) --> true (should be false)
- ]],
- patch = [[
- --- lstate.h 2014/10/30 18:53:28 2.119
- +++ lstate.h 2015/04/13 15:58:40
- @@ -94,6 +94,7 @@
- #define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
- #define CIST_TAIL (1<<5) /* call was tail called */
- #define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
- +#define CIST_LEQ (1<<7) /* using __lt for __le */
-
- #define isLua(ci) ((ci)->callstatus & CIST_LUA)
-
- --- lvm.c 2014/12/27 20:30:38 2.232
- +++ lvm.c 2015/04/13 15:51:30
- @@ -292,9 +292,14 @@
- return l_strcmp(tsvalue(l), tsvalue(r)) <= 0;
- else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try 'le' */
- return res;
- - else if ((res = luaT_callorderTM(L, r, l, TM_LT)) < 0) /* else try 'lt' */
- - luaG_ordererror(L, l, r);
- - return !res;
- + else { /* try 'lt': */
- + L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */
- + res = luaT_callorderTM(L, r, l, TM_LT);
- + L->ci->callstatus ^= CIST_LEQ; /* clear mark */
- + if (res < 0)
- + luaG_ordererror(L, l, r);
- + return !res; /* result is negated */
- + }
- }
-
-
- @@ -553,11 +558,11 @@
- case OP_LE: case OP_LT: case OP_EQ: {
- int res = !l_isfalse(L->top - 1);
- L->top--;
- - /* metamethod should not be called when operand is K */
- - lua_assert(!ISK(GETARG_B(inst)));
- - if (op == OP_LE && /* "<=" using "<" instead? */
- - ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE)))
- - res = !res; /* invert result */
- + if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */
- + lua_assert(op == OP_LE);
- + ci->callstatus ^= CIST_LEQ; /* clear mark */
- + res = !res; /* negate result */
- + }
- lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
- if (res != GETARG_A(inst)) /* condition failed? */
- ci->u.l.savedpc++; /* skip jump instruction */
- ]]
- }
- Bug{
- what = [[return hook may not see correct values for
- active local variables when function returns]],
- report = [[Philipp Janda/Peng Yi, 2015/05/19]],
- since = [[5.0]],
- fix = nil,
- example = [[
- see messasge http://lua-users.org/lists/lua-l/2015-05/msg00376.html]],
- patch = [[
- ]]
- }
- -----------------------------------------------------------------
- -- Lua 5.3.1
- Bug{
- what = [['io.lines' does not check maximum number of options]],
- report = [[Patrick Donnell, 2015/07/10]],
- since = [[3.0]],
- fix = nil,
- example = [[
- -- can segfault in some machines
- t ={}; for i = 1, 253 do t[i] = 1 end
- io.lines("someexistingfile", table.unpack(t))()
- ]],
- patch = [[
- --- liolib.c 2015/07/07 17:03:34 2.146
- +++ liolib.c 2015/07/15 14:40:28 2.147
- @@ -318,8 +318,15 @@
- static int io_readline (lua_State *L);
-
-
- +/*
- +** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
- +** in the limit for upvalues of a closure)
- +*/
- +#define MAXARGLINE 250
- +
- static void aux_lines (lua_State *L, int toclose) {
- int n = lua_gettop(L) - 1; /* number of arguments to read */
- + luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
- lua_pushinteger(L, n); /* number of arguments to read */
- lua_pushboolean(L, toclose); /* close/not close file when finished */
- lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */
- ]]
- }
- --[=[
- Bug{
- what = [[ ]],
- report = [[ ]],
- since = [[ ]],
- fix = nil,
- example = [[ ]],
- patch = [[
- ]]
- }
- ]=]
|