< prev index next >

src/java.base/share/classes/java/util/jar/Attributes.java

Print this page
rev 51096 : 8205525: Improve exception messages during manifest parsing of jar archives

*** 24,34 **** --- 24,38 ---- */ package java.util.jar; import java.io.DataOutputStream; + import java.io.File; import java.io.IOException; + import java.security.AccessController; + import java.security.PrivilegedAction; + import java.security.Security; import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects;
*** 59,68 **** --- 63,105 ---- * The attribute name-value mappings. */ protected Map<Object,Object> map; /** + * Security or system property which specifies categories of + * (potentially sensitive) information that may be included + * in exception text. This class only defines one category: + * "jarpath" which represents the path of a jar file + * relating to an IO exception. + * The property value is a comma separated list of + * case insignificant category names. + */ + private static final String enhancedTextPropname = "jdk.includeInExceptions"; + + private static final boolean jarPathInExceptionText = initTextProp(); + + private static boolean initTextProp() { + return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { + public Boolean run() { + String val = System.getProperty(enhancedTextPropname); + if (val == null) { + val = Security.getProperty(enhancedTextPropname); + if (val == null) + return false; + } + String[] tokens = val.split(","); + for (String token : tokens) { + if (token.equalsIgnoreCase("jarpath")) + return true; + } + return false; + } + }); + } + + + /** * Constructs a new, empty Attributes object with default size. */ public Attributes() { this(11); }
*** 367,387 **** /* * Reads attributes from the specified input stream. * XXX Need to handle UTF8 values. */ - @SuppressWarnings("deprecation") void read(Manifest.FastInputStream is, byte[] lbuf) throws IOException { String name = null, value; byte[] lastline = null; int len; while ((len = is.readLine(lbuf)) != -1) { boolean lineContinued = false; byte c = lbuf[--len]; if (c != '\n' && c != '\r') { ! throw new IOException("line too long"); } if (len > 0 && lbuf[len-1] == '\r') { --len; } if (len == 0) { --- 404,431 ---- /* * Reads attributes from the specified input stream. * XXX Need to handle UTF8 values. */ void read(Manifest.FastInputStream is, byte[] lbuf) throws IOException { + read(is, lbuf, null, 0); + } + + @SuppressWarnings("deprecation") + int read(Manifest.FastInputStream is, byte[] lbuf, String filename, int offset) throws IOException { String name = null, value; byte[] lastline = null; + int lineNumber = offset; int len; while ((len = is.readLine(lbuf)) != -1) { boolean lineContinued = false; byte c = lbuf[--len]; + lineNumber++; + if (c != '\n' && c != '\r') { ! throw new IOException("line too long (" + getErrorPosition(filename, lineNumber) + ")"); } if (len > 0 && lbuf[len-1] == '\r') { --len; } if (len == 0) {
*** 389,399 **** } int i = 0; if (lbuf[0] == ' ') { // continuation of previous line if (name == null) { ! throw new IOException("misplaced continuation line"); } lineContinued = true; byte[] buf = new byte[lastline.length + len - 1]; System.arraycopy(lastline, 0, buf, 0, lastline.length); System.arraycopy(lbuf, 1, buf, lastline.length, len - 1); --- 433,443 ---- } int i = 0; if (lbuf[0] == ' ') { // continuation of previous line if (name == null) { ! throw new IOException("misplaced continuation line (" + getErrorPosition(filename, lineNumber) + ")"); } lineContinued = true; byte[] buf = new byte[lastline.length + len - 1]; System.arraycopy(lastline, 0, buf, 0, lastline.length); System.arraycopy(lbuf, 1, buf, lastline.length, len - 1);
*** 404,418 **** value = new String(buf, 0, buf.length, "UTF8"); lastline = null; } else { while (lbuf[i++] != ':') { if (i >= len) { ! throw new IOException("invalid header field"); } } if (lbuf[i++] != ' ') { ! throw new IOException("invalid header field"); } name = new String(lbuf, 0, 0, i - 2); if (is.peek() == ' ') { lastline = new byte[len - i]; System.arraycopy(lbuf, i, lastline, 0, len - i); --- 448,462 ---- value = new String(buf, 0, buf.length, "UTF8"); lastline = null; } else { while (lbuf[i++] != ':') { if (i >= len) { ! throw new IOException("invalid header field (" + getErrorPosition(filename, lineNumber) + ")"); } } if (lbuf[i++] != ' ') { ! throw new IOException("invalid header field (" + getErrorPosition(filename, lineNumber) + ")"); } name = new String(lbuf, 0, 0, i - 2); if (is.peek() == ' ') { lastline = new byte[len - i]; System.arraycopy(lbuf, i, lastline, 0, len - i);
*** 431,443 **** + "individual sections in both your\n" + "manifest and in the META-INF/MANIFEST.MF " + "entry in the jar file."); } } catch (IllegalArgumentException e) { ! throw new IOException("invalid header field name: " + name); } } } /** * The Attributes.Name class represents an attribute name stored in * this Map. Valid attribute names are case-insensitive, are restricted --- 475,501 ---- + "individual sections in both your\n" + "manifest and in the META-INF/MANIFEST.MF " + "entry in the jar file."); } } catch (IllegalArgumentException e) { ! throw new IOException("invalid header field name: " + name + " (" + getErrorPosition(filename, lineNumber) + ")"); ! } } + return lineNumber; + } + + static String getErrorPosition(String filename, final int lineNumber) { + if (filename == null || !jarPathInExceptionText) { + return "line " + lineNumber; + } + + final File file = new File(filename); + return AccessController.doPrivileged(new PrivilegedAction<String>() { + public String run() { + return file.getAbsolutePath() + ":" + lineNumber; } + }); } /** * The Attributes.Name class represents an attribute name stored in * this Map. Valid attribute names are case-insensitive, are restricted
< prev index next >