@@ -138,22 +138,65 @@ public async Task ExtractEntry_PodmanImageTarWithRelativeSymlinksPointingInExtra
138138 [ InlineData ( TarEntryType . HardLink ) ]
139139 public async Task Extract_LinkEntry_TargetOutsideDirectory_Async ( TarEntryType entryType )
140140 {
141+ using TempDirectory tempDirectory = new ( ) ;
142+ string symlinkName = tempDirectory . GenerateRandomFilePath ( ) ;
143+ await File . WriteAllTextAsync ( symlinkName , new string ( 'x' , 100 ) ) ;
144+
141145 await using ( MemoryStream archive = new MemoryStream ( ) )
142146 {
143147 await using ( TarWriter writer = new TarWriter ( archive , TarEntryFormat . Ustar , leaveOpen : true ) )
144148 {
145149 UstarTarEntry entry = new UstarTarEntry ( entryType , "link" ) ;
146- entry . LinkName = PlatformDetection . IsWindows ? @"C:\Windows\System32\notepad.exe" : "/usr/bin/nano" ;
150+ entry . LinkName = symlinkName ;
147151 await writer . WriteEntryAsync ( entry ) ;
148152 }
149153
150154 archive . Seek ( 0 , SeekOrigin . Begin ) ;
151155
152- using ( TempDirectory root = new TempDirectory ( ) )
156+ using TempDirectory root = new TempDirectory ( ) ;
157+
158+ Exception exception = await Record . ExceptionAsync ( ( ) => TarFile . ExtractToDirectoryAsync ( archive , root . Path , overwriteFiles : true ) ) ;
159+ Assert . Null ( exception ) ;
160+
161+ string symlinkPath = Path . Join ( root . Path , "link" ) ;
162+ Assert . True ( File . Exists ( symlinkPath ) ) ;
163+
164+ if ( entryType is TarEntryType . SymbolicLink )
165+ {
166+ FileInfo ? fileInfo = new ( symlinkPath ) ;
167+ Assert . Equal ( symlinkName , fileInfo . LinkTarget ) ;
168+ }
169+ }
170+ }
171+
172+ [ Theory ]
173+ [ InlineData ( "foo" ) ]
174+ [ InlineData ( "../../foo" ) ]
175+ [ InlineData ( "/usr/tmp/foo" ) ]
176+ [ InlineData ( @"C:\tmp\foo" ) ]
177+ public async Task Extract_SymbolicLinkEntryWithExistingOrNonExistingPaths_TargetOutsideDirectoryPreservesOriginalPaths_Async ( string symlinkName )
178+ {
179+ await using ( MemoryStream archive = new ( ) )
180+ {
181+ await using ( TarWriter writer = new ( archive , TarEntryFormat . Ustar , leaveOpen : true ) )
153182 {
154- await Assert . ThrowsAsync < IOException > ( ( ) => TarFile . ExtractToDirectoryAsync ( archive , root . Path , overwriteFiles : false ) ) ;
155- Assert . Equal ( 0 , Directory . GetFileSystemEntries ( root . Path ) . Count ( ) ) ;
183+ UstarTarEntry entry = new UstarTarEntry ( TarEntryType . SymbolicLink , "link" ) ;
184+ entry . LinkName = symlinkName ;
185+ await writer . WriteEntryAsync ( entry ) ;
156186 }
187+
188+ archive . Seek ( 0 , SeekOrigin . Begin ) ;
189+
190+ using TempDirectory root = new TempDirectory ( ) ;
191+
192+ Exception exception = await Record . ExceptionAsync ( ( ) => TarFile . ExtractToDirectoryAsync ( archive , root . Path , overwriteFiles : true ) ) ;
193+ Assert . Null ( exception ) ;
194+
195+ string symlinkPath = Path . Join ( root . Path , "link" ) ;
196+ Assert . True ( File . Exists ( symlinkPath ) ) ;
197+
198+ FileInfo ? fileInfo = new ( symlinkPath ) ;
199+ Assert . Equal ( symlinkName , fileInfo . LinkTarget ) ;
157200 }
158201 }
159202
0 commit comments