fix(gnovm): deep-copy array elements in ArrayValue.Copy#5445
Open
thehowl wants to merge 2 commits intognolang:masterfrom
Open
fix(gnovm): deep-copy array elements in ArrayValue.Copy#5445thehowl wants to merge 2 commits intognolang:masterfrom
thehowl wants to merge 2 commits intognolang:masterfrom
Conversation
…ayValue.Copy
ArrayValue.Copy used Go's builtin copy() to duplicate its []TypedValue
slice, which copies TypedValue structs bitwise. For composite element
types (structs, nested arrays), this meant both the original and the
copy shared the same *StructValue/*ArrayValue pointers, silently
corrupting persistent realm state.
The fix mirrors StructValue.Copy, which already calls field.Copy(alloc)
per element for exactly this reason. TypedValue.Copy dispatches
correctly on the dynamic type: *StructValue and *ArrayValue are deep-
copied, while reference-like values (slices, maps, pointers, functions)
fall through to the shallow default — so interface-held reference types
are handled correctly.
The gas expectation for gnovm/tests/files/gas/nested_alloc.gno is
updated: building a 10000-deep [1]interface{}{x} chain now incurs O(n²)
copy cost because each assignment deep-copies the entire chain, which is
the correct cost under Gno's value semantics for interface-held arrays.
Fixes NEWTENDG-105.
Collaborator
🛠 PR Checks SummaryAll Automated Checks passed. ✅ Manual Checks (for Reviewers):
Read More🤖 This bot helps streamline PR reviews by verifying automated checks and providing guidance for contributors and reviewers. ✅ Automated Checks (for Contributors):🟢 Maintainers must be able to edit this pull request (more info) ☑️ Contributor Actions:
☑️ Reviewer Actions:
📚 Resources:Debug
|
davd-gzl
approved these changes
Apr 7, 2026
Member
|
I was working on a fix for that #5341 |
Member
See It was in draft :/ |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Co-authored-by: 6h057 <15034695+omarsy@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #5332
ArrayValue.Copy used Go's builtin copy() to duplicate its []TypedValue slice, which copies TypedValue structs by value. For composite element types (structs, nested arrays), this meant both the original and the copy shared the same *StructValue/*ArrayValue pointers, silently corrupting persistent realm state.
The fix mirrors StructValue.Copy, which already calls field.Copy(alloc) per element for exactly this reason. TypedValue.Copy dispatches correctly on the dynamic type: *StructValue and *ArrayValue are deep-copied, while reference-like values (slices, maps, pointers, functions) fall through to the shallow default — so interface-held reference types are handled correctly.
The gas expectation for gnovm/tests/files/gas/nested_alloc.gno is updated: building a 10000-deep [1]interface{}{x} chain now incurs O(n²) copy cost because each assignment deep-copies the entire chain, which is the correct cost under Gno's value semantics for interface-held arrays.