Additional check when unpacking archives. Contributed by Wilfred Spiegelenburg.
This commit is contained in:
parent
9502b47bd2
commit
e3236a9680
|
@ -117,12 +117,17 @@ public class RunJar {
|
||||||
throws IOException {
|
throws IOException {
|
||||||
try (JarInputStream jar = new JarInputStream(inputStream)) {
|
try (JarInputStream jar = new JarInputStream(inputStream)) {
|
||||||
int numOfFailedLastModifiedSet = 0;
|
int numOfFailedLastModifiedSet = 0;
|
||||||
|
String targetDirPath = toDir.getCanonicalPath() + File.separator;
|
||||||
for (JarEntry entry = jar.getNextJarEntry();
|
for (JarEntry entry = jar.getNextJarEntry();
|
||||||
entry != null;
|
entry != null;
|
||||||
entry = jar.getNextJarEntry()) {
|
entry = jar.getNextJarEntry()) {
|
||||||
if (!entry.isDirectory() &&
|
if (!entry.isDirectory() &&
|
||||||
unpackRegex.matcher(entry.getName()).matches()) {
|
unpackRegex.matcher(entry.getName()).matches()) {
|
||||||
File file = new File(toDir, entry.getName());
|
File file = new File(toDir, entry.getName());
|
||||||
|
if (!file.getCanonicalPath().startsWith(targetDirPath)) {
|
||||||
|
throw new IOException("expanding " + entry.getName()
|
||||||
|
+ " would create file outside of " + toDir);
|
||||||
|
}
|
||||||
ensureDirectory(file.getParentFile());
|
ensureDirectory(file.getParentFile());
|
||||||
try (OutputStream out = new FileOutputStream(file)) {
|
try (OutputStream out = new FileOutputStream(file)) {
|
||||||
IOUtils.copyBytes(jar, out, BUFFER_SIZE);
|
IOUtils.copyBytes(jar, out, BUFFER_SIZE);
|
||||||
|
@ -182,6 +187,7 @@ public class RunJar {
|
||||||
throws IOException {
|
throws IOException {
|
||||||
try (JarFile jar = new JarFile(jarFile)) {
|
try (JarFile jar = new JarFile(jarFile)) {
|
||||||
int numOfFailedLastModifiedSet = 0;
|
int numOfFailedLastModifiedSet = 0;
|
||||||
|
String targetDirPath = toDir.getCanonicalPath() + File.separator;
|
||||||
Enumeration<JarEntry> entries = jar.entries();
|
Enumeration<JarEntry> entries = jar.entries();
|
||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements()) {
|
||||||
final JarEntry entry = entries.nextElement();
|
final JarEntry entry = entries.nextElement();
|
||||||
|
@ -189,6 +195,10 @@ public class RunJar {
|
||||||
unpackRegex.matcher(entry.getName()).matches()) {
|
unpackRegex.matcher(entry.getName()).matches()) {
|
||||||
try (InputStream in = jar.getInputStream(entry)) {
|
try (InputStream in = jar.getInputStream(entry)) {
|
||||||
File file = new File(toDir, entry.getName());
|
File file = new File(toDir, entry.getName());
|
||||||
|
if (!file.getCanonicalPath().startsWith(targetDirPath)) {
|
||||||
|
throw new IOException("expanding " + entry.getName()
|
||||||
|
+ " would create file outside of " + toDir);
|
||||||
|
}
|
||||||
ensureDirectory(file.getParentFile());
|
ensureDirectory(file.getParentFile());
|
||||||
try (OutputStream out = new FileOutputStream(file)) {
|
try (OutputStream out = new FileOutputStream(file)) {
|
||||||
IOUtils.copyBytes(in, out, BUFFER_SIZE);
|
IOUtils.copyBytes(in, out, BUFFER_SIZE);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import static org.apache.hadoop.util.RunJar.MATCH_ANY;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
|
@ -32,6 +33,7 @@ import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarOutputStream;
|
import java.util.jar.JarOutputStream;
|
||||||
|
@ -255,4 +257,44 @@ public class TestRunJar {
|
||||||
// it should not throw an exception
|
// it should not throw an exception
|
||||||
verify(runJar, times(0)).unJar(any(File.class), any(File.class));
|
verify(runJar, times(0)).unJar(any(File.class), any(File.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnJar2() throws IOException {
|
||||||
|
// make a simple zip
|
||||||
|
File jarFile = new File(TEST_ROOT_DIR, TEST_JAR_NAME);
|
||||||
|
JarOutputStream jstream =
|
||||||
|
new JarOutputStream(new FileOutputStream(jarFile));
|
||||||
|
JarEntry je = new JarEntry("META-INF/MANIFEST.MF");
|
||||||
|
byte[] data = "Manifest-Version: 1.0\nCreated-By: 1.8.0_1 (Manual)"
|
||||||
|
.getBytes(StandardCharsets.UTF_8);
|
||||||
|
je.setSize(data.length);
|
||||||
|
jstream.putNextEntry(je);
|
||||||
|
jstream.write(data);
|
||||||
|
jstream.closeEntry();
|
||||||
|
je = new JarEntry("../outside.path");
|
||||||
|
data = "any data here".getBytes(StandardCharsets.UTF_8);
|
||||||
|
je.setSize(data.length);
|
||||||
|
jstream.putNextEntry(je);
|
||||||
|
jstream.write(data);
|
||||||
|
jstream.closeEntry();
|
||||||
|
jstream.close();
|
||||||
|
|
||||||
|
File unjarDir = getUnjarDir("unjar-path");
|
||||||
|
|
||||||
|
// Unjar everything
|
||||||
|
try {
|
||||||
|
RunJar.unJar(jarFile, unjarDir, MATCH_ANY);
|
||||||
|
fail("unJar should throw IOException.");
|
||||||
|
} catch (IOException e) {
|
||||||
|
GenericTestUtils.assertExceptionContains(
|
||||||
|
"would create file outside of", e);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
RunJar.unJar(new FileInputStream(jarFile), unjarDir, MATCH_ANY);
|
||||||
|
fail("unJar should throw IOException.");
|
||||||
|
} catch (IOException e) {
|
||||||
|
GenericTestUtils.assertExceptionContains(
|
||||||
|
"would create file outside of", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue