view patches/security/icedtea-6632886.patch @ 1768:3a122c249dda

Port latest security fixes from IcedTea6. 2009-04-06 Andrew John Hughes <ahughes@redhat.com> * Makefile.am: Add new patches. * patches/security/icedtea-6536193.patch, * patches/security/icedtea-6610888.patch, * patches/security/icedtea-6610896.patch, * patches/security/icedtea-6630639.patch, * patches/security/icedtea-6632886.patch, * patches/security/icedtea-6636360.patch, * patches/security/icedtea-6652463.patch, * patches/security/icedtea-6656633.patch, * patches/security/icedtea-6658158.patch, * patches/security/icedtea-6691246.patch, * patches/security/icedtea-6717680.patch, * patches/security/icedtea-6721651.patch, * patches/security/icedtea-6737315.patch, * patches/security/icedtea-6792554.patch, * patches/security/icedtea-6804996.patch, * patches/security/icedtea-6804997.patch, * patches/security/icedtea-6804998.patch: Security patches ported from IcedTea6.
author Andrew John Hughes <ahughes@redhat.com>
date Tue, 07 Apr 2009 01:02:17 +0100
parents
children
line wrap: on
line source

diff -Nru openjdk.orig/jdk/src/share/classes/java/awt/Font.java openjdk/jdk/src/share/classes/java/awt/Font.java
--- openjdk.orig/jdk/src/share/classes/java/awt/Font.java	2009-04-06 17:20:02.000000000 +0100
+++ openjdk/jdk/src/share/classes/java/awt/Font.java	2009-04-06 17:24:48.000000000 +0100
@@ -37,6 +37,8 @@
 import java.awt.peer.FontPeer;
 import java.io.*;
 import java.lang.ref.SoftReference;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
 import java.text.AttributedCharacterIterator.Attribute;
 import java.text.CharacterIterator;
 import java.text.StringCharacterIterator;
@@ -51,6 +53,7 @@
 import sun.font.AttributeValues;
 import sun.font.EAttribute;
 import sun.font.CompositeFont;
+import sun.font.CreatedFontTracker;
 import sun.font.Font2D;
 import sun.font.Font2DHandle;
 import sun.font.FontManager;
@@ -575,14 +578,16 @@
     }
 
     /* used to implement Font.createFont */
