zend_inference.c 135 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine, e-SSA based Type & Range Inference |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Dmitry Stogov <dmitry@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "php.h"
  19. #include "zend_compile.h"
  20. #include "zend_generators.h"
  21. #include "zend_inference.h"
  22. #include "zend_func_info.h"
  23. #include "zend_call_graph.h"
  24. #include "zend_worklist.h"
  25. /* The used range inference algorithm is described in:
  26. * V. Campos, R. Rodrigues, I. de Assis Costa and F. Pereira.
  27. * "Speed and Precision in Range Analysis", SBLP'12.
  28. *
  29. * There are a couple degrees of freedom, we use:
  30. * * Propagation on SCCs.
  31. * * e-SSA for live range splitting.
  32. * * Only intra-procedural inference.
  33. * * Widening with warmup passes, but without jump sets.
  34. */
  35. /* Whether to handle symbolic range constraints */
  36. #define SYM_RANGE
  37. /* Whether to handle negative range constraints */
  38. /* Negative range inference is buggy, so disabled for now */
  39. #undef NEG_RANGE
  40. /* Number of warmup passes to use prior to widening */
  41. #define RANGE_WARMUP_PASSES 16
  42. /* Logging for range inference in general */
  43. #if 0
  44. #define LOG_SSA_RANGE(...) fprintf(stderr, __VA_ARGS__)
  45. #else
  46. #define LOG_SSA_RANGE(...)
  47. #endif
  48. /* Logging for negative range constraints */
  49. #if 0
  50. #define LOG_NEG_RANGE(...) fprintf(stderr, __VA_ARGS__)
  51. #else
  52. #define LOG_NEG_RANGE(...)
  53. #endif
  54. /* Pop elements in unspecified order from worklist until it is empty */
  55. #define WHILE_WORKLIST(worklist, len, i) do { \
  56. zend_bool _done = 0; \
  57. while (!_done) { \
  58. _done = 1; \
  59. ZEND_BITSET_FOREACH(worklist, len, i) { \
  60. zend_bitset_excl(worklist, i); \
  61. _done = 0;
  62. #define WHILE_WORKLIST_END() \
  63. } ZEND_BITSET_FOREACH_END(); \
  64. } \
  65. } while (0)
  66. #define CHECK_SCC_VAR(var2) \
  67. do { \
  68. if (!ssa->vars[var2].no_val) { \
  69. if (dfs[var2] < 0) { \
  70. zend_ssa_check_scc_var(op_array, ssa, var2, index, dfs, root, stack); \
  71. } \
  72. if (ssa->vars[var2].scc < 0 && dfs[root[var]] >= dfs[root[var2]]) { \
  73. root[var] = root[var2]; \
  74. } \
  75. } \
  76. } while (0)
  77. #define CHECK_SCC_ENTRY(var2) \
  78. do { \
  79. if (ssa->vars[var2].scc != ssa->vars[var].scc) { \
  80. ssa->vars[var2].scc_entry = 1; \
  81. } \
  82. } while (0)
  83. #define ADD_SCC_VAR(_var) \
  84. do { \
  85. if (ssa->vars[_var].scc == scc) { \
  86. zend_bitset_incl(worklist, _var); \
  87. } \
  88. } while (0)
  89. #define ADD_SCC_VAR_1(_var) \
  90. do { \
  91. if (ssa->vars[_var].scc == scc && \
  92. !zend_bitset_in(visited, _var)) { \
  93. zend_bitset_incl(worklist, _var); \
  94. } \
  95. } while (0)
  96. #define FOR_EACH_DEFINED_VAR(line, MACRO) \
  97. do { \
  98. if (ssa->ops[line].op1_def >= 0) { \
  99. MACRO(ssa->ops[line].op1_def); \
  100. } \
  101. if (ssa->ops[line].op2_def >= 0) { \
  102. MACRO(ssa->ops[line].op2_def); \
  103. } \
  104. if (ssa->ops[line].result_def >= 0) { \
  105. MACRO(ssa->ops[line].result_def); \
  106. } \
  107. if (op_array->opcodes[line].opcode == ZEND_OP_DATA) { \
  108. if (ssa->ops[line-1].op1_def >= 0) { \
  109. MACRO(ssa->ops[line-1].op1_def); \
  110. } \
  111. if (ssa->ops[line-1].op2_def >= 0) { \
  112. MACRO(ssa->ops[line-1].op2_def); \
  113. } \
  114. if (ssa->ops[line-1].result_def >= 0) { \
  115. MACRO(ssa->ops[line-1].result_def); \
  116. } \
  117. } else if ((uint32_t)line+1 < op_array->last && \
  118. op_array->opcodes[line+1].opcode == ZEND_OP_DATA) { \
  119. if (ssa->ops[line+1].op1_def >= 0) { \
  120. MACRO(ssa->ops[line+1].op1_def); \
  121. } \
  122. if (ssa->ops[line+1].op2_def >= 0) { \
  123. MACRO(ssa->ops[line+1].op2_def); \
  124. } \
  125. if (ssa->ops[line+1].result_def >= 0) { \
  126. MACRO(ssa->ops[line+1].result_def); \
  127. } \
  128. } \
  129. } while (0)
  130. #define FOR_EACH_VAR_USAGE(_var, MACRO) \
  131. do { \
  132. zend_ssa_phi *p = ssa->vars[_var].phi_use_chain; \
  133. int use = ssa->vars[_var].use_chain; \
  134. while (use >= 0) { \
  135. FOR_EACH_DEFINED_VAR(use, MACRO); \
  136. use = zend_ssa_next_use(ssa->ops, _var, use); \
  137. } \
  138. p = ssa->vars[_var].phi_use_chain; \
  139. while (p) { \
  140. MACRO(p->ssa_var); \
  141. p = zend_ssa_next_use_phi(ssa, _var, p); \
  142. } \
  143. } while (0)
  144. static inline zend_bool add_will_overflow(zend_long a, zend_long b) {
  145. return (b > 0 && a > ZEND_LONG_MAX - b)
  146. || (b < 0 && a < ZEND_LONG_MIN - b);
  147. }
  148. #if 0
  149. static inline zend_bool sub_will_overflow(zend_long a, zend_long b) {
  150. return (b > 0 && a < ZEND_LONG_MIN + b)
  151. || (b < 0 && a > ZEND_LONG_MAX + b);
  152. }
  153. #endif
  154. static void zend_ssa_check_scc_var(const zend_op_array *op_array, zend_ssa *ssa, int var, int *index, int *dfs, int *root, zend_worklist_stack *stack) /* {{{ */
  155. {
  156. #ifdef SYM_RANGE
  157. zend_ssa_phi *p;
  158. #endif
  159. dfs[var] = *index;
  160. (*index)++;
  161. root[var] = var;
  162. FOR_EACH_VAR_USAGE(var, CHECK_SCC_VAR);
  163. #ifdef SYM_RANGE
  164. /* Process symbolic control-flow constraints */
  165. p = ssa->vars[var].sym_use_chain;
  166. while (p) {
  167. CHECK_SCC_VAR(p->ssa_var);
  168. p = p->sym_use_chain;
  169. }
  170. #endif
  171. if (root[var] == var) {
  172. ssa->vars[var].scc = ssa->sccs;
  173. while (stack->len > 0) {
  174. int var2 = zend_worklist_stack_peek(stack);
  175. if (dfs[var2] <= dfs[var]) {
  176. break;
  177. }
  178. zend_worklist_stack_pop(stack);
  179. ssa->vars[var2].scc = ssa->sccs;
  180. }
  181. ssa->sccs++;
  182. } else {
  183. zend_worklist_stack_push(stack, var);
  184. }
  185. }
  186. /* }}} */
  187. int zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
  188. {
  189. int index = 0, *dfs, *root;
  190. zend_worklist_stack stack;
  191. int j;
  192. ALLOCA_FLAG(dfs_use_heap)
  193. ALLOCA_FLAG(root_use_heap)
  194. ALLOCA_FLAG(stack_use_heap)
  195. dfs = do_alloca(sizeof(int) * ssa->vars_count, dfs_use_heap);
  196. memset(dfs, -1, sizeof(int) * ssa->vars_count);
  197. root = do_alloca(sizeof(int) * ssa->vars_count, root_use_heap);
  198. ZEND_WORKLIST_STACK_ALLOCA(&stack, ssa->vars_count, stack_use_heap);
  199. /* Find SCCs using Tarjan's algorithm. */
  200. for (j = 0; j < ssa->vars_count; j++) {
  201. if (!ssa->vars[j].no_val && dfs[j] < 0) {
  202. zend_ssa_check_scc_var(op_array, ssa, j, &index, dfs, root, &stack);
  203. }
  204. }
  205. /* Revert SCC order. This results in a topological order. */
  206. for (j = 0; j < ssa->vars_count; j++) {
  207. if (ssa->vars[j].scc >= 0) {
  208. ssa->vars[j].scc = ssa->sccs - (ssa->vars[j].scc + 1);
  209. }
  210. }
  211. for (j = 0; j < ssa->vars_count; j++) {
  212. if (ssa->vars[j].scc >= 0) {
  213. int var = j;
  214. if (root[j] == j) {
  215. ssa->vars[j].scc_entry = 1;
  216. }
  217. FOR_EACH_VAR_USAGE(var, CHECK_SCC_ENTRY);
  218. }
  219. }
  220. ZEND_WORKLIST_STACK_FREE_ALLOCA(&stack, stack_use_heap);
  221. free_alloca(root, root_use_heap);
  222. free_alloca(dfs, dfs_use_heap);
  223. return SUCCESS;
  224. }
  225. /* }}} */
  226. int zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
  227. {
  228. zend_ssa_var *ssa_vars = ssa->vars;
  229. zend_ssa_op *ssa_ops = ssa->ops;
  230. int ssa_vars_count = ssa->vars_count;
  231. zend_bitset worklist;
  232. int i, j, use;
  233. zend_ssa_phi *p;
  234. ALLOCA_FLAG(use_heap);
  235. if (!op_array->function_name || !ssa->vars || !ssa->ops) {
  236. return SUCCESS;
  237. }
  238. worklist = do_alloca(sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count), use_heap);
  239. memset(worklist, 0, sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
  240. for (i = 0; i < ssa_vars_count; i++) {
  241. ssa_vars[i].no_val = 1; /* mark as unused */
  242. use = ssa->vars[i].use_chain;
  243. while (use >= 0) {
  244. if (!zend_ssa_is_no_val_use(&op_array->opcodes[use], &ssa->ops[use], i)) {
  245. ssa_vars[i].no_val = 0; /* used directly */
  246. zend_bitset_incl(worklist, i);
  247. break;
  248. }
  249. use = zend_ssa_next_use(ssa_ops, i, use);
  250. }
  251. }
  252. WHILE_WORKLIST(worklist, zend_bitset_len(ssa_vars_count), i) {
  253. if (ssa_vars[i].definition_phi) {
  254. /* mark all possible sources as used */
  255. p = ssa_vars[i].definition_phi;
  256. if (p->pi >= 0) {
  257. if (ssa_vars[p->sources[0]].no_val) {
  258. ssa_vars[p->sources[0]].no_val = 0; /* used indirectly */
  259. zend_bitset_incl(worklist, p->sources[0]);
  260. }
  261. } else {
  262. for (j = 0; j < ssa->cfg.blocks[p->block].predecessors_count; j++) {
  263. ZEND_ASSERT(p->sources[j] >= 0);
  264. if (ssa->vars[p->sources[j]].no_val) {
  265. ssa_vars[p->sources[j]].no_val = 0; /* used indirectly */
  266. zend_bitset_incl(worklist, p->sources[j]);
  267. }
  268. }
  269. }
  270. }
  271. } WHILE_WORKLIST_END();
  272. free_alloca(worklist, use_heap);
  273. return SUCCESS;
  274. }
  275. /* }}} */
  276. /* From "Hacker's Delight" */
  277. zend_ulong minOR(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
  278. {
  279. zend_ulong m, temp;
  280. m = Z_UL(1) << (sizeof(zend_ulong) * 8 - 1);
  281. while (m != 0) {
  282. if (~a & c & m) {
  283. temp = (a | m) & -m;
  284. if (temp <= b) {
  285. a = temp;
  286. break;
  287. }
  288. } else if (a & ~c & m) {
  289. temp = (c | m) & -m;
  290. if (temp <= d) {
  291. c = temp;
  292. break;
  293. }
  294. }
  295. m = m >> 1;
  296. }
  297. return a | c;
  298. }
  299. zend_ulong maxOR(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
  300. {
  301. zend_ulong m, temp;
  302. m = Z_UL(1) << (sizeof(zend_ulong) * 8 - 1);
  303. while (m != 0) {
  304. if (b & d & m) {
  305. temp = (b - m) | (m - 1);
  306. if (temp >= a) {
  307. b = temp;
  308. break;
  309. }
  310. temp = (d - m) | (m - 1);
  311. if (temp >= c) {
  312. d = temp;
  313. break;
  314. }
  315. }
  316. m = m >> 1;
  317. }
  318. return b | d;
  319. }
  320. zend_ulong minAND(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
  321. {
  322. zend_ulong m, temp;
  323. m = Z_UL(1) << (sizeof(zend_ulong) * 8 - 1);
  324. while (m != 0) {
  325. if (~a & ~c & m) {
  326. temp = (a | m) & -m;
  327. if (temp <= b) {
  328. a = temp;
  329. break;
  330. }
  331. temp = (c | m) & -m;
  332. if (temp <= d) {
  333. c = temp;
  334. break;
  335. }
  336. }
  337. m = m >> 1;
  338. }
  339. return a & c;
  340. }
  341. zend_ulong maxAND(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
  342. {
  343. zend_ulong m, temp;
  344. m = Z_UL(1) << (sizeof(zend_ulong) * 8 - 1);
  345. while (m != 0) {
  346. if (b & ~d & m) {
  347. temp = (b | ~m) | (m - 1);
  348. if (temp >= a) {
  349. b = temp;
  350. break;
  351. }
  352. } else if (~b & d & m) {
  353. temp = (d | ~m) | (m - 1);
  354. if (temp >= c) {
  355. d = temp;
  356. break;
  357. }
  358. }
  359. m = m >> 1;
  360. }
  361. return b & d;
  362. }
  363. zend_ulong minXOR(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
  364. {
  365. return minAND(a, b, ~d, ~c) | minAND(~b, ~a, c, d);
  366. }
  367. zend_ulong maxXOR(zend_ulong a, zend_ulong b, zend_ulong c, zend_ulong d)
  368. {
  369. return maxOR(0, maxAND(a, b, ~d, ~c), 0, maxAND(~b, ~a, c, d));
  370. }
  371. /* Based on "Hacker's Delight" */
  372. /*
  373. 0: + + + + 0 0 0 0 => 0 0 + min/max
  374. 2: + + - + 0 0 1 0 => 1 0 ? min(a,b,c,-1)/max(a,b,0,d)
  375. 3: + + - - 0 0 1 1 => 1 1 - min/max
  376. 8: - + + + 1 0 0 0 => 1 0 ? min(a,-1,b,d)/max(0,b,c,d)
  377. a: - + - + 1 0 1 0 => 1 0 ? MIN(a,c)/max(0,b,0,d)
  378. b: - + - - 1 0 1 1 => 1 1 - c/-1
  379. c: - - + + 1 1 0 0 => 1 1 - min/max
  380. e: - - - + 1 1 1 0 => 1 1 - a/-1
  381. f - - - - 1 1 1 1 => 1 1 - min/max
  382. */
  383. static void zend_ssa_range_or(zend_long a, zend_long b, zend_long c, zend_long d, zend_ssa_range *tmp)
  384. {
  385. int x = ((a < 0) ? 8 : 0) |
  386. ((b < 0) ? 4 : 0) |
  387. ((c < 0) ? 2 : 0) |
  388. ((d < 0) ? 2 : 0);
  389. switch (x) {
  390. case 0x0:
  391. case 0x3:
  392. case 0xc:
  393. case 0xf:
  394. tmp->min = minOR(a, b, c, d);
  395. tmp->max = maxOR(a, b, c, d);
  396. break;
  397. case 0x2:
  398. tmp->min = minOR(a, b, c, -1);
  399. tmp->max = maxOR(a, b, 0, d);
  400. break;
  401. case 0x8:
  402. tmp->min = minOR(a, -1, c, d);
  403. tmp->max = maxOR(0, b, c, d);
  404. break;
  405. case 0xa:
  406. tmp->min = MIN(a, c);
  407. tmp->max = maxOR(0, b, 0, d);
  408. break;
  409. case 0xb:
  410. tmp->min = c;
  411. tmp->max = -1;
  412. break;
  413. case 0xe:
  414. tmp->min = a;
  415. tmp->max = -1;
  416. break;
  417. }
  418. }
  419. /*
  420. 0: + + + + 0 0 0 0 => 0 0 + min/max
  421. 2: + + - + 0 0 1 0 => 0 0 + 0/b
  422. 3: + + - - 0 0 1 1 => 0 0 + min/max
  423. 8: - + + + 1 0 0 0 => 0 0 + 0/d
  424. a: - + - + 1 0 1 0 => 1 0 ? min(a,-1,c,-1)/NAX(b,d)
  425. b: - + - - 1 0 1 1 => 1 0 ? min(a,-1,c,d)/max(0,b,c,d)
  426. c: - - + + 1 1 0 0 => 1 1 - min/max
  427. e: - - - + 1 1 1 0 => 1 0 ? min(a,b,c,-1)/max(a,b,0,d)
  428. f - - - - 1 1 1 1 => 1 1 - min/max
  429. */
  430. static void zend_ssa_range_and(zend_long a, zend_long b, zend_long c, zend_long d, zend_ssa_range *tmp)
  431. {
  432. int x = ((a < 0) ? 8 : 0) |
  433. ((b < 0) ? 4 : 0) |
  434. ((c < 0) ? 2 : 0) |
  435. ((d < 0) ? 2 : 0);
  436. switch (x) {
  437. case 0x0:
  438. case 0x3:
  439. case 0xc:
  440. case 0xf:
  441. tmp->min = minAND(a, b, c, d);
  442. tmp->max = maxAND(a, b, c, d);
  443. break;
  444. case 0x2:
  445. tmp->min = 0;
  446. tmp->max = b;
  447. break;
  448. case 0x8:
  449. tmp->min = 0;
  450. tmp->max = d;
  451. break;
  452. case 0xa:
  453. tmp->min = minAND(a, -1, c, -1);
  454. tmp->max = MAX(b, d);
  455. break;
  456. case 0xb:
  457. tmp->min = minAND(a, -1, c, d);
  458. tmp->max = maxAND(0, b, c, d);
  459. break;
  460. case 0xe:
  461. tmp->min = minAND(a, b, c, -1);
  462. tmp->max = maxAND(a, b, 0, d);
  463. break;
  464. }
  465. }
  466. static inline zend_bool zend_abs_range(
  467. zend_long min, zend_long max, zend_long *abs_min, zend_long *abs_max) {
  468. if (min == ZEND_LONG_MIN) {
  469. /* Cannot take absolute value of LONG_MIN */
  470. return 0;
  471. }
  472. if (min >= 0) {
  473. *abs_min = min;
  474. *abs_max = max;
  475. } else if (max <= 0) {
  476. *abs_min = -max;
  477. *abs_max = -min;
  478. } else {
  479. /* Range crossing zero */
  480. *abs_min = 0;
  481. *abs_max = MAX(max, -min);
  482. }
  483. return 1;
  484. }
  485. static inline zend_bool shift_left_overflows(zend_long n, zend_long s) {
  486. /* This considers shifts that shift in the sign bit to be overflowing as well */
  487. if (n >= 0) {
  488. return s >= SIZEOF_ZEND_LONG * 8 - 1 || (n << s) < n;
  489. } else {
  490. return s >= SIZEOF_ZEND_LONG * 8 - 1 || (n << s) > n;
  491. }
  492. }
  493. /* Get the normal op corresponding to a compound assignment op */
  494. static inline zend_uchar get_compound_assign_op(zend_uchar opcode) {
  495. switch (opcode) {
  496. case ZEND_ASSIGN_ADD: return ZEND_ADD;
  497. case ZEND_ASSIGN_SUB: return ZEND_SUB;
  498. case ZEND_ASSIGN_MUL: return ZEND_MUL;
  499. case ZEND_ASSIGN_DIV: return ZEND_DIV;
  500. case ZEND_ASSIGN_MOD: return ZEND_MOD;
  501. case ZEND_ASSIGN_SL: return ZEND_SL;
  502. case ZEND_ASSIGN_SR: return ZEND_SR;
  503. case ZEND_ASSIGN_CONCAT: return ZEND_CONCAT;
  504. case ZEND_ASSIGN_BW_OR: return ZEND_BW_OR;
  505. case ZEND_ASSIGN_BW_AND: return ZEND_BW_AND;
  506. case ZEND_ASSIGN_BW_XOR: return ZEND_BW_XOR;
  507. case ZEND_ASSIGN_POW: return ZEND_POW;
  508. EMPTY_SWITCH_DEFAULT_CASE()
  509. }
  510. }
  511. static int zend_inference_calc_binary_op_range(
  512. const zend_op_array *op_array, zend_ssa *ssa,
  513. zend_op *opline, zend_ssa_op *ssa_op, zend_uchar opcode, zend_ssa_range *tmp) {
  514. zend_long op1_min, op2_min, op1_max, op2_max, t1, t2, t3, t4;
  515. switch (opcode) {
  516. case ZEND_ADD:
  517. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  518. op1_min = OP1_MIN_RANGE();
  519. op2_min = OP2_MIN_RANGE();
  520. op1_max = OP1_MAX_RANGE();
  521. op2_max = OP2_MAX_RANGE();
  522. tmp->min = op1_min + op2_min;
  523. tmp->max = op1_max + op2_max;
  524. if (OP1_RANGE_UNDERFLOW() ||
  525. OP2_RANGE_UNDERFLOW() ||
  526. (op1_min < 0 && op2_min < 0 && tmp->min >= 0)) {
  527. tmp->underflow = 1;
  528. tmp->min = ZEND_LONG_MIN;
  529. }
  530. if (OP1_RANGE_OVERFLOW() ||
  531. OP2_RANGE_OVERFLOW() ||
  532. (op1_max > 0 && op2_max > 0 && tmp->max <= 0)) {
  533. tmp->overflow = 1;
  534. tmp->max = ZEND_LONG_MAX;
  535. }
  536. return 1;
  537. }
  538. break;
  539. case ZEND_SUB:
  540. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  541. op1_min = OP1_MIN_RANGE();
  542. op2_min = OP2_MIN_RANGE();
  543. op1_max = OP1_MAX_RANGE();
  544. op2_max = OP2_MAX_RANGE();
  545. tmp->min = op1_min - op2_max;
  546. tmp->max = op1_max - op2_min;
  547. if (OP1_RANGE_UNDERFLOW() ||
  548. OP2_RANGE_OVERFLOW() ||
  549. (op1_min < 0 && op2_max > 0 && tmp->min >= 0)) {
  550. tmp->underflow = 1;
  551. tmp->min = ZEND_LONG_MIN;
  552. }
  553. if (OP1_RANGE_OVERFLOW() ||
  554. OP2_RANGE_UNDERFLOW() ||
  555. (op1_max > 0 && op2_min < 0 && tmp->max <= 0)) {
  556. tmp->overflow = 1;
  557. tmp->max = ZEND_LONG_MAX;
  558. }
  559. return 1;
  560. }
  561. break;
  562. case ZEND_MUL:
  563. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  564. op1_min = OP1_MIN_RANGE();
  565. op2_min = OP2_MIN_RANGE();
  566. op1_max = OP1_MAX_RANGE();
  567. op2_max = OP2_MAX_RANGE();
  568. t1 = op1_min * op2_min;
  569. t2 = op1_min * op2_max;
  570. t3 = op1_max * op2_min;
  571. t4 = op1_max * op2_max;
  572. // FIXME: more careful overflow checks?
  573. if (OP1_RANGE_UNDERFLOW() ||
  574. OP2_RANGE_UNDERFLOW() ||
  575. OP1_RANGE_OVERFLOW() ||
  576. OP2_RANGE_OVERFLOW() ||
  577. (double)t1 != (double)op1_min * (double)op2_min ||
  578. (double)t2 != (double)op1_min * (double)op2_max ||
  579. (double)t3 != (double)op1_max * (double)op2_min ||
  580. (double)t4 != (double)op1_max * (double)op2_max) {
  581. tmp->underflow = 1;
  582. tmp->overflow = 1;
  583. tmp->min = ZEND_LONG_MIN;
  584. tmp->max = ZEND_LONG_MAX;
  585. } else {
  586. tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
  587. tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
  588. }
  589. return 1;
  590. }
  591. break;
  592. case ZEND_DIV:
  593. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  594. op1_min = OP1_MIN_RANGE();
  595. op2_min = OP2_MIN_RANGE();
  596. op1_max = OP1_MAX_RANGE();
  597. op2_max = OP2_MAX_RANGE();
  598. if (op2_min <= 0 && op2_max >= 0) {
  599. break;
  600. }
  601. if (op1_min == ZEND_LONG_MIN && op2_max == -1) {
  602. /* Avoid ill-defined division, which may trigger SIGFPE. */
  603. break;
  604. }
  605. t1 = op1_min / op2_min;
  606. t2 = op1_min / op2_max;
  607. t3 = op1_max / op2_min;
  608. t4 = op1_max / op2_max;
  609. // FIXME: more careful overflow checks?
  610. if (OP1_RANGE_UNDERFLOW() ||
  611. OP2_RANGE_UNDERFLOW() ||
  612. OP1_RANGE_OVERFLOW() ||
  613. OP2_RANGE_OVERFLOW() ||
  614. t1 != (zend_long)((double)op1_min / (double)op2_min) ||
  615. t2 != (zend_long)((double)op1_min / (double)op2_max) ||
  616. t3 != (zend_long)((double)op1_max / (double)op2_min) ||
  617. t4 != (zend_long)((double)op1_max / (double)op2_max)) {
  618. tmp->underflow = 1;
  619. tmp->overflow = 1;
  620. tmp->min = ZEND_LONG_MIN;
  621. tmp->max = ZEND_LONG_MAX;
  622. } else {
  623. tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
  624. tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
  625. }
  626. return 1;
  627. }
  628. break;
  629. case ZEND_MOD:
  630. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  631. if (OP1_RANGE_UNDERFLOW() ||
  632. OP2_RANGE_UNDERFLOW() ||
  633. OP1_RANGE_OVERFLOW() ||
  634. OP2_RANGE_OVERFLOW()) {
  635. tmp->min = ZEND_LONG_MIN;
  636. tmp->max = ZEND_LONG_MAX;
  637. } else {
  638. zend_long op2_abs_min, op2_abs_max;
  639. op1_min = OP1_MIN_RANGE();
  640. op2_min = OP2_MIN_RANGE();
  641. op1_max = OP1_MAX_RANGE();
  642. op2_max = OP2_MAX_RANGE();
  643. if (!zend_abs_range(op2_min, op2_max, &op2_abs_min, &op2_abs_max)) {
  644. break;
  645. }
  646. if (op2_abs_max == 0) {
  647. /* Always modulus by zero, nothing we can do */
  648. break;
  649. }
  650. if (op2_abs_min == 0) {
  651. /* Ignore the modulus by zero case, which will throw */
  652. op2_abs_min++;
  653. }
  654. if (op1_min >= 0) {
  655. tmp->min = op1_max < op2_abs_min ? op1_min : 0;
  656. tmp->max = MIN(op1_max, op2_abs_max - 1);
  657. } else if (op1_max <= 0) {
  658. tmp->min = MAX(op1_min, -op2_abs_max + 1);
  659. tmp->max = op1_min > -op2_abs_min ? op1_max : 0;
  660. } else {
  661. tmp->min = MAX(op1_min, -op2_abs_max + 1);
  662. tmp->max = MIN(op1_max, op2_abs_max - 1);
  663. }
  664. }
  665. return 1;
  666. }
  667. break;
  668. case ZEND_SL:
  669. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  670. if (OP1_RANGE_UNDERFLOW() ||
  671. OP2_RANGE_UNDERFLOW() ||
  672. OP1_RANGE_OVERFLOW() ||
  673. OP2_RANGE_OVERFLOW()) {
  674. tmp->min = ZEND_LONG_MIN;
  675. tmp->max = ZEND_LONG_MAX;
  676. } else {
  677. op1_min = OP1_MIN_RANGE();
  678. op2_min = OP2_MIN_RANGE();
  679. op1_max = OP1_MAX_RANGE();
  680. op2_max = OP2_MAX_RANGE();
  681. /* Shifts by negative numbers will throw, ignore them */
  682. if (op2_min < 0) {
  683. op2_min = 0;
  684. }
  685. if (op2_max < 0) {
  686. op2_max = 0;
  687. }
  688. if (shift_left_overflows(op1_min, op2_max)
  689. || shift_left_overflows(op1_max, op2_max)) {
  690. tmp->min = ZEND_LONG_MIN;
  691. tmp->max = ZEND_LONG_MAX;
  692. } else {
  693. t1 = op1_min << op2_min;
  694. t2 = op1_min << op2_max;
  695. t3 = op1_max << op2_min;
  696. t4 = op1_max << op2_max;
  697. tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
  698. tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
  699. }
  700. }
  701. return 1;
  702. }
  703. break;
  704. case ZEND_SR:
  705. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  706. if (OP1_RANGE_UNDERFLOW() ||
  707. OP2_RANGE_UNDERFLOW() ||
  708. OP1_RANGE_OVERFLOW() ||
  709. OP2_RANGE_OVERFLOW()) {
  710. tmp->min = ZEND_LONG_MIN;
  711. tmp->max = ZEND_LONG_MAX;
  712. } else {
  713. op1_min = OP1_MIN_RANGE();
  714. op2_min = OP2_MIN_RANGE();
  715. op1_max = OP1_MAX_RANGE();
  716. op2_max = OP2_MAX_RANGE();
  717. /* Shifts by negative numbers will throw, ignore them */
  718. if (op2_min < 0) {
  719. op2_min = 0;
  720. }
  721. if (op2_max < 0) {
  722. op2_max = 0;
  723. }
  724. /* Shifts by more than the integer size will be 0 or -1 */
  725. if (op2_min >= SIZEOF_ZEND_LONG * 8) {
  726. op2_min = SIZEOF_ZEND_LONG * 8 - 1;
  727. }
  728. if (op2_max >= SIZEOF_ZEND_LONG * 8) {
  729. op2_max = SIZEOF_ZEND_LONG * 8 - 1;
  730. }
  731. t1 = op1_min >> op2_min;
  732. t2 = op1_min >> op2_max;
  733. t3 = op1_max >> op2_min;
  734. t4 = op1_max >> op2_max;
  735. tmp->min = MIN(MIN(t1, t2), MIN(t3, t4));
  736. tmp->max = MAX(MAX(t1, t2), MAX(t3, t4));
  737. }
  738. return 1;
  739. }
  740. break;
  741. case ZEND_BW_OR:
  742. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  743. if (OP1_RANGE_UNDERFLOW() ||
  744. OP2_RANGE_UNDERFLOW() ||
  745. OP1_RANGE_OVERFLOW() ||
  746. OP2_RANGE_OVERFLOW()) {
  747. tmp->min = ZEND_LONG_MIN;
  748. tmp->max = ZEND_LONG_MAX;
  749. } else {
  750. op1_min = OP1_MIN_RANGE();
  751. op2_min = OP2_MIN_RANGE();
  752. op1_max = OP1_MAX_RANGE();
  753. op2_max = OP2_MAX_RANGE();
  754. zend_ssa_range_or(op1_min, op1_max, op2_min, op2_max, tmp);
  755. }
  756. return 1;
  757. }
  758. break;
  759. case ZEND_BW_AND:
  760. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  761. if (OP1_RANGE_UNDERFLOW() ||
  762. OP2_RANGE_UNDERFLOW() ||
  763. OP1_RANGE_OVERFLOW() ||
  764. OP2_RANGE_OVERFLOW()) {
  765. tmp->min = ZEND_LONG_MIN;
  766. tmp->max = ZEND_LONG_MAX;
  767. } else {
  768. op1_min = OP1_MIN_RANGE();
  769. op2_min = OP2_MIN_RANGE();
  770. op1_max = OP1_MAX_RANGE();
  771. op2_max = OP2_MAX_RANGE();
  772. zend_ssa_range_and(op1_min, op1_max, op2_min, op2_max, tmp);
  773. }
  774. return 1;
  775. }
  776. break;
  777. case ZEND_BW_XOR:
  778. // TODO
  779. break;
  780. EMPTY_SWITCH_DEFAULT_CASE()
  781. }
  782. return 0;
  783. }
  784. int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int var, int widening, int narrowing, zend_ssa_range *tmp)
  785. {
  786. uint32_t line;
  787. zend_op *opline;
  788. zend_long op1_min, op2_min, op1_max, op2_max;
  789. if (ssa->vars[var].definition_phi) {
  790. zend_ssa_phi *p = ssa->vars[var].definition_phi;
  791. int i;
  792. tmp->underflow = 0;
  793. tmp->min = ZEND_LONG_MAX;
  794. tmp->max = ZEND_LONG_MIN;
  795. tmp->overflow = 0;
  796. if (p->pi >= 0 && p->has_range_constraint) {
  797. zend_ssa_range_constraint *constraint = &p->constraint.range;
  798. if (constraint->negative) {
  799. if (ssa->var_info[p->sources[0]].has_range) {
  800. *tmp = ssa->var_info[p->sources[0]].range;
  801. } else if (narrowing) {
  802. tmp->underflow = 1;
  803. tmp->min = ZEND_LONG_MIN;
  804. tmp->max = ZEND_LONG_MAX;
  805. tmp->overflow = 1;
  806. }
  807. #ifdef NEG_RANGE
  808. if (constraint->min_ssa_var < 0 &&
  809. constraint->max_ssa_var < 0 &&
  810. ssa->var_info[p->ssa_var].has_range) {
  811. LOG_NEG_RANGE("%s() #%d [%ld..%ld] -> [%ld..%ld]?\n",
  812. ZSTR_VAL(op_array->function_name),
  813. p->ssa_var,
  814. ssa->var_info[p->ssa_var].range.min,
  815. ssa->var_info[p->ssa_var].range.max,
  816. tmp->min,
  817. tmp->max);
  818. if (constraint->negative == NEG_USE_LT &&
  819. tmp->max >= constraint->range.min) {
  820. tmp->overflow = 0;
  821. tmp->max = constraint->range.min - 1;
  822. LOG_NEG_RANGE(" => [%ld..%ld]\n", tmp->min, tmp->max);
  823. } else if (constraint->negative == NEG_USE_GT &&
  824. tmp->min <= constraint->range.max) {
  825. tmp->underflow = 0;
  826. tmp->min = constraint->range.max + 1;
  827. LOG_NEG_RANGE(" => [%ld..%ld]\n", tmp->min, tmp->max);
  828. }
  829. }
  830. #endif
  831. } else if (ssa->var_info[p->sources[0]].has_range) {
  832. /* intersection */
  833. *tmp = ssa->var_info[p->sources[0]].range;
  834. if (constraint->min_ssa_var < 0) {
  835. tmp->underflow = constraint->range.underflow && tmp->underflow;
  836. tmp->min = MAX(constraint->range.min, tmp->min);
  837. #ifdef SYM_RANGE
  838. } else if (narrowing && ssa->var_info[constraint->min_ssa_var].has_range) {
  839. tmp->underflow = ssa->var_info[constraint->min_ssa_var].range.underflow && tmp->underflow;
  840. if (!add_will_overflow(ssa->var_info[constraint->min_ssa_var].range.min, constraint->range.min)) {
  841. tmp->min = MAX(ssa->var_info[constraint->min_ssa_var].range.min + constraint->range.min, tmp->min);
  842. }
  843. #endif
  844. }
  845. if (constraint->max_ssa_var < 0) {
  846. tmp->max = MIN(constraint->range.max, tmp->max);
  847. tmp->overflow = constraint->range.overflow && tmp->overflow;
  848. #ifdef SYM_RANGE
  849. } else if (narrowing && ssa->var_info[constraint->max_ssa_var].has_range) {
  850. if (!add_will_overflow(ssa->var_info[constraint->max_ssa_var].range.max, constraint->range.max)) {
  851. tmp->max = MIN(ssa->var_info[constraint->max_ssa_var].range.max + constraint->range.max, tmp->max);
  852. }
  853. tmp->overflow = ssa->var_info[constraint->max_ssa_var].range.overflow && tmp->overflow;
  854. #endif
  855. }
  856. } else if (narrowing) {
  857. if (constraint->min_ssa_var < 0) {
  858. tmp->underflow = constraint->range.underflow;
  859. tmp->min = constraint->range.min;
  860. #ifdef SYM_RANGE
  861. } else if (narrowing && ssa->var_info[constraint->min_ssa_var].has_range) {
  862. if (add_will_overflow(ssa->var_info[constraint->min_ssa_var].range.min, constraint->range.min)) {
  863. tmp->underflow = 1;
  864. tmp->min = ZEND_LONG_MIN;
  865. } else {
  866. tmp->underflow = ssa->var_info[constraint->min_ssa_var].range.underflow;
  867. tmp->min = ssa->var_info[constraint->min_ssa_var].range.min + constraint->range.min;
  868. }
  869. #endif
  870. } else {
  871. tmp->underflow = 1;
  872. tmp->min = ZEND_LONG_MIN;
  873. }
  874. if (constraint->max_ssa_var < 0) {
  875. tmp->max = constraint->range.max;
  876. tmp->overflow = constraint->range.overflow;
  877. #ifdef SYM_RANGE
  878. } else if (narrowing && ssa->var_info[constraint->max_ssa_var].has_range) {
  879. if (add_will_overflow(ssa->var_info[constraint->max_ssa_var].range.max, constraint->range.max)) {
  880. tmp->overflow = 1;
  881. tmp->max = ZEND_LONG_MAX;
  882. } else {
  883. tmp->max = ssa->var_info[constraint->max_ssa_var].range.max + constraint->range.max;
  884. tmp->overflow = ssa->var_info[constraint->max_ssa_var].range.overflow;
  885. }
  886. #endif
  887. } else {
  888. tmp->max = ZEND_LONG_MAX;
  889. tmp->overflow = 1;
  890. }
  891. }
  892. } else {
  893. for (i = 0; i < ssa->cfg.blocks[p->block].predecessors_count; i++) {
  894. ZEND_ASSERT(p->sources[i] >= 0);
  895. if (ssa->var_info[p->sources[i]].has_range) {
  896. /* union */
  897. tmp->underflow |= ssa->var_info[p->sources[i]].range.underflow;
  898. tmp->min = MIN(tmp->min, ssa->var_info[p->sources[i]].range.min);
  899. tmp->max = MAX(tmp->max, ssa->var_info[p->sources[i]].range.max);
  900. tmp->overflow |= ssa->var_info[p->sources[i]].range.overflow;
  901. } else if (narrowing) {
  902. tmp->underflow = 1;
  903. tmp->min = ZEND_LONG_MIN;
  904. tmp->max = ZEND_LONG_MAX;
  905. tmp->overflow = 1;
  906. }
  907. }
  908. }
  909. return (tmp->min <= tmp->max);
  910. } else if (ssa->vars[var].definition < 0) {
  911. if (var < op_array->last_var &&
  912. op_array->function_name) {
  913. tmp->min = 0;
  914. tmp->max = 0;
  915. tmp->underflow = 0;
  916. tmp->overflow = 0;
  917. return 1;
  918. }
  919. return 0;
  920. }
  921. line = ssa->vars[var].definition;
  922. opline = op_array->opcodes + line;
  923. tmp->underflow = 0;
  924. tmp->overflow = 0;
  925. switch (opline->opcode) {
  926. case ZEND_ADD:
  927. case ZEND_SUB:
  928. case ZEND_MUL:
  929. case ZEND_DIV:
  930. case ZEND_MOD:
  931. case ZEND_SL:
  932. case ZEND_SR:
  933. case ZEND_BW_OR:
  934. case ZEND_BW_AND:
  935. case ZEND_BW_XOR:
  936. if (ssa->ops[line].result_def == var) {
  937. return zend_inference_calc_binary_op_range(
  938. op_array, ssa, opline, &ssa->ops[line], opline->opcode, tmp);
  939. }
  940. break;
  941. case ZEND_BW_NOT:
  942. if (ssa->ops[line].result_def == var) {
  943. if (OP1_HAS_RANGE()) {
  944. if (OP1_RANGE_UNDERFLOW() ||
  945. OP1_RANGE_OVERFLOW()) {
  946. tmp->min = ZEND_LONG_MIN;
  947. tmp->max = ZEND_LONG_MAX;
  948. } else {
  949. op1_min = OP1_MIN_RANGE();
  950. op1_max = OP1_MAX_RANGE();
  951. tmp->min = ~op1_max;
  952. tmp->max = ~op1_min;
  953. }
  954. return 1;
  955. }
  956. }
  957. break;
  958. case ZEND_CAST:
  959. if (ssa->ops[line].op1_def == var) {
  960. if (ssa->ops[line].op1_def >= 0) {
  961. if (OP1_HAS_RANGE()) {
  962. tmp->underflow = OP1_RANGE_UNDERFLOW();
  963. tmp->min = OP1_MIN_RANGE();
  964. tmp->max = OP1_MAX_RANGE();
  965. tmp->overflow = OP1_RANGE_OVERFLOW();
  966. return 1;
  967. }
  968. }
  969. } else if (ssa->ops[line].result_def == var) {
  970. if (opline->extended_value == IS_NULL) {
  971. tmp->min = 0;
  972. tmp->max = 0;
  973. return 1;
  974. } else if (opline->extended_value == _IS_BOOL) {
  975. if (OP1_HAS_RANGE()) {
  976. op1_min = OP1_MIN_RANGE();
  977. op1_max = OP1_MAX_RANGE();
  978. tmp->min = (op1_min > 0 || op1_max < 0);
  979. tmp->max = (op1_min != 0 || op1_max != 0);
  980. return 1;
  981. } else {
  982. tmp->min = 0;
  983. tmp->max = 1;
  984. return 1;
  985. }
  986. } else if (opline->extended_value == IS_LONG) {
  987. if (OP1_HAS_RANGE()) {
  988. tmp->min = OP1_MIN_RANGE();
  989. tmp->max = OP1_MAX_RANGE();
  990. return 1;
  991. } else {
  992. tmp->min = ZEND_LONG_MIN;
  993. tmp->max = ZEND_LONG_MAX;
  994. return 1;
  995. }
  996. }
  997. }
  998. break;
  999. case ZEND_BOOL:
  1000. case ZEND_JMPZ_EX:
  1001. case ZEND_JMPNZ_EX:
  1002. if (ssa->ops[line].result_def == var) {
  1003. if (OP1_HAS_RANGE()) {
  1004. op1_min = OP1_MIN_RANGE();
  1005. op1_max = OP1_MAX_RANGE();
  1006. tmp->min = (op1_min > 0 || op1_max < 0);
  1007. tmp->max = (op1_min != 0 || op1_max != 0);
  1008. return 1;
  1009. } else {
  1010. tmp->min = 0;
  1011. tmp->max = 1;
  1012. return 1;
  1013. }
  1014. }
  1015. break;
  1016. case ZEND_BOOL_NOT:
  1017. if (ssa->ops[line].result_def == var) {
  1018. if (OP1_HAS_RANGE()) {
  1019. op1_min = OP1_MIN_RANGE();
  1020. op1_max = OP1_MAX_RANGE();
  1021. tmp->min = (op1_min == 0 && op1_max == 0);
  1022. tmp->max = (op1_min <= 0 && op1_max >= 0);
  1023. return 1;
  1024. } else {
  1025. tmp->min = 0;
  1026. tmp->max = 1;
  1027. return 1;
  1028. }
  1029. }
  1030. break;
  1031. case ZEND_BOOL_XOR:
  1032. if (ssa->ops[line].result_def == var) {
  1033. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  1034. op1_min = OP1_MIN_RANGE();
  1035. op2_min = OP2_MIN_RANGE();
  1036. op1_max = OP1_MAX_RANGE();
  1037. op2_max = OP2_MAX_RANGE();
  1038. op1_min = (op1_min > 0 || op1_max < 0);
  1039. op1_max = (op1_min != 0 || op1_max != 0);
  1040. op2_min = (op2_min > 0 || op2_max < 0);
  1041. op2_max = (op2_min != 0 || op2_max != 0);
  1042. tmp->min = 0;
  1043. tmp->max = 1;
  1044. if (op1_min == op1_max && op2_min == op2_max) {
  1045. if (op1_min == op2_min) {
  1046. tmp->max = 0;
  1047. } else {
  1048. tmp->min = 1;
  1049. }
  1050. }
  1051. return 1;
  1052. } else {
  1053. tmp->min = 0;
  1054. tmp->max = 1;
  1055. return 1;
  1056. }
  1057. }
  1058. break;
  1059. case ZEND_IS_IDENTICAL:
  1060. case ZEND_IS_EQUAL:
  1061. if (ssa->ops[line].result_def == var) {
  1062. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  1063. op1_min = OP1_MIN_RANGE();
  1064. op2_min = OP2_MIN_RANGE();
  1065. op1_max = OP1_MAX_RANGE();
  1066. op2_max = OP2_MAX_RANGE();
  1067. tmp->min = (op1_min == op1_max &&
  1068. op2_min == op2_max &&
  1069. op1_min == op2_max);
  1070. tmp->max = (op1_min <= op2_max && op1_max >= op2_min);
  1071. return 1;
  1072. } else {
  1073. tmp->min = 0;
  1074. tmp->max = 1;
  1075. return 1;
  1076. }
  1077. }
  1078. break;
  1079. case ZEND_IS_NOT_IDENTICAL:
  1080. case ZEND_IS_NOT_EQUAL:
  1081. if (ssa->ops[line].result_def == var) {
  1082. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  1083. op1_min = OP1_MIN_RANGE();
  1084. op2_min = OP2_MIN_RANGE();
  1085. op1_max = OP1_MAX_RANGE();
  1086. op2_max = OP2_MAX_RANGE();
  1087. tmp->min = (op1_min > op2_max || op1_max < op2_min);
  1088. tmp->max = (op1_min != op1_max ||
  1089. op2_min != op2_max ||
  1090. op1_min != op2_max);
  1091. return 1;
  1092. } else {
  1093. tmp->min = 0;
  1094. tmp->max = 1;
  1095. return 1;
  1096. }
  1097. }
  1098. break;
  1099. case ZEND_IS_SMALLER:
  1100. if (ssa->ops[line].result_def == var) {
  1101. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  1102. op1_min = OP1_MIN_RANGE();
  1103. op2_min = OP2_MIN_RANGE();
  1104. op1_max = OP1_MAX_RANGE();
  1105. op2_max = OP2_MAX_RANGE();
  1106. tmp->min = op1_max < op2_min;
  1107. tmp->max = op1_min < op2_max;
  1108. return 1;
  1109. } else {
  1110. tmp->min = 0;
  1111. tmp->max = 1;
  1112. return 1;
  1113. }
  1114. }
  1115. break;
  1116. case ZEND_IS_SMALLER_OR_EQUAL:
  1117. if (ssa->ops[line].result_def == var) {
  1118. if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) {
  1119. op1_min = OP1_MIN_RANGE();
  1120. op2_min = OP2_MIN_RANGE();
  1121. op1_max = OP1_MAX_RANGE();
  1122. op2_max = OP2_MAX_RANGE();
  1123. tmp->min = op1_max <= op2_min;
  1124. tmp->max = op1_min <= op2_max;
  1125. return 1;
  1126. } else {
  1127. tmp->min = 0;
  1128. tmp->max = 1;
  1129. return 1;
  1130. }
  1131. }
  1132. break;
  1133. case ZEND_QM_ASSIGN:
  1134. case ZEND_JMP_SET:
  1135. case ZEND_COALESCE:
  1136. if (ssa->ops[line].op1_def == var) {
  1137. if (ssa->ops[line].op1_def >= 0) {
  1138. if (OP1_HAS_RANGE()) {
  1139. tmp->underflow = OP1_RANGE_UNDERFLOW();
  1140. tmp->min = OP1_MIN_RANGE();
  1141. tmp->max = OP1_MAX_RANGE();
  1142. tmp->overflow = OP1_RANGE_OVERFLOW();
  1143. return 1;
  1144. }
  1145. }
  1146. }
  1147. if (ssa->ops[line].result_def == var) {
  1148. if (OP1_HAS_RANGE()) {
  1149. tmp->min = OP1_MIN_RANGE();
  1150. tmp->max = OP1_MAX_RANGE();
  1151. tmp->underflow = OP1_RANGE_UNDERFLOW();
  1152. tmp->overflow = OP1_RANGE_OVERFLOW();
  1153. return 1;
  1154. }
  1155. }
  1156. break;
  1157. case ZEND_ASSERT_CHECK:
  1158. if (ssa->ops[line].result_def == var) {
  1159. tmp->min = 0;
  1160. tmp->max = 1;
  1161. return 1;
  1162. }
  1163. break;
  1164. case ZEND_SEND_VAR:
  1165. if (ssa->ops[line].op1_def == var) {
  1166. if (ssa->ops[line].op1_def >= 0) {
  1167. if (OP1_HAS_RANGE()) {
  1168. tmp->underflow = OP1_RANGE_UNDERFLOW();
  1169. tmp->min = OP1_MIN_RANGE();
  1170. tmp->max = OP1_MAX_RANGE();
  1171. tmp->overflow = OP1_RANGE_OVERFLOW();
  1172. return 1;
  1173. }
  1174. }
  1175. }
  1176. break;
  1177. case ZEND_PRE_INC:
  1178. if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) {
  1179. if (OP1_HAS_RANGE()) {
  1180. tmp->min = OP1_MIN_RANGE();
  1181. tmp->max = OP1_MAX_RANGE();
  1182. tmp->underflow = OP1_RANGE_UNDERFLOW();
  1183. tmp->overflow = OP1_RANGE_OVERFLOW();
  1184. if (tmp->max < ZEND_LONG_MAX) {
  1185. tmp->max++;
  1186. } else {
  1187. tmp->overflow = 1;
  1188. }
  1189. if (tmp->min < ZEND_LONG_MAX && !tmp->underflow) {
  1190. tmp->min++;
  1191. }
  1192. return 1;
  1193. }
  1194. }
  1195. break;
  1196. case ZEND_PRE_DEC:
  1197. if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) {
  1198. if (OP1_HAS_RANGE()) {
  1199. tmp->min = OP1_MIN_RANGE();
  1200. tmp->max = OP1_MAX_RANGE();
  1201. tmp->underflow = OP1_RANGE_UNDERFLOW();
  1202. tmp->overflow = OP1_RANGE_OVERFLOW();
  1203. if (tmp->min > ZEND_LONG_MIN) {
  1204. tmp->min--;
  1205. } else {
  1206. tmp->underflow = 1;
  1207. }
  1208. if (tmp->max > ZEND_LONG_MIN && !tmp->overflow) {
  1209. tmp->max--;
  1210. }
  1211. return 1;
  1212. }
  1213. }
  1214. break;
  1215. case ZEND_POST_INC:
  1216. if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) {
  1217. if (OP1_HAS_RANGE()) {
  1218. tmp->min = OP1_MIN_RANGE();
  1219. tmp->max = OP1_MAX_RANGE();
  1220. tmp->underflow = OP1_RANGE_UNDERFLOW();
  1221. tmp->overflow = OP1_RANGE_OVERFLOW();
  1222. if (ssa->ops[line].result_def == var) {
  1223. return 1;
  1224. }
  1225. if (tmp->max < ZEND_LONG_MAX) {
  1226. tmp->max++;
  1227. } else {
  1228. tmp->overflow = 1;
  1229. }
  1230. if (tmp->min < ZEND_LONG_MAX && !tmp->underflow) {
  1231. tmp->min++;
  1232. }
  1233. return 1;
  1234. }
  1235. }
  1236. break;
  1237. case ZEND_POST_DEC:
  1238. if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) {
  1239. if (OP1_HAS_RANGE()) {
  1240. tmp->min = OP1_MIN_RANGE();
  1241. tmp->max = OP1_MAX_RANGE();
  1242. tmp->underflow = OP1_RANGE_UNDERFLOW();
  1243. tmp->overflow = OP1_RANGE_OVERFLOW();
  1244. if (ssa->ops[line].result_def == var) {
  1245. return 1;
  1246. }
  1247. if (tmp->min > ZEND_LONG_MIN) {
  1248. tmp->min--;
  1249. } else {
  1250. tmp->underflow = 1;
  1251. }
  1252. if (tmp->max > ZEND_LONG_MIN && !tmp->overflow) {
  1253. tmp->max--;
  1254. }
  1255. return 1;
  1256. }
  1257. }
  1258. break;
  1259. case ZEND_UNSET_DIM:
  1260. case ZEND_UNSET_OBJ:
  1261. if (ssa->ops[line].op1_def == var) {
  1262. /* If op1 is scalar, UNSET_DIM and UNSET_OBJ have no effect, so we can keep
  1263. * the previous ranges. */
  1264. if (OP1_HAS_RANGE()) {
  1265. tmp->min = OP1_MIN_RANGE();
  1266. tmp->max = OP1_MAX_RANGE();
  1267. tmp->underflow = OP1_RANGE_UNDERFLOW();
  1268. tmp->overflow = OP1_RANGE_OVERFLOW();
  1269. return 1;
  1270. }
  1271. }
  1272. break;
  1273. case ZEND_ASSIGN:
  1274. if (ssa->ops[line].op1_def == var || ssa->ops[line].op2_def == var || ssa->ops[line].result_def == var) {
  1275. if (OP2_HAS_RANGE()) {
  1276. tmp->min = OP2_MIN_RANGE();
  1277. tmp->max = OP2_MAX_RANGE();
  1278. tmp->underflow = OP2_RANGE_UNDERFLOW();
  1279. tmp->overflow = OP2_RANGE_OVERFLOW();
  1280. return 1;
  1281. }
  1282. }
  1283. break;
  1284. case ZEND_ASSIGN_DIM:
  1285. case ZEND_ASSIGN_OBJ:
  1286. if (ssa->ops[line+1].op1_def == var) {
  1287. if ((opline+1)->opcode == ZEND_OP_DATA) {
  1288. opline++;
  1289. tmp->min = OP1_MIN_RANGE();
  1290. tmp->max = OP1_MAX_RANGE();
  1291. tmp->underflow = OP1_RANGE_UNDERFLOW();
  1292. tmp->overflow = OP1_RANGE_OVERFLOW();
  1293. return 1;
  1294. }
  1295. }
  1296. break;
  1297. case ZEND_ASSIGN_ADD:
  1298. case ZEND_ASSIGN_SUB:
  1299. case ZEND_ASSIGN_MUL:
  1300. case ZEND_ASSIGN_DIV:
  1301. case ZEND_ASSIGN_MOD:
  1302. case ZEND_ASSIGN_SL:
  1303. case ZEND_ASSIGN_SR:
  1304. case ZEND_ASSIGN_BW_OR:
  1305. case ZEND_ASSIGN_BW_AND:
  1306. case ZEND_ASSIGN_BW_XOR:
  1307. if (opline->extended_value == 0) {
  1308. if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) {
  1309. return zend_inference_calc_binary_op_range(
  1310. op_array, ssa, opline, &ssa->ops[line],
  1311. get_compound_assign_op(opline->opcode), tmp);
  1312. }
  1313. } else if ((opline+1)->opcode == ZEND_OP_DATA) {
  1314. if (ssa->ops[line+1].op1_def == var) {
  1315. opline++;
  1316. if (OP1_HAS_RANGE()) {
  1317. tmp->min = OP1_MIN_RANGE();
  1318. tmp->max = OP1_MAX_RANGE();
  1319. tmp->underflow = OP1_RANGE_UNDERFLOW();
  1320. tmp->overflow = OP1_RANGE_OVERFLOW();
  1321. return 1;
  1322. }
  1323. }
  1324. }
  1325. break;
  1326. // case ZEND_ASSIGN_CONCAT:
  1327. case ZEND_OP_DATA:
  1328. if ((opline-1)->opcode == ZEND_ASSIGN_DIM ||
  1329. (opline-1)->opcode == ZEND_ASSIGN_OBJ ||
  1330. (opline-1)->opcode == ZEND_ASSIGN_ADD ||
  1331. (opline-1)->opcode == ZEND_ASSIGN_SUB ||
  1332. (opline-1)->opcode == ZEND_ASSIGN_MUL) {
  1333. if (ssa->ops[line].op1_def == var) {
  1334. if (OP1_HAS_RANGE()) {
  1335. tmp->min = OP1_MIN_RANGE();
  1336. tmp->max = OP1_MAX_RANGE();
  1337. tmp->underflow = OP1_RANGE_UNDERFLOW();
  1338. tmp->overflow = OP1_RANGE_OVERFLOW();
  1339. return 1;
  1340. }
  1341. }
  1342. break;
  1343. }
  1344. break;
  1345. case ZEND_RECV:
  1346. case ZEND_RECV_INIT:
  1347. if (ssa->ops[line].result_def == var) {
  1348. zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
  1349. if (func_info &&
  1350. (int)opline->op1.num-1 < func_info->num_args &&
  1351. func_info->arg_info[opline->op1.num-1].info.has_range) {
  1352. *tmp = func_info->arg_info[opline->op1.num-1].info.range;
  1353. return 1;
  1354. } else if (op_array->arg_info &&
  1355. opline->op1.num <= op_array->num_args) {
  1356. if (ZEND_TYPE_CODE(op_array->arg_info[opline->op1.num-1].type) == IS_LONG) {
  1357. tmp->underflow = 0;
  1358. tmp->min = ZEND_LONG_MIN;
  1359. tmp->max = ZEND_LONG_MAX;
  1360. tmp->overflow = 0;
  1361. return 1;
  1362. } else if (ZEND_TYPE_CODE(op_array->arg_info[opline->op1.num-1].type) == _IS_BOOL) {
  1363. tmp->underflow = 0;
  1364. tmp->min = 0;
  1365. tmp->max = 1;
  1366. tmp->overflow = 0;
  1367. return 1;
  1368. }
  1369. }
  1370. }
  1371. break;
  1372. case ZEND_STRLEN:
  1373. if (ssa->ops[line].result_def == var) {
  1374. #if SIZEOF_ZEND_LONG == 4
  1375. /* The length of a string is a non-negative integer. However, on 32-bit
  1376. * platforms overflows into negative lengths may occur, so it's better
  1377. * to not assume any particular range. */
  1378. tmp->min = ZEND_LONG_MIN;
  1379. #else
  1380. tmp->min = 0;
  1381. #endif
  1382. tmp->max = ZEND_LONG_MAX;
  1383. return 1;
  1384. }
  1385. break;
  1386. case ZEND_FUNC_NUM_ARGS:
  1387. tmp->min = 0;
  1388. tmp->max = ZEND_LONG_MAX;
  1389. return 1;
  1390. case ZEND_COUNT:
  1391. /* count() on Countable objects may return negative numbers */
  1392. tmp->min = ZEND_LONG_MIN;
  1393. tmp->max = ZEND_LONG_MAX;
  1394. return 1;
  1395. case ZEND_DO_FCALL:
  1396. case ZEND_DO_ICALL:
  1397. case ZEND_DO_UCALL:
  1398. case ZEND_DO_FCALL_BY_NAME:
  1399. if (ssa->ops[line].result_def == var) {
  1400. zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
  1401. zend_call_info *call_info;
  1402. if (!func_info || !func_info->call_map) {
  1403. break;
  1404. }
  1405. call_info = func_info->call_map[opline - op_array->opcodes];
  1406. if (!call_info) {
  1407. break;
  1408. }
  1409. if (call_info->callee_func->type == ZEND_USER_FUNCTION) {
  1410. func_info = ZEND_FUNC_INFO(&call_info->callee_func->op_array);
  1411. if (func_info && func_info->return_info.has_range) {
  1412. *tmp = func_info->return_info.range;
  1413. return 1;
  1414. }
  1415. }
  1416. //TODO: we can't use type inference for internal functions at this point ???
  1417. #if 0
  1418. uint32_t type;
  1419. type = zend_get_func_info(call_info, ssa);
  1420. if (!(type & (MAY_BE_ANY - (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG)))) {
  1421. tmp->underflow = 0;
  1422. tmp->min = 0;
  1423. tmp->max = 0;
  1424. tmp->overflow = 0;
  1425. if (type & MAY_BE_LONG) {
  1426. tmp->min = ZEND_LONG_MIN;
  1427. tmp->max = ZEND_LONG_MAX;
  1428. } else if (type & MAY_BE_TRUE) {
  1429. if (!(type & (MAY_BE_NULL|MAY_BE_FALSE))) {
  1430. tmp->min = 1;
  1431. }
  1432. tmp->max = 1;
  1433. }
  1434. return 1;
  1435. }
  1436. #endif
  1437. }
  1438. break;
  1439. // FIXME: support for more opcodes
  1440. default:
  1441. break;
  1442. }
  1443. return 0;
  1444. }
  1445. void zend_inference_init_range(const zend_op_array *op_array, zend_ssa *ssa, int var, zend_bool underflow, zend_long min, zend_long max, zend_bool overflow)
  1446. {
  1447. if (underflow) {
  1448. min = ZEND_LONG_MIN;
  1449. }
  1450. if (overflow) {
  1451. max = ZEND_LONG_MAX;
  1452. }
  1453. ssa->var_info[var].has_range = 1;
  1454. ssa->var_info[var].range.underflow = underflow;
  1455. ssa->var_info[var].range.min = min;
  1456. ssa->var_info[var].range.max = max;
  1457. ssa->var_info[var].range.overflow = overflow;
  1458. LOG_SSA_RANGE(" change range (init SCC %2d) %2d [%s%ld..%ld%s]\n", ssa->vars[var].scc, var, (underflow?"-- ":""), min, max, (overflow?" ++":""));
  1459. }
  1460. int zend_inference_widening_meet(zend_ssa_var_info *var_info, zend_ssa_range *r)
  1461. {
  1462. if (!var_info->has_range) {
  1463. var_info->has_range = 1;
  1464. } else {
  1465. if (r->underflow ||
  1466. var_info->range.underflow ||
  1467. r->min < var_info->range.min) {
  1468. r->underflow = 1;
  1469. r->min = ZEND_LONG_MIN;
  1470. }
  1471. if (r->overflow ||
  1472. var_info->range.overflow ||
  1473. r->max > var_info->range.max) {
  1474. r->overflow = 1;
  1475. r->max = ZEND_LONG_MAX;
  1476. }
  1477. if (var_info->range.min == r->min &&
  1478. var_info->range.max == r->max &&
  1479. var_info->range.underflow == r->underflow &&
  1480. var_info->range.overflow == r->overflow) {
  1481. return 0;
  1482. }
  1483. }
  1484. var_info->range = *r;
  1485. return 1;
  1486. }
  1487. static int zend_ssa_range_widening(const zend_op_array *op_array, zend_ssa *ssa, int var, int scc)
  1488. {
  1489. zend_ssa_range tmp;
  1490. if (zend_inference_calc_range(op_array, ssa, var, 1, 0, &tmp)) {
  1491. if (zend_inference_widening_meet(&ssa->var_info[var], &tmp)) {
  1492. LOG_SSA_RANGE(" change range (widening SCC %2d) %2d [%s%ld..%ld%s]\n", scc, var, (tmp.underflow?"-- ":""), tmp.min, tmp.max, (tmp.overflow?" ++":""));
  1493. return 1;
  1494. }
  1495. }
  1496. return 0;
  1497. }
  1498. int zend_inference_narrowing_meet(zend_ssa_var_info *var_info, zend_ssa_range *r)
  1499. {
  1500. if (!var_info->has_range) {
  1501. var_info->has_range = 1;
  1502. } else {
  1503. if (!r->underflow &&
  1504. !var_info->range.underflow &&
  1505. var_info->range.min < r->min) {
  1506. r->min = var_info->range.min;
  1507. }
  1508. if (!r->overflow &&
  1509. !var_info->range.overflow &&
  1510. var_info->range.max > r->max) {
  1511. r->max = var_info->range.max;
  1512. }
  1513. if (r->underflow) {
  1514. r->min = ZEND_LONG_MIN;
  1515. }
  1516. if (r->overflow) {
  1517. r->max = ZEND_LONG_MAX;
  1518. }
  1519. if (var_info->range.min == r->min &&
  1520. var_info->range.max == r->max &&
  1521. var_info->range.underflow == r->underflow &&
  1522. var_info->range.overflow == r->overflow) {
  1523. return 0;
  1524. }
  1525. }
  1526. var_info->range = *r;
  1527. return 1;
  1528. }
  1529. static int zend_ssa_range_narrowing(const zend_op_array *op_array, zend_ssa *ssa, int var, int scc)
  1530. {
  1531. zend_ssa_range tmp;
  1532. if (zend_inference_calc_range(op_array, ssa, var, 0, 1, &tmp)) {
  1533. if (zend_inference_narrowing_meet(&ssa->var_info[var], &tmp)) {
  1534. LOG_SSA_RANGE(" change range (narrowing SCC %2d) %2d [%s%ld..%ld%s]\n", scc, var, (tmp.underflow?"-- ":""), tmp.min, tmp.max, (tmp.overflow?" ++":""));
  1535. return 1;
  1536. }
  1537. }
  1538. return 0;
  1539. }
  1540. #ifdef NEG_RANGE
  1541. # define CHECK_INNER_CYCLE(var2) \
  1542. do { \
  1543. if (ssa->vars[var2].scc == ssa->vars[var].scc && \
  1544. !ssa->vars[var2].scc_entry && \
  1545. !zend_bitset_in(visited, var2) && \
  1546. zend_check_inner_cycles(op_array, ssa, worklist, visited, var2)) { \
  1547. return 1; \
  1548. } \
  1549. } while (0)
  1550. static int zend_check_inner_cycles(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, zend_bitset visited, int var)
  1551. {
  1552. if (zend_bitset_in(worklist, var)) {
  1553. return 1;
  1554. }
  1555. zend_bitset_incl(worklist, var);
  1556. FOR_EACH_VAR_USAGE(var, CHECK_INNER_CYCLE);
  1557. zend_bitset_incl(visited, var);
  1558. return 0;
  1559. }
  1560. #endif
  1561. static void zend_infer_ranges_warmup(const zend_op_array *op_array, zend_ssa *ssa, int *scc_var, int *next_scc_var, int scc)
  1562. {
  1563. int worklist_len = zend_bitset_len(ssa->vars_count);
  1564. int j, n;
  1565. zend_ssa_range tmp;
  1566. ALLOCA_FLAG(use_heap)
  1567. zend_bitset worklist = do_alloca(sizeof(zend_ulong) * worklist_len * 2, use_heap);
  1568. zend_bitset visited = worklist + worklist_len;
  1569. #ifdef NEG_RANGE
  1570. int has_inner_cycles = 0;
  1571. memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
  1572. memset(visited, 0, sizeof(zend_ulong) * worklist_len);
  1573. j = scc_var[scc];
  1574. while (j >= 0) {
  1575. if (!zend_bitset_in(visited, j) &&
  1576. zend_check_inner_cycles(op_array, ssa, worklist, visited, j)) {
  1577. has_inner_cycles = 1;
  1578. break;
  1579. }
  1580. j = next_scc_var[j];
  1581. }
  1582. #endif
  1583. memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
  1584. for (n = 0; n < RANGE_WARMUP_PASSES; n++) {
  1585. j= scc_var[scc];
  1586. while (j >= 0) {
  1587. if (ssa->vars[j].scc_entry) {
  1588. zend_bitset_incl(worklist, j);
  1589. }
  1590. j = next_scc_var[j];
  1591. }
  1592. memset(visited, 0, sizeof(zend_ulong) * worklist_len);
  1593. WHILE_WORKLIST(worklist, worklist_len, j) {
  1594. if (zend_inference_calc_range(op_array, ssa, j, 0, 0, &tmp)) {
  1595. #ifdef NEG_RANGE
  1596. if (!has_inner_cycles &&
  1597. ssa->var_info[j].has_range &&
  1598. ssa->vars[j].definition_phi &&
  1599. ssa->vars[j].definition_phi->pi >= 0 &&
  1600. ssa->vars[j].definition_phi->has_range_constraint &&
  1601. ssa->vars[j].definition_phi->constraint.range.negative &&
  1602. ssa->vars[j].definition_phi->constraint.range.min_ssa_var < 0 &&
  1603. ssa->vars[j].definition_phi->constraint.range.max_ssa_var < 0) {
  1604. zend_ssa_range_constraint *constraint =
  1605. &ssa->vars[j].definition_phi->constraint.range;
  1606. if (tmp.min == ssa->var_info[j].range.min &&
  1607. tmp.max == ssa->var_info[j].range.max) {
  1608. if (constraint->negative == NEG_INIT) {
  1609. LOG_NEG_RANGE("#%d INVARIANT\n", j);
  1610. constraint->negative = NEG_INVARIANT;
  1611. }
  1612. } else if (tmp.min == ssa->var_info[j].range.min &&
  1613. tmp.max == ssa->var_info[j].range.max + 1 &&
  1614. tmp.max < constraint->range.min) {
  1615. if (constraint->negative == NEG_INIT ||
  1616. constraint->negative == NEG_INVARIANT) {
  1617. LOG_NEG_RANGE("#%d LT\n", j);
  1618. constraint->negative = NEG_USE_LT;
  1619. //???NEG
  1620. } else if (constraint->negative == NEG_USE_GT) {
  1621. LOG_NEG_RANGE("#%d UNKNOWN\n", j);
  1622. constraint->negative = NEG_UNKNOWN;
  1623. }
  1624. } else if (tmp.max == ssa->var_info[j].range.max &&
  1625. tmp.min == ssa->var_info[j].range.min - 1 &&
  1626. tmp.min > constraint->range.max) {
  1627. if (constraint->negative == NEG_INIT ||
  1628. constraint->negative == NEG_INVARIANT) {
  1629. LOG_NEG_RANGE("#%d GT\n", j);
  1630. constraint->negative = NEG_USE_GT;
  1631. //???NEG
  1632. } else if (constraint->negative == NEG_USE_LT) {
  1633. LOG_NEG_RANGE("#%d UNKNOWN\n", j);
  1634. constraint->negative = NEG_UNKNOWN;
  1635. }
  1636. } else {
  1637. LOG_NEG_RANGE("#%d UNKNOWN\n", j);
  1638. constraint->negative = NEG_UNKNOWN;
  1639. }
  1640. }
  1641. #endif
  1642. if (zend_inference_narrowing_meet(&ssa->var_info[j], &tmp)) {
  1643. LOG_SSA_RANGE(" change range (warmup %2d SCC %2d) %2d [%s%ld..%ld%s]\n", n, scc, j, (tmp.underflow?"-- ":""), tmp.min, tmp.max, (tmp.overflow?" ++":""));
  1644. zend_bitset_incl(visited, j);
  1645. FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR_1);
  1646. }
  1647. }
  1648. } WHILE_WORKLIST_END();
  1649. }
  1650. free_alloca(worklist, use_heap);
  1651. }
  1652. static int zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
  1653. {
  1654. int worklist_len = zend_bitset_len(ssa->vars_count);
  1655. zend_bitset worklist;
  1656. int *next_scc_var;
  1657. int *scc_var;
  1658. zend_ssa_phi *p;
  1659. zend_ssa_range tmp;
  1660. int scc, j;
  1661. ALLOCA_FLAG(use_heap);
  1662. worklist = do_alloca(
  1663. ZEND_MM_ALIGNED_SIZE(sizeof(zend_ulong) * worklist_len) +
  1664. ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->vars_count) +
  1665. sizeof(int) * ssa->sccs, use_heap);
  1666. next_scc_var = (int*)((char*)worklist + ZEND_MM_ALIGNED_SIZE(sizeof(zend_ulong) * worklist_len));
  1667. scc_var = (int*)((char*)next_scc_var + ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->vars_count));
  1668. LOG_SSA_RANGE("Range Inference\n");
  1669. /* Create linked lists of SSA variables for each SCC */
  1670. memset(scc_var, -1, sizeof(int) * ssa->sccs);
  1671. for (j = 0; j < ssa->vars_count; j++) {
  1672. if (ssa->vars[j].scc >= 0) {
  1673. next_scc_var[j] = scc_var[ssa->vars[j].scc];
  1674. scc_var[ssa->vars[j].scc] = j;
  1675. }
  1676. }
  1677. for (scc = 0; scc < ssa->sccs; scc++) {
  1678. j = scc_var[scc];
  1679. if (next_scc_var[j] < 0) {
  1680. /* SCC with a single element */
  1681. if (zend_inference_calc_range(op_array, ssa, j, 0, 1, &tmp)) {
  1682. zend_inference_init_range(op_array, ssa, j, tmp.underflow, tmp.min, tmp.max, tmp.overflow);
  1683. } else {
  1684. zend_inference_init_range(op_array, ssa, j, 1, ZEND_LONG_MIN, ZEND_LONG_MAX, 1);
  1685. }
  1686. } else {
  1687. /* Find SCC entry points */
  1688. memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
  1689. do {
  1690. if (ssa->vars[j].scc_entry) {
  1691. zend_bitset_incl(worklist, j);
  1692. }
  1693. j = next_scc_var[j];
  1694. } while (j >= 0);
  1695. #if RANGE_WARMUP_PASSES > 0
  1696. zend_infer_ranges_warmup(op_array, ssa, scc_var, next_scc_var, scc);
  1697. j = scc_var[scc];
  1698. do {
  1699. zend_bitset_incl(worklist, j);
  1700. j = next_scc_var[j];
  1701. } while (j >= 0);
  1702. #endif
  1703. /* widening */
  1704. WHILE_WORKLIST(worklist, worklist_len, j) {
  1705. if (zend_ssa_range_widening(op_array, ssa, j, scc)) {
  1706. FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR);
  1707. }
  1708. } WHILE_WORKLIST_END();
  1709. /* initialize missing ranges */
  1710. for (j = scc_var[scc]; j >= 0; j = next_scc_var[j]) {
  1711. if (!ssa->var_info[j].has_range) {
  1712. zend_inference_init_range(op_array, ssa, j, 1, ZEND_LONG_MIN, ZEND_LONG_MAX, 1);
  1713. FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR);
  1714. }
  1715. }
  1716. /* widening (second round) */
  1717. WHILE_WORKLIST(worklist, worklist_len, j) {
  1718. if (zend_ssa_range_widening(op_array, ssa, j, scc)) {
  1719. FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR);
  1720. }
  1721. } WHILE_WORKLIST_END();
  1722. /* Add all SCC entry variables into worklist for narrowing */
  1723. for (j = scc_var[scc]; j >= 0; j = next_scc_var[j]) {
  1724. if (ssa->vars[j].definition_phi
  1725. && ssa->vars[j].definition_phi->pi < 0) {
  1726. /* narrowing Phi functions first */
  1727. zend_ssa_range_narrowing(op_array, ssa, j, scc);
  1728. }
  1729. zend_bitset_incl(worklist, j);
  1730. }
  1731. /* narrowing */
  1732. WHILE_WORKLIST(worklist, worklist_len, j) {
  1733. if (zend_ssa_range_narrowing(op_array, ssa, j, scc)) {
  1734. FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR);
  1735. #ifdef SYM_RANGE
  1736. /* Process symbolic control-flow constraints */
  1737. p = ssa->vars[j].sym_use_chain;
  1738. while (p) {
  1739. ADD_SCC_VAR(p->ssa_var);
  1740. p = p->sym_use_chain;
  1741. }
  1742. #endif
  1743. }
  1744. } WHILE_WORKLIST_END();
  1745. }
  1746. }
  1747. free_alloca(worklist, use_heap);
  1748. return SUCCESS;
  1749. }
  1750. /* }}} */
  1751. static uint32_t get_ssa_alias_types(zend_ssa_alias_kind alias) {
  1752. if (alias == PHP_ERRORMSG_ALIAS) {
  1753. return MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN;
  1754. } else if (alias == HTTP_RESPONSE_HEADER_ALIAS) {
  1755. return MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_RC1 | MAY_BE_RCN;
  1756. } else {
  1757. return MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  1758. }
  1759. }
  1760. #define UPDATE_SSA_TYPE(_type, _var) \
  1761. do { \
  1762. uint32_t __type = (_type); \
  1763. int __var = (_var); \
  1764. if (__type & MAY_BE_REF) { \
  1765. __type |= MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; \
  1766. } \
  1767. if (__var >= 0) { \
  1768. zend_ssa_var *__ssa_var = &ssa_vars[__var]; \
  1769. if (__ssa_var->var < op_array->last_var) { \
  1770. if (__type & (MAY_BE_REF|MAY_BE_RCN)) { \
  1771. __type |= MAY_BE_RC1 | MAY_BE_RCN; \
  1772. } \
  1773. if ((__type & MAY_BE_RC1) && (__type & MAY_BE_STRING)) {\
  1774. /* TODO: support for array keys and ($str . "")*/ \
  1775. __type |= MAY_BE_RCN; \
  1776. } \
  1777. if (__ssa_var->alias) { \
  1778. __type |= get_ssa_alias_types(__ssa_var->alias); \
  1779. } \
  1780. } \
  1781. if (ssa_var_info[__var].type != __type) { \
  1782. if (ssa_var_info[__var].type & ~__type) { \
  1783. handle_type_narrowing(op_array, ssa, worklist, \
  1784. __var, ssa_var_info[__var].type, __type); \
  1785. return FAILURE; \
  1786. } \
  1787. ssa_var_info[__var].type = __type; \
  1788. add_usages(op_array, ssa, worklist, __var); \
  1789. } \
  1790. /*zend_bitset_excl(worklist, var);*/ \
  1791. } \
  1792. } while (0)
  1793. #define UPDATE_SSA_OBJ_TYPE(_ce, _is_instanceof, var) \
  1794. do { \
  1795. if (var >= 0) { \
  1796. if (ssa_var_info[var].ce != (_ce) || \
  1797. ssa_var_info[var].is_instanceof != (_is_instanceof)) { \
  1798. ssa_var_info[var].ce = (_ce); \
  1799. ssa_var_info[var].is_instanceof = (_is_instanceof); \
  1800. add_usages(op_array, ssa, worklist, var); \
  1801. } \
  1802. /*zend_bitset_excl(worklist, var);*/ \
  1803. } \
  1804. } while (0)
  1805. #define COPY_SSA_OBJ_TYPE(from_var, to_var) do { \
  1806. if ((from_var) >= 0 && (ssa_var_info[(from_var)].type & MAY_BE_OBJECT) \
  1807. && ssa_var_info[(from_var)].ce) { \
  1808. UPDATE_SSA_OBJ_TYPE(ssa_var_info[(from_var)].ce, \
  1809. ssa_var_info[(from_var)].is_instanceof, (to_var)); \
  1810. } else { \
  1811. UPDATE_SSA_OBJ_TYPE(NULL, 0, (to_var)); \
  1812. } \
  1813. } while (0)
  1814. static void add_usages(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, int var)
  1815. {
  1816. if (ssa->vars[var].phi_use_chain) {
  1817. zend_ssa_phi *p = ssa->vars[var].phi_use_chain;
  1818. do {
  1819. zend_bitset_incl(worklist, p->ssa_var);
  1820. p = zend_ssa_next_use_phi(ssa, var, p);
  1821. } while (p);
  1822. }
  1823. if (ssa->vars[var].use_chain >= 0) {
  1824. int use = ssa->vars[var].use_chain;
  1825. zend_ssa_op *op;
  1826. do {
  1827. op = ssa->ops + use;
  1828. if (op->result_def >= 0) {
  1829. zend_bitset_incl(worklist, op->result_def);
  1830. }
  1831. if (op->op1_def >= 0) {
  1832. zend_bitset_incl(worklist, op->op1_def);
  1833. }
  1834. if (op->op2_def >= 0) {
  1835. zend_bitset_incl(worklist, op->op2_def);
  1836. }
  1837. if (op_array->opcodes[use].opcode == ZEND_OP_DATA) {
  1838. op--;
  1839. if (op->result_def >= 0) {
  1840. zend_bitset_incl(worklist, op->result_def);
  1841. }
  1842. if (op->op1_def >= 0) {
  1843. zend_bitset_incl(worklist, op->op1_def);
  1844. }
  1845. if (op->op2_def >= 0) {
  1846. zend_bitset_incl(worklist, op->op2_def);
  1847. }
  1848. }
  1849. use = zend_ssa_next_use(ssa->ops, var, use);
  1850. } while (use >= 0);
  1851. }
  1852. }
  1853. static void reset_dependent_vars(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, int var)
  1854. {
  1855. zend_ssa_op *ssa_ops = ssa->ops;
  1856. zend_ssa_var *ssa_vars = ssa->vars;
  1857. zend_ssa_var_info *ssa_var_info = ssa->var_info;
  1858. zend_ssa_phi *p;
  1859. int use;
  1860. p = ssa_vars[var].phi_use_chain;
  1861. while (p) {
  1862. if (ssa_var_info[p->ssa_var].type) {
  1863. ssa_var_info[p->ssa_var].type = 0;
  1864. zend_bitset_incl(worklist, p->ssa_var);
  1865. reset_dependent_vars(op_array, ssa, worklist, p->ssa_var);
  1866. }
  1867. p = zend_ssa_next_use_phi(ssa, var, p);
  1868. }
  1869. use = ssa_vars[var].use_chain;
  1870. while (use >= 0) {
  1871. if (ssa_ops[use].op1_def >= 0 && ssa_var_info[ssa_ops[use].op1_def].type) {
  1872. ssa_var_info[ssa_ops[use].op1_def].type = 0;
  1873. zend_bitset_incl(worklist, ssa_ops[use].op1_def);
  1874. reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use].op1_def);
  1875. }
  1876. if (ssa_ops[use].op2_def >= 0 && ssa_var_info[ssa_ops[use].op2_def].type) {
  1877. ssa_var_info[ssa_ops[use].op2_def].type = 0;
  1878. zend_bitset_incl(worklist, ssa_ops[use].op2_def);
  1879. reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use].op2_def);
  1880. }
  1881. if (ssa_ops[use].result_def >= 0 && ssa_var_info[ssa_ops[use].result_def].type) {
  1882. ssa_var_info[ssa_ops[use].result_def].type = 0;
  1883. zend_bitset_incl(worklist, ssa_ops[use].result_def);
  1884. reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use].result_def);
  1885. }
  1886. if (op_array->opcodes[use+1].opcode == ZEND_OP_DATA) {
  1887. if (ssa_ops[use+1].op1_def >= 0 && ssa_var_info[ssa_ops[use+1].op1_def].type) {
  1888. ssa_var_info[ssa_ops[use+1].op1_def].type = 0;
  1889. zend_bitset_incl(worklist, ssa_ops[use+1].op1_def);
  1890. reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use+1].op1_def);
  1891. }
  1892. if (ssa_ops[use+1].op2_def >= 0 && ssa_var_info[ssa_ops[use+1].op2_def].type) {
  1893. ssa_var_info[ssa_ops[use+1].op2_def].type = 0;
  1894. zend_bitset_incl(worklist, ssa_ops[use+1].op2_def);
  1895. reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use+1].op2_def);
  1896. }
  1897. if (ssa_ops[use+1].result_def >= 0 && ssa_var_info[ssa_ops[use+1].result_def].type) {
  1898. ssa_var_info[ssa_ops[use+1].result_def].type = 0;
  1899. zend_bitset_incl(worklist, ssa_ops[use+1].result_def);
  1900. reset_dependent_vars(op_array, ssa, worklist, ssa_ops[use+1].result_def);
  1901. }
  1902. }
  1903. use = zend_ssa_next_use(ssa_ops, var, use);
  1904. }
  1905. #ifdef SYM_RANGE
  1906. /* Process symbolic control-flow constraints */
  1907. p = ssa->vars[var].sym_use_chain;
  1908. while (p) {
  1909. ssa_var_info[p->ssa_var].type = 0;
  1910. zend_bitset_incl(worklist, p->ssa_var);
  1911. reset_dependent_vars(op_array, ssa, worklist, p->ssa_var);
  1912. p = p->sym_use_chain;
  1913. }
  1914. #endif
  1915. }
  1916. static void handle_type_narrowing(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset worklist, int var, uint32_t old_type, uint32_t new_type)
  1917. {
  1918. if (1) {
  1919. /* Right now, this is always a bug */
  1920. int def_op_num = ssa->vars[var].definition;
  1921. const zend_op *def_opline = def_op_num >= 0 ? &op_array->opcodes[def_op_num] : NULL;
  1922. const char *def_op_name = def_opline ? zend_get_opcode_name(def_opline->opcode) : "PHI";
  1923. zend_error(E_WARNING, "Narrowing occurred during type inference of %s. Please file a bug report on bugs.php.net", def_op_name);
  1924. } else {
  1925. /* if new_type set resets some bits from old_type set
  1926. * We have completely recalculate types of some dependent SSA variables
  1927. * (this may occurs mainly because of incremental inter-precudure
  1928. * type inference)
  1929. */
  1930. reset_dependent_vars(op_array, ssa, worklist, var);
  1931. }
  1932. }
  1933. uint32_t zend_array_element_type(uint32_t t1, int write, int insert)
  1934. {
  1935. uint32_t tmp = 0;
  1936. if (t1 & MAY_BE_OBJECT) {
  1937. if (!write) {
  1938. /* can't be REF because of ZVAL_COPY_DEREF() usage */
  1939. tmp |= MAY_BE_ANY | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  1940. } else {
  1941. tmp |= MAY_BE_ANY | MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  1942. }
  1943. }
  1944. if (t1 & MAY_BE_ARRAY) {
  1945. if (insert) {
  1946. tmp |= MAY_BE_NULL;
  1947. } else {
  1948. tmp |= MAY_BE_NULL | ((t1 & MAY_BE_ARRAY_OF_ANY) >> MAY_BE_ARRAY_SHIFT);
  1949. if (tmp & MAY_BE_ARRAY) {
  1950. tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  1951. }
  1952. if (t1 & MAY_BE_ARRAY_OF_REF) {
  1953. if (!write) {
  1954. /* can't be REF because of ZVAL_COPY_DEREF() usage */
  1955. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  1956. } else {
  1957. tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN;
  1958. }
  1959. } else if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
  1960. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  1961. }
  1962. }
  1963. }
  1964. if (t1 & MAY_BE_STRING) {
  1965. tmp |= MAY_BE_STRING | MAY_BE_RC1;
  1966. if (write) {
  1967. tmp |= MAY_BE_NULL;
  1968. }
  1969. }
  1970. if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
  1971. tmp |= MAY_BE_NULL;
  1972. if (t1 & MAY_BE_ERROR) {
  1973. if (write) {
  1974. tmp |= MAY_BE_ERROR;
  1975. }
  1976. }
  1977. }
  1978. if (t1 & (MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE)) {
  1979. tmp |= MAY_BE_NULL;
  1980. if (write) {
  1981. tmp |= MAY_BE_ERROR;
  1982. }
  1983. }
  1984. return tmp;
  1985. }
  1986. static uint32_t assign_dim_result_type(
  1987. uint32_t arr_type, uint32_t dim_type, uint32_t value_type, zend_uchar dim_op_type) {
  1988. uint32_t tmp = arr_type & ~(MAY_BE_RC1|MAY_BE_RCN);
  1989. if (arr_type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
  1990. tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
  1991. tmp |= MAY_BE_ARRAY|MAY_BE_RC1;
  1992. }
  1993. if (tmp & (MAY_BE_ARRAY|MAY_BE_STRING)) {
  1994. tmp |= MAY_BE_RC1;
  1995. }
  1996. if (tmp & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
  1997. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  1998. }
  1999. if (tmp & MAY_BE_ARRAY) {
  2000. if (value_type & MAY_BE_UNDEF) {
  2001. tmp |= MAY_BE_ARRAY_OF_NULL;
  2002. }
  2003. if (dim_op_type == IS_UNUSED) {
  2004. tmp |= MAY_BE_ARRAY_KEY_LONG;
  2005. } else {
  2006. if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
  2007. tmp |= MAY_BE_ARRAY_KEY_LONG;
  2008. }
  2009. if (dim_type & MAY_BE_STRING) {
  2010. tmp |= MAY_BE_ARRAY_KEY_STRING;
  2011. if (dim_op_type != IS_CONST) {
  2012. // FIXME: numeric string
  2013. tmp |= MAY_BE_ARRAY_KEY_LONG;
  2014. }
  2015. }
  2016. if (dim_type & (MAY_BE_UNDEF|MAY_BE_NULL)) {
  2017. tmp |= MAY_BE_ARRAY_KEY_STRING;
  2018. }
  2019. }
  2020. /* Only add value type if we have a key type. It might be that the key type is illegal
  2021. * for arrays. */
  2022. if (tmp & MAY_BE_ARRAY_KEY_ANY) {
  2023. tmp |= (value_type & MAY_BE_ANY) << MAY_BE_ARRAY_SHIFT;
  2024. }
  2025. }
  2026. return tmp;
  2027. }
  2028. /* For binary ops that have compound assignment operators */
  2029. static uint32_t binary_op_result_type(
  2030. zend_ssa *ssa, zend_uchar opcode, uint32_t t1, uint32_t t2, uint32_t result_var,
  2031. zend_long optimization_level) {
  2032. uint32_t tmp = 0;
  2033. uint32_t t1_type = (t1 & MAY_BE_ANY) | (t1 & MAY_BE_UNDEF ? MAY_BE_NULL : 0);
  2034. uint32_t t2_type = (t2 & MAY_BE_ANY) | (t2 & MAY_BE_UNDEF ? MAY_BE_NULL : 0);
  2035. if (!(ZEND_OPTIMIZER_IGNORE_OVERLOADING & optimization_level)) {
  2036. /* Handle potentially overloaded operators.
  2037. * This could be made more precise by checking the class type, if known. */
  2038. if ((t1_type & MAY_BE_OBJECT) || (t2_type & MAY_BE_OBJECT)) {
  2039. /* This is somewhat GMP specific. */
  2040. tmp |= MAY_BE_OBJECT | MAY_BE_FALSE | MAY_BE_RC1;
  2041. }
  2042. }
  2043. switch (opcode) {
  2044. case ZEND_ADD:
  2045. if (t1_type == MAY_BE_LONG && t2_type == MAY_BE_LONG) {
  2046. if (!ssa->var_info[result_var].has_range ||
  2047. ssa->var_info[result_var].range.underflow ||
  2048. ssa->var_info[result_var].range.overflow) {
  2049. /* may overflow */
  2050. tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
  2051. } else {
  2052. tmp |= MAY_BE_LONG;
  2053. }
  2054. } else if (t1_type == MAY_BE_DOUBLE || t2_type == MAY_BE_DOUBLE) {
  2055. tmp |= MAY_BE_DOUBLE;
  2056. } else if (t1_type == MAY_BE_ARRAY && t2_type == MAY_BE_ARRAY) {
  2057. tmp |= MAY_BE_ARRAY | MAY_BE_RC1;
  2058. tmp |= t1 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
  2059. tmp |= t2 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
  2060. } else {
  2061. tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
  2062. if ((t1_type & MAY_BE_ARRAY) && (t2_type & MAY_BE_ARRAY)) {
  2063. tmp |= MAY_BE_ARRAY | MAY_BE_RC1;
  2064. tmp |= t1 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
  2065. tmp |= t2 & (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF);
  2066. }
  2067. }
  2068. break;
  2069. case ZEND_SUB:
  2070. case ZEND_MUL:
  2071. if (t1_type == MAY_BE_LONG && t2_type == MAY_BE_LONG) {
  2072. if (!ssa->var_info[result_var].has_range ||
  2073. ssa->var_info[result_var].range.underflow ||
  2074. ssa->var_info[result_var].range.overflow) {
  2075. /* may overflow */
  2076. tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
  2077. } else {
  2078. tmp |= MAY_BE_LONG;
  2079. }
  2080. } else if (t1_type == MAY_BE_DOUBLE || t2_type == MAY_BE_DOUBLE) {
  2081. tmp |= MAY_BE_DOUBLE;
  2082. } else {
  2083. tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
  2084. }
  2085. break;
  2086. case ZEND_DIV:
  2087. case ZEND_POW:
  2088. if (t1_type == MAY_BE_DOUBLE || t2_type == MAY_BE_DOUBLE) {
  2089. tmp |= MAY_BE_DOUBLE;
  2090. } else {
  2091. tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
  2092. }
  2093. /* Division by zero results in Inf/-Inf/Nan (double), so it doesn't need any special
  2094. * handling */
  2095. break;
  2096. case ZEND_MOD:
  2097. tmp |= MAY_BE_LONG;
  2098. /* Division by zero results in an exception, so it doesn't need any special handling */
  2099. break;
  2100. case ZEND_BW_OR:
  2101. case ZEND_BW_AND:
  2102. case ZEND_BW_XOR:
  2103. if ((t1_type & MAY_BE_STRING) && (t2_type & MAY_BE_STRING)) {
  2104. tmp |= MAY_BE_STRING | MAY_BE_RC1;
  2105. }
  2106. if ((t1_type & ~MAY_BE_STRING) || (t2_type & ~MAY_BE_STRING)) {
  2107. tmp |= MAY_BE_LONG;
  2108. }
  2109. break;
  2110. case ZEND_SL:
  2111. case ZEND_SR:
  2112. tmp |= MAY_BE_LONG;
  2113. break;
  2114. case ZEND_CONCAT:
  2115. case ZEND_FAST_CONCAT:
  2116. /* TODO: +MAY_BE_OBJECT ??? */
  2117. tmp = MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN;
  2118. break;
  2119. EMPTY_SWITCH_DEFAULT_CASE()
  2120. }
  2121. return tmp;
  2122. }
  2123. static inline zend_class_entry *get_class_entry(const zend_script *script, zend_string *lcname) {
  2124. zend_class_entry *ce = script ? zend_hash_find_ptr(&script->class_table, lcname) : NULL;
  2125. if (ce) {
  2126. return ce;
  2127. }
  2128. ce = zend_hash_find_ptr(CG(class_table), lcname);
  2129. if (ce && ce->type == ZEND_INTERNAL_CLASS) {
  2130. return ce;
  2131. }
  2132. return NULL;
  2133. }
  2134. static uint32_t zend_fetch_arg_info(const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce)
  2135. {
  2136. uint32_t tmp = 0;
  2137. *pce = NULL;
  2138. if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
  2139. // class type hinting...
  2140. zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(arg_info->type));
  2141. tmp |= MAY_BE_OBJECT;
  2142. *pce = get_class_entry(script, lcname);
  2143. zend_string_release_ex(lcname, 0);
  2144. } else if (ZEND_TYPE_IS_CODE(arg_info->type)) {
  2145. zend_uchar type_hint = ZEND_TYPE_CODE(arg_info->type);
  2146. if (type_hint == IS_VOID) {
  2147. tmp |= MAY_BE_NULL;
  2148. } else if (type_hint == IS_CALLABLE) {
  2149. tmp |= MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
  2150. } else if (type_hint == IS_ITERABLE) {
  2151. tmp |= MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
  2152. } else if (type_hint == IS_ARRAY) {
  2153. tmp |= MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
  2154. } else if (type_hint == _IS_BOOL) {
  2155. tmp |= MAY_BE_TRUE|MAY_BE_FALSE;
  2156. } else {
  2157. ZEND_ASSERT(type_hint < IS_REFERENCE);
  2158. tmp |= 1 << type_hint;
  2159. }
  2160. } else {
  2161. tmp |= MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
  2162. }
  2163. if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
  2164. tmp |= MAY_BE_NULL;
  2165. }
  2166. return tmp;
  2167. }
  2168. static int zend_update_type_info(const zend_op_array *op_array,
  2169. zend_ssa *ssa,
  2170. const zend_script *script,
  2171. zend_bitset worklist,
  2172. int i,
  2173. zend_long optimization_level)
  2174. {
  2175. uint32_t t1, t2;
  2176. uint32_t tmp, orig;
  2177. zend_op *opline = op_array->opcodes + i;
  2178. zend_ssa_op *ssa_ops = ssa->ops;
  2179. zend_ssa_var *ssa_vars = ssa->vars;
  2180. zend_ssa_var_info *ssa_var_info = ssa->var_info;
  2181. zend_class_entry *ce;
  2182. int j;
  2183. if (opline->opcode == ZEND_OP_DATA) {
  2184. opline--;
  2185. i--;
  2186. }
  2187. t1 = OP1_INFO();
  2188. t2 = OP2_INFO();
  2189. /* If one of the operands cannot have any type, this means the operand derives from
  2190. * unreachable code. Propagate the empty result early, so that that the following
  2191. * code may assume that operands have at least one type. */
  2192. if (!(t1 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_CLASS|MAY_BE_ERROR))
  2193. || !(t2 & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_CLASS|MAY_BE_ERROR))) {
  2194. tmp = 0;
  2195. if (ssa_ops[i].result_def >= 0) {
  2196. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2197. }
  2198. if (ssa_ops[i].op1_def >= 0) {
  2199. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2200. }
  2201. if (ssa_ops[i].op2_def >= 0) {
  2202. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op2_def);
  2203. }
  2204. return 1;
  2205. }
  2206. switch (opline->opcode) {
  2207. case ZEND_ADD:
  2208. case ZEND_SUB:
  2209. case ZEND_MUL:
  2210. case ZEND_DIV:
  2211. case ZEND_POW:
  2212. case ZEND_MOD:
  2213. case ZEND_BW_OR:
  2214. case ZEND_BW_AND:
  2215. case ZEND_BW_XOR:
  2216. case ZEND_SL:
  2217. case ZEND_SR:
  2218. case ZEND_CONCAT:
  2219. tmp = binary_op_result_type(ssa, opline->opcode, t1, t2, ssa_ops[i].result_def, optimization_level);
  2220. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2221. break;
  2222. case ZEND_BW_NOT:
  2223. tmp = 0;
  2224. if (t1 & MAY_BE_STRING) {
  2225. tmp |= MAY_BE_STRING | MAY_BE_RC1;
  2226. }
  2227. if (t1 & (MAY_BE_ANY-MAY_BE_STRING)) {
  2228. tmp |= MAY_BE_LONG;
  2229. }
  2230. if (!(ZEND_OPTIMIZER_IGNORE_OVERLOADING & optimization_level)) {
  2231. if (t1 & MAY_BE_OBJECT) {
  2232. /* Potentially overloaded operator. */
  2233. tmp |= MAY_BE_OBJECT | MAY_BE_RC1;
  2234. }
  2235. }
  2236. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2237. break;
  2238. case ZEND_BEGIN_SILENCE:
  2239. UPDATE_SSA_TYPE(MAY_BE_LONG, ssa_ops[i].result_def);
  2240. break;
  2241. case ZEND_BOOL_NOT:
  2242. case ZEND_BOOL_XOR:
  2243. case ZEND_IS_IDENTICAL:
  2244. case ZEND_IS_NOT_IDENTICAL:
  2245. case ZEND_IS_EQUAL:
  2246. case ZEND_IS_NOT_EQUAL:
  2247. case ZEND_IS_SMALLER:
  2248. case ZEND_IS_SMALLER_OR_EQUAL:
  2249. case ZEND_INSTANCEOF:
  2250. case ZEND_JMPZ_EX:
  2251. case ZEND_JMPNZ_EX:
  2252. case ZEND_CASE:
  2253. case ZEND_BOOL:
  2254. case ZEND_ISSET_ISEMPTY_CV:
  2255. case ZEND_ISSET_ISEMPTY_VAR:
  2256. case ZEND_ISSET_ISEMPTY_DIM_OBJ:
  2257. case ZEND_ISSET_ISEMPTY_PROP_OBJ:
  2258. case ZEND_ISSET_ISEMPTY_STATIC_PROP:
  2259. case ZEND_ASSERT_CHECK:
  2260. case ZEND_IN_ARRAY:
  2261. UPDATE_SSA_TYPE(MAY_BE_FALSE|MAY_BE_TRUE, ssa_ops[i].result_def);
  2262. break;
  2263. case ZEND_CAST:
  2264. if (ssa_ops[i].op1_def >= 0) {
  2265. tmp = t1;
  2266. if ((t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT)) &&
  2267. (opline->op1_type == IS_CV) &&
  2268. (opline->extended_value == IS_ARRAY ||
  2269. opline->extended_value == IS_OBJECT)) {
  2270. tmp |= MAY_BE_RCN;
  2271. } else if ((t1 & MAY_BE_STRING) &&
  2272. (opline->op1_type == IS_CV) &&
  2273. opline->extended_value == IS_STRING) {
  2274. tmp |= MAY_BE_RCN;
  2275. }
  2276. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2277. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  2278. }
  2279. tmp = 0;
  2280. if (opline->extended_value == _IS_BOOL) {
  2281. tmp |= MAY_BE_TRUE|MAY_BE_FALSE;
  2282. } else {
  2283. tmp |= 1 << opline->extended_value;
  2284. if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
  2285. if ((tmp & MAY_BE_ANY) == (t1 & MAY_BE_ANY)) {
  2286. tmp |= (t1 & MAY_BE_RC1) | MAY_BE_RCN;
  2287. } else if ((opline->extended_value == IS_ARRAY ||
  2288. opline->extended_value == IS_OBJECT) &&
  2289. (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT))) {
  2290. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  2291. } else if (opline->extended_value == IS_STRING &&
  2292. (t1 & (MAY_BE_STRING|MAY_BE_OBJECT))) {
  2293. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  2294. } else {
  2295. tmp |= MAY_BE_RC1;
  2296. }
  2297. }
  2298. }
  2299. if (opline->extended_value == IS_ARRAY) {
  2300. if (t1 & MAY_BE_ARRAY) {
  2301. tmp |= t1 & (MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF);
  2302. }
  2303. if (t1 & MAY_BE_OBJECT) {
  2304. tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  2305. } else {
  2306. tmp |= ((t1 & MAY_BE_ANY) << MAY_BE_ARRAY_SHIFT) | ((t1 & MAY_BE_ANY)? MAY_BE_ARRAY_KEY_LONG : 0);
  2307. }
  2308. }
  2309. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2310. break;
  2311. case ZEND_QM_ASSIGN:
  2312. case ZEND_JMP_SET:
  2313. case ZEND_COALESCE:
  2314. if (ssa_ops[i].op1_def >= 0) {
  2315. tmp = t1;
  2316. if ((t1 & (MAY_BE_RC1|MAY_BE_REF)) && (opline->op1_type == IS_CV)) {
  2317. tmp |= MAY_BE_RCN;
  2318. }
  2319. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2320. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  2321. }
  2322. tmp = t1 & ~(MAY_BE_UNDEF|MAY_BE_REF);
  2323. if (t1 & MAY_BE_UNDEF) {
  2324. tmp |= MAY_BE_NULL;
  2325. }
  2326. if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
  2327. tmp |= (t1 & (MAY_BE_RC1|MAY_BE_RCN));
  2328. if (opline->op1_type == IS_CV) {
  2329. tmp |= MAY_BE_RCN;
  2330. }
  2331. }
  2332. if (opline->opcode != ZEND_QM_ASSIGN) {
  2333. /* COALESCE and JMP_SET result can't be null */
  2334. tmp &= ~MAY_BE_NULL;
  2335. if (opline->opcode == ZEND_JMP_SET) {
  2336. /* JMP_SET result can't be false either */
  2337. tmp &= ~MAY_BE_FALSE;
  2338. }
  2339. }
  2340. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2341. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].result_def);
  2342. break;
  2343. case ZEND_ASSIGN_ADD:
  2344. case ZEND_ASSIGN_SUB:
  2345. case ZEND_ASSIGN_MUL:
  2346. case ZEND_ASSIGN_DIV:
  2347. case ZEND_ASSIGN_POW:
  2348. case ZEND_ASSIGN_MOD:
  2349. case ZEND_ASSIGN_SL:
  2350. case ZEND_ASSIGN_SR:
  2351. case ZEND_ASSIGN_BW_OR:
  2352. case ZEND_ASSIGN_BW_AND:
  2353. case ZEND_ASSIGN_BW_XOR:
  2354. case ZEND_ASSIGN_CONCAT:
  2355. orig = 0;
  2356. tmp = 0;
  2357. if (opline->extended_value == ZEND_ASSIGN_OBJ) {
  2358. tmp |= MAY_BE_REF;
  2359. orig = t1;
  2360. t1 = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  2361. t2 = OP1_DATA_INFO();
  2362. } else if (opline->extended_value == ZEND_ASSIGN_DIM) {
  2363. if (t1 & MAY_BE_ARRAY_OF_REF) {
  2364. tmp |= MAY_BE_REF;
  2365. }
  2366. orig = t1;
  2367. t1 = zend_array_element_type(t1, 1, 0);
  2368. t2 = OP1_DATA_INFO();
  2369. } else {
  2370. if (t1 & MAY_BE_REF) {
  2371. tmp |= MAY_BE_REF;
  2372. }
  2373. }
  2374. tmp |= binary_op_result_type(
  2375. ssa, get_compound_assign_op(opline->opcode), t1, t2, ssa_ops[i].op1_def, optimization_level);
  2376. if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY)) {
  2377. tmp |= MAY_BE_RC1;
  2378. }
  2379. if (tmp & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
  2380. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  2381. }
  2382. if (opline->extended_value == ZEND_ASSIGN_DIM) {
  2383. if (opline->op1_type == IS_CV) {
  2384. orig = assign_dim_result_type(orig, OP2_INFO(), tmp, opline->op2_type);
  2385. UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
  2386. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  2387. }
  2388. } else if (opline->extended_value == ZEND_ASSIGN_OBJ) {
  2389. if (opline->op1_type == IS_CV) {
  2390. if (!(orig & MAY_BE_REF)) {
  2391. if (orig & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
  2392. orig &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
  2393. orig |= MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
  2394. }
  2395. if (orig & MAY_BE_OBJECT) {
  2396. orig |= (MAY_BE_RC1|MAY_BE_RCN);
  2397. }
  2398. }
  2399. UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
  2400. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  2401. }
  2402. } else {
  2403. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2404. }
  2405. if (ssa_ops[i].result_def >= 0) {
  2406. if (opline->extended_value == ZEND_ASSIGN_DIM) {
  2407. if (opline->op2_type == IS_UNUSED) {
  2408. /* When appending to an array and the LONG_MAX key is already used
  2409. * null will be returned. */
  2410. tmp |= MAY_BE_NULL;
  2411. }
  2412. if (t2 & (MAY_BE_ARRAY | MAY_BE_OBJECT)) {
  2413. /* Arrays and objects cannot be used as keys. */
  2414. tmp |= MAY_BE_NULL;
  2415. }
  2416. if (t1 & (MAY_BE_ANY - (MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING | MAY_BE_ARRAY))) {
  2417. /* null and false are implicitly converted to array, anything else
  2418. * results in a null return value. */
  2419. tmp |= MAY_BE_NULL;
  2420. }
  2421. } else if (opline->extended_value == ZEND_ASSIGN_OBJ) {
  2422. if (orig & (MAY_BE_ANY - (MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_OBJECT))) {
  2423. /* null and false (and empty string) are implicitly converted to object,
  2424. * anything else results in a null return value. */
  2425. tmp |= MAY_BE_NULL;
  2426. }
  2427. }
  2428. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2429. }
  2430. break;
  2431. case ZEND_PRE_INC:
  2432. case ZEND_PRE_DEC:
  2433. tmp = 0;
  2434. if (t1 & MAY_BE_REF) {
  2435. tmp |= MAY_BE_REF;
  2436. }
  2437. if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
  2438. tmp |= MAY_BE_RC1;
  2439. if (ssa_ops[i].result_def >= 0) {
  2440. tmp |= MAY_BE_RCN;
  2441. }
  2442. }
  2443. if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) {
  2444. if (!ssa_var_info[ssa_ops[i].op1_use].has_range ||
  2445. (opline->opcode == ZEND_PRE_DEC &&
  2446. (ssa_var_info[ssa_ops[i].op1_use].range.underflow ||
  2447. ssa_var_info[ssa_ops[i].op1_use].range.min == ZEND_LONG_MIN)) ||
  2448. (opline->opcode == ZEND_PRE_INC &&
  2449. (ssa_var_info[ssa_ops[i].op1_use].range.overflow ||
  2450. ssa_var_info[ssa_ops[i].op1_use].range.max == ZEND_LONG_MAX))) {
  2451. /* may overflow */
  2452. tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
  2453. } else {
  2454. tmp |= MAY_BE_LONG;
  2455. }
  2456. } else {
  2457. if (t1 & MAY_BE_ERROR) {
  2458. tmp |= MAY_BE_NULL;
  2459. }
  2460. if (t1 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
  2461. if (opline->opcode == ZEND_PRE_INC) {
  2462. tmp |= MAY_BE_LONG;
  2463. } else {
  2464. tmp |= MAY_BE_NULL;
  2465. }
  2466. }
  2467. if (t1 & MAY_BE_LONG) {
  2468. tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
  2469. }
  2470. if (t1 & MAY_BE_DOUBLE) {
  2471. tmp |= MAY_BE_DOUBLE;
  2472. }
  2473. if (t1 & MAY_BE_STRING) {
  2474. tmp |= MAY_BE_STRING | MAY_BE_LONG | MAY_BE_DOUBLE;
  2475. }
  2476. tmp |= t1 & (MAY_BE_FALSE | MAY_BE_TRUE | MAY_BE_RESOURCE | MAY_BE_ARRAY | MAY_BE_OBJECT | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF | MAY_BE_ARRAY_KEY_ANY);
  2477. }
  2478. if (ssa_ops[i].op1_def >= 0) {
  2479. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2480. }
  2481. if (ssa_ops[i].result_def >= 0) {
  2482. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2483. }
  2484. break;
  2485. case ZEND_POST_INC:
  2486. case ZEND_POST_DEC:
  2487. if (ssa_ops[i].result_def >= 0) {
  2488. tmp = 0;
  2489. if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
  2490. tmp |= MAY_BE_RC1|MAY_BE_RCN;
  2491. }
  2492. tmp |= t1 & ~(MAY_BE_UNDEF|MAY_BE_ERROR|MAY_BE_REF|MAY_BE_RCN);
  2493. if (t1 & MAY_BE_UNDEF) {
  2494. tmp |= MAY_BE_NULL;
  2495. }
  2496. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2497. }
  2498. tmp = 0;
  2499. if (t1 & MAY_BE_REF) {
  2500. tmp |= MAY_BE_REF;
  2501. }
  2502. if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
  2503. tmp |= MAY_BE_RC1;
  2504. }
  2505. if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) {
  2506. if (!ssa_var_info[ssa_ops[i].op1_use].has_range ||
  2507. (opline->opcode == ZEND_POST_DEC &&
  2508. (ssa_var_info[ssa_ops[i].op1_use].range.underflow ||
  2509. ssa_var_info[ssa_ops[i].op1_use].range.min == ZEND_LONG_MIN)) ||
  2510. (opline->opcode == ZEND_POST_INC &&
  2511. (ssa_var_info[ssa_ops[i].op1_use].range.overflow ||
  2512. ssa_var_info[ssa_ops[i].op1_use].range.max == ZEND_LONG_MAX))) {
  2513. /* may overflow */
  2514. tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
  2515. } else {
  2516. tmp |= MAY_BE_LONG;
  2517. }
  2518. } else {
  2519. if (t1 & MAY_BE_ERROR) {
  2520. tmp |= MAY_BE_NULL;
  2521. }
  2522. if (t1 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
  2523. if (opline->opcode == ZEND_POST_INC) {
  2524. tmp |= MAY_BE_LONG;
  2525. } else {
  2526. tmp |= MAY_BE_NULL;
  2527. }
  2528. }
  2529. if (t1 & MAY_BE_LONG) {
  2530. tmp |= MAY_BE_LONG | MAY_BE_DOUBLE;
  2531. }
  2532. if (t1 & MAY_BE_DOUBLE) {
  2533. tmp |= MAY_BE_DOUBLE;
  2534. }
  2535. if (t1 & MAY_BE_STRING) {
  2536. tmp |= MAY_BE_STRING | MAY_BE_LONG | MAY_BE_DOUBLE;
  2537. }
  2538. tmp |= t1 & (MAY_BE_FALSE | MAY_BE_TRUE | MAY_BE_RESOURCE | MAY_BE_ARRAY | MAY_BE_OBJECT | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF | MAY_BE_ARRAY_KEY_ANY);
  2539. }
  2540. if (ssa_ops[i].op1_def >= 0) {
  2541. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2542. }
  2543. break;
  2544. case ZEND_ASSIGN_DIM:
  2545. if (opline->op1_type == IS_CV) {
  2546. tmp = assign_dim_result_type(t1, t2, OP1_DATA_INFO(), opline->op2_type);
  2547. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2548. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  2549. }
  2550. if (ssa_ops[i].result_def >= 0) {
  2551. tmp = 0;
  2552. if (t1 & MAY_BE_STRING) {
  2553. tmp |= MAY_BE_STRING;
  2554. }
  2555. if (t1 & ((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_STRING)) {
  2556. tmp |= (OP1_DATA_INFO() & (MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF));
  2557. if (opline->op2_type == IS_UNUSED) {
  2558. /* When appending to an array and the LONG_MAX key is already used
  2559. * null will be returned. */
  2560. tmp |= MAY_BE_NULL;
  2561. }
  2562. if (t2 & (MAY_BE_ARRAY | MAY_BE_OBJECT)) {
  2563. /* Arrays and objects cannot be used as keys. */
  2564. tmp |= MAY_BE_NULL;
  2565. }
  2566. if (t1 & (MAY_BE_ANY - (MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING | MAY_BE_ARRAY))) {
  2567. /* undef, null and false are implicitly converted to array, anything else
  2568. * results in a null return value. */
  2569. tmp |= MAY_BE_NULL;
  2570. }
  2571. }
  2572. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  2573. if (t1 & MAY_BE_OBJECT) {
  2574. tmp |= MAY_BE_REF;
  2575. }
  2576. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2577. }
  2578. if ((opline+1)->op1_type == IS_CV && ssa_ops[i+1].op1_def >= 0) {
  2579. opline++;
  2580. i++;
  2581. tmp = OP1_INFO();
  2582. if (tmp & (MAY_BE_ANY | MAY_BE_REF)) {
  2583. if (tmp & MAY_BE_RC1) {
  2584. tmp |= MAY_BE_RCN;
  2585. }
  2586. }
  2587. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2588. }
  2589. break;
  2590. case ZEND_ASSIGN_OBJ:
  2591. if (opline->op1_type == IS_CV) {
  2592. tmp = t1;
  2593. if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
  2594. tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
  2595. tmp |= MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
  2596. }
  2597. if (tmp & MAY_BE_OBJECT) {
  2598. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  2599. }
  2600. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2601. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  2602. }
  2603. if (ssa_ops[i].result_def >= 0) {
  2604. // TODO: ???
  2605. tmp = MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  2606. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2607. }
  2608. if ((opline+1)->op1_type == IS_CV) {
  2609. opline++;
  2610. i++;
  2611. tmp = OP1_INFO();
  2612. if (tmp & (MAY_BE_ANY | MAY_BE_REF)) {
  2613. if (tmp & MAY_BE_RC1) {
  2614. tmp |= MAY_BE_RCN;
  2615. }
  2616. }
  2617. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2618. }
  2619. break;
  2620. case ZEND_PRE_INC_OBJ:
  2621. case ZEND_PRE_DEC_OBJ:
  2622. case ZEND_POST_INC_OBJ:
  2623. case ZEND_POST_DEC_OBJ:
  2624. if (opline->op1_type == IS_CV) {
  2625. tmp = t1;
  2626. if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
  2627. tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
  2628. tmp |= MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
  2629. }
  2630. if (tmp & MAY_BE_OBJECT) {
  2631. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  2632. }
  2633. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2634. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  2635. }
  2636. if (ssa_ops[i].result_def >= 0) {
  2637. // TODO: ???
  2638. tmp = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  2639. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2640. }
  2641. break;
  2642. case ZEND_ASSIGN:
  2643. if (opline->op2_type == IS_CV && ssa_ops[i].op2_def >= 0) {
  2644. tmp = t2;
  2645. if (tmp & (MAY_BE_ANY | MAY_BE_REF)) {
  2646. if (tmp & MAY_BE_RC1) {
  2647. tmp |= MAY_BE_RCN;
  2648. }
  2649. }
  2650. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op2_def);
  2651. }
  2652. tmp = t2 & ~(MAY_BE_UNDEF|MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN);
  2653. if (t2 & MAY_BE_UNDEF) {
  2654. tmp |= MAY_BE_NULL;
  2655. }
  2656. if (t1 & MAY_BE_REF) {
  2657. tmp |= MAY_BE_REF;
  2658. }
  2659. if (t2 & MAY_BE_REF) {
  2660. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  2661. } else if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
  2662. tmp |= t2 & (MAY_BE_RC1|MAY_BE_RCN);
  2663. } else if (t2 & (MAY_BE_RC1|MAY_BE_RCN)) {
  2664. tmp |= MAY_BE_RCN;
  2665. }
  2666. if (RETURN_VALUE_USED(opline) && (tmp & MAY_BE_RC1)) {
  2667. tmp |= MAY_BE_RCN;
  2668. }
  2669. if (ssa_ops[i].op1_def >= 0) {
  2670. if (ssa_var_info[ssa_ops[i].op1_def].use_as_double) {
  2671. tmp &= ~MAY_BE_LONG;
  2672. tmp |= MAY_BE_DOUBLE;
  2673. }
  2674. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2675. COPY_SSA_OBJ_TYPE(ssa_ops[i].op2_use, ssa_ops[i].op1_def);
  2676. }
  2677. if (ssa_ops[i].result_def >= 0) {
  2678. UPDATE_SSA_TYPE(tmp & ~MAY_BE_REF, ssa_ops[i].result_def);
  2679. COPY_SSA_OBJ_TYPE(ssa_ops[i].op2_use, ssa_ops[i].result_def);
  2680. }
  2681. break;
  2682. case ZEND_ASSIGN_REF:
  2683. // TODO: ???
  2684. if (opline->op2_type == IS_CV) {
  2685. tmp = (MAY_BE_REF | t2) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
  2686. if (t2 & MAY_BE_UNDEF) {
  2687. tmp |= MAY_BE_NULL;
  2688. }
  2689. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op2_def);
  2690. }
  2691. if (opline->op2_type == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION) {
  2692. tmp = (MAY_BE_REF | MAY_BE_RCN | MAY_BE_RC1 | t2) & ~MAY_BE_UNDEF;
  2693. } else {
  2694. tmp = (MAY_BE_REF | t2) & ~(MAY_BE_UNDEF|MAY_BE_ERROR|MAY_BE_RC1|MAY_BE_RCN);
  2695. }
  2696. if (t2 & MAY_BE_UNDEF) {
  2697. tmp |= MAY_BE_NULL;
  2698. }
  2699. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2700. if (ssa_ops[i].result_def >= 0) {
  2701. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2702. }
  2703. break;
  2704. case ZEND_BIND_GLOBAL:
  2705. tmp = MAY_BE_REF | MAY_BE_ANY
  2706. | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  2707. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2708. break;
  2709. case ZEND_BIND_STATIC:
  2710. tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF
  2711. | ((opline->extended_value & ZEND_BIND_REF) ? MAY_BE_REF : (MAY_BE_RC1 | MAY_BE_RCN));
  2712. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2713. break;
  2714. case ZEND_SEND_VAR:
  2715. if (ssa_ops[i].op1_def >= 0) {
  2716. tmp = t1;
  2717. if ((t1 & (MAY_BE_RC1|MAY_BE_REF)) && (opline->op1_type == IS_CV)) {
  2718. tmp |= MAY_BE_RCN;
  2719. }
  2720. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2721. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  2722. }
  2723. break;
  2724. case ZEND_BIND_LEXICAL:
  2725. if (ssa_ops[i].op2_def >= 0) {
  2726. if (opline->extended_value & ZEND_BIND_REF) {
  2727. tmp = t2 | MAY_BE_REF;
  2728. } else {
  2729. tmp = t2 & ~(MAY_BE_RC1|MAY_BE_RCN);
  2730. if (t2 & (MAY_BE_RC1|MAY_BE_RCN)) {
  2731. tmp |= MAY_BE_RCN;
  2732. }
  2733. }
  2734. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op2_def);
  2735. COPY_SSA_OBJ_TYPE(ssa_ops[i].op2_use, ssa_ops[i].op2_def);
  2736. }
  2737. break;
  2738. case ZEND_YIELD:
  2739. if (ssa_ops[i].op1_def >= 0) {
  2740. if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
  2741. tmp = t1 | MAY_BE_REF;
  2742. } else {
  2743. tmp = t1 & ~(MAY_BE_RC1|MAY_BE_RCN);
  2744. if (t1 & (MAY_BE_RC1|MAY_BE_RCN)) {
  2745. tmp |= MAY_BE_RCN;
  2746. }
  2747. }
  2748. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2749. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  2750. }
  2751. if (ssa_ops[i].result_def >= 0) {
  2752. tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF
  2753. | MAY_BE_RC1 | MAY_BE_RCN;
  2754. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2755. }
  2756. break;
  2757. case ZEND_SEND_VAR_EX:
  2758. case ZEND_SEND_FUNC_ARG:
  2759. if (ssa_ops[i].op1_def >= 0) {
  2760. tmp = (t1 & MAY_BE_UNDEF)|MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
  2761. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2762. }
  2763. break;
  2764. case ZEND_SEND_REF:
  2765. if (ssa_ops[i].op1_def >= 0) {
  2766. tmp = MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
  2767. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2768. }
  2769. break;
  2770. case ZEND_SEND_UNPACK:
  2771. if (ssa_ops[i].op1_def >= 0) {
  2772. tmp = t1;
  2773. if (t1 & MAY_BE_ARRAY) {
  2774. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  2775. if (t1 & MAY_BE_ARRAY_OF_ANY) {
  2776. /* SEND_UNPACK may acquire references into the array */
  2777. tmp |= MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  2778. }
  2779. }
  2780. if (t1 & MAY_BE_OBJECT) {
  2781. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  2782. }
  2783. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2784. }
  2785. break;
  2786. case ZEND_FAST_CONCAT:
  2787. case ZEND_ROPE_INIT:
  2788. case ZEND_ROPE_ADD:
  2789. case ZEND_ROPE_END:
  2790. UPDATE_SSA_TYPE(MAY_BE_STRING|MAY_BE_RC1|MAY_BE_RCN, ssa_ops[i].result_def);
  2791. break;
  2792. case ZEND_RECV:
  2793. case ZEND_RECV_INIT:
  2794. {
  2795. /* Typehinting */
  2796. zend_func_info *func_info;
  2797. zend_arg_info *arg_info = NULL;
  2798. if (op_array->arg_info && opline->op1.num <= op_array->num_args) {
  2799. arg_info = &op_array->arg_info[opline->op1.num-1];
  2800. }
  2801. ce = NULL;
  2802. if (arg_info) {
  2803. tmp = zend_fetch_arg_info(script, arg_info, &ce);
  2804. if (opline->opcode == ZEND_RECV_INIT &&
  2805. Z_TYPE_P(CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants)) == IS_CONSTANT_AST) {
  2806. /* The constant may resolve to NULL */
  2807. tmp |= MAY_BE_NULL;
  2808. }
  2809. if (arg_info->pass_by_reference) {
  2810. tmp |= MAY_BE_REF;
  2811. } else if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
  2812. tmp |= MAY_BE_RC1|MAY_BE_RCN;
  2813. }
  2814. } else {
  2815. tmp = MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
  2816. }
  2817. func_info = ZEND_FUNC_INFO(op_array);
  2818. if (func_info && (int)opline->op1.num-1 < func_info->num_args) {
  2819. tmp = (tmp & (MAY_BE_RC1|MAY_BE_RCN|MAY_BE_REF)) |
  2820. (tmp & func_info->arg_info[opline->op1.num-1].info.type);
  2821. }
  2822. #if 0
  2823. /* We won't receive unused arguments */
  2824. if (ssa_vars[ssa_ops[i].result_def].use_chain < 0 &&
  2825. ssa_vars[ssa_ops[i].result_def].phi_use_chain == NULL &&
  2826. op_array->arg_info &&
  2827. opline->op1.num <= op_array->num_args &&
  2828. op_array->arg_info[opline->op1.num-1].class_name == NULL &&
  2829. !op_array->arg_info[opline->op1.num-1].type_hint) {
  2830. tmp = MAY_BE_UNDEF|MAY_BE_RCN;
  2831. }
  2832. #endif
  2833. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2834. if (func_info &&
  2835. (int)opline->op1.num-1 < func_info->num_args &&
  2836. func_info->arg_info[opline->op1.num-1].info.ce) {
  2837. UPDATE_SSA_OBJ_TYPE(
  2838. func_info->arg_info[opline->op1.num-1].info.ce,
  2839. func_info->arg_info[opline->op1.num-1].info.is_instanceof,
  2840. ssa_ops[i].result_def);
  2841. } else if (ce) {
  2842. UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_ops[i].result_def);
  2843. } else {
  2844. UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
  2845. }
  2846. break;
  2847. }
  2848. case ZEND_DECLARE_CLASS:
  2849. case ZEND_DECLARE_INHERITED_CLASS:
  2850. case ZEND_DECLARE_ANON_CLASS:
  2851. case ZEND_DECLARE_ANON_INHERITED_CLASS:
  2852. UPDATE_SSA_TYPE(MAY_BE_CLASS, ssa_ops[i].result_def);
  2853. if (script && (ce = zend_hash_find_ptr(&script->class_table, Z_STR_P(CRT_CONSTANT_EX(op_array, opline, opline->op1, ssa->rt_constants)))) != NULL) {
  2854. UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_ops[i].result_def);
  2855. }
  2856. break;
  2857. case ZEND_FETCH_CLASS:
  2858. UPDATE_SSA_TYPE(MAY_BE_CLASS, ssa_ops[i].result_def);
  2859. if (opline->op2_type == IS_UNUSED) {
  2860. switch (opline->op1.num & ZEND_FETCH_CLASS_MASK) {
  2861. case ZEND_FETCH_CLASS_SELF:
  2862. if (op_array->scope) {
  2863. UPDATE_SSA_OBJ_TYPE(op_array->scope, 0, ssa_ops[i].result_def);
  2864. } else {
  2865. UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
  2866. }
  2867. break;
  2868. case ZEND_FETCH_CLASS_PARENT:
  2869. if (op_array->scope && op_array->scope->parent) {
  2870. UPDATE_SSA_OBJ_TYPE(op_array->scope->parent, 0, ssa_ops[i].result_def);
  2871. } else {
  2872. UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
  2873. }
  2874. break;
  2875. case ZEND_FETCH_CLASS_STATIC:
  2876. default:
  2877. UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
  2878. break;
  2879. }
  2880. } else if (opline->op2_type == IS_CONST) {
  2881. zval *zv = CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants);
  2882. if (Z_TYPE_P(zv) == IS_STRING) {
  2883. ce = get_class_entry(script, Z_STR_P(zv+1));
  2884. UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_ops[i].result_def);
  2885. } else {
  2886. UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
  2887. }
  2888. } else {
  2889. COPY_SSA_OBJ_TYPE(ssa_ops[i].op2_use, ssa_ops[i].result_def);
  2890. }
  2891. break;
  2892. case ZEND_NEW:
  2893. tmp = MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT;
  2894. if (opline->op1_type == IS_CONST &&
  2895. (ce = get_class_entry(script, Z_STR_P(CRT_CONSTANT_EX(op_array, opline, opline->op1, ssa->rt_constants)+1))) != NULL) {
  2896. UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_ops[i].result_def);
  2897. } else if ((t1 & MAY_BE_CLASS) && ssa_ops[i].op1_use >= 0 && ssa_var_info[ssa_ops[i].op1_use].ce) {
  2898. UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_ops[i].op1_use].ce, ssa_var_info[ssa_ops[i].op1_use].is_instanceof, ssa_ops[i].result_def);
  2899. } else {
  2900. UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
  2901. }
  2902. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2903. break;
  2904. case ZEND_CLONE:
  2905. UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT, ssa_ops[i].result_def);
  2906. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].result_def);
  2907. break;
  2908. case ZEND_INIT_ARRAY:
  2909. case ZEND_ADD_ARRAY_ELEMENT:
  2910. if (opline->op1_type == IS_CV && ssa_ops[i].op1_def >= 0) {
  2911. if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) {
  2912. tmp = (MAY_BE_REF | t1) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
  2913. if (t1 & MAY_BE_UNDEF) {
  2914. tmp |= MAY_BE_NULL;
  2915. }
  2916. } else if ((t1 & (MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN)) == MAY_BE_REF) {
  2917. tmp = (MAY_BE_REF | t1) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
  2918. if (t1 & MAY_BE_UNDEF) {
  2919. tmp |= MAY_BE_NULL;
  2920. }
  2921. } else if (t1 & MAY_BE_REF) {
  2922. tmp = (MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | t1);
  2923. } else {
  2924. tmp = t1;
  2925. if (t1 & MAY_BE_RC1) {
  2926. tmp |= MAY_BE_RCN;
  2927. }
  2928. }
  2929. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2930. }
  2931. if (ssa_ops[i].result_def >= 0) {
  2932. tmp = MAY_BE_RC1|MAY_BE_ARRAY;
  2933. if (opline->op1_type != IS_UNUSED) {
  2934. tmp |= (t1 & MAY_BE_ANY) << MAY_BE_ARRAY_SHIFT;
  2935. if (t1 & MAY_BE_UNDEF) {
  2936. tmp |= MAY_BE_ARRAY_OF_NULL;
  2937. }
  2938. if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) {
  2939. tmp |= MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
  2940. }
  2941. }
  2942. if (ssa_ops[i].result_use >= 0) {
  2943. tmp |= ssa_var_info[ssa_ops[i].result_use].type;
  2944. }
  2945. if (opline->op2_type == IS_UNUSED) {
  2946. tmp |= MAY_BE_ARRAY_KEY_LONG;
  2947. } else {
  2948. if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_DOUBLE)) {
  2949. tmp |= MAY_BE_ARRAY_KEY_LONG;
  2950. }
  2951. if (t2 & (MAY_BE_STRING)) {
  2952. tmp |= MAY_BE_ARRAY_KEY_STRING;
  2953. if (opline->op2_type != IS_CONST) {
  2954. // FIXME: numeric string
  2955. tmp |= MAY_BE_ARRAY_KEY_LONG;
  2956. }
  2957. }
  2958. if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
  2959. tmp |= MAY_BE_ARRAY_KEY_STRING;
  2960. }
  2961. }
  2962. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  2963. }
  2964. break;
  2965. case ZEND_UNSET_CV:
  2966. tmp = MAY_BE_UNDEF;
  2967. if (!op_array->function_name) {
  2968. /* In global scope, we know nothing */
  2969. tmp |= MAY_BE_REF;
  2970. }
  2971. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2972. break;
  2973. case ZEND_UNSET_DIM:
  2974. case ZEND_UNSET_OBJ:
  2975. if (ssa_ops[i].op1_def >= 0) {
  2976. UPDATE_SSA_TYPE(t1, ssa_ops[i].op1_def);
  2977. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  2978. }
  2979. break;
  2980. case ZEND_FE_RESET_R:
  2981. case ZEND_FE_RESET_RW:
  2982. if (ssa_ops[i].op1_def >= 0) {
  2983. tmp = t1;
  2984. if (opline->opcode == ZEND_FE_RESET_RW) {
  2985. tmp |= MAY_BE_REF;
  2986. } else {
  2987. if ((t1 & MAY_BE_RC1) && opline->op1_type != IS_TMP_VAR) {
  2988. tmp |= MAY_BE_RCN;
  2989. }
  2990. }
  2991. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  2992. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  2993. }
  2994. if (opline->opcode == ZEND_FE_RESET_RW) {
  2995. //???
  2996. tmp = MAY_BE_REF | (t1 & (MAY_BE_ARRAY | MAY_BE_OBJECT));
  2997. } else {
  2998. tmp = MAY_BE_RC1 | MAY_BE_RCN | (t1 & (MAY_BE_ARRAY | MAY_BE_OBJECT | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF));
  2999. }
  3000. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  3001. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].result_def);
  3002. break;
  3003. case ZEND_FE_FETCH_R:
  3004. case ZEND_FE_FETCH_RW:
  3005. tmp = t2;
  3006. if (t1 & MAY_BE_OBJECT) {
  3007. if (opline->opcode == ZEND_FE_FETCH_RW) {
  3008. tmp |= MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  3009. } else {
  3010. tmp |= MAY_BE_REF | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  3011. }
  3012. }
  3013. if (t1 & MAY_BE_ARRAY) {
  3014. if (opline->opcode == ZEND_FE_FETCH_RW) {
  3015. tmp |= MAY_BE_REF | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  3016. } else {
  3017. tmp |= ((t1 & MAY_BE_ARRAY_OF_ANY) >> MAY_BE_ARRAY_SHIFT);
  3018. if (tmp & MAY_BE_ARRAY) {
  3019. tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  3020. }
  3021. if (t1 & MAY_BE_ARRAY_OF_REF) {
  3022. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  3023. } else if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
  3024. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  3025. }
  3026. }
  3027. }
  3028. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op2_def);
  3029. if (ssa_ops[i].result_def >= 0) {
  3030. tmp = (ssa_ops[i].result_use >= 0) ? RES_USE_INFO() : 0;
  3031. if (t1 & MAY_BE_OBJECT) {
  3032. tmp |= MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  3033. }
  3034. if (t1 & MAY_BE_ARRAY) {
  3035. if (t1 & MAY_BE_ARRAY_KEY_LONG) {
  3036. tmp |= MAY_BE_LONG;
  3037. }
  3038. if (t1 & MAY_BE_ARRAY_KEY_STRING) {
  3039. tmp |= MAY_BE_STRING | MAY_BE_RCN;
  3040. }
  3041. }
  3042. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  3043. }
  3044. break;
  3045. case ZEND_FETCH_DIM_R:
  3046. case ZEND_FETCH_DIM_IS:
  3047. case ZEND_FETCH_DIM_RW:
  3048. case ZEND_FETCH_DIM_W:
  3049. case ZEND_FETCH_DIM_UNSET:
  3050. case ZEND_FETCH_DIM_FUNC_ARG:
  3051. case ZEND_FETCH_LIST_R:
  3052. case ZEND_FETCH_LIST_W:
  3053. if (ssa_ops[i].op1_def >= 0) {
  3054. tmp = t1 & ~(MAY_BE_RC1|MAY_BE_RCN);
  3055. if (opline->opcode == ZEND_FETCH_DIM_W ||
  3056. opline->opcode == ZEND_FETCH_DIM_RW ||
  3057. opline->opcode == ZEND_FETCH_DIM_FUNC_ARG ||
  3058. opline->opcode == ZEND_FETCH_LIST_W) {
  3059. if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
  3060. if (opline->opcode != ZEND_FETCH_DIM_FUNC_ARG) {
  3061. tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
  3062. }
  3063. tmp |= MAY_BE_ARRAY | MAY_BE_RC1;
  3064. }
  3065. if (t1 & (MAY_BE_STRING|MAY_BE_ARRAY)) {
  3066. tmp |= MAY_BE_RC1;
  3067. if (opline->opcode == ZEND_FETCH_DIM_FUNC_ARG) {
  3068. tmp |= t1 & MAY_BE_RCN;
  3069. }
  3070. }
  3071. if (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
  3072. tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN);
  3073. }
  3074. if (opline->op2_type == IS_UNUSED) {
  3075. tmp |= MAY_BE_ARRAY_KEY_LONG;
  3076. } else {
  3077. if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
  3078. tmp |= MAY_BE_ARRAY_KEY_LONG;
  3079. }
  3080. if (t2 & MAY_BE_STRING) {
  3081. tmp |= MAY_BE_ARRAY_KEY_STRING;
  3082. if (opline->op2_type != IS_CONST) {
  3083. // FIXME: numeric string
  3084. tmp |= MAY_BE_ARRAY_KEY_LONG;
  3085. }
  3086. }
  3087. if (t2 & (MAY_BE_UNDEF | MAY_BE_NULL)) {
  3088. tmp |= MAY_BE_ARRAY_KEY_STRING;
  3089. }
  3090. }
  3091. } else if (opline->opcode == ZEND_FETCH_DIM_UNSET) {
  3092. if (t1 & MAY_BE_ARRAY) {
  3093. tmp |= MAY_BE_RC1;
  3094. }
  3095. if (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
  3096. tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN);
  3097. }
  3098. }
  3099. j = ssa_vars[ssa_ops[i].result_def].use_chain;
  3100. while (j >= 0) {
  3101. switch (op_array->opcodes[j].opcode) {
  3102. case ZEND_FETCH_DIM_W:
  3103. case ZEND_FETCH_DIM_RW:
  3104. case ZEND_FETCH_DIM_FUNC_ARG:
  3105. case ZEND_FETCH_LIST_W:
  3106. case ZEND_ASSIGN_DIM:
  3107. tmp |= MAY_BE_ARRAY | MAY_BE_ARRAY_OF_ARRAY;
  3108. break;
  3109. case ZEND_ASSIGN_ADD:
  3110. case ZEND_ASSIGN_SUB:
  3111. case ZEND_ASSIGN_MUL:
  3112. case ZEND_ASSIGN_DIV:
  3113. case ZEND_ASSIGN_MOD:
  3114. case ZEND_ASSIGN_SL:
  3115. case ZEND_ASSIGN_SR:
  3116. case ZEND_ASSIGN_CONCAT:
  3117. case ZEND_ASSIGN_BW_OR:
  3118. case ZEND_ASSIGN_BW_AND:
  3119. case ZEND_ASSIGN_BW_XOR:
  3120. case ZEND_ASSIGN_POW:
  3121. if (op_array->opcodes[j].extended_value == ZEND_ASSIGN_DIM) {
  3122. tmp |= MAY_BE_ARRAY | MAY_BE_ARRAY_OF_ARRAY;
  3123. } else if (op_array->opcodes[j].extended_value == ZEND_ASSIGN_OBJ) {
  3124. tmp |= MAY_BE_ARRAY_OF_OBJECT;
  3125. }
  3126. break;
  3127. case ZEND_FETCH_OBJ_W:
  3128. case ZEND_FETCH_OBJ_RW:
  3129. case ZEND_FETCH_OBJ_FUNC_ARG:
  3130. case ZEND_ASSIGN_OBJ:
  3131. case ZEND_PRE_INC_OBJ:
  3132. case ZEND_PRE_DEC_OBJ:
  3133. case ZEND_POST_INC_OBJ:
  3134. case ZEND_POST_DEC_OBJ:
  3135. tmp |= MAY_BE_ARRAY_OF_OBJECT;
  3136. break;
  3137. case ZEND_SEND_VAR_EX:
  3138. case ZEND_SEND_FUNC_ARG:
  3139. case ZEND_SEND_VAR_NO_REF:
  3140. case ZEND_SEND_VAR_NO_REF_EX:
  3141. case ZEND_SEND_REF:
  3142. case ZEND_ASSIGN_REF:
  3143. case ZEND_YIELD:
  3144. case ZEND_INIT_ARRAY:
  3145. case ZEND_ADD_ARRAY_ELEMENT:
  3146. case ZEND_RETURN_BY_REF:
  3147. case ZEND_VERIFY_RETURN_TYPE:
  3148. case ZEND_MAKE_REF:
  3149. case ZEND_FE_RESET_RW:
  3150. tmp |= MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  3151. break;
  3152. case ZEND_PRE_INC:
  3153. case ZEND_PRE_DEC:
  3154. case ZEND_POST_INC:
  3155. case ZEND_POST_DEC:
  3156. if (tmp & MAY_BE_ARRAY_OF_LONG) {
  3157. /* may overflow */
  3158. tmp |= MAY_BE_ARRAY_OF_DOUBLE;
  3159. } else if (!(tmp & (MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_DOUBLE))) {
  3160. tmp |= MAY_BE_ARRAY_OF_LONG | MAY_BE_ARRAY_OF_DOUBLE;
  3161. }
  3162. break;
  3163. case ZEND_UNSET_DIM:
  3164. case ZEND_UNSET_OBJ:
  3165. case ZEND_FETCH_DIM_UNSET:
  3166. case ZEND_FETCH_OBJ_UNSET:
  3167. break;
  3168. default :
  3169. break;
  3170. }
  3171. j = zend_ssa_next_use(ssa_ops, ssa_ops[i].result_def, j);
  3172. }
  3173. if ((tmp & MAY_BE_ARRAY) && (tmp & MAY_BE_ARRAY_KEY_ANY)) {
  3174. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  3175. } else {
  3176. /* invalid key type */
  3177. tmp = (tmp & (MAY_BE_RC1|MAY_BE_RCN)) | (t1 & ~(MAY_BE_RC1|MAY_BE_RCN));
  3178. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  3179. }
  3180. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  3181. }
  3182. /* FETCH_LIST on a string behaves like FETCH_R on null */
  3183. tmp = zend_array_element_type(
  3184. opline->opcode != ZEND_FETCH_LIST_R ? t1 : ((t1 & ~MAY_BE_STRING) | MAY_BE_NULL),
  3185. opline->result_type == IS_VAR,
  3186. opline->op2_type == IS_UNUSED);
  3187. if (opline->opcode == ZEND_FETCH_DIM_W ||
  3188. opline->opcode == ZEND_FETCH_DIM_RW ||
  3189. opline->opcode == ZEND_FETCH_DIM_FUNC_ARG ||
  3190. opline->opcode == ZEND_FETCH_LIST_W) {
  3191. if (t1 & (MAY_BE_ERROR|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE|MAY_BE_OBJECT)) {
  3192. tmp |= MAY_BE_ERROR;
  3193. } else if (opline->op2_type == IS_UNUSED) {
  3194. tmp |= MAY_BE_ERROR;
  3195. } else if (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT)) {
  3196. tmp |= MAY_BE_ERROR;
  3197. }
  3198. } else if (opline->opcode == ZEND_FETCH_DIM_IS && (t1 & MAY_BE_STRING)) {
  3199. tmp |= MAY_BE_NULL;
  3200. }
  3201. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  3202. break;
  3203. case ZEND_FETCH_THIS:
  3204. UPDATE_SSA_OBJ_TYPE(op_array->scope, 1, ssa_ops[i].result_def);
  3205. UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT, ssa_ops[i].result_def);
  3206. break;
  3207. case ZEND_FETCH_OBJ_R:
  3208. case ZEND_FETCH_OBJ_IS:
  3209. case ZEND_FETCH_OBJ_RW:
  3210. case ZEND_FETCH_OBJ_W:
  3211. case ZEND_FETCH_OBJ_UNSET:
  3212. case ZEND_FETCH_OBJ_FUNC_ARG:
  3213. if (ssa_ops[i].op1_def >= 0) {
  3214. tmp = t1;
  3215. if (opline->opcode == ZEND_FETCH_OBJ_W ||
  3216. opline->opcode == ZEND_FETCH_OBJ_RW ||
  3217. opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG) {
  3218. if (opline->opcode != ZEND_FETCH_DIM_FUNC_ARG) {
  3219. if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
  3220. tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
  3221. tmp |= MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
  3222. }
  3223. }
  3224. }
  3225. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  3226. COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
  3227. }
  3228. if (ssa_ops[i].result_def >= 0) {
  3229. tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  3230. if (opline->result_type == IS_TMP_VAR) {
  3231. /* can't be REF because of ZVAL_COPY_DEREF() usage */
  3232. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  3233. } else {
  3234. tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ERROR;
  3235. }
  3236. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  3237. }
  3238. break;
  3239. case ZEND_DO_FCALL:
  3240. case ZEND_DO_ICALL:
  3241. case ZEND_DO_UCALL:
  3242. case ZEND_DO_FCALL_BY_NAME:
  3243. if (ssa_ops[i].result_def >= 0) {
  3244. zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
  3245. zend_call_info *call_info;
  3246. if (!func_info || !func_info->call_map) {
  3247. goto unknown_opcode;
  3248. }
  3249. call_info = func_info->call_map[opline - op_array->opcodes];
  3250. if (!call_info) {
  3251. goto unknown_opcode;
  3252. }
  3253. tmp = zend_get_func_info(call_info, ssa) & ~FUNC_MAY_WARN;
  3254. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  3255. if (call_info->callee_func->type == ZEND_USER_FUNCTION) {
  3256. func_info = ZEND_FUNC_INFO(&call_info->callee_func->op_array);
  3257. if (func_info) {
  3258. UPDATE_SSA_OBJ_TYPE(
  3259. func_info->return_info.ce,
  3260. func_info->return_info.is_instanceof,
  3261. ssa_ops[i].result_def);
  3262. }
  3263. }
  3264. }
  3265. break;
  3266. case ZEND_FETCH_CONSTANT:
  3267. case ZEND_FETCH_CLASS_CONSTANT:
  3268. UPDATE_SSA_TYPE(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_RESOURCE|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY, ssa_ops[i].result_def);
  3269. break;
  3270. case ZEND_STRLEN:
  3271. tmp = MAY_BE_LONG;
  3272. if (t1 & (MAY_BE_ANY - (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING))) {
  3273. tmp |= MAY_BE_NULL;
  3274. }
  3275. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  3276. break;
  3277. case ZEND_COUNT:
  3278. case ZEND_FUNC_NUM_ARGS:
  3279. UPDATE_SSA_TYPE(MAY_BE_LONG, ssa_ops[i].result_def);
  3280. break;
  3281. case ZEND_FUNC_GET_ARGS:
  3282. UPDATE_SSA_TYPE(MAY_BE_RC1| MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_ANY, ssa_ops[i].result_def);
  3283. break;
  3284. case ZEND_GET_CLASS:
  3285. case ZEND_GET_CALLED_CLASS:
  3286. UPDATE_SSA_TYPE(MAY_BE_FALSE|MAY_BE_STRING|MAY_BE_RCN, ssa_ops[i].result_def);
  3287. break;
  3288. case ZEND_GET_TYPE:
  3289. UPDATE_SSA_TYPE(MAY_BE_STRING|MAY_BE_RC1|MAY_BE_RCN, ssa_ops[i].result_def);
  3290. break;
  3291. case ZEND_TYPE_CHECK:
  3292. case ZEND_DEFINED:
  3293. UPDATE_SSA_TYPE(MAY_BE_FALSE|MAY_BE_TRUE, ssa_ops[i].result_def);
  3294. break;
  3295. case ZEND_VERIFY_RETURN_TYPE:
  3296. if (t1 & MAY_BE_REF) {
  3297. tmp = t1;
  3298. ce = NULL;
  3299. } else {
  3300. zend_arg_info *ret_info = op_array->arg_info - 1;
  3301. tmp = zend_fetch_arg_info(script, ret_info, &ce);
  3302. if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
  3303. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  3304. }
  3305. }
  3306. if (opline->op1_type & (IS_TMP_VAR|IS_VAR|IS_CV)) {
  3307. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  3308. if (ce) {
  3309. UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_ops[i].op1_def);
  3310. } else {
  3311. UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].op1_def);
  3312. }
  3313. } else {
  3314. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  3315. if (ce) {
  3316. UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_ops[i].result_def);
  3317. } else {
  3318. UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def);
  3319. }
  3320. }
  3321. break;
  3322. case ZEND_MAKE_REF:
  3323. tmp = MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
  3324. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  3325. if (ssa_ops[i].op1_def >= 0) {
  3326. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  3327. }
  3328. break;
  3329. case ZEND_CATCH:
  3330. case ZEND_INCLUDE_OR_EVAL:
  3331. /* Forbidden opcodes */
  3332. ZEND_ASSERT(0);
  3333. break;
  3334. default:
  3335. unknown_opcode:
  3336. if (ssa_ops[i].op1_def >= 0) {
  3337. tmp = MAY_BE_ANY | MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  3338. UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
  3339. }
  3340. if (ssa_ops[i].result_def >= 0) {
  3341. tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  3342. if (opline->result_type == IS_TMP_VAR) {
  3343. tmp |= MAY_BE_RC1 | MAY_BE_RCN;
  3344. } else {
  3345. tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN;
  3346. }
  3347. UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
  3348. }
  3349. break;
  3350. }
  3351. return SUCCESS;
  3352. }
  3353. static uint32_t get_class_entry_rank(zend_class_entry *ce) {
  3354. uint32_t rank = 0;
  3355. while (ce->parent) {
  3356. rank++;
  3357. ce = ce->parent;
  3358. }
  3359. return rank;
  3360. }
  3361. /* Compute least common ancestor on class inheritance tree only */
  3362. static zend_class_entry *join_class_entries(
  3363. zend_class_entry *ce1, zend_class_entry *ce2, int *is_instanceof) {
  3364. uint32_t rank1, rank2;
  3365. if (ce1 == ce2) {
  3366. return ce1;
  3367. }
  3368. if (!ce1 || !ce2) {
  3369. return NULL;
  3370. }
  3371. rank1 = get_class_entry_rank(ce1);
  3372. rank2 = get_class_entry_rank(ce2);
  3373. while (rank1 != rank2) {
  3374. if (rank1 > rank2) {
  3375. ce1 = ce1->parent;
  3376. rank1--;
  3377. } else {
  3378. ce2 = ce2->parent;
  3379. rank2--;
  3380. }
  3381. }
  3382. while (ce1 != ce2) {
  3383. ce1 = ce1->parent;
  3384. ce2 = ce2->parent;
  3385. }
  3386. if (ce1) {
  3387. *is_instanceof = 1;
  3388. }
  3389. return ce1;
  3390. }
  3391. int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_bitset worklist, zend_long optimization_level)
  3392. {
  3393. zend_basic_block *blocks = ssa->cfg.blocks;
  3394. zend_ssa_var *ssa_vars = ssa->vars;
  3395. zend_ssa_var_info *ssa_var_info = ssa->var_info;
  3396. int ssa_vars_count = ssa->vars_count;
  3397. int i, j;
  3398. uint32_t tmp, worklist_len = zend_bitset_len(ssa_vars_count);
  3399. while (!zend_bitset_empty(worklist, worklist_len)) {
  3400. j = zend_bitset_first(worklist, worklist_len);
  3401. zend_bitset_excl(worklist, j);
  3402. if (ssa_vars[j].definition_phi) {
  3403. zend_ssa_phi *p = ssa_vars[j].definition_phi;
  3404. if (p->pi >= 0) {
  3405. zend_class_entry *ce = ssa_var_info[p->sources[0]].ce;
  3406. int is_instanceof = ssa_var_info[p->sources[0]].is_instanceof;
  3407. tmp = get_ssa_var_info(ssa, p->sources[0]);
  3408. if (!p->has_range_constraint) {
  3409. zend_ssa_type_constraint *constraint = &p->constraint.type;
  3410. tmp &= constraint->type_mask;
  3411. if ((tmp & MAY_BE_OBJECT) && constraint->ce && ce != constraint->ce) {
  3412. if (!ce) {
  3413. ce = constraint->ce;
  3414. is_instanceof = 1;
  3415. } else if (is_instanceof && instanceof_function(constraint->ce, ce)) {
  3416. ce = constraint->ce;
  3417. } else {
  3418. /* Ignore the constraint (either ce instanceof constraint->ce or
  3419. * they are unrelated, as far as we can statically determine) */
  3420. }
  3421. }
  3422. }
  3423. UPDATE_SSA_TYPE(tmp, j);
  3424. UPDATE_SSA_OBJ_TYPE(ce, is_instanceof, j);
  3425. } else {
  3426. int first = 1;
  3427. int is_instanceof = 0;
  3428. zend_class_entry *ce = NULL;
  3429. tmp = 0;
  3430. for (i = 0; i < blocks[p->block].predecessors_count; i++) {
  3431. tmp |= get_ssa_var_info(ssa, p->sources[i]);
  3432. }
  3433. UPDATE_SSA_TYPE(tmp, j);
  3434. for (i = 0; i < blocks[p->block].predecessors_count; i++) {
  3435. zend_ssa_var_info *info;
  3436. ZEND_ASSERT(p->sources[i] >= 0);
  3437. info = &ssa_var_info[p->sources[i]];
  3438. if (info->type & MAY_BE_OBJECT) {
  3439. if (first) {
  3440. ce = info->ce;
  3441. is_instanceof = info->is_instanceof;
  3442. first = 0;
  3443. } else {
  3444. is_instanceof |= info->is_instanceof;
  3445. ce = join_class_entries(ce, info->ce, &is_instanceof);
  3446. }
  3447. }
  3448. }
  3449. UPDATE_SSA_OBJ_TYPE(ce, ce ? is_instanceof : 0, j);
  3450. }
  3451. } else if (ssa_vars[j].definition >= 0) {
  3452. i = ssa_vars[j].definition;
  3453. if (zend_update_type_info(op_array, ssa, script, worklist, i, optimization_level) == FAILURE) {
  3454. return FAILURE;
  3455. }
  3456. }
  3457. }
  3458. return SUCCESS;
  3459. }
  3460. static zend_bool is_narrowable_instr(zend_op *opline) {
  3461. return opline->opcode == ZEND_ADD || opline->opcode == ZEND_SUB
  3462. || opline->opcode == ZEND_MUL || opline->opcode == ZEND_DIV;
  3463. }
  3464. static zend_bool is_effective_op1_double_cast(zend_op *opline, zval *op2) {
  3465. return (opline->opcode == ZEND_ADD && Z_LVAL_P(op2) == 0)
  3466. || (opline->opcode == ZEND_SUB && Z_LVAL_P(op2) == 0)
  3467. || (opline->opcode == ZEND_MUL && Z_LVAL_P(op2) == 1)
  3468. || (opline->opcode == ZEND_DIV && Z_LVAL_P(op2) == 1);
  3469. }
  3470. static zend_bool is_effective_op2_double_cast(zend_op *opline, zval *op1) {
  3471. /* In PHP it holds that (double)(0-$int) is bitwise identical to 0.0-(double)$int,
  3472. * so allowing SUB here is fine. */
  3473. return (opline->opcode == ZEND_ADD && Z_LVAL_P(op1) == 0)
  3474. || (opline->opcode == ZEND_SUB && Z_LVAL_P(op1) == 0)
  3475. || (opline->opcode == ZEND_MUL && Z_LVAL_P(op1) == 1);
  3476. }
  3477. /* This function recursively checks whether it's possible to convert an integer variable
  3478. * initialization to a double initialization. The basic idea is that if the value is used
  3479. * only in add/sub/mul/div ("narrowable" instructions) with a double result value, then it
  3480. * will be cast to double at that point anyway, so we may as well do it earlier already.
  3481. *
  3482. * The tricky case are chains of operations, where it's not necessarily a given that converting
  3483. * an integer to double before the chain of operations is the same as converting it after the
  3484. * chain. What this function does is detect two cases where it is safe:
  3485. * * If the operations only involve constants, then we can simply verify that performing the
  3486. * calculation on integers and doubles yields the same value.
  3487. * * Even if one operand is not known, we may be able to determine that the operations with the
  3488. * integer replaced by a double only acts as an effective double cast on the unknown operand.
  3489. * E.g. 0+$i and 0.0+$i only differ by that cast. If then the consuming instruction of this
  3490. * result will perform a double cast anyway, the conversion is safe.
  3491. *
  3492. * The checks happens recursively, while keeping track of which variables are already visisted to
  3493. * avoid infinite loops. An iterative, worklist driven approach would be possible, but the state
  3494. * management more cumbersome to implement, so we don't bother for now.
  3495. */
  3496. static zend_bool can_convert_to_double(
  3497. const zend_op_array *op_array, zend_ssa *ssa, int var_num,
  3498. zval *value, zend_bitset visited) {
  3499. zend_ssa_var *var = &ssa->vars[var_num];
  3500. zend_ssa_phi *phi;
  3501. int use;
  3502. uint32_t type;
  3503. if (zend_bitset_in(visited, var_num)) {
  3504. return 1;
  3505. }
  3506. zend_bitset_incl(visited, var_num);
  3507. for (use = var->use_chain; use >= 0; use = zend_ssa_next_use(ssa->ops, var_num, use)) {
  3508. zend_op *opline = &op_array->opcodes[use];
  3509. zend_ssa_op *ssa_op = &ssa->ops[use];
  3510. if (zend_ssa_is_no_val_use(opline, ssa_op, var_num)) {
  3511. continue;
  3512. }
  3513. if (!is_narrowable_instr(opline)) {
  3514. return 0;
  3515. }
  3516. /* Instruction always returns double, the conversion is certainly fine */
  3517. type = ssa->var_info[ssa_op->result_def].type;
  3518. if ((type & MAY_BE_ANY) == MAY_BE_DOUBLE) {
  3519. continue;
  3520. }
  3521. /* UNDEF signals that the previous result is an effective double cast, this is only allowed
  3522. * if this instruction would have done the cast anyway (previous check). */
  3523. if (Z_ISUNDEF_P(value)) {
  3524. return 0;
  3525. }
  3526. /* Check that narrowing can actually be useful */
  3527. if ((type & MAY_BE_ANY) & ~(MAY_BE_LONG|MAY_BE_DOUBLE)) {
  3528. return 0;
  3529. }
  3530. {
  3531. /* For calculation on original values */
  3532. zval orig_op1, orig_op2, orig_result;
  3533. /* For calculation with var_num cast to double */
  3534. zval dval_op1, dval_op2, dval_result;
  3535. ZVAL_UNDEF(&orig_op1);
  3536. ZVAL_UNDEF(&dval_op1);
  3537. if (ssa_op->op1_use == var_num) {
  3538. ZVAL_COPY_VALUE(&orig_op1, value);
  3539. ZVAL_DOUBLE(&dval_op1, (double) Z_LVAL_P(value));
  3540. } else if (opline->op1_type == IS_CONST) {
  3541. zval *zv = CRT_CONSTANT_EX(op_array, opline, opline->op1, ssa->rt_constants);
  3542. if (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_DOUBLE) {
  3543. ZVAL_COPY_VALUE(&orig_op1, zv);
  3544. ZVAL_COPY_VALUE(&dval_op1, zv);
  3545. }
  3546. }
  3547. ZVAL_UNDEF(&orig_op2);
  3548. ZVAL_UNDEF(&dval_op2);
  3549. if (ssa_op->op2_use == var_num) {
  3550. ZVAL_COPY_VALUE(&orig_op2, value);
  3551. ZVAL_DOUBLE(&dval_op2, (double) Z_LVAL_P(value));
  3552. } else if (opline->op2_type == IS_CONST) {
  3553. zval *zv = CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants);
  3554. if (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_DOUBLE) {
  3555. ZVAL_COPY_VALUE(&orig_op2, zv);
  3556. ZVAL_COPY_VALUE(&dval_op2, zv);
  3557. }
  3558. }
  3559. ZEND_ASSERT(!Z_ISUNDEF(orig_op1) || !Z_ISUNDEF(orig_op2));
  3560. if (Z_ISUNDEF(orig_op1)) {
  3561. if (opline->opcode == ZEND_MUL && Z_LVAL(orig_op2) == 0) {
  3562. ZVAL_LONG(&orig_result, 0);
  3563. } else if (is_effective_op1_double_cast(opline, &orig_op2)) {
  3564. ZVAL_UNDEF(&orig_result);
  3565. } else {
  3566. return 0;
  3567. }
  3568. } else if (Z_ISUNDEF(orig_op2)) {
  3569. if (opline->opcode == ZEND_MUL && Z_LVAL(orig_op1) == 0) {
  3570. ZVAL_LONG(&orig_result, 0);
  3571. } else if (is_effective_op2_double_cast(opline, &orig_op1)) {
  3572. ZVAL_UNDEF(&orig_result);
  3573. } else {
  3574. return 0;
  3575. }
  3576. } else {
  3577. /* Avoid division by zero */
  3578. if (opline->opcode == ZEND_DIV && zval_get_double(&orig_op2) == 0.0) {
  3579. return 0;
  3580. }
  3581. get_binary_op(opline->opcode)(&orig_result, &orig_op1, &orig_op2);
  3582. get_binary_op(opline->opcode)(&dval_result, &dval_op1, &dval_op2);
  3583. ZEND_ASSERT(Z_TYPE(dval_result) == IS_DOUBLE);
  3584. if (zval_get_double(&orig_result) != Z_DVAL(dval_result)) {
  3585. return 0;
  3586. }
  3587. }
  3588. if (!can_convert_to_double(op_array, ssa, ssa_op->result_def, &orig_result, visited)) {
  3589. return 0;
  3590. }
  3591. }
  3592. }
  3593. for (phi = var->phi_use_chain; phi; phi = zend_ssa_next_use_phi(ssa, var_num, phi)) {
  3594. /* Check that narrowing can actually be useful */
  3595. type = ssa->var_info[phi->ssa_var].type;
  3596. if ((type & MAY_BE_ANY) & ~(MAY_BE_LONG|MAY_BE_DOUBLE)) {
  3597. return 0;
  3598. }
  3599. if (!can_convert_to_double(op_array, ssa, phi->ssa_var, value, visited)) {
  3600. return 0;
  3601. }
  3602. }
  3603. return 1;
  3604. }
  3605. static int zend_type_narrowing(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level)
  3606. {
  3607. uint32_t bitset_len = zend_bitset_len(ssa->vars_count);
  3608. zend_bitset visited, worklist;
  3609. int i, v;
  3610. zend_op *opline;
  3611. zend_bool narrowed = 0;
  3612. ALLOCA_FLAG(use_heap)
  3613. visited = ZEND_BITSET_ALLOCA(2 * bitset_len, use_heap);
  3614. worklist = visited + bitset_len;
  3615. zend_bitset_clear(worklist, bitset_len);
  3616. for (v = op_array->last_var; v < ssa->vars_count; v++) {
  3617. if ((ssa->var_info[v].type & (MAY_BE_REF | MAY_BE_ANY | MAY_BE_UNDEF)) != MAY_BE_LONG) continue;
  3618. if (ssa->vars[v].definition < 0) continue;
  3619. if (ssa->vars[v].no_val) continue;
  3620. opline = op_array->opcodes + ssa->vars[v].definition;
  3621. /* Go through assignments of literal integers and check if they can be converted to
  3622. * doubles instead, in the hope that we'll narrow long|double to double. */
  3623. if (opline->opcode == ZEND_ASSIGN && opline->result_type == IS_UNUSED &&
  3624. opline->op1_type == IS_CV && opline->op2_type == IS_CONST) {
  3625. zval *value = CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants);
  3626. zend_bitset_clear(visited, bitset_len);
  3627. if (can_convert_to_double(op_array, ssa, v, value, visited)) {
  3628. narrowed = 1;
  3629. ssa->var_info[v].use_as_double = 1;
  3630. /* The "visited" vars are exactly those which may change their type due to
  3631. * narrowing. Reset their types and add them to the type inference worklist */
  3632. ZEND_BITSET_FOREACH(visited, bitset_len, i) {
  3633. ssa->var_info[i].type &= ~MAY_BE_ANY;
  3634. } ZEND_BITSET_FOREACH_END();
  3635. zend_bitset_union(worklist, visited, bitset_len);
  3636. }
  3637. }
  3638. }
  3639. if (!narrowed) {
  3640. free_alloca(visited, use_heap);
  3641. return SUCCESS;
  3642. }
  3643. if (zend_infer_types_ex(op_array, script, ssa, worklist, optimization_level) != SUCCESS) {
  3644. free_alloca(visited, use_heap);
  3645. return FAILURE;
  3646. }
  3647. free_alloca(visited, use_heap);
  3648. return SUCCESS;
  3649. }
  3650. static int is_recursive_tail_call(const zend_op_array *op_array,
  3651. zend_op *opline)
  3652. {
  3653. zend_func_info *info = ZEND_FUNC_INFO(op_array);
  3654. if (info->ssa.ops && info->ssa.vars && info->call_map &&
  3655. info->ssa.ops[opline - op_array->opcodes].op1_use >= 0 &&
  3656. info->ssa.vars[info->ssa.ops[opline - op_array->opcodes].op1_use].definition >= 0) {
  3657. zend_op *op = op_array->opcodes + info->ssa.vars[info->ssa.ops[opline - op_array->opcodes].op1_use].definition;
  3658. if (op->opcode == ZEND_DO_UCALL) {
  3659. zend_call_info *call_info = info->call_map[op - op_array->opcodes];
  3660. if (call_info && op_array == &call_info->callee_func->op_array) {
  3661. return 1;
  3662. }
  3663. }
  3664. }
  3665. return 0;
  3666. }
  3667. void zend_init_func_return_info(const zend_op_array *op_array,
  3668. const zend_script *script,
  3669. zend_ssa_var_info *ret)
  3670. {
  3671. if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  3672. zend_arg_info *ret_info = op_array->arg_info - 1;
  3673. zend_ssa_range tmp_range = {0, 0, 0, 0};
  3674. ret->type = zend_fetch_arg_info(script, ret_info, &ret->ce);
  3675. if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
  3676. ret->type |= MAY_BE_REF;
  3677. } else if (ret->type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
  3678. ret->type |= MAY_BE_RC1|MAY_BE_RCN;
  3679. }
  3680. ret->is_instanceof = (ret->ce) ? 1 : 0;
  3681. ret->range = tmp_range;
  3682. ret->has_range = 0;
  3683. }
  3684. }
  3685. void zend_func_return_info(const zend_op_array *op_array,
  3686. const zend_script *script,
  3687. int recursive,
  3688. int widening,
  3689. zend_ssa_var_info *ret)
  3690. {
  3691. zend_func_info *info = ZEND_FUNC_INFO(op_array);
  3692. zend_ssa *ssa = &info->ssa;
  3693. int blocks_count = info->ssa.cfg.blocks_count;
  3694. zend_basic_block *blocks = info->ssa.cfg.blocks;
  3695. int j;
  3696. uint32_t t1;
  3697. uint32_t tmp = 0;
  3698. zend_class_entry *tmp_ce = NULL;
  3699. int tmp_is_instanceof = -1;
  3700. zend_class_entry *arg_ce;
  3701. int arg_is_instanceof;
  3702. zend_ssa_range tmp_range = {0, 0, 0, 0};
  3703. int tmp_has_range = -1;
  3704. if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
  3705. ret->type = MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
  3706. ret->ce = zend_ce_generator;
  3707. ret->is_instanceof = 0;
  3708. ret->range = tmp_range;
  3709. ret->has_range = 0;
  3710. return;
  3711. }
  3712. for (j = 0; j < blocks_count; j++) {
  3713. if ((blocks[j].flags & ZEND_BB_REACHABLE) && blocks[j].len != 0) {
  3714. zend_op *opline = op_array->opcodes + blocks[j].start + blocks[j].len - 1;
  3715. if (opline->opcode == ZEND_RETURN || opline->opcode == ZEND_RETURN_BY_REF) {
  3716. if (!recursive &&
  3717. info->ssa.ops &&
  3718. info->ssa.var_info &&
  3719. info->ssa.ops[opline - op_array->opcodes].op1_use >= 0 &&
  3720. info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].recursive) {
  3721. continue;
  3722. }
  3723. if (is_recursive_tail_call(op_array, opline)) {
  3724. continue;
  3725. }
  3726. t1 = OP1_INFO();
  3727. if (t1 & MAY_BE_UNDEF) {
  3728. t1 |= MAY_BE_NULL;
  3729. }
  3730. if (opline->opcode == ZEND_RETURN) {
  3731. if (t1 & MAY_BE_RC1) {
  3732. t1 |= MAY_BE_RCN;
  3733. }
  3734. t1 &= ~(MAY_BE_UNDEF | MAY_BE_REF);
  3735. } else {
  3736. t1 |= MAY_BE_REF;
  3737. t1 &= ~(MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN);
  3738. }
  3739. tmp |= t1;
  3740. if (info->ssa.ops &&
  3741. info->ssa.var_info &&
  3742. info->ssa.ops[opline - op_array->opcodes].op1_use >= 0 &&
  3743. info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].ce) {
  3744. arg_ce = info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].ce;
  3745. arg_is_instanceof = info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].is_instanceof;
  3746. } else {
  3747. arg_ce = NULL;
  3748. arg_is_instanceof = 0;
  3749. }
  3750. if (tmp_is_instanceof < 0) {
  3751. tmp_ce = arg_ce;
  3752. tmp_is_instanceof = arg_is_instanceof;
  3753. } else if (arg_ce && arg_ce == tmp_ce) {
  3754. if (tmp_is_instanceof != arg_is_instanceof) {
  3755. tmp_is_instanceof = 1;
  3756. }
  3757. } else {
  3758. tmp_ce = NULL;
  3759. tmp_is_instanceof = 0;
  3760. }
  3761. if (opline->op1_type == IS_CONST) {
  3762. zval *zv = CRT_CONSTANT_EX(op_array, opline, opline->op1, info->ssa.rt_constants);
  3763. if (Z_TYPE_P(zv) == IS_NULL) {
  3764. if (tmp_has_range < 0) {
  3765. tmp_has_range = 1;
  3766. tmp_range.underflow = 0;
  3767. tmp_range.min = 0;
  3768. tmp_range.max = 0;
  3769. tmp_range.overflow = 0;
  3770. } else if (tmp_has_range) {
  3771. if (!tmp_range.underflow) {
  3772. tmp_range.min = MIN(tmp_range.min, 0);
  3773. }
  3774. if (!tmp_range.overflow) {
  3775. tmp_range.max = MAX(tmp_range.max, 0);
  3776. }
  3777. }
  3778. } else if (Z_TYPE_P(zv) == IS_FALSE) {
  3779. if (tmp_has_range < 0) {
  3780. tmp_has_range = 1;
  3781. tmp_range.underflow = 0;
  3782. tmp_range.min = 0;
  3783. tmp_range.max = 0;
  3784. tmp_range.overflow = 0;
  3785. } else if (tmp_has_range) {
  3786. if (!tmp_range.underflow) {
  3787. tmp_range.min = MIN(tmp_range.min, 0);
  3788. }
  3789. if (!tmp_range.overflow) {
  3790. tmp_range.max = MAX(tmp_range.max, 0);
  3791. }
  3792. }
  3793. } else if (Z_TYPE_P(zv) == IS_TRUE) {
  3794. if (tmp_has_range < 0) {
  3795. tmp_has_range = 1;
  3796. tmp_range.underflow = 0;
  3797. tmp_range.min = 1;
  3798. tmp_range.max = 1;
  3799. tmp_range.overflow = 0;
  3800. } else if (tmp_has_range) {
  3801. if (!tmp_range.underflow) {
  3802. tmp_range.min = MIN(tmp_range.min, 1);
  3803. }
  3804. if (!tmp_range.overflow) {
  3805. tmp_range.max = MAX(tmp_range.max, 1);
  3806. }
  3807. }
  3808. } else if (Z_TYPE_P(zv) == IS_LONG) {
  3809. if (tmp_has_range < 0) {
  3810. tmp_has_range = 1;
  3811. tmp_range.underflow = 0;
  3812. tmp_range.min = Z_LVAL_P(zv);
  3813. tmp_range.max = Z_LVAL_P(zv);
  3814. tmp_range.overflow = 0;
  3815. } else if (tmp_has_range) {
  3816. if (!tmp_range.underflow) {
  3817. tmp_range.min = MIN(tmp_range.min, Z_LVAL_P(zv));
  3818. }
  3819. if (!tmp_range.overflow) {
  3820. tmp_range.max = MAX(tmp_range.max, Z_LVAL_P(zv));
  3821. }
  3822. }
  3823. } else {
  3824. tmp_has_range = 0;
  3825. }
  3826. } else if (info->ssa.ops &&
  3827. info->ssa.var_info &&
  3828. info->ssa.ops[opline - op_array->opcodes].op1_use >= 0) {
  3829. if (info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].has_range) {
  3830. if (tmp_has_range < 0) {
  3831. tmp_has_range = 1;
  3832. tmp_range = info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].range;
  3833. } else if (tmp_has_range) {
  3834. /* union */
  3835. if (info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].range.underflow) {
  3836. tmp_range.underflow = 1;
  3837. tmp_range.min = ZEND_LONG_MIN;
  3838. } else {
  3839. tmp_range.min = MIN(tmp_range.min, info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].range.min);
  3840. }
  3841. if (info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].range.overflow) {
  3842. tmp_range.overflow = 1;
  3843. tmp_range.max = ZEND_LONG_MAX;
  3844. } else {
  3845. tmp_range.max = MAX(tmp_range.max, info->ssa.var_info[info->ssa.ops[opline - op_array->opcodes].op1_use].range.max);
  3846. }
  3847. }
  3848. } else if (!widening) {
  3849. tmp_has_range = 1;
  3850. tmp_range.underflow = 1;
  3851. tmp_range.min = ZEND_LONG_MIN;
  3852. tmp_range.max = ZEND_LONG_MAX;
  3853. tmp_range.overflow = 1;
  3854. }
  3855. } else {
  3856. tmp_has_range = 0;
  3857. }
  3858. }
  3859. }
  3860. }
  3861. if (!(op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
  3862. if (tmp_is_instanceof < 0) {
  3863. tmp_is_instanceof = 0;
  3864. tmp_ce = NULL;
  3865. }
  3866. if (tmp_has_range < 0) {
  3867. tmp_has_range = 0;
  3868. }
  3869. ret->type = tmp;
  3870. ret->ce = tmp_ce;
  3871. ret->is_instanceof = tmp_is_instanceof;
  3872. }
  3873. ret->range = tmp_range;
  3874. ret->has_range = tmp_has_range;
  3875. }
  3876. static int zend_infer_types(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level)
  3877. {
  3878. zend_ssa_var_info *ssa_var_info = ssa->var_info;
  3879. int ssa_vars_count = ssa->vars_count;
  3880. int j;
  3881. zend_bitset worklist;
  3882. ALLOCA_FLAG(use_heap);
  3883. worklist = do_alloca(sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count), use_heap);
  3884. memset(worklist, 0, sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
  3885. /* Type Inference */
  3886. for (j = op_array->last_var; j < ssa_vars_count; j++) {
  3887. zend_bitset_incl(worklist, j);
  3888. ssa_var_info[j].type = 0;
  3889. }
  3890. if (zend_infer_types_ex(op_array, script, ssa, worklist, optimization_level) != SUCCESS) {
  3891. free_alloca(worklist, use_heap);
  3892. return FAILURE;
  3893. }
  3894. /* Narrowing integer initialization to doubles */
  3895. zend_type_narrowing(op_array, script, ssa, optimization_level);
  3896. if (ZEND_FUNC_INFO(op_array)) {
  3897. zend_func_return_info(op_array, script, 1, 0, &ZEND_FUNC_INFO(op_array)->return_info);
  3898. }
  3899. free_alloca(worklist, use_heap);
  3900. return SUCCESS;
  3901. }
  3902. int zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level) /* {{{ */
  3903. {
  3904. zend_ssa_var_info *ssa_var_info;
  3905. int i;
  3906. if (!ssa->var_info) {
  3907. ssa->var_info = zend_arena_calloc(arena, ssa->vars_count, sizeof(zend_ssa_var_info));
  3908. }
  3909. ssa_var_info = ssa->var_info;
  3910. if (!op_array->function_name) {
  3911. for (i = 0; i < op_array->last_var; i++) {
  3912. ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
  3913. ssa_var_info[i].has_range = 0;
  3914. }
  3915. } else {
  3916. for (i = 0; i < op_array->last_var; i++) {
  3917. ssa_var_info[i].type = MAY_BE_UNDEF;
  3918. ssa_var_info[i].has_range = 0;
  3919. if (ssa->vars[i].alias) {
  3920. ssa_var_info[i].type |= get_ssa_alias_types(ssa->vars[i].alias);
  3921. }
  3922. }
  3923. }
  3924. for (i = op_array->last_var; i < ssa->vars_count; i++) {
  3925. ssa_var_info[i].type = 0;
  3926. ssa_var_info[i].has_range = 0;
  3927. }
  3928. if (zend_infer_ranges(op_array, ssa) != SUCCESS) {
  3929. return FAILURE;
  3930. }
  3931. if (zend_infer_types(op_array, script, ssa, optimization_level) != SUCCESS) {
  3932. return FAILURE;
  3933. }
  3934. return SUCCESS;
  3935. }
  3936. /* }}} */
  3937. void zend_inference_check_recursive_dependencies(zend_op_array *op_array)
  3938. {
  3939. zend_func_info *info = ZEND_FUNC_INFO(op_array);
  3940. zend_call_info *call_info;
  3941. zend_bitset worklist;
  3942. int worklist_len, i;
  3943. ALLOCA_FLAG(use_heap);
  3944. if (!info->ssa.var_info || !(info->flags & ZEND_FUNC_RECURSIVE)) {
  3945. return;
  3946. }
  3947. worklist_len = zend_bitset_len(info->ssa.vars_count);
  3948. worklist = do_alloca(sizeof(zend_ulong) * worklist_len, use_heap);
  3949. memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
  3950. call_info = info->callee_info;
  3951. while (call_info) {
  3952. if (call_info->recursive && call_info->caller_call_opline &&
  3953. info->ssa.ops[call_info->caller_call_opline - op_array->opcodes].result_def >= 0) {
  3954. zend_bitset_incl(worklist, info->ssa.ops[call_info->caller_call_opline - op_array->opcodes].result_def);
  3955. }
  3956. call_info = call_info->next_callee;
  3957. }
  3958. WHILE_WORKLIST(worklist, worklist_len, i) {
  3959. if (!info->ssa.var_info[i].recursive) {
  3960. info->ssa.var_info[i].recursive = 1;
  3961. add_usages(op_array, &info->ssa, worklist, i);
  3962. }
  3963. } WHILE_WORKLIST_END();
  3964. free_alloca(worklist, use_heap);
  3965. }
  3966. int zend_may_throw(const zend_op *opline, zend_op_array *op_array, zend_ssa *ssa)
  3967. {
  3968. uint32_t t1 = OP1_INFO();
  3969. uint32_t t2 = OP2_INFO();
  3970. if (opline->op1_type == IS_CV) {
  3971. if (t1 & MAY_BE_UNDEF) {
  3972. switch (opline->opcode) {
  3973. case ZEND_UNSET_VAR:
  3974. case ZEND_ISSET_ISEMPTY_VAR:
  3975. return 1;
  3976. case ZEND_ISSET_ISEMPTY_DIM_OBJ:
  3977. case ZEND_ISSET_ISEMPTY_PROP_OBJ:
  3978. case ZEND_ASSIGN:
  3979. case ZEND_ASSIGN_DIM:
  3980. case ZEND_ASSIGN_REF:
  3981. case ZEND_BIND_GLOBAL:
  3982. case ZEND_FETCH_DIM_IS:
  3983. case ZEND_FETCH_OBJ_IS:
  3984. case ZEND_SEND_REF:
  3985. case ZEND_UNSET_CV:
  3986. case ZEND_ISSET_ISEMPTY_CV:
  3987. break;
  3988. default:
  3989. /* undefined variable warning */
  3990. return 1;
  3991. }
  3992. }
  3993. } else if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
  3994. if (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY)) {
  3995. switch (opline->opcode) {
  3996. case ZEND_CASE:
  3997. case ZEND_FE_FETCH_R:
  3998. case ZEND_FE_FETCH_RW:
  3999. case ZEND_FETCH_LIST_R:
  4000. case ZEND_QM_ASSIGN:
  4001. case ZEND_SEND_VAL:
  4002. case ZEND_SEND_VAL_EX:
  4003. case ZEND_SEND_VAR:
  4004. case ZEND_SEND_VAR_EX:
  4005. case ZEND_SEND_FUNC_ARG:
  4006. case ZEND_SEND_VAR_NO_REF:
  4007. case ZEND_SEND_VAR_NO_REF_EX:
  4008. case ZEND_SEND_REF:
  4009. case ZEND_SEPARATE:
  4010. case ZEND_END_SILENCE:
  4011. break;
  4012. default:
  4013. /* destructor may be called */
  4014. return 1;
  4015. }
  4016. }
  4017. }
  4018. if (opline->op2_type == IS_CV) {
  4019. if (t2 & MAY_BE_UNDEF) {
  4020. switch (opline->opcode) {
  4021. case ZEND_ASSIGN_REF:
  4022. break;
  4023. default:
  4024. /* undefined variable warning */
  4025. return 1;
  4026. }
  4027. }
  4028. } else if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
  4029. if (t2 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY)) {
  4030. switch (opline->opcode) {
  4031. case ZEND_ASSIGN:
  4032. break;
  4033. default:
  4034. /* destructor may be called */
  4035. return 1;
  4036. }
  4037. }
  4038. }
  4039. switch (opline->opcode) {
  4040. case ZEND_NOP:
  4041. case ZEND_IS_IDENTICAL:
  4042. case ZEND_IS_NOT_IDENTICAL:
  4043. case ZEND_QM_ASSIGN:
  4044. case ZEND_JMP:
  4045. case ZEND_CHECK_VAR:
  4046. case ZEND_MAKE_REF:
  4047. case ZEND_SEND_VAR:
  4048. case ZEND_BEGIN_SILENCE:
  4049. case ZEND_END_SILENCE:
  4050. case ZEND_SEND_VAL:
  4051. case ZEND_SEND_REF:
  4052. case ZEND_SEND_VAR_EX:
  4053. case ZEND_SEND_FUNC_ARG:
  4054. case ZEND_FREE:
  4055. case ZEND_SEPARATE:
  4056. case ZEND_TYPE_CHECK:
  4057. case ZEND_DEFINED:
  4058. case ZEND_ISSET_ISEMPTY_THIS:
  4059. case ZEND_COALESCE:
  4060. case ZEND_SWITCH_LONG:
  4061. case ZEND_SWITCH_STRING:
  4062. case ZEND_ISSET_ISEMPTY_VAR:
  4063. case ZEND_ISSET_ISEMPTY_CV:
  4064. case ZEND_FUNC_NUM_ARGS:
  4065. case ZEND_FUNC_GET_ARGS:
  4066. return 0;
  4067. case ZEND_INIT_FCALL:
  4068. /* can't throw, because call is resolved at compile time */
  4069. return 0;
  4070. case ZEND_BIND_GLOBAL:
  4071. if ((opline+1)->opcode == ZEND_BIND_GLOBAL) {
  4072. return zend_may_throw(opline + 1, op_array, ssa);
  4073. }
  4074. return 0;
  4075. case ZEND_ADD:
  4076. if ((t1 & MAY_BE_ANY) == MAY_BE_ARRAY
  4077. && (t2 & MAY_BE_ANY) == MAY_BE_ARRAY) {
  4078. return 0;
  4079. }
  4080. return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4081. (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT));
  4082. case ZEND_DIV:
  4083. case ZEND_MOD:
  4084. if (!OP2_HAS_RANGE() ||
  4085. (OP2_MIN_RANGE() <= 0 && OP2_MAX_RANGE() >= 0)) {
  4086. /* Division by zero */
  4087. return 1;
  4088. }
  4089. /* break missing intentionally */
  4090. case ZEND_SUB:
  4091. case ZEND_MUL:
  4092. case ZEND_POW:
  4093. return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4094. (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT));
  4095. case ZEND_SL:
  4096. case ZEND_SR:
  4097. return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4098. (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4099. !OP2_HAS_RANGE() ||
  4100. OP2_MIN_RANGE() < 0;
  4101. case ZEND_CONCAT:
  4102. case ZEND_FAST_CONCAT:
  4103. return (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4104. (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT));
  4105. case ZEND_BW_OR:
  4106. case ZEND_BW_AND:
  4107. case ZEND_BW_XOR:
  4108. if ((t1 & MAY_BE_ANY) == MAY_BE_STRING
  4109. && (t2 & MAY_BE_ANY) == MAY_BE_STRING) {
  4110. return 0;
  4111. }
  4112. return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4113. (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT));
  4114. case ZEND_BW_NOT:
  4115. return (t1 & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
  4116. case ZEND_BOOL_NOT:
  4117. case ZEND_PRE_INC:
  4118. case ZEND_POST_INC:
  4119. case ZEND_PRE_DEC:
  4120. case ZEND_POST_DEC:
  4121. case ZEND_JMPZ:
  4122. case ZEND_JMPNZ:
  4123. case ZEND_JMPZNZ:
  4124. case ZEND_JMPZ_EX:
  4125. case ZEND_JMPNZ_EX:
  4126. case ZEND_BOOL:
  4127. case ZEND_JMP_SET:
  4128. return (t1 & MAY_BE_OBJECT);
  4129. case ZEND_BOOL_XOR:
  4130. return (t1 & MAY_BE_OBJECT) || (t2 & MAY_BE_OBJECT);
  4131. case ZEND_IS_EQUAL:
  4132. case ZEND_IS_NOT_EQUAL:
  4133. case ZEND_IS_SMALLER:
  4134. case ZEND_IS_SMALLER_OR_EQUAL:
  4135. case ZEND_CASE:
  4136. case ZEND_SPACESHIP:
  4137. if ((t1 & MAY_BE_ANY) == MAY_BE_NULL
  4138. || (t2 & MAY_BE_ANY) == MAY_BE_NULL) {
  4139. return 0;
  4140. }
  4141. return (t1 & (MAY_BE_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_OBJECT)) || (t2 & (MAY_BE_OBJECT|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_OBJECT));
  4142. case ZEND_ASSIGN_ADD:
  4143. if (opline->extended_value != 0) {
  4144. return 1;
  4145. }
  4146. if ((t1 & MAY_BE_ANY) == MAY_BE_ARRAY
  4147. && (t2 & MAY_BE_ANY) == MAY_BE_ARRAY) {
  4148. return 0;
  4149. }
  4150. return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4151. (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT));
  4152. case ZEND_ASSIGN_DIV:
  4153. case ZEND_ASSIGN_MOD:
  4154. if (opline->extended_value != 0) {
  4155. return 1;
  4156. }
  4157. if (!OP2_HAS_RANGE() ||
  4158. (OP2_MIN_RANGE() <= 0 && OP2_MAX_RANGE() >= 0)) {
  4159. /* Division by zero */
  4160. return 1;
  4161. }
  4162. /* break missing intentionally */
  4163. case ZEND_ASSIGN_SUB:
  4164. case ZEND_ASSIGN_MUL:
  4165. case ZEND_ASSIGN_POW:
  4166. if (opline->extended_value != 0) {
  4167. return 1;
  4168. }
  4169. return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4170. (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT));
  4171. case ZEND_ASSIGN_SL:
  4172. case ZEND_ASSIGN_SR:
  4173. if (opline->extended_value != 0) {
  4174. return 1;
  4175. }
  4176. return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4177. (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4178. !OP2_HAS_RANGE() ||
  4179. OP2_MIN_RANGE() < 0;
  4180. case ZEND_ASSIGN_CONCAT:
  4181. if (opline->extended_value != 0) {
  4182. return 1;
  4183. }
  4184. return (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4185. (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT));
  4186. case ZEND_ASSIGN_BW_OR:
  4187. case ZEND_ASSIGN_BW_AND:
  4188. case ZEND_ASSIGN_BW_XOR:
  4189. if (opline->extended_value != 0) {
  4190. return 1;
  4191. }
  4192. if ((t1 & MAY_BE_ANY) == MAY_BE_STRING
  4193. && (t2 & MAY_BE_ANY) == MAY_BE_STRING) {
  4194. return 0;
  4195. }
  4196. return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
  4197. (t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT));
  4198. case ZEND_ASSIGN:
  4199. case ZEND_UNSET_VAR:
  4200. return (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY));
  4201. case ZEND_ASSIGN_DIM:
  4202. if ((opline+1)->op1_type == IS_CV) {
  4203. if (_ssa_op1_info(op_array, ssa, opline+1) & MAY_BE_UNDEF) {
  4204. return 1;
  4205. }
  4206. }
  4207. return (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE)) || opline->op2_type == IS_UNUSED ||
  4208. (t2 & (MAY_BE_UNDEF|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
  4209. case ZEND_ASSIGN_OBJ:
  4210. if (t1 & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_OBJECT))) {
  4211. return 1;
  4212. }
  4213. if (ssa->ops[opline - op_array->opcodes].op1_use) {
  4214. zend_ssa_var_info *var_info = ssa->var_info + ssa->ops[opline - op_array->opcodes].op1_use;
  4215. zend_class_entry *ce = var_info->ce;
  4216. if (var_info->is_instanceof ||
  4217. !ce || ce->create_object || ce->__get || ce->__set ||
  4218. (ce->ce_flags & ZEND_ACC_INHERITED)) {
  4219. return 1;
  4220. }
  4221. if (op_array->scope != ce && ce->default_properties_count) {
  4222. zend_property_info *prop_info;
  4223. if (opline->op2_type == IS_CONST) {
  4224. prop_info = zend_hash_find_ptr(&ce->properties_info,
  4225. Z_STR_P(CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants)));
  4226. if (prop_info && !(prop_info->flags & ZEND_ACC_PUBLIC)) {
  4227. return 1;
  4228. }
  4229. } else {
  4230. if (t2 & (MAY_BE_ANY-MAY_BE_STRING)) {
  4231. return 1;
  4232. }
  4233. ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
  4234. if (!(prop_info->flags & ZEND_ACC_PUBLIC)) {
  4235. return 1;
  4236. }
  4237. } ZEND_HASH_FOREACH_END();
  4238. }
  4239. }
  4240. return 0;
  4241. }
  4242. return 1;
  4243. case ZEND_ROPE_INIT:
  4244. case ZEND_ROPE_ADD:
  4245. case ZEND_ROPE_END:
  4246. return t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT);
  4247. case ZEND_INIT_ARRAY:
  4248. case ZEND_ADD_ARRAY_ELEMENT:
  4249. return (opline->op2_type != IS_UNUSED) && (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
  4250. case ZEND_STRLEN:
  4251. return (t1 & MAY_BE_ANY) != MAY_BE_STRING;
  4252. case ZEND_COUNT:
  4253. return (t1 & MAY_BE_ANY) != MAY_BE_ARRAY;
  4254. case ZEND_RECV_INIT:
  4255. if (Z_TYPE_P(CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants)) == IS_CONSTANT_AST) {
  4256. return 1;
  4257. }
  4258. if (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
  4259. uint32_t arg_num = opline->op1.num;
  4260. zend_arg_info *cur_arg_info;
  4261. if (EXPECTED(arg_num <= op_array->num_args)) {
  4262. cur_arg_info = &op_array->arg_info[arg_num-1];
  4263. } else if (UNEXPECTED(op_array->fn_flags & ZEND_ACC_VARIADIC)) {
  4264. cur_arg_info = &op_array->arg_info[op_array->num_args];
  4265. } else {
  4266. return 0;
  4267. }
  4268. return ZEND_TYPE_IS_SET(cur_arg_info->type);
  4269. } else {
  4270. return 0;
  4271. }
  4272. case ZEND_FETCH_IS:
  4273. return (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT));
  4274. case ZEND_ISSET_ISEMPTY_DIM_OBJ:
  4275. return (t1 & MAY_BE_OBJECT) || (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT));
  4276. case ZEND_FETCH_DIM_IS:
  4277. return (t1 & MAY_BE_OBJECT) || (t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
  4278. case ZEND_CAST:
  4279. switch (opline->extended_value) {
  4280. case IS_NULL:
  4281. return 0;
  4282. case _IS_BOOL:
  4283. return (t1 & MAY_BE_OBJECT);
  4284. case IS_LONG:
  4285. case IS_DOUBLE:
  4286. return (t1 & MAY_BE_OBJECT);
  4287. case IS_STRING:
  4288. return (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT));
  4289. case IS_ARRAY:
  4290. return (t1 & MAY_BE_OBJECT);
  4291. case IS_OBJECT:
  4292. return (t1 & MAY_BE_ARRAY);
  4293. default:
  4294. return 1;
  4295. }
  4296. default:
  4297. return 1;
  4298. }
  4299. }
  4300. /*
  4301. * Local variables:
  4302. * tab-width: 4
  4303. * c-basic-offset: 4
  4304. * indent-tabs-mode: t
  4305. * End:
  4306. */