< prev index next >

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

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

@@ -24,18 +24,24 @@
  */
 
 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;
 import java.util.Set;
 
+import sun.security.util.SecurityProperties;
+
 import sun.util.logging.PlatformLogger;
 
 /**
  * The Attributes class maps Manifest attribute names to associated string
  * values. Valid attribute names are case-insensitive, are restricted to

@@ -58,10 +64,13 @@
     /**
      * The attribute name-value mappings.
      */
     protected Map<Object,Object> map;
 
+    private static final boolean jarPathInExceptionText = 
+                 SecurityProperties.includedInExceptions("jarPath"); 
+
     /**
      * Constructs a new, empty Attributes object with default size.
      */
     public Attributes() {
         this(11);

@@ -367,21 +376,29 @@
 
     /*
      * Reads attributes from the specified input stream.
      * XXX Need to handle UTF8 values.
      */
-    @SuppressWarnings("deprecation")
     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");
+                throw new IOException("line too long ("
+                            + getErrorPosition(filename, lineNumber) + ")");
             }
             if (len > 0 && lbuf[len-1] == '\r') {
                 --len;
             }
             if (len == 0) {

@@ -389,11 +406,12 @@
             }
             int i = 0;
             if (lbuf[0] == ' ') {
                 // continuation of previous line
                 if (name == null) {
-                    throw new IOException("misplaced continuation line");
+                    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,15 +422,17 @@
                 value = new String(buf, 0, buf.length, "UTF8");
                 lastline = null;
             } else {
                 while (lbuf[i++] != ':') {
                     if (i >= len) {
-                        throw new IOException("invalid header field");
+                        throw new IOException("invalid header field ("
+                                    + getErrorPosition(filename, lineNumber) + ")");
                     }
                 }
                 if (lbuf[i++] != ' ') {
-                    throw new IOException("invalid header field");
+                    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,13 +451,28 @@
                                      + "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);
+                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 >