4040import java .nio .file .AccessDeniedException ;
4141import java .nio .file .FileSystems ;
4242import java .nio .file .Files ;
43+ import java .nio .file .Paths ;
4344import java .util .ArrayList ;
4445import java .util .Enumeration ;
4546import java .util .List ;
@@ -971,6 +972,14 @@ private static void unpackEntries(TarArchiveInputStream tis,
971972 + " would create entry outside of " + outputDir );
972973 }
973974
975+ if (entry .isSymbolicLink () || entry .isLink ()) {
976+ String canonicalTargetPath = getCanonicalPath (entry .getLinkName (), outputDir );
977+ if (!canonicalTargetPath .startsWith (targetDirPath )) {
978+ throw new IOException (
979+ "expanding " + entry .getName () + " would create entry outside of " + outputDir );
980+ }
981+ }
982+
974983 if (entry .isDirectory ()) {
975984 File subDir = new File (outputDir , entry .getName ());
976985 if (!subDir .mkdirs () && !subDir .isDirectory ()) {
@@ -986,10 +995,12 @@ private static void unpackEntries(TarArchiveInputStream tis,
986995 }
987996
988997 if (entry .isSymbolicLink ()) {
989- // Create symbolic link relative to tar parent dir
990- Files .createSymbolicLink (FileSystems .getDefault ()
991- .getPath (outputDir .getPath (), entry .getName ()),
992- FileSystems .getDefault ().getPath (entry .getLinkName ()));
998+ // Create symlink with canonical target path to ensure that we don't extract
999+ // outside targetDirPath
1000+ String canonicalTargetPath = getCanonicalPath (entry .getLinkName (), outputDir );
1001+ Files .createSymbolicLink (
1002+ FileSystems .getDefault ().getPath (outputDir .getPath (), entry .getName ()),
1003+ FileSystems .getDefault ().getPath (canonicalTargetPath ));
9931004 return ;
9941005 }
9951006
@@ -1001,7 +1012,8 @@ private static void unpackEntries(TarArchiveInputStream tis,
10011012 }
10021013
10031014 if (entry .isLink ()) {
1004- File src = new File (outputDir , entry .getLinkName ());
1015+ String canonicalTargetPath = getCanonicalPath (entry .getLinkName (), outputDir );
1016+ File src = new File (canonicalTargetPath );
10051017 HardLink .createHardLink (src , outputFile );
10061018 return ;
10071019 }
@@ -1019,6 +1031,20 @@ private static void unpackEntries(TarArchiveInputStream tis,
10191031 }
10201032 }
10211033
1034+ /**
1035+ * Gets the canonical path for the given path.
1036+ *
1037+ * @param path The path for which the canonical path needs to be computed.
1038+ * @param parentDir The parent directory to use if the path is a relative path.
1039+ * @return The canonical path of the given path.
1040+ */
1041+ private static String getCanonicalPath (String path , File parentDir ) throws IOException {
1042+ java .nio .file .Path targetPath = Paths .get (path );
1043+ return (targetPath .isAbsolute () ?
1044+ new File (path ) :
1045+ new File (parentDir , path )).getCanonicalPath ();
1046+ }
1047+
10221048 /**
10231049 * Class for creating hardlinks.
10241050 * Supports Unix, WindXP.
0 commit comments