--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Mon Jan 19 20:02:31 2015 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java Wed Jan 28 12:36:25 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -74,8 +74,9 @@
* Mflag: DO NOT generate a manifest file (just ZIP)
* iflag: generate jar index
* nflag: Perform jar normalization at the end
+ * pflag: preserve/don't strip leading slash and .. component from file name
*/
- boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag;
+ boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag;
static final String MANIFEST_DIR = "META-INF/";
static final String VERSION = "1.0";
@@ -187,6 +188,7 @@
addMainClass(manifest, ename);
}
}
+ expand(null, files, false);
OutputStream out;
if (fname != null) {
out = new FileOutputStream(fname);
@@ -208,7 +210,6 @@
tmpfile = createTemporaryFile(tmpbase, ".jar");
out = new FileOutputStream(tmpfile);
}
- expand(null, files, false);
create(new BufferedOutputStream(out, 4096), manifest);
if (in != null) {
in.close();
@@ -424,6 +425,9 @@
case 'e':
ename = args[count++];
break;
+ case 'P':
+ pflag = true;
+ break;
default:
error(formatMsg("error.illegal.option",
String.valueOf(flags.charAt(i))));
@@ -713,6 +717,47 @@
return true;
}
+ private static final boolean isWinDriveLetter(char c) {
+ return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
+ }
+
+ private String safeName(String name) {
+ if (!pflag) {
+ int len = name.length();
+ int i = name.lastIndexOf("../");
+ if (i == -1) {
+ i = 0;
+ } else {
+ i += 3; // strip any dot-dot components
+ }
+ if (File.separatorChar == '\\') {
+ // the spec requests no drive letter. skip if
+ // the entry name has one.
+ while (i < len) {
+ int off = i;
+ if (i + 1 < len &&
+ name.charAt(i + 1) == ':' &&
+ isWinDriveLetter(name.charAt(i))) {
+ i += 2;
+ }
+ while (i < len && name.charAt(i) == '/') {
+ i++;
+ }
+ if (i == off) {
+ break;
+ }
+ }
+ } else {
+ while (i < len && name.charAt(i) == '/') {
+ i++;
+ }
+ }
+ if (i != 0) {
+ name = name.substring(i);
+ }
+ }
+ return name;
+ }
private String entryName(String name) {
name = name.replace(File.separatorChar, '/');
@@ -723,11 +768,10 @@
matchPath = path;
}
}
- name = name.substring(matchPath.length());
-
- if (name.startsWith("/")) {
- name = name.substring(1);
- } else if (name.startsWith("./")) {
+ name = safeName(name.substring(matchPath.length()));
+ // the old implementaton doesn't remove
+ // "./" if it was led by "/" (?)
+ if (name.startsWith("./")) {
name = name.substring(2);
}
return name;
@@ -927,8 +971,11 @@
for (ZipEntry ze : zes) {
long lastModified = ze.getTime();
if (lastModified != -1) {
- File f = new File(ze.getName().replace('/', File.separatorChar));
- f.setLastModified(lastModified);
+ String name = safeName(ze.getName().replace(File.separatorChar, '/'));
+ if (name.length() != 0) {
+ File f = new File(name.replace('/', File.separatorChar));
+ f.setLastModified(lastModified);
+ }
}
}
}
@@ -1002,8 +1049,16 @@
*/
ZipEntry extractFile(InputStream is, ZipEntry e) throws IOException {
ZipEntry rc = null;
- String name = e.getName();
- File f = new File(e.getName().replace('/', File.separatorChar));
+ // The spec requres all slashes MUST be forward '/', it is possible
+ // an offending zip/jar entry may uses the backwards slash in its
+ // name. It might cause problem on Windows platform as it skips
+ // our "safe" check for leading slahs and dot-dot. So replace them
+ // with '/'.
+ String name = safeName(e.getName().replace(File.separatorChar, '/'));
+ if (name.length() == 0) {
+ return rc; // leading '/' or 'dot-dot' only path
+ }
+ File f = new File(name.replace('/', File.separatorChar));
if (e.isDirectory()) {
if (f.exists()) {
if (!f.isDirectory()) {
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Mon Jan 19 20:02:31 2015 +0300
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Wed Jan 28 12:36:25 2015 -0800
@@ -68,7 +68,7 @@
(in = {0}) (out= {1})
usage=\
-Usage: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\
+Usage: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\
Options:\n\
\ \ -c create new archive\n\
\ \ -t list table of contents for archive\n\
@@ -81,6 +81,7 @@
\ \ -e specify application entry point for stand-alone application \n\
\ \ bundled into an executable jar file\n\
\ \ -0 store only; use no ZIP compression\n\
+\ \ -P preserve leading '/' (absolute path) and ".." (parent directory) components from file names\n\
\ \ -M do not create a manifest file for the entries\n\
\ \ -i generate index information for the specified jar files\n\
\ \ -C change to the specified directory and include the following file\n\