changeset 1121:6a4e03cc03bb

6632886: Font.createFont can be persuaded to leak temporary files 6522586: Enforce limits on Font creation 6652929: Font.createFont(int,File) trusts File.getPath Reviewed-by: igor
author prr
date Mon, 05 Jan 2009 11:28:43 -0800
parents a8ec0998704e
children 392c4225d636
files src/share/classes/java/awt/Font.java src/share/classes/sun/font/CreatedFontTracker.java src/share/classes/sun/font/FileFont.java src/share/classes/sun/font/FontManager.java test/java/awt/FontClass/CreateFont/A.ttf test/java/awt/FontClass/CreateFont/BigFont.java test/java/awt/FontClass/CreateFont/DeleteFont.java test/java/awt/FontClass/CreateFont/DeleteFont.sh test/java/awt/FontClass/CreateFont/bigfont.html test/java/awt/FontClass/CreateFont/fileaccess/FontFile.java
diffstat 10 files changed, 616 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/awt/Font.java	Tue Dec 30 10:42:45 2008 +0800
+++ b/src/share/classes/java/awt/Font.java	Mon Jan 05 11:28:43 2009 -0800
@@ -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;
-              }
-          });
+        boolean copiedFontData = false;
 
-        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");
+        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);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/font/CreatedFontTracker.java	Mon Jan 05 11:28:43 2009 -0800
@@ -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;
+    }
+}
--- a/src/share/classes/sun/font/FileFont.java	Tue Dec 30 10:42:45 2008 +0800
+++ b/src/share/classes/sun/font/FileFont.java	Mon Jan 05 11:28:43 2009 -0800
@@ -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
--- a/src/share/classes/sun/font/FontManager.java	Tue Dec 30 10:42:45 2008 +0800
+++ b/src/share/classes/sun/font/FontManager.java	Mon Jan 05 11:28:43 2009 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2007 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
@@ -2347,12 +2347,14 @@
     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:
