Skip to content

Commit

Permalink
Avoid illegal reflective access on ZipEntry.xdostime
Browse files Browse the repository at this point in the history
  • Loading branch information
dreis2211 committed Jun 25, 2021
1 parent 5e6bed2 commit faa0002
Showing 1 changed file with 34 additions and 12 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,6 +28,7 @@
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.util.ArrayList;
Expand All @@ -53,7 +54,6 @@

import org.springframework.boot.loader.TestJarCreator;
import org.springframework.boot.loader.data.RandomAccessDataFile;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StopWatch;
import org.springframework.util.StreamUtils;
Expand Down Expand Up @@ -621,23 +621,45 @@ private byte[] zip64Jar() throws IOException {

@Test
void jarFileEntryWithEpochTimeOfZeroShouldNotFail() throws Exception {
File file = new File(this.tempDir, "timed.jar");
FileOutputStream fileOutputStream = new FileOutputStream(file);
File file = createJarFileWithEpochTimeOfZero();
try (JarFile jar = new JarFile(file)) {
Enumeration<java.util.jar.JarEntry> entries = jar.entries();
JarEntry entry = entries.nextElement();
assertThat(entry.getLastModifiedTime().toInstant()).isEqualTo(Instant.EPOCH);
assertThat(entry.getName()).isEqualTo("1.dat");
}
}

private File createJarFileWithEpochTimeOfZero() throws Exception {
File jarFile = new File(this.tempDir, "temp.jar");
FileOutputStream fileOutputStream = new FileOutputStream(jarFile);
String comment = "outer";
try (JarOutputStream jarOutputStream = new JarOutputStream(fileOutputStream)) {
jarOutputStream.setComment("outer");
jarOutputStream.setComment(comment);
JarEntry entry = new JarEntry("1.dat");
entry.setLastModifiedTime(FileTime.from(Instant.EPOCH));
ReflectionTestUtils.setField(entry, "xdostime", 0);
jarOutputStream.putNextEntry(entry);
jarOutputStream.write(new byte[] { (byte) 1 });
jarOutputStream.closeEntry();
}
try (JarFile jar = new JarFile(file)) {
Enumeration<java.util.jar.JarEntry> entries = jar.entries();
JarEntry entry = entries.nextElement();
assertThat(entry.getLastModifiedTime().toInstant()).isEqualTo(Instant.EPOCH);
assertThat(entry.getName()).isEqualTo("1.dat");
}

byte[] data = Files.readAllBytes(jarFile.toPath());
int headerPosition = data.length - ZipFile.ENDHDR - comment.getBytes().length;
int centralHeaderPosition = (int) Bytes.littleEndianValue(data, headerPosition + ZipFile.ENDOFF, 1);
int localHeaderPosition = (int) Bytes.littleEndianValue(data, centralHeaderPosition + ZipFile.CENOFF, 1);
writeTimeBlock(data, centralHeaderPosition + ZipFile.CENTIM, 0);
writeTimeBlock(data, localHeaderPosition + ZipFile.LOCTIM, 0);

File jar = new File(this.tempDir, "zerotimed.jar");
Files.write(jar.toPath(), data);
return jar;
}

private static void writeTimeBlock(byte[] data, int pos, int value) {
data[pos] = (byte) (value & 0xff);
data[pos + 1] = (byte) ((value >> 8) & 0xff);
data[pos + 2] = (byte) ((value >> 16) & 0xff);
data[pos + 3] = (byte) ((value >> 24) & 0xff);
}

@Test
Expand Down

0 comments on commit faa0002

Please sign in to comment.