File tree Expand file tree Collapse file tree 2 files changed +26
-0
lines changed Expand file tree Collapse file tree 2 files changed +26
-0
lines changed Original file line number Diff line number Diff line change @@ -341,11 +341,14 @@ private struct IndexOutOfDateChecker {
341341
342342 private enum Error : Swift . Error , CustomStringConvertible {
343343 case fileAttributesDontHaveModificationDate
344+ case circularSymlink( URL )
344345
345346 var description : String {
346347 switch self {
347348 case . fileAttributesDontHaveModificationDate:
348349 return " File attributes don't contain a modification date "
350+ case . circularSymlink( let url) :
351+ return " Circular symlink at \( url) "
349352 }
350353 }
351354 }
@@ -484,6 +487,8 @@ private struct IndexOutOfDateChecker {
484487 }
485488 var modificationDate = try Self . modificationDate ( atPath: fileURL. filePath)
486489
490+ var visited : Set < URL > = [ fileURL]
491+
487492 // Get the maximum mtime in the symlink chain as the modification date of the URI. That way if either the symlink
488493 // is changed to point to a different file or if the underlying file is modified, the modification time is
489494 // updated.
@@ -492,6 +497,9 @@ private struct IndexOutOfDateChecker {
492497 ) ,
493498 let symlinkDestination = URL ( string: relativeSymlinkDestination, relativeTo: fileURL)
494499 {
500+ if !visited. insert ( symlinkDestination) . inserted {
501+ throw Error . circularSymlink ( symlinkDestination)
502+ }
495503 fileURL = symlinkDestination
496504 modificationDate = max ( modificationDate, try Self . modificationDate ( atPath: fileURL. filePath) )
497505 }
Original file line number Diff line number Diff line change @@ -2281,6 +2281,24 @@ final class BackgroundIndexingTests: XCTestCase {
22812281 try await project. testClient. send ( SynchronizeRequest ( index: true ) )
22822282 XCTAssertEqual ( indexedFiles. value, [ try project. uri ( for: " test.c " ) ] )
22832283 }
2284+
2285+ func testCircularSymlink( ) async throws {
2286+ let project = try await SwiftPMTestProject (
2287+ files: [
2288+ " Symlink.swift " : " "
2289+ ] ,
2290+ enableBackgroundIndexing: true
2291+ )
2292+ let circularSymlink = try XCTUnwrap ( project. uri ( for: " Symlink.swift " ) . fileURL)
2293+ try FileManager . default. removeItem ( at: circularSymlink)
2294+ try FileManager . default. createSymbolicLink ( at: circularSymlink, withDestinationURL: circularSymlink)
2295+
2296+ project. testClient. send (
2297+ DidChangeWatchedFilesNotification ( changes: [ FileEvent ( uri: URI ( circularSymlink) , type: . changed) ] )
2298+ )
2299+ // Check that we don't enter an infinite loop trying to index the circular symlink.
2300+ try await project. testClient. send ( SynchronizeRequest ( index: true ) )
2301+ }
22842302}
22852303
22862304extension HoverResponseContents {
You can’t perform that action at this time.
0 commit comments