{"id":1246,"date":"2026-10-10T22:15:26","date_gmt":"2026-10-10T22:15:26","guid":{"rendered":"https:\/\/smartcryptosecurity.com\/?p=1246"},"modified":"2026-10-10T22:15:26","modified_gmt":"2026-10-10T22:15:26","slug":"critical-memory-corruption-vulnerability-discovered-in-solidity-code-generator-affects-versions-up-to-0-8-37-2","status":"publish","type":"post","link":"https:\/\/smartcryptosecurity.com\/?p=1246","title":{"rendered":"Critical Memory Corruption Vulnerability Discovered in Solidity Code Generator Affects Versions up to 0.8.37"},"content":{"rendered":"<p>A significant bug has been discovered within the Solidity code generator, impacting all historical versions of the Ethereum smart contract language up to and including version 0.8.36. The vulnerability, which causes the <code>delete<\/code> operator to overwrite significantly more memory than intended when applied to elements of memory-based <code>bytes<\/code> and <code>string<\/code> arrays under the default compilation pipeline, was patched in Solidity 0.8.37 following a responsible disclosure.<\/p>\n<p>The issue was formally brought to light on August 14, 2026, by researcher Shaheen Fazim, who submitted a comprehensive bug report complete with a reproducer through the official Ethereum Foundation bug bounty program. Internal security assessments by the Solidity team classified the flaw as a low-to-medium severity vulnerability. While the bug carries the potential for severe data corruption under specific conditions, subsequent ecosystem analyses indicate that actual exploitation in deployed smart contracts is exceedingly rare.<\/p>\n<h2>Understanding the Vulnerability Mechanics<\/h2>\n<p>To comprehend the nature of the bug, one must understand how Solidity manages dynamic memory allocation for byte arrays. In the Ethereum Virtual Machine (EVM) memory architecture, most data structures occupy clean, uniform 32-byte words. Dynamic byte arrays (<code>bytes<\/code>) and string values (<code>string<\/code>), however, are notable exceptions. A memory-based byte array consists of an initial 32-byte length descriptor followed immediately by the raw data bytes packed back-to-back without internal word gaps.<\/p>\n<p>Solidity allocates memory sequentially by advancing a global free memory pointer, ensuring that consecutive allocations sit flush against one another. Normally, when developers target an individual element of a byte array for erasure\u2014such as writing <code>b[i] = 0<\/code>\u2014the compiler utilizes a targeted single-byte store instruction (<code>mstore8<\/code>), correctly modifying only the single byte requested while leaving adjacent data pristine.<\/p>\n<p>The vulnerability specifically plagues the <code>delete<\/code> code path within the default, legacy <code>evmasm<\/code> compilation pipeline. When <code>delete b[i]<\/code> is invoked on a memory-based byte array, the code generator erroneously executes a full 32-byte zero write (<code>mstore<\/code>) starting directly at the offset of the designated element. Because this write initiates at the element&#8217;s specific index rather than aligning to a standard 32-byte word boundary, it bleeds forward into subsequent memory locations. <\/p>\n<p>Consequently, applying the <code>delete<\/code> operation to an element does not merely clear that single byte; it systematically wipes out up to 31 additional bytes immediately following it. Because the array&#8217;s length descriptor remains completely untouched, the data structure retains its original logical length while its contents are silently corrupted with trailing zeros. Any subsequent operations relying on the array\u2014including hashing functions like <code>keccak256<\/code>, ABI encoding routines, or external function returns\u2014will process this corrupted memory state.<\/p>\n<h2>Scope, Affected Configurations, and Pipeline Discrepancies<\/h2>\n<p>The vulnerability&#8217;s presence is strictly tied to specific compilation pathways and data structures. Crucially, the alternative Intermediate Representation (IR) compilation pipeline is entirely unaffected, as it properly routes <code>delete<\/code> operations through the correct single-byte store logic. Furthermore, the use of the Solidity optimizer is neither required to trigger the bug nor capable of preventing it, because the faulty semantic behavior originates directly from the initial code generation phase.<\/p>\n<p>The bug&#8217;s historical footprint is extensive, affecting every single released version of Solidity since the language&#8217;s inception up to version 0.8.36. However, triggering the defect requires a precise intersection of architectural conditions: the code must be compiled using the default <code>evmasm<\/code> pipeline, the data structure must be a dynamic <code>bytes<\/code> or <code>string<\/code> array located in memory, and the operation must specifically apply the <code>delete<\/code> keyword to an individual element rather than clearing the entire array or assigning a zero value directly via indexing.<\/p>\n<p>Storage-based byte arrays remain completely unaffected because they rely on an entirely separate storage-layout code path, and the <code>delete<\/code> operator cannot be applied to calldata arrays. Similarly, fixed-size byte arrays or arrays whose elements each occupy a full 32-byte word in memory\u2014such as <code>bytes1[] memory<\/code>\u2014are immune to the defect, because their individual elements already align with word boundaries.<\/p>\n<figure class=\"article-inline-figure\"><img decoding=\"async\" src=\"https:\/\/soliditylang.org\/assets\/logo-og-image.png\" alt=\"Memory Byte Array Element Delete Clears Whole Word Bug | Solidity Programming Language\" class=\"article-inline-img\" loading=\"lazy\" \/><\/figure>\n<h2>Analyzing Memory Corruption Inside and Beyond the Array<\/h2>\n<p>The physical consequences of the rogue 32-byte zero write depend heavily on where the targeted element resides within the array and how the array itself was allocated in memory. Developers must differentiate between internal array corruption and external memory corruption.<\/p>\n<p>When an element located safely within the interior of a byte array is deleted, the ensuing 32-byte zero wipe overwrites up to 31 subsequent elements belonging to the same array. Unless the array happens to consist entirely of zero bytes past the deletion point, this results in immediate data corruption within the structure itself.<\/p>\n<p>A more critical scenario arises when the delete operation targets one of the final 31 elements of an array, potentially causing the write to bleed past the array&#8217;s allocated boundary into whatever data structure happens to sit immediately afterward in memory. The extent of this overflow depends on whether the compiler padded the array during allocation. <\/p>\n<p>Byte arrays created via literals or expressions like <code>new bytes(n)<\/code> are typically padded with up to 31 trailing zero bytes so that the subsequent memory allocation begins cleanly on a 32-byte word boundary. Conversely, unpadded arrays\u2014such as the dynamic results returned by <code>bytes.concat<\/code>, <code>string.concat<\/code>, and various <code>abi.encode<\/code> functions\u2014end precisely where the next memory allocation begins, leaving no buffer whatsoever. For unpadded arrays, deleting any of the final 31 elements will invariably overwrite the beginning of the next adjacent memory block, which may contain critical execution context, local variables, or reference pointers.<\/p>\n<h2>Ecosystem Impact and Security Assessment<\/h2>\n<p>To gauge the real-world exposure of smart contracts to this defect, security researchers scanned the Sourcify database, encompassing approximately 870,000 verified contract compilations. The analysis revealed that the vulnerable source code pattern appeared in a mere 17 compilations, pointing to only two distinct deployed functions across the entire verified ecosystem. <\/p>\n<p>A rigorous follow-up severity assessment determined that neither of those two functions was actually vulnerable to exploitation. In both instances, the bytes overwritten inside the array were subsequently discarded or overwritten by design, while memory allocations residing beyond the arrays were either structurally protected by sufficient padding or resided in entirely unused memory spaces. Consequently, no deployed smart contracts are currently known to have suffered malicious exploitation or unintended state corruption as a result of this bug.<\/p>\n<p>The Solidity development team formally resolved the issue in version 0.8.37 by updating the code generator to ensure that the <code>delete<\/code> path consults element-width parameters in the exact same manner as standard assignment statements. When clearing elements within packed byte arrays, the compiler now correctly emits a single-byte store (<code>mstore8<\/code>) rather than a full-word instruction.<\/p>\n<p>Developers maintaining codebases utilizing legacy versions of Solidity up to 0.8.36 are strongly advised to audit their code for memory-based byte and string array element deletions, refactor vulnerable statements to use direct assignments where appropriate, or upgrade their compiler toolchain to Solidity 0.8.37 or later to permanently eliminate the risk.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A significant bug has been discovered within the Solidity code generator, impacting all historical versions&#8230;<\/p>\n","protected":false},"author":14,"featured_media":1245,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[366],"tags":[963,401,406,961,201,962,407,960,5,400,402,964,773],"class_list":["post-1246","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-smart-contract-auditing","tag-affects","tag-auditing","tag-code","tag-corruption","tag-critical","tag-discovered","tag-generator","tag-memory","tag-security","tag-smart-contracts","tag-solidity","tag-versions","tag-vulnerability"],"_links":{"self":[{"href":"https:\/\/smartcryptosecurity.com\/index.php?rest_route=\/wp\/v2\/posts\/1246","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/smartcryptosecurity.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/smartcryptosecurity.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/smartcryptosecurity.com\/index.php?rest_route=\/wp\/v2\/users\/14"}],"replies":[{"embeddable":true,"href":"https:\/\/smartcryptosecurity.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1246"}],"version-history":[{"count":0,"href":"https:\/\/smartcryptosecurity.com\/index.php?rest_route=\/wp\/v2\/posts\/1246\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/smartcryptosecurity.com\/index.php?rest_route=\/wp\/v2\/media\/1245"}],"wp:attachment":[{"href":"https:\/\/smartcryptosecurity.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smartcryptosecurity.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1246"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smartcryptosecurity.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}