-    private Font(File fontFile, int fontFormat, boolean isCopy)
+    private Font(File fontFile, int fontFormat,
+                 boolean isCopy, CreatedFontTracker tracker)
         throws FontFormatException {
         this.createdFont = true;
         /* Font2D instances created by this method track their font file
          * so that when the Font2D is GC'd it can also remove the file.
          */
         this.font2DHandle =
-            FontManager.createFont2D(fontFile, fontFormat, isCopy).handle;
+            FontManager.createFont2D(fontFile, fontFormat,
+                                     isCopy, tracker).handle;
         this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
         this.style = Font.PLAIN;
         this.size = 1;
@@ -788,6 +793,29 @@
     }
 
     /**
+     * Used with the byte count tracker for fonts created from streams.
+     * If a thread can create temp files anyway, no point in counting
+     * font bytes.
+     */
+    private static boolean hasTempPermission() {
+
+        if (System.getSecurityManager() == null) {
+            return true;
+        }
+        File f = null;
+        boolean hasPerm = false;
+        try {
+            f = File.createTempFile("+~JT", ".tmp", null);
+            f.delete();
+            f = null;
+            hasPerm = true;
+        } catch (Throwable t) {
+            /* inc. any kind of SecurityException */
+        }
+        return hasPerm;
+    }
+
+    /**
      * Returns a new <code>Font</code> using the specified font type
      * and input data.  The new <code>Font</code> is
      * created with a point size of 1 and style {@link #PLAIN PLAIN}.
@@ -822,58 +850,96 @@
             fontFormat != Font.TYPE1_FONT) {
             throw new IllegalArgumentException ("font format not recognized");
         }
-        final InputStream fStream = fontStream;
-        Object ret = java.security.AccessController.doPrivileged(
-           new java.security.PrivilegedAction() {
-              public Object run() {
-                  File tFile = null;
-                  FileOutputStream outStream = null;
-                  try {
-                      tFile = File.createTempFile("+~JF", ".tmp", null);
-                      /* Temp file deleted by font shutdown hook */
-                      BufferedInputStream inStream =
-                          new BufferedInputStream(fStream);
-                      outStream = new FileOutputStream(tFile);
-                      int bytesRead = 0;
-                      int bufSize = 8192;
-                      byte [] buf = new byte[bufSize];
-                      while (bytesRead != -1) {
-                          try {
-                              bytesRead = inStream.read(buf, 0, bufSize);
-                          } catch (Throwable t) {
-                              throw new IOException();
-                          }
-                          if (bytesRead != -1) {
-                              outStream.write(buf, 0, bytesRead);
-                          }
-                      }
-                      /* don't close the input stream */
-                      outStream.close();
-                  } catch (IOException e) {
-                      if (outStream != null) {
-                          try {
-                              outStream.close();
-                          } catch (Exception e1) {
-                          }
-                      }
-                      if (tFile != null) {
-                          try {
-                              tFile.delete();
-                          }  catch (Exception e2) {
-                          }
-                      }
-                      return e;
-                  }
-                  return tFile;
-              }
-          });
-
-        if (ret instanceof File) {
-            return new Font((File)ret, fontFormat, true);
-        } else if (ret instanceof IOException) {
-            throw (IOException)ret;
-        } else {
-            throw new FontFormatException("Couldn't access font stream");
+        boolean copiedFontData = false;
+
+        try {
+            final File tFile = AccessController.doPrivileged(
+                new PrivilegedExceptionAction<File>() {
+                    public File run() throws IOException {
+                        return File.createTempFile("+~JF", ".tmp", null);
+                    }
+                }
+            );
+
+            int totalSize = 0;
+            CreatedFontTracker tracker = null;
+            try {
+                final OutputStream outStream =
+                    AccessController.doPrivileged(
+                        new PrivilegedExceptionAction<OutputStream>() {
+                            public OutputStream run() throws IOException {
+                                return new FileOutputStream(tFile);
+                            }
+                        }
+                    );
+                if (!hasTempPermission()) {
+                    tracker = CreatedFontTracker.getTracker();
+                }
+                try {
+                    byte[] buf = new byte[8192]; 
+                    for (;;) {
+                        int bytesRead = fontStream.read(buf);
+                        if (bytesRead < 0) {
+                            break;
+                        }
+                        if (tracker != null) {
+                            if (totalSize+bytesRead > tracker.MAX_FILE_SIZE) {
+                                throw new IOException("File too big.");
+                            }
+                            if (totalSize+tracker.getNumBytes() >
+                                tracker.MAX_TOTAL_BYTES)
+                              {
+                                throw new IOException("Total files too big.");
+                            }
+                            totalSize += bytesRead;
+                            tracker.addBytes(bytesRead);
+                        }
+                        outStream.write(buf, 0, bytesRead);
+                    }
+                    /* don't close the input stream */
+                } finally {
+                    outStream.close();
+                }
+                /* After all references to a Font2D are dropped, the file
+                 * will be removed. To support long-lived AppContexts,
+                 * we need to then decrement the byte count by the size
+                 * of the file.
+                 * If the data isn't a valid font, the implementation will
+                 * delete the tmp file and decrement the byte count
+                 * in the tracker object before returning from the
+                 * constructor, so we can set 'copiedFontData' to true here
+                 * without waiting for the results of that constructor.
+                 */
+                copiedFontData = true;
+                Font font = new Font(tFile, fontFormat, true, tracker);
+                return font;
+            } finally {
+                if (!copiedFontData) {
+                    if (tracker != null) {
+                        tracker.subBytes(totalSize);
+                    }
+                    AccessController.doPrivileged(
+                        new PrivilegedExceptionAction<Void>() {
+                            public Void run() {
+                                tFile.delete();
+                                return null;
+                            }
+                        }
+                    );
+                }
+            }
+        } catch (Throwable t) {
+            if (t instanceof FontFormatException) {
+                throw (FontFormatException)t;
+            }
+            if (t instanceof IOException) {
+                throw (IOException)t;
+            }
+            Throwable cause = t.getCause();
+            if (cause instanceof FontFormatException) {
+                throw (FontFormatException)cause;
+            }
+            throw new IOException("Problem reading font data.");
         }
     }
 
