From b5808cec7c28848211401e7c9866690a508e97f4 Mon Sep 17 00:00:00 2001 From: Awn Umar Date: Wed, 27 Aug 2025 23:00:48 +0100 Subject: [PATCH 1/7] Replace use of depreciated SliceHeader with new unsafe.Slice --- core/auxiliary.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/auxiliary.go b/core/auxiliary.go index 7d3321e..166a9b6 100644 --- a/core/auxiliary.go +++ b/core/auxiliary.go @@ -2,7 +2,6 @@ package core import ( "os" - "reflect" "unsafe" ) @@ -18,6 +17,5 @@ func roundToPageSize(length int) int { // Convert a pointer and length to a byte slice that describes that memory. func getBytes(ptr *byte, len int) []byte { - var sl = reflect.SliceHeader{Data: uintptr(unsafe.Pointer(ptr)), Len: len, Cap: len} - return *(*[]byte)(unsafe.Pointer(&sl)) + return unsafe.Slice(ptr, len) } From 048a2e6aa905ffc613d3494f0e06b24340abcee4 Mon Sep 17 00:00:00 2001 From: Awn Umar Date: Wed, 27 Aug 2025 23:00:59 +0100 Subject: [PATCH 2/7] Improve TestCofferConcurrent --- core/coffer_test.go | 71 +++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 51 deletions(-) diff --git a/core/coffer_test.go b/core/coffer_test.go index ecb6acd..2f7eac1 100644 --- a/core/coffer_test.go +++ b/core/coffer_test.go @@ -2,9 +2,7 @@ package core import ( "bytes" - "context" - "os" - "strconv" + "math/rand/v2" "sync" "testing" "time" @@ -176,24 +174,10 @@ func TestCofferDestroy(t *testing.T) { } func TestCofferConcurrent(t *testing.T) { - testConcurrency := 3 - envVar := os.Getenv("TEST_CONCURRENCY") - if len(envVar) > 0 { - envVarValue, err := strconv.Atoi(envVar) - if envVarValue > 0 { - testConcurrency = envVarValue - t.Logf("test concurrency set to %v", testConcurrency) - } else { - t.Logf("cannot use test concurrency %v: %v", envVar, err) - } - } - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() + testConcurrency := 20 + testDuration := 4 * time.Second funcs := []func(s *Coffer) error{ - func(s *Coffer) error { - return s.Init() - }, func(s *Coffer) error { return s.Rekey() }, @@ -204,39 +188,24 @@ func TestCofferConcurrent(t *testing.T) { } wg := &sync.WaitGroup{} - for _, fn := range funcs { - for i := 0; i != testConcurrency; i++ { - s := NewCoffer() - wg.Add(1) - - go func(ctx context.Context, wg *sync.WaitGroup, s *Coffer, target func(s *Coffer) error) { - defer wg.Done() - for { - select { - case <-time.After(time.Millisecond): - err := target(s) - if err != nil { - if err == ErrCofferExpired { - return - } - t.Fatalf("unexpected error: %v", err) - } - case <-ctx.Done(): - return - } - } - }(ctx, wg, s, fn) - - wg.Add(1) - go func(ctx context.Context, wg *sync.WaitGroup, s *Coffer, i int) { - defer wg.Done() - select { - case <-time.After(time.Duration(i) * time.Millisecond): - case <-ctx.Done(): + s := NewCoffer() + defer s.Destroy() + + start := time.Now() + + for range testConcurrency { + wg.Add(1) + go func(t *testing.T) { + defer wg.Done() + fIndex := rand.IntN(len(funcs)) + for time.Since(start) < testDuration { + err := funcs[fIndex](s) + if err != nil { + t.Errorf("unexpected error: %v", err) } - s.Destroy() - }(ctx, wg, s, i) - } + } + }(t) } + wg.Wait() } From 766a8f7313c7f159f3f771756b12bb36baa2df3f Mon Sep 17 00:00:00 2001 From: Awn Umar Date: Wed, 27 Aug 2025 23:04:04 +0100 Subject: [PATCH 3/7] Reduce test concurrency to avoid hittimg mlock limit --- core/coffer_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/coffer_test.go b/core/coffer_test.go index 2f7eac1..a29474f 100644 --- a/core/coffer_test.go +++ b/core/coffer_test.go @@ -174,8 +174,8 @@ func TestCofferDestroy(t *testing.T) { } func TestCofferConcurrent(t *testing.T) { - testConcurrency := 20 - testDuration := 4 * time.Second + testConcurrency := 5 + testDuration := 2 * time.Second funcs := []func(s *Coffer) error{ func(s *Coffer) error { From 07a3ccde731081847c7b69f86470835881989118 Mon Sep 17 00:00:00 2001 From: Awn Umar Date: Wed, 27 Aug 2025 23:08:29 +0100 Subject: [PATCH 4/7] Remove getBytes function --- core/auxiliary.go | 6 ------ core/auxiliary_test.go | 30 ------------------------------ core/buffer.go | 11 ++++++----- 3 files changed, 6 insertions(+), 41 deletions(-) diff --git a/core/auxiliary.go b/core/auxiliary.go index 166a9b6..ea4fb70 100644 --- a/core/auxiliary.go +++ b/core/auxiliary.go @@ -2,7 +2,6 @@ package core import ( "os" - "unsafe" ) var ( @@ -14,8 +13,3 @@ var ( func roundToPageSize(length int) int { return (length + (pageSize - 1)) & (^(pageSize - 1)) } - -// Convert a pointer and length to a byte slice that describes that memory. -func getBytes(ptr *byte, len int) []byte { - return unsafe.Slice(ptr, len) -} diff --git a/core/auxiliary_test.go b/core/auxiliary_test.go index 67b5432..793eecd 100644 --- a/core/auxiliary_test.go +++ b/core/auxiliary_test.go @@ -1,10 +1,8 @@ package core import ( - "bytes" "fmt" "testing" - "unsafe" ) func TestRoundToPageSize(t *testing.T) { @@ -23,31 +21,3 @@ func TestRoundToPageSize(t *testing.T) { t.Error("failed with test input page_size + 1") } } - -func TestGetBytes(t *testing.T) { - // Allocate an ordinary buffer. - buffer := make([]byte, 32) - - // Get am alternate reference to it using our slice builder. - derived := getBytes(&buffer[0], len(buffer)) - - // Check for naive equality. - if !bytes.Equal(buffer, derived) { - t.Error("naive equality check failed") - } - - // Modify and check if the change was reflected in both. - buffer[0] = 1 - buffer[31] = 1 - if !bytes.Equal(buffer, derived) { - t.Error("modified equality check failed") - } - - // Do a deep comparison. - if uintptr(unsafe.Pointer(&buffer[0])) != uintptr(unsafe.Pointer(&derived[0])) { - t.Error("pointer values differ") - } - if len(buffer) != len(derived) || cap(buffer) != cap(derived) { - t.Error("length or capacity values differ") - } -} diff --git a/core/buffer.go b/core/buffer.go index afea842..fd10029 100644 --- a/core/buffer.go +++ b/core/buffer.go @@ -3,6 +3,7 @@ package core import ( "errors" "sync" + "unsafe" "github.com/awnumar/memcall" ) @@ -58,15 +59,15 @@ func NewBuffer(size int) (*Buffer, error) { } // Construct slice reference for data buffer. - b.data = getBytes(&b.memory[pageSize+innerLen-size], size) + b.data = unsafe.Slice(&b.memory[pageSize+innerLen-size], size) // Construct slice references for page sectors. - b.preguard = getBytes(&b.memory[0], pageSize) - b.inner = getBytes(&b.memory[pageSize], innerLen) - b.postguard = getBytes(&b.memory[pageSize+innerLen], pageSize) + b.preguard = unsafe.Slice(&b.memory[0], pageSize) + b.inner = unsafe.Slice(&b.memory[pageSize], innerLen) + b.postguard = unsafe.Slice(&b.memory[pageSize+innerLen], pageSize) // Construct slice reference for canary portion of inner page. - b.canary = getBytes(&b.memory[pageSize], len(b.inner)-len(b.data)) + b.canary = unsafe.Slice(&b.memory[pageSize], len(b.inner)-len(b.data)) // Lock the pages that will hold sensitive data. if err := memcall.Lock(b.inner); err != nil { From e91b1dc8ced2e9f2c2dd1767812a9c98fb129226 Mon Sep 17 00:00:00 2001 From: Awn Umar Date: Wed, 27 Aug 2025 23:08:36 +0100 Subject: [PATCH 5/7] Reduce test concurrency to avoid hittimg mlock limit --- core/coffer_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/coffer_test.go b/core/coffer_test.go index a29474f..fedb04f 100644 --- a/core/coffer_test.go +++ b/core/coffer_test.go @@ -174,8 +174,8 @@ func TestCofferDestroy(t *testing.T) { } func TestCofferConcurrent(t *testing.T) { - testConcurrency := 5 - testDuration := 2 * time.Second + testConcurrency := 4 + testDuration := 1 * time.Second funcs := []func(s *Coffer) error{ func(s *Coffer) error { From 450a3e0a6700fdf09d466b0f30759b92a9d172ae Mon Sep 17 00:00:00 2001 From: Awn Umar Date: Wed, 27 Aug 2025 23:14:36 +0100 Subject: [PATCH 6/7] Add panic recovery and expect destored coffer --- core/coffer_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/coffer_test.go b/core/coffer_test.go index fedb04f..077d1e4 100644 --- a/core/coffer_test.go +++ b/core/coffer_test.go @@ -197,10 +197,16 @@ func TestCofferConcurrent(t *testing.T) { wg.Add(1) go func(t *testing.T) { defer wg.Done() + defer func() { + if r := recover(); r != nil { + // Log panic -- it's likely just ran out of mlock space. + t.Logf("Recovered from panic: %s", r) + } + }() fIndex := rand.IntN(len(funcs)) for time.Since(start) < testDuration { err := funcs[fIndex](s) - if err != nil { + if err != nil && err != ErrCofferExpired { t.Errorf("unexpected error: %v", err) } } From 45966622882450cfda521839cd8fc14794c14206 Mon Sep 17 00:00:00 2001 From: Awn Umar Date: Wed, 27 Aug 2025 23:16:35 +0100 Subject: [PATCH 7/7] Raise concurrency limit --- core/coffer_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/coffer_test.go b/core/coffer_test.go index 077d1e4..297365a 100644 --- a/core/coffer_test.go +++ b/core/coffer_test.go @@ -174,8 +174,8 @@ func TestCofferDestroy(t *testing.T) { } func TestCofferConcurrent(t *testing.T) { - testConcurrency := 4 - testDuration := 1 * time.Second + testConcurrency := 10 + testDuration := 2 * time.Second funcs := []func(s *Coffer) error{ func(s *Coffer) error {