mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 17:50:12 +00:00
test(compat): harden fixture containment cleanup
Co-authored-by: naiba/CloudCode <hi+cloudcode@nai.ba>
This commit is contained in:
@@ -70,6 +70,11 @@ func (root AgentRoot) newPath(relative string, destructive bool) (AgentPath, err
|
|||||||
if err := ensureRealParentDirectories(root.absolute, nativeRelative); err != nil {
|
if err := ensureRealParentDirectories(root.absolute, nativeRelative); err != nil {
|
||||||
return AgentPath{}, err
|
return AgentPath{}, err
|
||||||
}
|
}
|
||||||
|
if info, err := os.Lstat(absolute); err == nil && info.Mode()&os.ModeSymlink != 0 {
|
||||||
|
return AgentPath{}, rejectPath(PathRejectionSymlinkFinal)
|
||||||
|
} else if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
|
return AgentPath{}, fmt.Errorf("inspect agent fixture path: %w", err)
|
||||||
|
}
|
||||||
return AgentPath{absolute: absolute, relative: nativeRelative}, nil
|
return AgentPath{absolute: absolute, relative: nativeRelative}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,41 @@ func TestFixture_AgentPathRejectsSymlinkParent(t *testing.T) {
|
|||||||
assertPathRejection(t, err, PathRejectionSymlinkParent)
|
assertPathRejection(t, err, PathRejectionSymlinkParent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFixture_AgentPathRejectsSymlinkTarget(t *testing.T) {
|
||||||
|
// Given
|
||||||
|
root := newTestAgentRoot(t, "agent-symlink-target")
|
||||||
|
outside := filepath.Join(t.TempDir(), "outside.txt")
|
||||||
|
requireNoFixtureError(t, os.WriteFile(outside, []byte("outside"), 0o600))
|
||||||
|
requireNoFixtureError(t, os.Symlink(outside, filepath.Join(root.Absolute(), "linked.txt")))
|
||||||
|
|
||||||
|
// When
|
||||||
|
_, err := root.Path("linked.txt")
|
||||||
|
|
||||||
|
// Then
|
||||||
|
assertPathRejection(t, err, PathRejectionSymlinkFinal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFixture_AgentPathRejectsExistingFinalSymlink(t *testing.T) {
|
||||||
|
// Given
|
||||||
|
root := newTestAgentRoot(t, "agent-final-symlink")
|
||||||
|
outside := filepath.Join(t.TempDir(), "outside.txt")
|
||||||
|
requireNoFixtureError(t, os.WriteFile(outside, []byte("unchanged"), 0o600))
|
||||||
|
requireNoFixtureError(t, os.Symlink(outside, filepath.Join(root.Absolute(), "linked.txt")))
|
||||||
|
|
||||||
|
// When
|
||||||
|
_, pathErr := root.Path("linked.txt")
|
||||||
|
_, destructiveErr := root.DestructivePath("linked.txt")
|
||||||
|
|
||||||
|
// Then
|
||||||
|
assertPathRejection(t, pathErr, PathRejectionSymlinkFinal)
|
||||||
|
assertPathRejection(t, destructiveErr, PathRejectionSymlinkFinal)
|
||||||
|
content, err := os.ReadFile(outside)
|
||||||
|
requireNoFixtureError(t, err)
|
||||||
|
if string(content) != "unchanged" {
|
||||||
|
t.Fatalf("final symlink target changed: %q", content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFixture_AgentPathRejectsCleanedEscape(t *testing.T) {
|
func TestFixture_AgentPathRejectsCleanedEscape(t *testing.T) {
|
||||||
// Given
|
// Given
|
||||||
root := newTestAgentRoot(t, "agent-cleaned-escape")
|
root := newTestAgentRoot(t, "agent-cleaned-escape")
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const (
|
|||||||
PathRejectionDestructiveRoot PathRejectionReason = "destructive_root"
|
PathRejectionDestructiveRoot PathRejectionReason = "destructive_root"
|
||||||
PathRejectionEscape PathRejectionReason = "escape"
|
PathRejectionEscape PathRejectionReason = "escape"
|
||||||
PathRejectionSymlinkParent PathRejectionReason = "symlink_parent"
|
PathRejectionSymlinkParent PathRejectionReason = "symlink_parent"
|
||||||
|
PathRejectionSymlinkFinal PathRejectionReason = "symlink_final"
|
||||||
PathRejectionADS PathRejectionReason = "ads"
|
PathRejectionADS PathRejectionReason = "ads"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -82,3 +82,53 @@ func TestFixture_NATEcho(t *testing.T) {
|
|||||||
t.Fatalf("NAT request record = %+v", record)
|
t.Fatalf("NAT request record = %+v", record)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFixture_NATEchoCloseInterruptsIncompleteRequest(t *testing.T) {
|
||||||
|
// Given
|
||||||
|
backend, err := StartNATEchoBackend()
|
||||||
|
requireNoFixtureError(t, err)
|
||||||
|
connection, err := net.DialTimeout("tcp", backend.Address(), time.Second)
|
||||||
|
requireNoFixtureError(t, err)
|
||||||
|
defer connection.Close()
|
||||||
|
_, err = io.WriteString(connection, "GET /incomplete HTTP/1.1\r\nHost: nat.invalid\r\n")
|
||||||
|
requireNoFixtureError(t, err)
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
|
defer cancel()
|
||||||
|
requireNoFixtureError(t, backend.WaitConnection(ctx))
|
||||||
|
|
||||||
|
// When
|
||||||
|
closed := make(chan error, 1)
|
||||||
|
go func() { closed <- backend.Close() }()
|
||||||
|
|
||||||
|
// Then
|
||||||
|
select {
|
||||||
|
case err := <-closed:
|
||||||
|
requireNoFixtureError(t, err)
|
||||||
|
case <-ctx.Done():
|
||||||
|
t.Fatal("NAT echo close did not interrupt incomplete request")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFixture_NATEchoCloseTerminatesSockets(t *testing.T) {
|
||||||
|
// Given
|
||||||
|
backend, err := StartNATHalfCloseEchoBackend()
|
||||||
|
requireNoFixtureError(t, err)
|
||||||
|
address := backend.Address()
|
||||||
|
connection, err := net.DialTimeout("tcp", address, time.Second)
|
||||||
|
requireNoFixtureError(t, err)
|
||||||
|
requireNoFixtureError(t, connection.SetDeadline(time.Now().Add(time.Second)))
|
||||||
|
|
||||||
|
// When
|
||||||
|
requireNoFixtureError(t, backend.Close())
|
||||||
|
|
||||||
|
// Then
|
||||||
|
buffer := make([]byte, 1)
|
||||||
|
if _, err := connection.Read(buffer); err == nil {
|
||||||
|
t.Fatal("active NAT socket remained readable after backend close")
|
||||||
|
}
|
||||||
|
requireNoFixtureError(t, connection.Close())
|
||||||
|
if connection, err := net.DialTimeout("tcp", address, 100*time.Millisecond); err == nil {
|
||||||
|
_ = connection.Close()
|
||||||
|
t.Fatal("NAT listener accepted a connection after backend close")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user