@@ -913,6 +979,9 @@
      */
     public static Font createFont(int fontFormat, File fontFile)
         throws java.awt.FontFormatException, java.io.IOException {
+
+        fontFile = new File(fontFile.getPath());
+
         if (fontFormat != Font.TRUETYPE_FONT &&
             fontFormat != Font.TYPE1_FONT) {
             throw new IllegalArgumentException ("font format not recognized");
@@ -926,7 +995,7 @@
         if (!fontFile.canRead()) {
             throw new IOException("Can't read " + fontFile);
         }
-        return new Font(fontFile, fontFormat, false);
+        return new Font(fontFile, fontFormat, false, null);
     }
 
     /**
diff -Nru openjdk.orig/jdk/src/share/classes/sun/font/CreatedFontTracker.java openjdk/jdk/src/share/classes/sun/font/CreatedFontTracker.java
--- openjdk.orig/jdk/src/share/classes/sun/font/CreatedFontTracker.java	1970-01-01 01:00:00.000000000 +0100
+++ openjdk/jdk/src/share/classes/sun/font/CreatedFontTracker.java	2009-04-06 17:24:48.000000000 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.font;
+
+public class CreatedFontTracker {
+
+    public static final int MAX_FILE_SIZE = 32 * 1024 * 1024;
+    public static final int MAX_TOTAL_BYTES = 10 * MAX_FILE_SIZE;
+
+    static int numBytes;
+    static CreatedFontTracker tracker;
+
+    public static synchronized CreatedFontTracker getTracker() {
+        if (tracker == null) {
+            tracker = new CreatedFontTracker();
+        }
+        return tracker;
+    }
+
+    public synchronized int getNumBytes() {
+        return numBytes;
+    }
+
+    public synchronized void addBytes(int sz) {
+        numBytes += sz;
+    }
+
+    public synchronized void subBytes(int sz) {
+        numBytes -= sz;
+    }
+}
diff -Nru openjdk.orig/jdk/src/share/classes/sun/font/FileFont.java openjdk/jdk/src/share/classes/sun/font/FileFont.java
--- openjdk.orig/jdk/src/share/classes/sun/font/FileFont.java	2009-04-06 17:19:53.000000000 +0100
+++ openjdk/jdk/src/share/classes/sun/font/FileFont.java	2009-04-06 17:24:48.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc.  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
@@ -125,9 +125,9 @@
         return true;
     }
 
-    void setFileToRemove(File file) {
+    void setFileToRemove(File file, CreatedFontTracker tracker) {
         Disposer.addObjectRecord(this,
-                                 new CreatedFontFileDisposerRecord(file));
+                         new CreatedFontFileDisposerRecord(file, tracker));
     }
 
     /* This is called when a font scaler is determined to
@@ -246,12 +246,16 @@
         return getScaler().getUnitsPerEm();
     }
 
-    private static class CreatedFontFileDisposerRecord implements DisposerRecord {
+    private static class CreatedFontFileDisposerRecord
+        implements DisposerRecord {
 
         File fontFile = null;
+        CreatedFontTracker tracker;
 
-        private CreatedFontFileDisposerRecord(File file) {
+        private CreatedFontFileDisposerRecord(File file,
+                                              CreatedFontTracker tracker) {
             fontFile = file;
+            this.tracker = tracker;
         }
 
         public void dispose() {
@@ -260,6 +264,9 @@
                       public Object run() {
                           if (fontFile != null) {
                               try {
+                                  if (tracker != null) {
+                                      tracker.subBytes((int)fontFile.length());
+                                  }
                                   /* REMIND: is it possible that the file is
                                    * still open? It will be closed when the
                                    * font2D is disposed but could this code
diff -Nru openjdk.orig/jdk/src/share/classes/sun/font/TrueTypeFont.java openjdk/jdk/src/share/classes/sun/font/TrueTypeFont.java
--- openjdk.orig/jdk/src/share/classes/sun/font/TrueTypeFont.java	2009-04-06 17:19:53.000000000 +0100
+++ openjdk/jdk/src/share/classes/sun/font/TrueTypeFont.java	2009-04-06 17:24:48.000000000 +0100
@@ -175,8 +175,17 @@
         super(platname, nativeNames);
         useJavaRasterizer = javaRasterizer;
         fontRank = Font2D.TTF_RANK;
-        verify();
-        init(fIndex);
+        try {
+            verify();
+            init(fIndex);
+        } catch (Throwable t) {
+            close();
+            if (t instanceof FontFormatException) {
+                throw (FontFormatException)t;
+            } else {
+                throw new FontFormatException("Unexpected runtime exception.");
+            }
+        }
         Disposer.addObjectRecord(this, disposerRecord);
     }
 
diff -Nru openjdk.orig/jdk/src/share/classes/sun/font/Type1Font.java openjdk/jdk/src/share/classes/sun/font/Type1Font.java
--- openjdk.orig/jdk/src/share/classes/sun/font/Type1Font.java	2009-04-06 17:19:53.000000000 +0100
+++ openjdk/jdk/src/share/classes/sun/font/Type1Font.java	2009-04-06 17:24:48.000000000 +0100
@@ -39,6 +39,7 @@
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.FileChannel;
 import sun.java2d.Disposer;
+import sun.java2d.DisposerRecord;
 import java.util.HashSet;
 import java.util.HashMap;
 import java.awt.Font;
@@ -76,6 +77,27 @@
  */
 public class Type1Font extends FileFont {
 
+     private static class T1DisposerRecord  implements DisposerRecord {
+        String fileName = null;
+
+        T1DisposerRecord(String name) {
+            fileName = name;
+        }
+
+        public synchronized void dispose() {
+            java.security.AccessController.doPrivileged(
+	        new java.security.PrivilegedAction() {
+	            public Object run() {
+
+                        if (fileName != null) {
+                            (new java.io.File(fileName)).delete();
+                        }
+                        return null;
+		    }
+	     });
+        }
+    }
+
     WeakReference bufferRef = new WeakReference(null);
 
     private String psName = null;
@@ -125,18 +147,42 @@
 
 
     /**
+     * Constructs a Type1 Font.
+     * @param platname - Platform identifier of the font. Typically file name.
+     * @param nativeNames - Native names - typically XLFDs on Unix.
+     */
+    public Type1Font(String platname, Object nativeNames)
+        throws FontFormatException {
+
+        this(platname, nativeNames, false);
+    }
+
+    /**
      * - does basic verification of the file
      * - reads the names (full, family).
      * - determines the style of the font.
      * @throws FontFormatException - if the font can't be opened
      * or fails verification,  or there's no usable cmap
      */
-    public Type1Font(String platname, Object nativeNames)
+    public Type1Font(String platname, Object nativeNames, boolean createdCopy)
         throws FontFormatException {
         super(platname, nativeNames);
         fontRank = Font2D.TYPE1_RANK;
         checkedNatives = true;
-        verify();
+        try {
+            verify();
+        } catch (Throwable t) {
+            if (createdCopy) {
+                T1DisposerRecord ref = new T1DisposerRecord(platname);
+                Disposer.addObjectRecord(bufferRef, ref);
+                bufferRef = null;
+            }
+            if (t instanceof FontFormatException) {
+                throw (FontFormatException)t;
+            } else {
+                throw new FontFormatException("Unexpected runtime exception.");
+            }
+        }
     }
 
     private synchronized ByteBuffer getBuffer() throws FontFormatException {
--- openjdk.orig/jdk/src/share/classes/sun/font/FontManager.java	2009-04-06 21:46:26.000000000 +0100
+++ openjdk/jdk/src/share/classes/sun/font/FontManager.java	2009-04-06 21:48:08.000000000 +0100
@@ -2348,19 +2348,21 @@
     static Vector<File> tmpFontFiles = null;
 
     public static Font2D createFont2D(File fontFile, int fontFormat,
-                                      boolean isCopy)
+				      boolean isCopy,
+				      CreatedFontTracker tracker)
         throws FontFormatException {
 
         String fontFilePath = fontFile.getPath();
         FileFont font2D = null;
         final File fFile = fontFile;
+        final CreatedFontTracker _tracker = tracker;
         try {
             switch (fontFormat) {
             case Font.TRUETYPE_FONT:
                 font2D = new TrueTypeFont(fontFilePath, null, 0, true);
                 break;
             case Font.TYPE1_FONT:
-                font2D = new Type1Font(fontFilePath, null);
+                font2D = new Type1Font(fontFilePath, null, isCopy);
                 break;
             default:
                 throw new FontFormatException("Unrecognised Font Format");
@@ -2370,6 +2372,9 @@
                 java.security.AccessController.doPrivileged(
                      new java.security.PrivilegedAction() {
                           public Object run() {
+                              if (_tracker != null) {
+                                  _tracker.subBytes((int)fFile.length());
+                              }
                               fFile.delete();
                               return null;
                           }
@@ -2378,7 +2383,7 @@
             throw(e);
         }
         if (isCopy) {
-            font2D.setFileToRemove(fontFile);
+            font2D.setFileToRemove(fontFile, tracker);
             synchronized (FontManager.class) {
 
                 if (tmpFontFiles == null) {