Skip to content

Commit

Permalink
Fix timestamp roundtripping issue (#36)
Browse files Browse the repository at this point in the history
* Fix timestamp roundtripping issue

* remove stray comment

---------

Co-authored-by: Oscar Boykin <oboykin@netflix.com>
  • Loading branch information
johnynek and Oscar Boykin authored Oct 3, 2023
1 parent 78c8c13 commit cf13301
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@

public class StandaloneJarProcessor
{
// this repairs the incorrect UTC on write, but Local on read
// timestamp. Apply this to a read timestamp before writing
// see: https://github.com/eed3si9n/jarjar-abrams/pull/37/files#r1344693775
public static long fixTimestamp(long ts) {
return ts - java.util.TimeZone.getDefault().getOffset(ts);
}

public static void run(File from, File to, JarProcessor proc, Boolean warnOnDuplicateClass) throws IOException {
byte[] buf = new byte[0x2000];

Expand All @@ -39,7 +46,11 @@ public static void run(File from, File to, JarProcessor proc, Boolean warnOnDupl
EntryStruct struct = new EntryStruct();
JarEntry entry = e.nextElement();
struct.name = entry.getName();
struct.time = entry.getTime();
// In the JDK, getTime converts the dos time in the zip
// into local time using a deprecated Date api that uses
// the default timezone, which often won't be UTC.
// but when setting, it assumes we are in UTC.
struct.time = fixTimestamp(entry.getTime());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IoUtil.pipe(in.getInputStream(entry), baos, buf);
struct.data = baos.toByteArray();
Expand Down
11 changes: 11 additions & 0 deletions src/test/java/com/github/johnynek/jarjar/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,14 @@ java_test(
"//src/main/java/com/github/johnynek/jarjar",
],
)

java_test(
name = "TimestampFixTest",
srcs = ["TimestampFixTest.java"],
test_class = "com.github.johnynek.jarjar.TimestampFixTest",
deps = [
"@bazel_jar_jar_asm//jar",
"@bazel_jar_jar_asm_commons//jar",
"//src/main/java/com/github/johnynek/jarjar",
],
)
35 changes: 35 additions & 0 deletions src/test/java/com/github/johnynek/jarjar/TimestampFixTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.github.johnynek.jarjar;

import java.util.jar.JarEntry;
import junit.framework.TestCase;
import org.junit.Test;
import com.github.johnynek.jarjar.util.StandaloneJarProcessor;
import java.util.jar.JarOutputStream;
import java.util.jar.JarInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;

public class TimestampFixTest extends TestCase {
@Test
public void testTimestampFix() throws java.io.IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
JarOutputStream out = new JarOutputStream(baos);
JarEntry je = new JarEntry("foo.txt");
// we can only have second resolution
long nowSeconds = System.currentTimeMillis() / 1000;
if ((nowSeconds & 1L) == 1L) {
// make sure we have an even timestamp
nowSeconds -= 1L;
}
long startTime = (nowSeconds * 1000);
je.setTime(startTime);
out.putNextEntry(je);
out.write(new byte[]{});
out.close();
JarInputStream in = new JarInputStream(new ByteArrayInputStream(baos.toByteArray()));
je = in.getNextJarEntry();
long readTime = StandaloneJarProcessor.fixTimestamp(je.getTime());
assertEquals(startTime, readTime);
}

}

0 comments on commit cf13301

Please sign in to comment.