zend_inference.c 147 KB

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