@@ -2369,6 +2371,9 @@
                 java.security.AccessController.doPrivileged(
                      new java.security.PrivilegedAction() {
                           public Object run() {
+                              if (_tracker != null) {
+                                  _tracker.subBytes((int)fFile.length());
+                              }
                               fFile.delete();
                               return null;
                           }
@@ -2377,7 +2382,7 @@
             throw(e);
         }
         if (isCopy) {
-            font2D.setFileToRemove(fontFile);
+            font2D.setFileToRemove(fontFile, tracker);
             synchronized (FontManager.class) {
 
                 if (tmpFontFiles == null) {
Binary file test/java/awt/FontClass/CreateFont/A.ttf has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/FontClass/CreateFont/BigFont.java	Mon Jan 05 11:28:43 2009 -0800
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+import java.applet.*;
+import java.awt.*;
+import java.io.*;
+import java.net.*;
+
+public class BigFont extends Applet {
+
+   static private class SizedInputStream extends InputStream {
+
+       int size;
+       int cnt = 0;
+
+       SizedInputStream(int size) {
+           this.size = size;
+       }
+
+       public int read() {
+           if (cnt < size) {
+              cnt++;
+              return 0;
+           } else {
+              return -1;
+           }
+       }
+
+       public int getCurrentSize() {
+           return cnt;
+       }
+   }
+
+    String id;
+    String fileName;
+
+    public void init() {
+        id = getParameter("number");
+        fileName = getParameter("font");
+
+        System.out.println("Applet " + id + " "+
+                           Thread.currentThread().getThreadGroup());
+        // Larger than size for a single font.
+        int fontSize = 64 * 1000 * 1000;
+        SizedInputStream sis = new SizedInputStream(fontSize);
+        try {
+             Font font = Font.createFont(Font.TRUETYPE_FONT, sis);
+        } catch (Throwable t) {
+            if (t instanceof FontFormatException ||
+                fontSize <= sis.getCurrentSize())
+            {
+                System.out.println(sis.getCurrentSize());
+                System.out.println(t);
+                throw new RuntimeException("Allowed file to be too large.");
+            }
+        }
+        // The following part of the test was verified manually but
+        // is impractical to enable  because it requires a fairly large
+        // valid font to be part of the test, and we can't easily include
+        // that, nor dependably reference one from the applet environment.
+        /*
+        if (fileName == null) {
+            return;
+        }
+        int size = getFileSize(fileName);
+        if (size == 0) {
+            return;
+        }
+        int fontCnt = 1000 * 1000 * 1000 / size;
+        loadMany(size, fontCnt, fileName);
+        System.gc(); System.gc();
+        fontCnt = fontCnt / 2;
+        System.out.println("Applet " + id + " load more.");
+        loadMany(size, fontCnt, fileName);
+        */
+        System.out.println("Applet " + id + " finished.");
+    }
+
+    int getFileSize(String fileName) {
+        try {
+            URL url = new URL(getCodeBase(), fileName);
+            InputStream inStream = url.openStream();
+            BufferedInputStream fontStream = new BufferedInputStream(inStream);
+            int size = 0;
+            while (fontStream.read() != -1) {
+                size++;
+            }
+            fontStream.close();
+            return size;
+        } catch (IOException e) {
+            return 0;
+        }
+
+    }
+    void loadMany(int oneFont, int fontCnt, String fileName) {
+        System.out.println("fontcnt= " + fontCnt);
+        Font[] fonts = new Font[fontCnt];
+        int totalSize = 0;
+        boolean gotException = false;
+        for (int i=0; i<fontCnt; i++) {
+            try {
+                URL url = new URL(getCodeBase(), fileName);
+                InputStream inStream = url.openStream();
+                BufferedInputStream fontStream =
+                    new BufferedInputStream(inStream);
+                fonts[i] = Font.createFont(Font.TRUETYPE_FONT, fontStream);
+                totalSize += oneFont;
+                fontStream.close();
+            } catch (Throwable t) {
+                gotException = true;
+                System.out.println("Applet " + id + " " + t);
+            }
+        }
+        if (!gotException) {
+          throw new RuntimeException("No expected exception");
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/FontClass/CreateFont/DeleteFont.java	Mon Jan 05 11:28:43 2009 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2004-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.
+ *
+ * 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.
+ */
+
+import java.io.*;
+import java.awt.*;
+
+public class DeleteFont {
+
+    public static void main(String args[]) throws Exception {
+
+        String font = "A.ttf";
+        String sep = System.getProperty("file.separator");
+        String testSrc = System.getenv("TESTSRC");
+        if (testSrc != null) {
+            font = testSrc + sep + font;
+        }
+        System.out.println("Using font file: " + font);
+        FileInputStream fis = new FileInputStream(font);
+        Font f = Font.createFont(Font.TRUETYPE_FONT, fis);
+        f.toString();
+        f.deriveFont(Font.BOLD);
+        f.canDisplay('X');
+
+       InputStream in = new InputStream() {
+            public int read() {
+                throw new RuntimeException();
+            }
+        };
+        boolean gotException = false;
+        try {
+           Font.createFont(java.awt.Font.TRUETYPE_FONT, in);
+        } catch (IOException e) {
+            gotException = true;
+        }
+        if (!gotException) {
+            throw new RuntimeException("No expected IOException");
+        }
+        badRead(-2);
+        badRead(8193);
+    }
+
+    static void badRead(final int retval) {
+        int num = 2;
+        byte[] buff = new byte[16*8192]; // Multiple of 8192 is important.
+        for (int ct=0; ct<num; ++ct) {
+            try {
+                Font.createFont(
+                    Font.TRUETYPE_FONT,
+                    new ByteArrayInputStream(buff) {
+                        @Override
+                        public int read(byte[] buff, int off, int len) {
+                            int read = super.read(buff, off, len);
+                            return read<0 ? retval : read;
+                        }
+                    }
+                );
+            } catch (Throwable exc) {
+                //exc.printStackTrace();
+            }
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/FontClass/CreateFont/DeleteFont.sh	Mon Jan 05 11:28:43 2009 -0800
@@ -0,0 +1,66 @@
+# Copyright 2004-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.
+#
+# 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.
+
+# @test
+# @bug 6189812 6380357 6632886
+# @summary Verify that temporary font files are deleted on exit.
+
+if [ -z "${TESTSRC}" ]; then
+  echo "TESTSRC undefined: defaulting to ."
+  TESTSRC=.
+fi
+
+if [ -z "${TESTCLASSES}" ]; then
+  echo "TESTCLASSES undefined: defaulting to ."
+  TESTCLASSES=.
+fi
+
+if [ -z "${TESTJAVA}" ]; then
+  echo "TESTJAVA undefined: can't continue."
+  exit 1
+fi
+
+echo "TESTJAVA=${TESTJAVA}"
+echo "TESTSRC=${TESTSRC}"
+echo "TESTCLASSES=${TESTCLASSES}"
+cd ${TESTSRC}
+${TESTJAVA}/bin/javac -d ${TESTCLASSES} DeleteFont.java
+
+cd ${TESTCLASSES}
+
+numfiles0=`ls ${TESTCLASSES} | wc -l`
+${TESTJAVA}/bin/java -Djava.io.tmpdir=${TESTCLASSES} DeleteFont
+
+if [ $? -ne 0 ]
+    then
+      echo "Test fails: exception thrown!"
+      exit 1
+fi
+
+numfiles1=`ls ${TESTCLASSES} | wc -l`
+
+if [ $numfiles0 -ne $numfiles1 ]
+    then
+      echo "Test fails: tmp file exists!"
+      ls ${TESTCLASSES}
+      exit 1
+fi
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/FontClass/CreateFont/bigfont.html	Mon Jan 05 11:28:43 2009 -0800
@@ -0,0 +1,48 @@
+<!--
+
+ 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.
+
+ 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.
+
+  @test
+  @bug 6522586
+  @run applet bigfont.html
+  @summary Enforce limits on font creation
+
+-->
+
+<html>
+  <head>
+      <title>Test Font Creation Limits</title>
+  </head>
+  <body>
+<hr>
+<APPLET CODE = BigFont.class WIDTH = 100 HEIGHT = 100 >
+<param name="number" value="1">
+<param name="font" value="A.ttf">
+</APPLET>
+<APPLET CODE = BigFont.class WIDTH = 100 HEIGHT = 100>
+<param name="number" value="2">
+<param name="font" value="A.ttf">
+</APPLET>
+<hr>
+  </body>
+</html>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/FontClass/CreateFont/fileaccess/FontFile.java	Mon Jan 05 11:28:43 2009 -0800
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6652929
+ * @summary verify handling of File.getPath()
+ */
+
+import java.awt.*;
+import java.io.*;
+
+public class FontFile {
+    public static void main(String[] args) throws Exception {
+        String sep = System.getProperty("file.separator");
+        String fname = ".." + sep + "A.ttf";
+        String dir = System.getProperty("test.src");
+        if (dir != null) {
+            fname = dir + sep + fname;
+        }
+        final String name = fname;
+        System.out.println("Will try to access " + name);
+        if (!(new File(name)).canRead()) {
+           System.out.println("File not available : can't run test");
+           return;
+        }
+        System.out.println("File is available. Verify no access under SM");
+
+        System.setSecurityManager(new SecurityManager());
+
+
+        // Check cannot read file.
+        try {
+            new FileInputStream(name);
+            throw new Error("Something wrong with test environment");
+        } catch (SecurityException exc) {
+            // Good.
+        }
+
+        try {
+            Font font = Font.createFont(Font.TRUETYPE_FONT,
+            new File("nosuchfile") {
+                    private boolean read;
+                    @Override public String getPath() {
+                        if (read) {
+                            return name;
+                        } else {
+                            read = true;
+                            return "somefile";
+                        }
+                    }
+                    @Override public boolean canRead() {
+                        return true;
+                    }
+               }
+            );
+          System.err.println(font.getFontName());
+          throw new RuntimeException("No expected exception");
+        }  catch (IOException e) {
+          System.err.println("Test passed.");
+        }
+    }
+}