Files
versitygw/rdma/rcserver/rcserver_cgo_linux_test.go
Jihyeon Gim 9edd21eb78 rdma: drop the personal name from copyright notices
The Versity copyright line names the project, not an individual.
The personal name stays in Signed-off-by. No functional change.

Signed-off-by: Jihyeon Gim <potatogim@potatogim.net>
2026-10-08 05:36:43 +09:00

74 lines
2.5 KiB
Go

// Copyright 2026 Versity Software
// Copyright 2026 Gluesys
// This file is licensed under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//go:build linux && amd64 && cgo && rdma
package rcserver
import (
"errors"
"strings"
"testing"
"unsafe"
)
// heapSubstring returns a substring whose backing array is heap-allocated
// and whose data pointer is an interior pointer, mirroring how header
// strings reach the binding from the gateway routes.
func heapSubstring(value string) string {
const prefix = "prefix:"
backing := strings.Clone(prefix + value + ":suffix")
return backing[len(prefix) : len(prefix)+len(value)]
}
// TestPrepareHeapStringsReachCValidation calls the real Prepare wrapper
// with heap-backed strings. The request uses an invalid opcode so the C
// entrypoint returns RC_E_ARG from its argument validation before the
// server handle is dereferenced; the dummy handle below is never touched.
// Before the pinnedStrIn fix this call panics at the cgo pointer check;
// after it, the C argument validation runs and the error surfaces.
func TestPrepareHeapStringsReachCValidation(t *testing.T) {
const literalTarget = "/bucket1/obj1"
heapTarget := heapSubstring(literalTarget)
heapToken := heapSubstring(strings.Repeat("0", 88))
for _, tc := range []struct {
name, target, token string
}{
{"literal_control", literalTarget, ""},
{"heap_target", heapTarget, ""},
{"heap_token", literalTarget, heapToken},
{"both_heap", heapTarget, heapToken},
{"empty_control", "", ""},
} {
t.Run(tc.name, func(t *testing.T) {
var svc RCSvc
// Test-only opaque sentinel, not an initialized rc_server.
// Op=255 returns in C argument validation before the
// server pointer is dereferenced.
dummy := new(uint64)
*(*unsafe.Pointer)(unsafe.Pointer(&svc.srv)) = unsafe.Pointer(dummy)
resp, err := svc.Prepare(PrepareRequest{
Op: 255,
Size: 1,
Target: tc.target,
ClientToken: tc.token,
})
if resp != nil || !errors.Is(err, ErrArg) {
t.Fatalf("Prepare = (%v, %v), want (nil, ErrArg)", resp, err)
}
})
}
}