-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 0xCERT Security Advisory 0xCERT-2026-0166 ============================================================ Advisory-ID: 0xCERT-2026-0166 Severity: Medium Published: 2026-09-10T00:00:00.000Z Updated: 2026-10-08T22:46:34.338Z Chains: Ethereum URL: https://www.0xcert.com/advisory/0xCERT-2026-0166 Title: Solidity compiler bug SOL-2026-4: Spill Slot Collision Across Mutual Recursion Summary - ------- Local variables of two simultaneously active functions moved to fixed memory offsets by the stack limit evader may be assigned the same offset if the call graph contains mutual recursion, so that one variable is silently overwritten by the other. Affects 0.7.2 ≤ solc < 0.8.37. Details - ------- Summary Local variables of two simultaneously active functions moved to fixed memory offsets by the stack limit evader may be assigned the same offset if the call graph contains mutual recursion, so that one variable is silently overwritten by the other. Details To work around the 16-slot stack access limit of the EVM, the IR-based code generator can, under some preconditions, move local variables to fixed memory offsets. Variables that can never be active at the same time may safely share an offset, so the reserved memory area is sized by a depth-first walk of the call graph that computes for every node the number of slots it and its callees need. To keep this walk from descending infinitely into recursive call chains, the slot count was initialized with zero upon entering it. This provisional zero was observable: a function reached again through a call graph cycle reported an empty footprint to its caller, the caller's count was finalized and cached on that basis, and the undercount propagated to every later caller, including functions outside the cycle. As a result, a function called by such a cycle and a function calling into it could be assigned the same memory slot even though both can be active at the same time. A relocated variable still needed after the call into the cycle returned had then been silently overwritten by the called function, producing wrong results. Triggering the bug requires the IR pipeline and a call graph in which a cycle of at least two mutually recursive functions both reaches a function needing relocation of variables to memory and is entered from a separate call chain whose own relocated variable is read again after the call towards the cycle returns. From 0.8.21 onward, it is independent of whether the optimizer is enabled. Affected - - Solidity compiler (solc), 0.7.2 ≤ solc < 0.8.37 Severity Medium (upstream rating: "low/medium"). Recommended actions - - Contracts compiled with an affected solc version: check whether the conditions apply to your code; recompile with solc 0.8.37+ - - Auditors: add this bug to version-specific checklists Source & attribution This 0xCERT advisory summarises Solidity compiler bug SOL-2026-4 (SpillSlotCollisionAcrossMutualRecursion) from the Solidity team's bug list: https://blog.soliditylang.org/2026/09/10/spill-slot-collision-across-mutual-recursion-bug/. References - ---------- - - https://blog.soliditylang.org/2026/09/10/spill-slot-collision-across-mutual-recursion-bug/ - - https://github.com/ethereum/solidity/blob/develop/docs/bugs.json Verify with the 0xCERT OpenPGP key: https://www.0xcert.com/pgp.asc Fingerprint: 5F94 3ED1 1E50 CF31 2128 C493 CCC7 D9EC 9415 723D -----BEGIN PGP SIGNATURE----- wrsEARYKAG0FgmrI9OsJEDe9Tbcr+ZxrRRQAAAAAABwAIHNhbHRAbm90YXRp b25zLm9wZW5wZ3Bqcy5vcmfITnjMKOHkCKWJurSdCdxZl7WIO1EyszFZ4Qyx 2gUq1hYhBGCkkFZbJcT5QWu27ze9Tbcr+ZxrAAC0bgEAnSe99eMo6Hab+moZ 4hjCDq4JdSJbYOkXb4W2AOp575QA/jXLA1krQQE2BOuSp3MJyZsa4HrMVfDZ FR/m74LyCAUI =Zma4 -----END PGP SIGNATURE-----