Skip to content

Commit b2be8de

Browse files
authored
Remove the incorrect check for visited inodes (#659)
Removes the incorrect check for visited inodes. Fixes the added failing tests: > ✘ Test sameAbsoluteSymlinkFollowedTwice() recorded an issue at TestEXT4Reader+IO.swift:502:6: Caught error: symlink loop while resolving: target/../symlink/file.txt > ✘ Test sameAbsoluteSymlinkFollowedTwice() failed after 0.009 seconds with 1 issue. > ✘ Test sameRelativeSymlinkFollowedTwice() recorded an issue at TestEXT4Reader+IO.swift:516:6: Caught error: symlink loop while resolving: ../target/../symlink/file.txt > ✘ Test sameRelativeSymlinkFollowedTwice() failed after 0.010 seconds with 1 issue.
1 parent d8ec470 commit b2be8de

2 files changed

Lines changed: 28 additions & 7 deletions

File tree

Sources/ContainerizationEXT4/EXT4Reader+IO.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,6 @@ extension EXT4.EXT4Reader {
281281
var parentStack: [EXT4.InodeNumber] = [] // Track parent chain for proper ".." handling
282282

283283
var symlinkHops = 0
284-
var visitedInodes = Set<EXT4.InodeNumber>()
285284

286285
// Process components one at a time to handle symlinks in the middle of paths
287286
var componentIndex = 0
@@ -330,12 +329,6 @@ extension EXT4.EXT4Reader {
330329
// Check if child is a symlink
331330
let childInode = try getInode(number: child.1)
332331
if childInode.mode.isLink() && followSymlinks {
333-
// Check for symlink loop
334-
if visitedInodes.contains(child.1) {
335-
throw EXT4.PathIOError.symlinkLoop(FilePath(components.joined(separator: "/")).description)
336-
}
337-
visitedInodes.insert(child.1)
338-
339332
// Enforce max symlink depth
340333
symlinkHops += 1
341334
if symlinkHops > maxSymlinks {

Tests/ContainerizationEXT4Tests/TestEXT4Reader+IO.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,34 @@ struct EXT4PathIOTests {
499499
}
500500
}
501501

502+
@Test
503+
func sameAbsoluteSymlinkFollowedTwice() throws {
504+
let url = try buildFS { fmt in
505+
try self.createDir(fmt, "/target")
506+
try self.createFile(fmt, "/target/file.txt", "OK")
507+
try self.createSymlink(fmt, "/symlink", "/target")
508+
}
509+
defer { try? FileManager.default.removeItem(at: url) }
510+
511+
let r = try openReader(url)
512+
let data = try r.readFile(at: FilePath("/symlink/../symlink/file.txt"))
513+
#expect(String(decoding: data, as: UTF8.self) == "OK")
514+
}
515+
516+
@Test
517+
func sameRelativeSymlinkFollowedTwice() throws {
518+
let url = try buildFS { fmt in
519+
try self.createDir(fmt, "/target")
520+
try self.createFile(fmt, "/target/file.txt", "OK")
521+
try self.createSymlink(fmt, "/symlink", "../target")
522+
}
523+
defer { try? FileManager.default.removeItem(at: url) }
524+
525+
let r = try openReader(url)
526+
let data = try r.readFile(at: FilePath("/symlink/../symlink/file.txt"))
527+
#expect(String(decoding: data, as: UTF8.self) == "OK")
528+
}
529+
502530
@Test
503531
func boundsCheckingForInvalidExtents() throws {
504532
// This test verifies that the reader properly validates extent addresses

0 commit comments

Comments
 (0)