# Non memory-safe assembly

**URL:** <https://forum.soliditylang.org/t/non-memory-safe-assembly/2368>\
**Category:** Uncategorized\
**Created:** [June 18, 2024, 9:53am UTC](https://forum.soliditylang.org/t/non-memory-safe-assembly/2368 "2024-06-18T09:53:59Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![jhoenicke](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.soliditylang.org/jhoenicke/32/1332_2.png) [@jhoenicke](https://forum.soliditylang.org/u/jhoenicke)\
**Post date:** [June 18, 2024, 9:53am UTC](https://forum.soliditylang.org/t/non-memory-safe-assembly/2368/1 "2024-06-18T09:53:59Z")

</div>

Reviewing some code I several times see memory-unsafe assembly that is marked as “memory-safe”. In particular code that temporarily overwrites the free pointer and restores it at the end of the block, or that overwrites it and then immediately reverts.

From the documentation I gather that this is not memory-safe and declaring it as memory-safe may lead to problems. In the examples I saw it didn’t, but maybe they just got lucky? Is the danger just that the next version of the compiler may move more things around, or can it already happen with some optimization settings?

Would you recommend to just remove the “memory-safe” or would it be better (maybe even more gas efficient) to fix the assembly code and use the space starting at the free memory pointer as scratch space instead?

---

<div class="post-metadata">

**Author:** ![mehtavishwa30](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.soliditylang.org/mehtavishwa30/32/1079_2.png) [@mehtavishwa30](https://forum.soliditylang.org/u/mehtavishwa30)\
**Post date:** [July 1, 2024, 12:43pm UTC](https://forum.soliditylang.org/t/non-memory-safe-assembly/2368/2 "2024-07-01T12:43:07Z")

</div>

Hello @jhoenicke! Thanks for the question.

Overwriting free memory pointer is safe as long as it is restored at the end of the block. I believe that the following section in the docs mentions the same as memory safe:  
[https://docs.soliditylang.org/en/stable/assembly.html#memory-safety](https://docs.soliditylang.org/en/stable/assembly.html#memory-safety)

Could you please clarify as to why you think this shouldn’t be declared as memory safe?

---

<div class="post-metadata">

**Author:** ![ekpyron](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.soliditylang.org/ekpyron/32/62_2.png) [@ekpyron](https://forum.soliditylang.org/u/ekpyron)\
**Post date:** [July 1, 2024, 4:56pm UTC](https://forum.soliditylang.org/t/non-memory-safe-assembly/2368/3 "2024-07-01T16:56:26Z")

</div>

Do the docs say that :-)? I’d be surprised if they did and I don’t see anything of the sort there.

If I understand the cases this post is about correctly, technically, they’re _not_ memory-safe. Memory-safe accesses are only accesses to the scratch space at `0-64` and space beyond the current value of the free memory pointer - that doesn’t include the free memory pointer itself (_at_ offset 64), no matter whether it is restored or not.

So much for memory-safety by definition in the docs.

De-facto, at least currently, nothing bad will happen if you _also_ use the free memory pointer itself as scratch space, as long as you restore it or terminate. Properly unsafe use that can in fact cause issues _currently_ is only code that moves further and overwrites memory starting at `0x80` - both `0x40` and `0x60` are fine as long as you restore the original values before going back to Solidity (or you _don’t_ go back to Solidity). We’re _unlikely_ to change this, but we _could_ and wouldn’t have to consider that breaking. Note that if you’re using memory beyond `0x80` and don’t run into issues, then you’re merely lucky - no matter whether you restore things or terminate.

That being said, there is no guarantee for this behaviour and I’d indeed recommend using the scratch space _at_ the free memory pointer instead, if you need more than 64 bytes.

---

<div class="post-metadata">

**Author:** ![jhoenicke](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.soliditylang.org/jhoenicke/32/1332_2.png) [@jhoenicke](https://forum.soliditylang.org/u/jhoenicke)\
**Post date:** [July 2, 2024, 11:53am UTC](https://forum.soliditylang.org/t/non-memory-safe-assembly/2368/4 "2024-07-02T11:53:15Z")

</div>

Thanks for the replies. I also heard the opinion that overwriting memory pointer is okay, because there is even an example that overwrites the free memory pointer to allocate memory, but overwriting the zero pointer at 0x60 is not memory safe and may even currently break (although I haven’t seen an example where this happens). But as I get from ekpyron’s reply, everyone relying on this is risking problems with a later solidity release, even though they will probably be fine.

I’ve also seen code where the memory pointer is partly overwritten in the most significant bytes without saving it and then restored by clearing these bytes (`mstore(0x34, data)` followed later by `mstore(0x34,0)`. I guess if you overwrite only the first 28 bytes of the free memory pointer, you can be quite sure they were zero anyway, at least with the gas model of ethereum. But this feels even less safe.

---

<div class="post-metadata">

**Author:** ![ekpyron](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.soliditylang.org/ekpyron/32/62_2.png) [@ekpyron](https://forum.soliditylang.org/u/ekpyron)\
**Post date:** [July 2, 2024, 4:05pm UTC](https://forum.soliditylang.org/t/non-memory-safe-assembly/2368/5 "2024-07-02T16:05:57Z")

</div>

Yeah, using the free memory pointer for allocating memory according to Solidity’s memory model is definitely valid, that’s indeed even in the docs in the form of the `allocate` function.  
Now the compiler will never itself inject new allocations in the middle of an assembly block - the compiler only relies on it having “sane” values for generating code for high-level Solidity.  
So yeah, by that argument it’s not merely unlikely for us to break this, but we really couldn’t. Maybe we should actually even officialize that and change the docs to declare this explicitly as safe (and thus strongly guarantee that this won’t break).

---

<div class="post-metadata">

**Author:** ![0xth0mas](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.soliditylang.org/0xth0mas/32/1129_2.png) [@0xth0mas](https://forum.soliditylang.org/u/0xth0mas)\
**Post date:** [July 2, 2024, 4:09pm UTC](https://forum.soliditylang.org/t/non-memory-safe-assembly/2368/6 "2024-07-02T16:09:06Z")

</div>

I would certainly hope that if Solidity ever starts managing memory inside of an assembly block without an explicit memory instruction that it is considered/documented as a breaking change.

IMO as long as you restore the memory state within the block you’re still respecting the memory model.

---

<div class="post-metadata">

**Author:** ![ekpyron](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.soliditylang.org/ekpyron/32/62_2.png) [@ekpyron](https://forum.soliditylang.org/u/ekpyron)\
**Post date:** [July 2, 2024, 4:33pm UTC](https://forum.soliditylang.org/t/non-memory-safe-assembly/2368/7 "2024-07-02T16:33:21Z")

</div>

I actually just created [Relax the definition of memory safety in the documentation. by ekpyron · Pull Request #15238 · ethereum/solidity · GitHub](https://github.com/ethereum/solidity/pull/15238) to explicitly document this as safe - we’ll discuss this internally, so don’t take it for granted until we merge it, but I think it likely that we will at least properly guarantee this for the free memory pointer at 0x40, potentially also for the zero value at 0x60.

---

<div class="post-metadata">

**Author:** ![jpmorais](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.soliditylang.org/jpmorais/32/1540_2.png) [@jpmorais](https://forum.soliditylang.org/u/jpmorais)\
**Post date:** [February 5, 2025, 8:38am UTC](https://forum.soliditylang.org/t/non-memory-safe-assembly/2368/8 "2025-02-05T08:38:57Z")

</div>

Hi All,

I would like to resume this conversation because I have had a question for days and I can’t solve it. It’s related to memory unsafe assembly code.

From what I understood reading the compiler PRs, one way to check if the optimizer will work (and if the memory is safe) is to look for memoryguard in the compilation. In my compilation, mstore(64, memoryguard(128)) always appears and stack too deep never happens. So, it seems that my code is all memory safe.

The problem is that I do the craziest things in memory. I can store values ​​wherever I want in memory, like mstore(0x60, 0x123) or mstore(0x80, 0x123) and even then memoryguard keeps appearing.

Long story short, I’m not able to simulate code where the compiler doesn’t try to optimize stack too deep. I would really appreciate it if someone could help me understand what I’m doing wrong and give me an example of code where memoryguard is not activated.

Thanks
