-
Notifications
You must be signed in to change notification settings - Fork 663
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
contract preparation: actually replace all memories with a single memory import, including imported memories #8029
contract preparation: actually replace all memories with a single memory import, including imported memories #8029
Conversation
…ory import, including imported memories Before this change, our behavior regarding memory items was erratic at best: - If passed with exactly one module-local memory, we would correctly remove it and replace it with an import - If passed with more than one module-local memory, we would fail deserialization due to multiple memories being defined, and then ensure_no_internal_memory would be pointless - If passed with one or many memory imports, they would be left in the prepared code, resulting in two memories being in the output webassembly, that would then fail the second validation With this change, memory items are just all ignored, and a single memory import with the parameters we defined is added. The test_multiple_memories test is updated to actually be a (manually-crafted because no tools seem to accept doing it) wasm blob that defines two memories, instead of a wasm blob that defines a memory import and incidentally due to preparation bugs turns out having multiple memories after preparation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m happy with this.
They probably want multi-memory extension to be enabled. |
Hm, I think that's not the entirely correct logic here. My understanding is we do not support multiple memories proposal. So our intention is only to allow contracts with exactly zero or one memory. We shouldn't be making contracts with multiple memories valid (if there are two memories, and we remove one, than code might try to access non-existing memories). We also shouldn't allow to "manually" improt memories. I think the code today mostly does all this:
But yeah, it' be great do to all this in the preparation. And I think this doesn't have to be a protocol chage? We don't want to allow more contracts (so, two memories is still an error), we just want to shift a place where we emit an error to preparation from our defence in depth in compiler? |
Correct.
Well, sort of. In practice it is okay if we "internally" always normalize this to exactly one imported memory. This is I believe what our prep was already trying to implement.
We’re still rejecting any contracts with multiple memories by the virtue of running any instrumentation code after validation has already passed (which rejects multiple memories). So the only contracts that reach this instrumentation code are: those that have no memories, those that have 1 internal memory, and those that import one memory. That is, for contracts, if there was a valid memory index, this index is 0, and the same both before and after this PR. There isn’t a behaviour change for contract semantics. This PR brings the behaviour wrt. contracts with imported memories in-line with the behaviour wrt. contracts with internal memories. In principle, this change means |
I’ve just implemented the review comments :) @matklad As @nagisa mentioned, the current behavior is:
And we have a choice between:
TBH, upon more thought I’m no longer sure this PR is the right way to go, and maybe instead we should just go with option 2, because that’s one fewer protocol upgrade and we don’t really care about contracts with imported memories anyway… WDYT? |
Hm, my reading is slightly different: I think the intention is to take contract with one internal memory, and make it a contract with one imported memory. I think the motivation is basically "accidents of our implementation". Compilers produce Again, not sure, but the fact that the code explicitly does |
I think the case where ther is an imported memory, no local memories, and the imported memory happens to match our own config,we also accept. I think what we should do is:
The core is that I think we can fix the bug (catching invalid contract too late) while not doing a protocol version? Separately from that, it does seem to me that the current behavior of swapping one local memory for one import is the reasonable one (*), and that the proposal to remove arbitrary number of memories is less so. (*) the best behavior would probably be to not mess with contract memories at all, as I don't think theer's a fundamental reason why we need this imported memory at all, but that's very out of scope. |
That works for me too! To sum up, the final state would be:
@nagisa Are you also OK with this plan? |
Yeah, keeping the current behaviour seems reasonable enough to me. |
Closing in favor of #8146 |
They were already rejected by wasmer2 before this change, just after preparation. So this should not be a protocol change. Second attempt at #8029, without a protocol change this time
Before this change, our behavior regarding memory items was erratic at best:
With this change, memory items are just all ignored, and a single memory import with the parameters we defined is added.
The test_multiple_memories test is updated to actually be a (manually-crafted because no tools seem to accept doing it) wasm blob that defines two memories, instead of a wasm blob that defines a memory import and incidentally due to preparation bugs turns out having multiple memories after preparation.
This is a draft PR because it will require a protocol upgrade. However, before doing this boilerplate work, I’d like to put that out here for other people to have a look and check they’d be ok with this in a finalized form.
Fixes #6042