summaryrefslogtreecommitdiff
path: root/internal/generate
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-30 17:00:49 +0300
committerPaul Buetow <paul@buetow.org>2026-05-30 17:00:49 +0300
commitd071a75f44bc14dce364142483b072272c81313e (patch)
treed07851904ed25d04465a00115051ab16f3a5ebeb /internal/generate
parent2e018ccde462cd9083cfaf9e74c50cec19518815 (diff)
test(getcwd): lock in KindNull enter + exit-time cwd resolution
Audit of the getcwd(2) tracing path. getcwd's args[0] is a char *buf OUTPUT buffer: the kernel writes the absolute cwd path into it and the contents are only valid AFTER the syscall returns. Reading it at enter would capture an empty/garbage string, so getcwd is correctly KindNull at enter and the cwd is resolved at EXIT from /proc/<tid>/cwd when the return value is positive (handleNullExit). Family FS, docs and drift tests already aligned; no behavior change required. Add lock-in tests pinning the correct behavior: - generate: strengthen TestClassifyNullGetcwd to assert the enter kind is never KindPathname/KindName and no pathname field is captured; add TestClassifyByFieldGetcwdBufNotPath proving the generic field classifier never treats char *buf as a path (defense-in-depth). - eventloop: add GetcwdFailureEventTest asserting that a failed getcwd (negative errno, e.g. -ERANGE) attaches no cwd path, and document the output-buffer nuance in the success-case test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'internal/generate')
-rw-r--r--internal/generate/classify_test.go27
1 files changed, 27 insertions, 0 deletions
diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go
index 06cf1d7..4efdaee 100644
--- a/internal/generate/classify_test.go
+++ b/internal/generate/classify_test.go
@@ -214,11 +214,38 @@ func TestClassifyNullSyslog(t *testing.T) {
}
}
+// TestClassifyNullGetcwd pins getcwd as KindNull at enter.
+//
+// getcwd's args[0] is `char *buf`, an OUTPUT buffer: the kernel writes the
+// absolute cwd path into it and the contents only become valid AFTER the
+// syscall returns (sys_exit). Reading buf at enter would capture an empty or
+// garbage string, so getcwd must NOT be classified as a path-input syscall.
+// KindNull is the correct enter kind; the cwd is resolved at exit from
+// /proc/<tid>/cwd (see eventLoop.handleNullExit). This test locks that in:
+// - the enter kind is KindNull (not KindPathname/KindName), and
+// - no pathname field is captured from the buffer at enter.
func TestClassifyNullGetcwd(t *testing.T) {
r := classifyFromData(t, FormatGetcwd)
if r.Kind != KindNull {
t.Errorf("getcwd: got kind %d, want KindNull", r.Kind)
}
+ if r.Kind == KindPathname || r.Kind == KindName {
+ t.Errorf("getcwd: enter must not capture output buf as a path, got kind %d", r.Kind)
+ }
+ if r.PathnameField != "" {
+ t.Errorf("getcwd: no enter-time pathname field expected, got %q", r.PathnameField)
+ }
+}
+
+// TestClassifyByFieldGetcwdBufNotPath is a defense-in-depth lock-in: even if
+// the name-only KindNull override for getcwd were removed, the generic
+// field-based classifier must not treat `char *buf` as a pathname. Only the
+// field names pathname/path/filename/newname are path-like; "buf" is not, so
+// classifyByField must report no match for getcwd's output buffer.
+func TestClassifyByFieldGetcwdBufNotPath(t *testing.T) {
+ if r, ok := classifyByField("char *", "buf"); ok {
+ t.Errorf("getcwd buf: char *buf must not classify as a field kind, got %d", r.Kind)
+ }
}
func TestClassifyNullIoUring(t *testing.T) {