From 9e0bebda71aafc90c04e64a46c7a9048e0a303b1 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Tue, 28 Feb 2023 17:06:51 +0900 Subject: [PATCH] internal/packing: bug fix: node's links were not synced correctly Closes #2584 --- internal/packing/packing.go | 8 ++++-- internal/packing/packing_test.go | 42 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/internal/packing/packing.go b/internal/packing/packing.go index 65a1c381e..705343ce2 100644 --- a/internal/packing/packing.go +++ b/internal/packing/packing.go @@ -245,7 +245,8 @@ func (p *Page) Extend(count int) bool { } if aborted { - origRoot := *p.root + origRoot := p.root + origRootCloned := *p.root leftUpper := p.root leftLower := &Node{ @@ -285,7 +286,10 @@ func (p *Page) Extend(count int) bool { origSize := p.size p.rollbackExtension = func() { p.size = origSize - p.root = &origRoot + // The node address must not be changed, so use the original root node's pointer (#2584). + // As the root node might be modified, recover the content from the cloned content. + p.root = origRoot + *p.root = origRootCloned } } else { origSize := p.size diff --git a/internal/packing/packing_test.go b/internal/packing/packing_test.go index 946a45b6d..8dfbe3140 100644 --- a/internal/packing/packing_test.go +++ b/internal/packing/packing_test.go @@ -359,3 +359,45 @@ func TestExtendWithoutAllocation(t *testing.T) { t.Errorf("p.Size(): got: %d, want: %d", got, want) } } + +// Issue #2584 +func TestRemoveAtRootsChild(t *testing.T) { + p := packing.NewPage(32, 1024) + + alloc := func(width, height int) *packing.Node { + n := p.Alloc(width, height) + if n != nil { + return n + } + + for i := 1; i < 100; i++ { + if !p.Extend(i) { + t.Fatalf("p.Extend(%d) failed", i) + } + if n = p.Alloc(width, height); n != nil { + p.CommitExtension() + return n + } + p.RollbackExtension() + } + + t.Fatalf("never reached") + return nil + } + + n0 := alloc(18, 18) + n1 := alloc(28, 59) + n2 := alloc(18, 18) + n3 := alloc(18, 18) + n4 := alloc(8, 10) + n5 := alloc(322, 242) + _ = n5 + p.Free(n0) + p.Free(n2) + p.Free(n1) + p.Free(n3) + p.Free(n4) + + n6 := alloc(18, 18) + p.Free(n6) +}