From abeb67964f52f245f7d529e4dfe01f8347932bfd Mon Sep 17 00:00:00 2001 From: Ophestra Date: Thu, 13 Nov 2025 07:08:07 +0900 Subject: [PATCH] treewide: document linkname uses These provide justification for each use of linkname. Poorly thought out uses of linkname are removed. Signed-off-by: Ophestra --- cmd/hakurei/command.go | 7 +++++-- cmd/hakurei/json_test.go | 12 ++---------- container/check/absolute_test.go | 4 +++- container/fhs/abs.go | 4 +++- container/stub/exit_test.go | 4 +++- hst/instance_test.go | 4 +++- internal/outcome/main.go | 2 ++ internal/store/data_test.go | 12 ++++++------ internal/store/segment_test.go | 23 ++++++++++++++--------- internal/store/store_test.go | 4 +++- 10 files changed, 44 insertions(+), 32 deletions(-) diff --git a/cmd/hakurei/command.go b/cmd/hakurei/command.go index e1f4c51..94fe7ea 100644 --- a/cmd/hakurei/command.go +++ b/cmd/hakurei/command.go @@ -11,7 +11,7 @@ import ( "strconv" "sync" "time" - _ "unsafe" + _ "unsafe" // for go:linkname "hakurei.app/command" "hakurei.app/container/check" @@ -24,8 +24,11 @@ import ( "hakurei.app/message" ) +// optionalErrorUnwrap calls [errors.Unwrap] and returns the resulting value +// if it is not nil, or the original value if it is. +// //go:linkname optionalErrorUnwrap hakurei.app/container.optionalErrorUnwrap -func optionalErrorUnwrap(_ error) error +func optionalErrorUnwrap(err error) error func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErrs, out io.Writer) command.Command { var ( diff --git a/cmd/hakurei/json_test.go b/cmd/hakurei/json_test.go index 5e5daf0..13e7e9f 100644 --- a/cmd/hakurei/json_test.go +++ b/cmd/hakurei/json_test.go @@ -1,18 +1,13 @@ -package main_test +package main import ( - "io" "reflect" "strings" "testing" - _ "unsafe" "hakurei.app/container/stub" ) -//go:linkname decodeJSON hakurei.app/cmd/hakurei.decodeJSON -func decodeJSON(fatal func(v ...any), op string, r io.Reader, v any) - func TestDecodeJSON(t *testing.T) { t.Parallel() @@ -62,9 +57,6 @@ func TestDecodeJSON(t *testing.T) { } } -//go:linkname encodeJSON hakurei.app/cmd/hakurei.encodeJSON -func encodeJSON(fatal func(v ...any), output io.Writer, short bool, v any) - func TestEncodeJSON(t *testing.T) { t.Parallel() @@ -74,7 +66,7 @@ func TestEncodeJSON(t *testing.T) { want string }{ {"marshaler", errorJSONMarshaler{}, - `cannot encode json for main_test.errorJSONMarshaler: unique error 3735928559 injected by the test suite`}, + `cannot encode json for main.errorJSONMarshaler: unique error 3735928559 injected by the test suite`}, {"default", func() {}, `cannot write json: json: unsupported type: func()`}, } diff --git a/container/check/absolute_test.go b/container/check/absolute_test.go index 466bbac..91cd3c9 100644 --- a/container/check/absolute_test.go +++ b/container/check/absolute_test.go @@ -14,8 +14,10 @@ import ( . "hakurei.app/container/check" ) +// unsafeAbs returns check.Absolute on any string value. +// //go:linkname unsafeAbs hakurei.app/container/check.unsafeAbs -func unsafeAbs(_ string) *Absolute +func unsafeAbs(pathname string) *Absolute func TestAbsoluteError(t *testing.T) { t.Parallel() diff --git a/container/fhs/abs.go b/container/fhs/abs.go index 6bb7216..9175c1f 100644 --- a/container/fhs/abs.go +++ b/container/fhs/abs.go @@ -8,8 +8,10 @@ import ( /* constants in this file bypass abs check, be extremely careful when changing them! */ +// unsafeAbs returns check.Absolute on any string value. +// //go:linkname unsafeAbs hakurei.app/container/check.unsafeAbs -func unsafeAbs(_ string) *check.Absolute +func unsafeAbs(pathname string) *check.Absolute var ( // AbsRoot is [Root] as [check.Absolute]. diff --git a/container/stub/exit_test.go b/container/stub/exit_test.go index e4c4f96..3e71c58 100644 --- a/container/stub/exit_test.go +++ b/container/stub/exit_test.go @@ -7,8 +7,10 @@ import ( "hakurei.app/container/stub" ) +// Made available here to check panic recovery behaviour. +// //go:linkname handleExitNew hakurei.app/container/stub.handleExitNew -func handleExitNew(_ testing.TB) +func handleExitNew(t testing.TB) // overrideTFailNow overrides the Fail and FailNow method. type overrideTFailNow struct { diff --git a/hst/instance_test.go b/hst/instance_test.go index 5be9fc8..290e7fb 100644 --- a/hst/instance_test.go +++ b/hst/instance_test.go @@ -6,11 +6,13 @@ import ( "reflect" "testing" "time" - _ "unsafe" + _ "unsafe" // for go:linkname "hakurei.app/hst" ) +// Made available here to check time encoding behaviour of [hst.ID]. +// //go:linkname newInstanceID hakurei.app/hst.newInstanceID func newInstanceID(id *hst.ID, p uint64) error diff --git a/internal/outcome/main.go b/internal/outcome/main.go index 1f02faf..8bf666b 100644 --- a/internal/outcome/main.go +++ b/internal/outcome/main.go @@ -12,6 +12,8 @@ import ( // IsPollDescriptor reports whether fd is the descriptor being used by the poller. // +// Made available here to determine and reject impossible fd. +// //go:linkname IsPollDescriptor internal/poll.IsPollDescriptor func IsPollDescriptor(fd uintptr) bool diff --git a/internal/store/data_test.go b/internal/store/data_test.go index 62fd3c9..fe0e212 100644 --- a/internal/store/data_test.go +++ b/internal/store/data_test.go @@ -27,7 +27,7 @@ func TestEntryData(t *testing.T) { return buf.String() } } - templateStateGob := mustEncodeGob(newTemplateState()) + templateStateGob := mustEncodeGob(NewTemplateState()) testCases := []struct { name string @@ -45,11 +45,11 @@ func TestEntryData(t *testing.T) { Step: "validate configuration", Err: hst.ErrConfigNull, Msg: "invalid configuration"}}, - {"inconsistent enablement", "\x00\xff\xca\xfe\x00\x00\xff\x00" + templateStateGob, newTemplateState(), &hst.AppError{ + {"inconsistent enablement", "\x00\xff\xca\xfe\x00\x00\xff\x00" + templateStateGob, NewTemplateState(), &hst.AppError{ Step: "validate state enablement", Err: os.ErrInvalid, Msg: "state entry aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa has unexpected enablement byte 0xd, 0xff"}}, - {"template", "\x00\xff\xca\xfe\x00\x00\x0d\xf2" + templateStateGob, newTemplateState(), nil}, + {"template", "\x00\xff\xca\xfe\x00\x00\x0d\xf2" + templateStateGob, NewTemplateState(), nil}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { @@ -105,7 +105,7 @@ func TestEntryData(t *testing.T) { t.Run("encode fault", func(t *testing.T) { t.Parallel() - s := newTemplateState() + s := NewTemplateState() t.Run("gob", func(t *testing.T) { var want = &hst.AppError{Step: "encode state body", Err: stub.UniqueError(0xcafe)} @@ -123,8 +123,8 @@ func TestEntryData(t *testing.T) { }) } -// newTemplateState returns the address of a new template [hst.State] struct. -func newTemplateState() *hst.State { +// NewTemplateState returns the address of a new template [hst.State] struct. +func NewTemplateState() *hst.State { return &hst.State{ ID: hst.ID(bytes.Repeat([]byte{0xaa}, len(hst.ID{}))), PID: 0xcafe, diff --git a/internal/store/segment_test.go b/internal/store/segment_test.go index 8d4d7f3..6791545 100644 --- a/internal/store/segment_test.go +++ b/internal/store/segment_test.go @@ -10,7 +10,7 @@ import ( "strings" "syscall" "testing" - _ "unsafe" + _ "unsafe" // for go:linkname "hakurei.app/container/check" "hakurei.app/container/stub" @@ -18,18 +18,23 @@ import ( "hakurei.app/internal/store" ) -//go:linkname newTemplateState hakurei.app/internal/store.newTemplateState -func newTemplateState() *hst.State - +// Made available here for direct validation of state entry files. +// //go:linkname entryDecode hakurei.app/internal/store.entryDecode func entryDecode(r io.Reader, p *hst.State) (hst.Enablement, error) +// Made available here for direct access to known segment handles. +// //go:linkname newHandle hakurei.app/internal/store.newHandle func newHandle(base *check.Absolute, identity int) *store.Handle +// Made available here to check open error handling behaviour. +// //go:linkname open hakurei.app/internal/store.(*EntryHandle).open func open(eh *store.EntryHandle, flag int, perm os.FileMode) (*os.File, error) +// Made available here to check the saveload cycle. +// //go:linkname save hakurei.app/internal/store.(*EntryHandle).save func save(eh *store.EntryHandle, state *hst.State) error @@ -91,9 +96,9 @@ func TestStateEntryHandle(t *testing.T) { t.Run("saveload", func(t *testing.T) { t.Parallel() eh := store.EntryHandle{Pathname: check.MustAbs(t.TempDir()).Append("entry"), - ID: newTemplateState().ID} + ID: store.NewTemplateState().ID} - if err := save(&eh, newTemplateState()); err != nil { + if err := save(&eh, store.NewTemplateState()); err != nil { t.Fatalf("save: error = %v", err) } @@ -112,7 +117,7 @@ func TestStateEntryHandle(t *testing.T) { t.Fatal(f.Close()) } - if want := newTemplateState(); !reflect.DeepEqual(&got, want) { + if want := store.NewTemplateState(); !reflect.DeepEqual(&got, want) { t.Errorf("entryDecode: %#v, want %#v", &got, want) } }) @@ -122,7 +127,7 @@ func TestStateEntryHandle(t *testing.T) { if et, err := eh.Load(nil); err != nil { t.Fatalf("load: error = %v", err) - } else if want := newTemplateState().Enablements.Unwrap(); et != want { + } else if want := store.NewTemplateState().Enablements.Unwrap(); et != want { t.Errorf("load: et = %x, want %x", et, want) } }) @@ -133,7 +138,7 @@ func TestStateEntryHandle(t *testing.T) { var got hst.State if _, err := eh.Load(&got); err != nil { t.Fatalf("load: error = %v", err) - } else if want := newTemplateState(); !reflect.DeepEqual(&got, want) { + } else if want := store.NewTemplateState(); !reflect.DeepEqual(&got, want) { t.Errorf("load: %#v, want %#v", &got, want) } }) diff --git a/internal/store/store_test.go b/internal/store/store_test.go index 54f28bd..9abf480 100644 --- a/internal/store/store_test.go +++ b/internal/store/store_test.go @@ -12,13 +12,15 @@ import ( "syscall" "testing" "time" - _ "unsafe" + _ "unsafe" // for go:linkname "hakurei.app/container/check" "hakurei.app/hst" "hakurei.app/internal/store" ) +// Made available here to check bigLock error handling behaviour. +// //go:linkname bigLock hakurei.app/internal/store.(*Store).bigLock func bigLock(s *store.Store) (unlock func(), err error)