Skip to content

Commit 3617178

Browse files
aajisakaSean Mackrory
authored andcommitted
Additional check when unpacking archives. Contributed by Jason Lowe and Akira Ajisaka.
(cherry picked from commit bd98d4e) Change-Id: I47cb71c731ea815626c99e39e855a9dcad621db7
1 parent 2892558 commit 3617178

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -651,15 +651,20 @@ public static void unZip(InputStream inputStream, File toDir)
651651
public static void unZip(File inFile, File unzipDir) throws IOException {
652652
Enumeration<? extends ZipEntry> entries;
653653
ZipFile zipFile = new ZipFile(inFile);
654+
String targetDirPath = unzipDir.getCanonicalPath() + File.separator;
654655

655656
try {
656657
entries = zipFile.entries();
657658
while (entries.hasMoreElements()) {
658659
ZipEntry entry = entries.nextElement();
659660
if (!entry.isDirectory()) {
661+
File file = new File(unzipDir, entry.getName());
662+
if (!file.getCanonicalPath().startsWith(targetDirPath)) {
663+
throw new IOException("expanding " + entry.getName()
664+
+ " would create file outside of " + unzipDir);
665+
}
660666
InputStream in = zipFile.getInputStream(entry);
661667
try {
662-
File file = new File(unzipDir, entry.getName());
663668
if (!file.getParentFile().mkdirs()) {
664669
if (!file.getParentFile().isDirectory()) {
665670
throw new IOException("Mkdirs failed to create " +
@@ -942,6 +947,13 @@ private static void unTarUsingJava(InputStream inputStream, File untarDir,
942947

943948
private static void unpackEntries(TarArchiveInputStream tis,
944949
TarArchiveEntry entry, File outputDir) throws IOException {
950+
String targetDirPath = outputDir.getCanonicalPath() + File.separator;
951+
File outputFile = new File(outputDir, entry.getName());
952+
if (!outputFile.getCanonicalPath().startsWith(targetDirPath)) {
953+
throw new IOException("expanding " + entry.getName()
954+
+ " would create entry outside of " + outputDir);
955+
}
956+
945957
if (entry.isDirectory()) {
946958
File subDir = new File(outputDir, entry.getName());
947959
if (!subDir.mkdirs() && !subDir.isDirectory()) {
@@ -956,7 +968,6 @@ private static void unpackEntries(TarArchiveInputStream tis,
956968
return;
957969
}
958970

959-
File outputFile = new File(outputDir, entry.getName());
960971
if (!outputFile.getParentFile().exists()) {
961972
if (!outputFile.getParentFile().mkdirs()) {
962973
throw new IOException("Mkdirs failed to create tar internal dir "

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFileUtil.java

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.net.URISyntaxException;
3838
import java.net.URL;
3939
import java.net.UnknownHostException;
40+
import java.nio.charset.StandardCharsets;
4041
import java.util.ArrayList;
4142
import java.util.Arrays;
4243
import java.util.Collections;
@@ -679,10 +680,8 @@ public void testCreateLocalTempFile() throws IOException {
679680

680681
@Test (timeout = 30000)
681682
public void testUnZip() throws IOException {
682-
// make sa simple zip
683683
setupDirs();
684-
685-
// make a simple tar:
684+
// make a simple zip
686685
final File simpleZip = new File(del, FILE);
687686
OutputStream os = new FileOutputStream(simpleZip);
688687
ZipOutputStream tos = new ZipOutputStream(os);
@@ -699,7 +698,7 @@ public void testUnZip() throws IOException {
699698
tos.close();
700699
}
701700

702-
// successfully untar it into an existing dir:
701+
// successfully unzip it into an existing dir:
703702
FileUtil.unZip(simpleZip, tmp);
704703
// check result:
705704
assertTrue(new File(tmp, "foo").exists());
@@ -714,8 +713,36 @@ public void testUnZip() throws IOException {
714713
} catch (IOException ioe) {
715714
// okay
716715
}
717-
}
718-
716+
}
717+
718+
@Test (timeout = 30000)
719+
public void testUnZip2() throws IOException {
720+
setupDirs();
721+
// make a simple zip
722+
final File simpleZip = new File(del, FILE);
723+
OutputStream os = new FileOutputStream(simpleZip);
724+
try (ZipOutputStream tos = new ZipOutputStream(os)) {
725+
// Add an entry that contains invalid filename
726+
ZipEntry ze = new ZipEntry("../foo");
727+
byte[] data = "some-content".getBytes(StandardCharsets.UTF_8);
728+
ze.setSize(data.length);
729+
tos.putNextEntry(ze);
730+
tos.write(data);
731+
tos.closeEntry();
732+
tos.flush();
733+
tos.finish();
734+
}
735+
736+
// Unzip it into an existing dir
737+
try {
738+
FileUtil.unZip(simpleZip, tmp);
739+
Assert.fail("unZip should throw IOException.");
740+
} catch (IOException e) {
741+
GenericTestUtils.assertExceptionContains(
742+
"would create file outside of", e);
743+
}
744+
}
745+
719746
@Test (timeout = 30000)
720747
/*
721748
* Test method copy(FileSystem srcFS, Path src, File dst, boolean deleteSource, Configuration conf)

0 commit comments

Comments
 (0)