Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions Sources/ContainerizationEXT4/EXT4Reader+IO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,6 @@ extension EXT4.EXT4Reader {
var parentStack: [EXT4.InodeNumber] = [] // Track parent chain for proper ".." handling

var symlinkHops = 0
var visitedInodes = Set<EXT4.InodeNumber>()

// Process components one at a time to handle symlinks in the middle of paths
var componentIndex = 0
Expand Down Expand Up @@ -330,12 +329,6 @@ extension EXT4.EXT4Reader {
// Check if child is a symlink
let childInode = try getInode(number: child.1)
if childInode.mode.isLink() && followSymlinks {
// Check for symlink loop
if visitedInodes.contains(child.1) {
throw EXT4.PathIOError.symlinkLoop(FilePath(components.joined(separator: "/")).description)
}
visitedInodes.insert(child.1)

// Enforce max symlink depth
symlinkHops += 1
if symlinkHops > maxSymlinks {
Expand Down
28 changes: 28 additions & 0 deletions Tests/ContainerizationEXT4Tests/TestEXT4Reader+IO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,34 @@ struct EXT4PathIOTests {
}
}

@Test
func sameAbsoluteSymlinkFollowedTwice() throws {
let url = try buildFS { fmt in
try self.createDir(fmt, "/target")
try self.createFile(fmt, "/target/file.txt", "OK")
try self.createSymlink(fmt, "/symlink", "/target")
}
defer { try? FileManager.default.removeItem(at: url) }

let r = try openReader(url)
let data = try r.readFile(at: FilePath("/symlink/../symlink/file.txt"))
#expect(String(decoding: data, as: UTF8.self) == "OK")
}

@Test
func sameRelativeSymlinkFollowedTwice() throws {
let url = try buildFS { fmt in
try self.createDir(fmt, "/target")
try self.createFile(fmt, "/target/file.txt", "OK")
try self.createSymlink(fmt, "/symlink", "../target")
}
defer { try? FileManager.default.removeItem(at: url) }

let r = try openReader(url)
let data = try r.readFile(at: FilePath("/symlink/../symlink/file.txt"))
#expect(String(decoding: data, as: UTF8.self) == "OK")
}

@Test
func boundsCheckingForInvalidExtents() throws {
// This test verifies that the reader properly validates extent addresses
Expand Down
Loading