changeset 1139:e51956c74e5c

Merge
author asaha
date Thu, 16 Apr 2009 21:08:04 -0700
parents 572d3f36c8a9 255dcd4f19b6
children 16c5e63f32d2
files make/common/shared/Defs-windows.gmk src/share/bin/emessages.h src/share/bin/java.c src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java src/share/classes/java/awt/Font.java src/share/classes/java/io/File.java src/share/classes/java/util/Calendar.java src/share/classes/javax/management/monitor/CounterMonitor.java src/share/classes/javax/management/monitor/GaugeMonitor.java src/share/classes/javax/management/monitor/Monitor.java src/share/classes/sun/font/FontManager.java src/share/classes/sun/font/TrueTypeFont.java src/share/classes/sun/font/Type1Font.java src/share/classes/sun/net/httpserver/Request.java src/share/classes/sun/net/httpserver/ServerImpl.java src/share/native/com/sun/java/util/jar/pack/bands.cpp src/share/native/com/sun/java/util/jar/pack/bytes.cpp src/share/native/com/sun/java/util/jar/pack/coding.cpp src/share/native/com/sun/java/util/jar/pack/defines.h src/share/native/com/sun/java/util/jar/pack/main.cpp src/share/native/com/sun/java/util/jar/pack/unpack.cpp src/share/native/com/sun/java/util/jar/pack/unpack.h src/share/native/com/sun/java/util/jar/pack/utils.cpp src/share/native/com/sun/java/util/jar/pack/utils.h
diffstat 62 files changed, 2249 insertions(+), 513 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/bin/emessages.h	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/bin/emessages.h	Thu Apr 16 21:08:04 2009 -0700
@@ -50,6 +50,12 @@
 #define JAR_ERROR2      "Error: Unable to access jarfile %s"
 #define JAR_ERROR3      "Error: Invalid or corrupt jarfile %s"
 
+#define CLS_ERROR1      "Error: Could not find the main class %s.\n" JNI_ERROR
+#define CLS_ERROR2      "Error: Failed to load Main Class: %s\n%s"
+#define CLS_ERROR3      "Error: No main method found in specified class.\n" GEN_ERROR
+#define CLS_ERROR4      "Error: Main method not public\n" GEN_ERROR
+#define CLS_ERROR5      "Error: main-class: attribute exceeds system limits of %d bytes\n" GEN_ERROR
+
 #define CFG_WARN1       "Warning: %s VM not supported; %s VM will be used"
 #define CFG_WARN2       "Warning: No leading - on line %d of `%s'"
 #define CFG_WARN3       "Warning: Missing VM type on line %d of `%s'"
--- a/src/share/bin/java.c	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/bin/java.c	Thu Apr 16 21:08:04 2009 -0700
@@ -915,8 +915,14 @@
      * to avoid locating, expanding and parsing the manifest extra
      * times.
      */
-    if (info.main_class != NULL)
-        (void)JLI_StrCat(env_entry, info.main_class);
+    if (info.main_class != NULL) {
+        if (JLI_StrLen(info.main_class) <= MAXNAMELEN) {
+            (void)JLI_StrCat(env_entry, info.main_class);
+        } else {
+            JLI_ReportErrorMessage(CLS_ERROR5, MAXNAMELEN);
+            exit(1);
+        }
+    }
     (void)putenv(env_entry);
     ExecJRE(jre, new_argv);
     JLI_FreeManifest();
--- a/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java	Thu Apr 16 21:08:04 2009 -0700
@@ -22,7 +22,6 @@
  * CA 95054 USA or visit www.sun.com if you need additional information or
  * have any questions.
  */
-
 package com.sun.jmx.remote.internal;
 
 import java.io.IOException;
@@ -34,6 +33,7 @@
 import java.util.Map;
 import java.util.concurrent.Executor;
 
+import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import javax.security.auth.Subject;
@@ -54,7 +54,10 @@
 
 
 public abstract class ClientNotifForwarder {
-    public ClientNotifForwarder(Map<String, ?> env) {
+
+    private final AccessControlContext acc;
+
+    public ClientNotifForwarder(Map env) {
         this(null, env);
     }
 
@@ -87,6 +90,8 @@
             this.command = command;
             if (thread == null) {
                 thread = new Thread() {
+
+                    @Override
                     public void run() {
                         while (true) {
                             Runnable r;
@@ -130,6 +135,7 @@
 
         this.defaultClassLoader = defaultClassLoader;
         this.executor = ex;
+        this.acc = AccessController.getContext();
     }
 
     /**
@@ -380,28 +386,85 @@
         setState(TERMINATED);
     }
 
-// -------------------------------------------------
-// private classes
-// -------------------------------------------------
+
+    // -------------------------------------------------
+    // private classes
+    // -------------------------------------------------
     //
+
     private class NotifFetcher implements Runnable {
+
+        private volatile boolean alreadyLogged = false;
+
+        private void logOnce(String msg, SecurityException x) {
+            if (alreadyLogged) return;
+            // Log only once.
+            logger.config("setContextClassLoader",msg);
+            if (x != null) logger.fine("setContextClassLoader", x);
+            alreadyLogged = true;
+        }
+
+        // Set new context class loader, returns previous one.
+        private final ClassLoader setContextClassLoader(final ClassLoader loader) {
+            final AccessControlContext ctxt = ClientNotifForwarder.this.acc;
+            // if ctxt is null, log a config message and throw a
+            // SecurityException.
+            if (ctxt == null) {
+                logOnce("AccessControlContext must not be null.",null);
+                throw new SecurityException("AccessControlContext must not be null");
+            }
+            return AccessController.doPrivileged(
+                new PrivilegedAction<ClassLoader>() {
+                    public ClassLoader run() {
+                        try {
+                            // get context class loader - may throw
+                            // SecurityException - though unlikely.
+                            final ClassLoader previous =
+                                Thread.currentThread().getContextClassLoader();
+
+                            // if nothing needs to be done, break here...
+                            if (loader == previous) return previous;
+
+                            // reset context class loader - may throw
+                            // SecurityException
+                            Thread.currentThread().setContextClassLoader(loader);
+                            return previous;
+                        } catch (SecurityException x) {
+                            logOnce("Permission to set ContextClassLoader missing. " +
+                                    "Notifications will not be dispatched. " +
+                                    "Please check your Java policy configuration: " +
+                                    x, x);
+                            throw x;
+                        }
+                    }
+                }, ctxt);
+        }
+
         public void run() {
+            final ClassLoader previous;
+            if (defaultClassLoader != null) {
+                previous = setContextClassLoader(defaultClassLoader);
+            } else {
+                previous = null;
+            }
+            try {
+                doRun();
+            } finally {
+                if (defaultClassLoader != null) {
+                    setContextClassLoader(previous);
+                }
+            }
+        }
+
+        private void doRun() {
             synchronized (ClientNotifForwarder.this) {
                 currentFetchThread = Thread.currentThread();
 
-                if (state == STARTING)
+                if (state == STARTING) {
                     setState(STARTED);
+                }
             }
 
-            if (defaultClassLoader != null) {
-                AccessController.doPrivileged(new PrivilegedAction<Void>() {
-                        public Void run() {
-                            Thread.currentThread().
-                                setContextClassLoader(defaultClassLoader);
-                            return null;
-                        }
-                    });
-            }
 
             NotificationResult nr = null;
             if (!shouldStop() && (nr = fetchNotifs()) != null) {
@@ -434,8 +497,9 @@
                         // check if an mbean unregistration notif
                         if (!listenerID.equals(mbeanRemovedNotifID)) {
                             final ClientListenerInfo li = infoList.get(listenerID);
-                            if (li != null)
-                                listeners.put(listenerID,li);
+                            if (li != null) {
+                                listeners.put(listenerID, li);
+                            }
                             continue;
                         }
                         final Notification notif = tn.getNotification();
@@ -799,9 +863,7 @@
     private long clientSequenceNumber = -1;
     private final int maxNotifications;
     private final long timeout;
-
     private Integer mbeanRemovedNotifID = null;
-
     private Thread currentFetchThread;
 
     // state
--- a/src/share/classes/com/sun/jmx/remote/security/MBeanServerAccessController.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/com/sun/jmx/remote/security/MBeanServerAccessController.java	Thu Apr 16 21:08:04 2009 -0700
@@ -111,6 +111,22 @@
      */
     protected abstract void checkWrite();
 
+    /**
+     * Check if the caller can create the named class.  The default
+     * implementation of this method calls {@link #checkWrite()}.
+     */
+    protected void checkCreate(String className) {
+        checkWrite();
+    }
+
+    /**
+     * Check if the caller can unregister the named MBean.  The default
+     * implementation of this method calls {@link #checkWrite()}.
+     */
+    protected void checkUnregister(ObjectName name) {
+        checkWrite();
+    }
+
     //--------------------------------------------
     //--------------------------------------------
     //
@@ -148,7 +164,7 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public ObjectInstance createMBean(String className, ObjectName name)
@@ -158,7 +174,7 @@
         MBeanRegistrationException,
         MBeanException,
         NotCompliantMBeanException {
-        checkWrite();
+        checkCreate(className);
         SecurityManager sm = System.getSecurityManager();
         if (sm == null) {
             Object object = getMBeanServer().instantiate(className);
@@ -170,7 +186,7 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public ObjectInstance createMBean(String className, ObjectName name,
@@ -181,7 +197,7 @@
         MBeanRegistrationException,
         MBeanException,
         NotCompliantMBeanException {
-        checkWrite();
+        checkCreate(className);
         SecurityManager sm = System.getSecurityManager();
         if (sm == null) {
             Object object = getMBeanServer().instantiate(className,
@@ -196,7 +212,7 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public ObjectInstance createMBean(String className,
@@ -209,7 +225,7 @@
         MBeanException,
         NotCompliantMBeanException,
         InstanceNotFoundException {
-        checkWrite();
+        checkCreate(className);
         SecurityManager sm = System.getSecurityManager();
         if (sm == null) {
             Object object = getMBeanServer().instantiate(className,
@@ -222,7 +238,7 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public ObjectInstance createMBean(String className,
@@ -237,7 +253,7 @@
         MBeanException,
         NotCompliantMBeanException,
         InstanceNotFoundException {
-        checkWrite();
+        checkCreate(className);
         SecurityManager sm = System.getSecurityManager();
         if (sm == null) {
             Object object = getMBeanServer().instantiate(className,
@@ -394,45 +410,45 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public Object instantiate(String className)
         throws ReflectionException, MBeanException {
-        checkWrite();
+        checkCreate(className);
         return getMBeanServer().instantiate(className);
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public Object instantiate(String className,
                               Object params[],
                               String signature[])
         throws ReflectionException, MBeanException {
-        checkWrite();
+        checkCreate(className);
         return getMBeanServer().instantiate(className, params, signature);
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public Object instantiate(String className, ObjectName loaderName)
         throws ReflectionException, MBeanException, InstanceNotFoundException {
-        checkWrite();
+        checkCreate(className);
         return getMBeanServer().instantiate(className, loaderName);
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkCreate(className)</code>, then forward this method to the
      * wrapped object.
      */
     public Object instantiate(String className, ObjectName loaderName,
                               Object params[], String signature[])
         throws ReflectionException, MBeanException, InstanceNotFoundException {
-        checkWrite();
+        checkCreate(className);
         return getMBeanServer().instantiate(className, loaderName,
                                             params, signature);
     }
@@ -579,12 +595,12 @@
     }
 
     /**
-     * Call <code>checkWrite()</code>, then forward this method to the
+     * Call <code>checkUnregister()</code>, then forward this method to the
      * wrapped object.
      */
     public void unregisterMBean(ObjectName name)
         throws InstanceNotFoundException, MBeanRegistrationException {
-        checkWrite();
+        checkUnregister(name);
         getMBeanServer().unregisterMBean(name);
     }
 
--- a/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java	Thu Apr 16 21:08:04 2009 -0700
@@ -31,11 +31,17 @@
 import java.security.AccessController;
 import java.security.Principal;
 import java.security.PrivilegedAction;
-import java.util.Collection;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.regex.Pattern;
 import javax.management.MBeanServer;
+import javax.management.ObjectName;
 import javax.security.auth.Subject;
 
 /**
@@ -46,7 +52,8 @@
  * not allowed; in this case the request is not forwarded to the
  * wrapped object.</p>
  *
- * <p>This class implements the {@link #checkRead()} and {@link #checkWrite()}
+ * <p>This class implements the {@link #checkRead()}, {@link #checkWrite()},
+ * {@link #checkCreate(String)}, and {@link #checkUnregister(ObjectName)}
  * methods based on an access level properties file containing username/access
  * level pairs. The set of username/access level pairs is passed either as a
  * filename which denotes a properties file on disk, or directly as an instance
@@ -56,14 +63,50 @@
  * has exactly one access level. The same access level can be shared by several
  * usernames.</p>
  *
- * <p>The supported access level values are <i>readonly</i> and
- * <i>readwrite</i>.</p>
+ * <p>The supported access level values are {@code readonly} and
+ * {@code readwrite}.  The {@code readwrite} access level can be
+ * qualified by one or more <i>clauses</i>, where each clause looks
+ * like <code>create <i>classNamePattern</i></code> or {@code
+ * unregister}.  For example:</p>
+ *
+ * <pre>
+ * monitorRole  readonly
+ * controlRole  readwrite \
+ *              create javax.management.timer.*,javax.management.monitor.* \
+ *              unregister
+ * </pre>
+ *
+ * <p>(The continuation lines with {@code \} come from the parser for
+ * Properties files.)</p>
  */
 public class MBeanServerFileAccessController
     extends MBeanServerAccessController {
 
-    public static final String READONLY = "readonly";
-    public static final String READWRITE = "readwrite";
+    static final String READONLY = "readonly";
+    static final String READWRITE = "readwrite";
+
+    static final String CREATE = "create";
+    static final String UNREGISTER = "unregister";
+
+    private enum AccessType {READ, WRITE, CREATE, UNREGISTER};
+
+    private static class Access {
+        final boolean write;
+        final String[] createPatterns;
+        private boolean unregister;
+
+        Access(boolean write, boolean unregister, List<String> createPatternList) {
+            this.write = write;
+            int npats = (createPatternList == null) ? 0 : createPatternList.size();
+            if (npats == 0)
+                this.createPatterns = NO_STRINGS;
+            else
+                this.createPatterns = createPatternList.toArray(new String[npats]);
+            this.unregister = unregister;
+        }
+
+        private final String[] NO_STRINGS = new String[0];
+    }
 
     /**
      * <p>Create a new MBeanServerAccessController that forwards all the
@@ -87,8 +130,8 @@
         throws IOException {
         super();
         this.accessFileName = accessFileName;
-        props = propertiesFromFile(accessFileName);
-        checkValues(props);
+        Properties props = propertiesFromFile(accessFileName);
+        parseProperties(props);
     }
 
     /**
@@ -123,14 +166,14 @@
      * #setMBeanServer} method after doing access checks based on read and
      * write permissions.</p>
      *
-     * <p>This instance is initialized from the specified properties instance.
-     * This constructor makes a copy of the properties instance using its
-     * <code>clone</code> method and it is the copy that is consulted to check
-     * the username and access level of an incoming connection. The original
-     * properties object can be modified without affecting the copy. If the
-     * {@link #refresh} method is then called, the
-     * <code>MBeanServerFileAccessController</code> will make a new copy of the
-     * properties object at that time.</p>
+     * <p>This instance is initialized from the specified properties
+     * instance.  This constructor makes a copy of the properties
+     * instance and it is the copy that is consulted to check the
+     * username and access level of an incoming connection. The
+     * original properties object can be modified without affecting
+     * the copy. If the {@link #refresh} method is then called, the
+     * <code>MBeanServerFileAccessController</code> will make a new
+     * copy of the properties object at that time.</p>
      *
      * @param accessFileProps properties list containing the username/access
      * level entries.
@@ -145,8 +188,7 @@
         if (accessFileProps == null)
             throw new IllegalArgumentException("Null properties");
         originalProps = accessFileProps;
-        props = (Properties) accessFileProps.clone();
-        checkValues(props);
+        parseProperties(accessFileProps);
     }
 
     /**
@@ -155,14 +197,14 @@
      * #setMBeanServer} method after doing access checks based on read and
      * write permissions.</p>
      *
-     * <p>This instance is initialized from the specified properties instance.
-     * This constructor makes a copy of the properties instance using its
-     * <code>clone</code> method and it is the copy that is consulted to check
-     * the username and access level of an incoming connection. The original
-     * properties object can be modified without affecting the copy. If the
-     * {@link #refresh} method is then called, the
-     * <code>MBeanServerFileAccessController</code> will make a new copy of the
-     * properties object at that time.</p>
+     * <p>This instance is initialized from the specified properties
+     * instance.  This constructor makes a copy of the properties
+     * instance and it is the copy that is consulted to check the
+     * username and access level of an incoming connection. The
+     * original properties object can be modified without affecting
+     * the copy. If the {@link #refresh} method is then called, the
+     * <code>MBeanServerFileAccessController</code> will make a new
+     * copy of the properties object at that time.</p>
      *
      * @param accessFileProps properties list containing the username/access
      * level entries.
@@ -184,16 +226,36 @@
      * Check if the caller can do read operations. This method does
      * nothing if so, otherwise throws SecurityException.
      */
+    @Override
     public void checkRead() {
-        checkAccessLevel(READONLY);
+        checkAccess(AccessType.READ, null);
     }
 
     /**
      * Check if the caller can do write operations.  This method does
      * nothing if so, otherwise throws SecurityException.
      */
+    @Override
     public void checkWrite() {
-        checkAccessLevel(READWRITE);
+        checkAccess(AccessType.WRITE, null);
+    }
+
+    /**
+     * Check if the caller can create MBeans or instances of the given class.
+     * This method does nothing if so, otherwise throws SecurityException.
+     */
+    @Override
+    public void checkCreate(String className) {
+        checkAccess(AccessType.CREATE, className);
+    }
+
+    /**
+     * Check if the caller can do unregister operations.  This method does
+     * nothing if so, otherwise throws SecurityException.
+     */
+    @Override
+    public void checkUnregister(ObjectName name) {
+        checkAccess(AccessType.UNREGISTER, null);
     }
 
     /**
@@ -218,14 +280,13 @@
      * @exception IllegalArgumentException if any of the supplied access
      * level values differs from "readonly" or "readwrite".
      */
-    public void refresh() throws IOException {
-        synchronized (props) {
-            if (accessFileName == null)
-                props = (Properties) originalProps.clone();
-            else
-                props = propertiesFromFile(accessFileName);
-            checkValues(props);
-        }
+    public synchronized void refresh() throws IOException {
+        Properties props;
+        if (accessFileName == null)
+            props = (Properties) originalProps;
+        else
+            props = propertiesFromFile(accessFileName);
+        parseProperties(props);
     }
 
     private static Properties propertiesFromFile(String fname)
@@ -240,7 +301,7 @@
         }
     }
 
-    private void checkAccessLevel(String accessLevel) {
+    private synchronized void checkAccess(AccessType requiredAccess, String arg) {
         final AccessControlContext acc = AccessController.getContext();
         final Subject s =
             AccessController.doPrivileged(new PrivilegedAction<Subject>() {
@@ -249,39 +310,235 @@
                     }
                 });
         if (s == null) return; /* security has not been enabled */
-        final Set<Principal> principals = s.getPrincipals();
-        for (Principal p : principals) {
-            String grantedAccessLevel;
-            synchronized (props) {
-                grantedAccessLevel = props.getProperty(p.getName());
-            }
-            if (grantedAccessLevel != null) {
-                if (accessLevel.equals(READONLY) &&
-                    (grantedAccessLevel.equals(READONLY) ||
-                     grantedAccessLevel.equals(READWRITE)))
-                    return;
-                if (accessLevel.equals(READWRITE) &&
-                    grantedAccessLevel.equals(READWRITE))
+        final Set principals = s.getPrincipals();
+        String newPropertyValue = null;
+        for (Iterator i = principals.iterator(); i.hasNext(); ) {
+            final Principal p = (Principal) i.next();
+            Access access = accessMap.get(p.getName());
+            if (access != null) {
+                boolean ok;
+                switch (requiredAccess) {
+                    case READ:
+                        ok = true;  // all access entries imply read
+                        break;
+                    case WRITE:
+                        ok = access.write;
+                        break;
+                    case UNREGISTER:
+                        ok = access.unregister;
+                        if (!ok && access.write)
+                            newPropertyValue = "unregister";
+                        break;
+                    case CREATE:
+                        ok = checkCreateAccess(access, arg);
+                        if (!ok && access.write)
+                            newPropertyValue = "create " + arg;
+                        break;
+                    default:
+                        throw new AssertionError();
+                }
+                if (ok)
                     return;
             }
         }
-        throw new SecurityException("Access denied! Invalid access level for " +
-                                    "requested MBeanServer operation.");
+        SecurityException se = new SecurityException("Access denied! Invalid " +
+                "access level for requested MBeanServer operation.");
+        // Add some more information to help people with deployments that
+        // worked before we required explicit create clauses. We're not giving
+        // any information to the bad guys, other than that the access control
+        // is based on a file, which they could have worked out from the stack
+        // trace anyway.
+        if (newPropertyValue != null) {
+            SecurityException se2 = new SecurityException("Access property " +
+                    "for this identity should be similar to: " + READWRITE +
+                    " " + newPropertyValue);
+            se.initCause(se2);
+        }
+        throw se;
     }
 
-    private void checkValues(Properties props) {
-        Collection<?> c = props.values();
-        for (Iterator<?> i = c.iterator(); i.hasNext(); ) {
-            final String accessLevel = (String) i.next();
-            if (!accessLevel.equals(READONLY) &&
-                !accessLevel.equals(READWRITE)) {
-                throw new IllegalArgumentException(
-                    "Syntax error in access level entry [" + accessLevel + "]");
-            }
+    private static boolean checkCreateAccess(Access access, String className) {
+        for (String classNamePattern : access.createPatterns) {
+            if (classNameMatch(classNamePattern, className))
+                return true;
+        }
+        return false;
+    }
+
+    private static boolean classNameMatch(String pattern, String className) {
+        // We studiously avoided regexes when parsing the properties file,
+        // because that is done whenever the VM is started with the
+        // appropriate -Dcom.sun.management options, even if nobody ever
+        // creates an MBean.  We don't want to incur the overhead of loading
+        // all the regex code whenever those options are specified, but if we
+        // get as far as here then the VM is already running and somebody is
+        // doing the very unusual operation of remotely creating an MBean.
+        // Because that operation is so unusual, we don't try to optimize
+        // by hand-matching or by caching compiled Pattern objects.
+        StringBuilder sb = new StringBuilder();
+        StringTokenizer stok = new StringTokenizer(pattern, "*", true);
+        while (stok.hasMoreTokens()) {
+            String tok = stok.nextToken();
+            if (tok.equals("*"))
+                sb.append("[^.]*");
+            else
+                sb.append(Pattern.quote(tok));
+        }
+        return className.matches(sb.toString());
+    }
+
+    private void parseProperties(Properties props) {
+        this.accessMap = new HashMap<String, Access>();
+        for (Map.Entry<Object, Object> entry : props.entrySet()) {
+            String identity = (String) entry.getKey();
+            String accessString = (String) entry.getValue();
+            Access access = Parser.parseAccess(identity, accessString);
+            accessMap.put(identity, access);
         }
     }
 
-    private Properties props;
+    private static class Parser {
+        private final static int EOS = -1;  // pseudo-codepoint "end of string"
+        static {
+            assert !Character.isWhitespace(EOS);
+        }
+
+        private final String identity;  // just for better error messages
+        private final String s;  // the string we're parsing
+        private final int len;   // s.length()
+        private int i;
+        private int c;
+        // At any point, either c is s.codePointAt(i), or i == len and
+        // c is EOS.  We use int rather than char because it is conceivable
+        // (if unlikely) that a classname in a create clause might contain
+        // "supplementary characters", the ones that don't fit in the original
+        // 16 bits for Unicode.
+
+        private Parser(String identity, String s) {
+            this.identity = identity;
+            this.s = s;
+            this.len = s.length();
+            this.i = 0;
+            if (i < len)
+                this.c = s.codePointAt(i);
+            else
+                this.c = EOS;
+        }
+
+        static Access parseAccess(String identity, String s) {
+            return new Parser(identity, s).parseAccess();
+        }
+
+        private Access parseAccess() {
+            skipSpace();
+            String type = parseWord();
+            Access access;
+            if (type.equals(READONLY))
+                access = new Access(false, false, null);
+            else if (type.equals(READWRITE))
+                access = parseReadWrite();
+            else {
+                throw syntax("Expected " + READONLY + " or " + READWRITE +
+                        ": " + type);
+            }
+            if (c != EOS)
+                throw syntax("Extra text at end of line");
+            return access;
+        }
+
+        private Access parseReadWrite() {
+            List<String> createClasses = new ArrayList<String>();
+            boolean unregister = false;
+            while (true) {
+                skipSpace();
+                if (c == EOS)
+                    break;
+                String type = parseWord();
+                if (type.equals(UNREGISTER))
+                    unregister = true;
+                else if (type.equals(CREATE))
+                    parseCreate(createClasses);
+                else
+                    throw syntax("Unrecognized keyword " + type);
+            }
+            return new Access(true, unregister, createClasses);
+        }
+
+        private void parseCreate(List<String> createClasses) {
+            while (true) {
+                skipSpace();
+                createClasses.add(parseClassName());
+                skipSpace();
+                if (c == ',')
+                    next();
+                else
+                    break;
+            }
+        }
+
+        private String parseClassName() {
+            // We don't check that classname components begin with suitable
+            // characters (so we accept 1.2.3 for example).  This means that
+            // there are only two states, which we can call dotOK and !dotOK
+            // according as a dot (.) is legal or not.  Initially we're in
+            // !dotOK since a classname can't start with a dot; after a dot
+            // we're in !dotOK again; and after any other characters we're in
+            // dotOK.  The classname is only accepted if we end in dotOK,
+            // so we reject an empty name or a name that ends with a dot.
+            final int start = i;
+            boolean dotOK = false;
+            while (true) {
+                if (c == '.') {
+                    if (!dotOK)
+                        throw syntax("Bad . in class name");
+                    dotOK = false;
+                } else if (c == '*' || Character.isJavaIdentifierPart(c))
+                    dotOK = true;
+                else
+                    break;
+                next();
+            }
+            String className = s.substring(start, i);
+            if (!dotOK)
+                throw syntax("Bad class name " + className);
+            return className;
+        }
+
+        // Advance c and i to the next character, unless already at EOS.
+        private void next() {
+            if (c != EOS) {
+                i += Character.charCount(c);
+                if (i < len)
+                    c = s.codePointAt(i);
+                else
+                    c = EOS;
+            }
+        }
+
+        private void skipSpace() {
+            while (Character.isWhitespace(c))
+                next();
+        }
+
+        private String parseWord() {
+            skipSpace();
+            if (c == EOS)
+                throw syntax("Expected word at end of line");
+            final int start = i;
+            while (c != EOS && !Character.isWhitespace(c))
+                next();
+            String word = s.substring(start, i);
+            skipSpace();
+            return word;
+        }
+
+        private IllegalArgumentException syntax(String msg) {
+            return new IllegalArgumentException(
+                    msg + " [" + identity + " " + s + "]");
+        }
+    }
+
+    private Map<String, Access> accessMap;
     private Properties originalProps;
     private String accessFileName;
 }
--- a/src/share/classes/com/sun/jndi/ldap/LdapCtx.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/com/sun/jndi/ldap/LdapCtx.java	Thu Apr 16 21:08:04 2009 -0700
@@ -302,7 +302,16 @@
 
         schemaTrees = new Hashtable(11, 0.75f);
         initEnv();
-        connect(false);
+        try {
+            connect(false);
+        } catch (NamingException e) {
+            try {
+                close();
+            } catch (Exception e2) {
+                // Nothing
+            }
+            throw e;
+        }
     }
 
     LdapCtx(LdapCtx existing, String newDN) throws NamingException {
--- a/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1999-2009 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
@@ -33,12 +33,33 @@
 
 final class VersionHelper12 extends VersionHelper {
 
+    // System property to control whether classes may be loaded from an
+    // arbitrary URL code base.
+    private static final String TRUST_URL_CODEBASE_PROPERTY =
+        "com.sun.jndi.ldap.object.trustURLCodebase";
+
+    // Determine whether classes may be loaded from an arbitrary URL code base.
+    private static final String trustURLCodebase =
+        AccessController.doPrivileged(
+            new PrivilegedAction<String>() {
+                public String run() {
+                    return System.getProperty(TRUST_URL_CODEBASE_PROPERTY,
+                            "false");
+                }
+            }
+        );
+
     VersionHelper12() {} // Disallow external from creating one of these.
 
     ClassLoader getURLClassLoader(String[] url)
         throws MalformedURLException {
             ClassLoader parent = getContextClassLoader();
-            if (url != null) {
+            /*
+             * Classes may only be loaded from an arbitrary URL code base when
+             * the system property com.sun.jndi.ldap.object.trustURLCodebase
+             * has been set to "true".
+             */
+            if (url != null && "true".equalsIgnoreCase(trustURLCodebase)) {
                 return URLClassLoader.newInstance(getUrlArray(url), parent);
             } else {
                 return parent;
--- a/src/share/classes/java/awt/Font.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/java/awt/Font.java	Thu Apr 16 21:08:04 2009 -0700
@@ -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);
     }
 
     /**
--- a/src/share/classes/java/util/Calendar.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/java/util/Calendar.java	Thu Apr 16 21:08:04 2009 -0700
@@ -41,9 +41,14 @@
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
 import java.io.Serializable;
+import java.security.AccessControlContext;
 import java.security.AccessController;
+import java.security.PermissionCollection;
+import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
 import java.text.DateFormat;
 import java.text.DateFormatSymbols;
 import sun.util.BuddhistCalendar;
@@ -2628,6 +2633,18 @@
         }
     }
 
+    private static class CalendarAccessControlContext {
+        private static final AccessControlContext INSTANCE;
+        static {
+            RuntimePermission perm = new RuntimePermission("accessClassInPackage.sun.util.calendar");
+            PermissionCollection perms = perm.newPermissionCollection();
+            perms.add(perm);
+            INSTANCE = new AccessControlContext(new ProtectionDomain[] {
+                                                    new ProtectionDomain(null, perms)
+                                                });
+        }
+    }
+
     /**
      * Reconstitutes this object from a stream (i.e., deserialize it).
      */
@@ -2657,17 +2674,30 @@
         serialVersionOnStream = currentSerialVersion;
 
         // If there's a ZoneInfo object, use it for zone.
+        ZoneInfo zi = null;
         try {
-            ZoneInfo zi = (ZoneInfo) AccessController.doPrivileged(
-                new PrivilegedExceptionAction() {
-                    public Object run() throws Exception {
-                        return input.readObject();
-                    }
-                });
-            if (zi != null) {
-                zone = zi;
+            zi = AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<ZoneInfo>() {
+                        public ZoneInfo run() throws Exception {
+                            return (ZoneInfo) input.readObject();
+                        }
+                    },
+                    CalendarAccessControlContext.INSTANCE);
+        } catch (PrivilegedActionException pae) {
+            Exception e = pae.getException();
+            if (!(e instanceof OptionalDataException)) {
+                if (e instanceof RuntimeException) {
+                    throw (RuntimeException) e;
+                } else if (e instanceof IOException) {
+                    throw (IOException) e;
+                } else if (e instanceof ClassNotFoundException) {
+                    throw (ClassNotFoundException) e;
+                }
+                throw new RuntimeException(e);
             }
-        } catch (Exception e) {
+        }
+        if (zi != null) {
+            zone = zi;
         }
 
         // If the deserialized object has a SimpleTimeZone, try to
@@ -2676,9 +2706,9 @@
         // implementation as much as possible.
         if (zone instanceof SimpleTimeZone) {
             String id = zone.getID();
-            TimeZone zi = TimeZone.getTimeZone(id);
-            if (zi != null && zi.hasSameRules(zone) && zi.getID().equals(id)) {
-                zone = zi;
+            TimeZone tz = TimeZone.getTimeZone(id);
+            if (tz != null && tz.hasSameRules(zone) && tz.getID().equals(id)) {
+                zone = tz;
             }
         }
     }
--- a/src/share/classes/javax/management/monitor/CounterMonitor.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/javax/management/monitor/CounterMonitor.java	Thu Apr 16 21:08:04 2009 -0700
@@ -599,7 +599,7 @@
      */
     @Override
     public MBeanNotificationInfo[] getNotificationInfo() {
-        return notifsInfo;
+        return notifsInfo.clone();
     }
 
     /*
--- a/src/share/classes/javax/management/monitor/GaugeMonitor.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/javax/management/monitor/GaugeMonitor.java	Thu Apr 16 21:08:04 2009 -0700
@@ -481,7 +481,7 @@
      */
     @Override
     public MBeanNotificationInfo[] getNotificationInfo() {
-        return notifsInfo;
+        return notifsInfo.clone();
     }
 
     /*
--- a/src/share/classes/javax/management/monitor/Monitor.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/javax/management/monitor/Monitor.java	Thu Apr 16 21:08:04 2009 -0700
@@ -32,7 +32,10 @@
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
 import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
@@ -163,7 +166,10 @@
     /**
      * AccessControlContext of the Monitor.start() caller.
      */
-    private AccessControlContext acc;
+    private static final AccessControlContext noPermissionsACC =
+            new AccessControlContext(
+            new ProtectionDomain[] {new ProtectionDomain(null, null)});
+    private volatile AccessControlContext acc = noPermissionsACC;
 
     /**
      * Scheduler Service.
@@ -173,14 +179,20 @@
             new DaemonThreadFactory("Scheduler"));
 
     /**
+     * Map containing the thread pool executor per thread group.
+     */
+    private static final Map<ThreadPoolExecutor, Void> executors =
+            new WeakHashMap<ThreadPoolExecutor, Void>();
+
+    /**
+     * Lock for executors map.
+     */
+    private static final Object executorsLock = new Object();
+
+    /**
      * Maximum Pool Size
      */
     private static final int maximumPoolSize;
-
-    /**
-     * Executor Service.
-     */
-    private static final ThreadPoolExecutor executor;
     static {
         final String maximumPoolSizeSysProp = "jmx.x.monitor.maximum.pool.size";
         final String maximumPoolSizeStr = AccessController.doPrivileged(
@@ -210,22 +222,9 @@
                 maximumPoolSize = maximumPoolSizeTmp;
             }
         }
-        executor = new ThreadPoolExecutor(
-                maximumPoolSize,
-                maximumPoolSize,
-                60L,
-                TimeUnit.SECONDS,
-                new LinkedBlockingQueue<Runnable>(),
-                new DaemonThreadFactory("Executor"));
-        executor.allowCoreThreadTimeOut(true);
     }
 
     /**
-     * Monitor task to be executed by the Executor Service.
-     */
-    private final MonitorTask monitorTask = new MonitorTask();
-
-    /**
      * Future associated to the current monitor task.
      */
     private Future<?> monitorFuture;
@@ -233,7 +232,7 @@
     /**
      * Scheduler task to be executed by the Scheduler Service.
      */
-    private final SchedulerTask schedulerTask = new SchedulerTask(monitorTask);
+    private final SchedulerTask schedulerTask = new SchedulerTask();
 
     /**
      * ScheduledFuture associated to the current scheduler task.
@@ -719,6 +718,7 @@
             // Start the scheduler.
             //
             cleanupFutures();
+            schedulerTask.setMonitorTask(new MonitorTask());
             schedulerFuture = scheduler.schedule(schedulerTask,
                                                  getGranularityPeriod(),
                                                  TimeUnit.MILLISECONDS);
@@ -748,7 +748,7 @@
 
             // Reset the AccessControlContext.
             //
-            acc = null;
+            acc = noPermissionsACC;
 
             // Reset the complex type attribute information
             // such that it is recalculated again.
@@ -1467,7 +1467,7 @@
      */
     private class SchedulerTask implements Runnable {
 
-        private Runnable task = null;
+        private MonitorTask task;
 
         /*
          * ------------------------------------------
@@ -1475,7 +1475,16 @@
          * ------------------------------------------
          */
 
-        public SchedulerTask(Runnable task) {
+        public SchedulerTask() {
+        }
+
+        /*
+         * ------------------------------------------
+         *  GETTERS/SETTERS
+         * ------------------------------------------
+         */
+
+        public void setMonitorTask(MonitorTask task) {
             this.task = task;
         }
 
@@ -1487,7 +1496,7 @@
 
         public void run() {
             synchronized (Monitor.this) {
-                Monitor.this.monitorFuture = executor.submit(task);
+                Monitor.this.monitorFuture = task.submit();
             }
         }
     }
@@ -1500,6 +1509,8 @@
      */
     private class MonitorTask implements Runnable {
 
+        private ThreadPoolExecutor executor;
+
         /*
          * ------------------------------------------
          *  CONSTRUCTORS
@@ -1507,6 +1518,38 @@
          */
 
         public MonitorTask() {
+            // Find out if there's already an existing executor for the calling
+            // thread and reuse it. Otherwise, create a new one and store it in
+            // the executors map. If there is a SecurityManager, the group of
+            // System.getSecurityManager() is used, else the group of the thread
+            // instantiating this MonitorTask, i.e. the group of the thread that
+            // calls "Monitor.start()".
+            SecurityManager s = System.getSecurityManager();
+            ThreadGroup group = (s != null) ? s.getThreadGroup() :
+                Thread.currentThread().getThreadGroup();
+            synchronized (executorsLock) {
+                for (ThreadPoolExecutor e : executors.keySet()) {
+                    DaemonThreadFactory tf =
+                            (DaemonThreadFactory) e.getThreadFactory();
+                    ThreadGroup tg = tf.getThreadGroup();
+                    if (tg == group) {
+                        executor = e;
+                        break;
+                    }
+                }
+                if (executor == null) {
+                    executor = new ThreadPoolExecutor(
+                            maximumPoolSize,
+                            maximumPoolSize,
+                            60L,
+                            TimeUnit.SECONDS,
+                            new LinkedBlockingQueue<Runnable>(),
+                            new DaemonThreadFactory("ThreadGroup<" +
+                            group.getName() + "> Executor", group));
+                    executor.allowCoreThreadTimeOut(true);
+                    executors.put(executor, null);
+                }
+            }
         }
 
         /*
@@ -1515,12 +1558,18 @@
          * ------------------------------------------
          */
 
+        public Future<?> submit() {
+            return executor.submit(this);
+        }
+
         public void run() {
             final ScheduledFuture<?> sf;
+            final AccessControlContext ac;
             synchronized (Monitor.this) {
                 sf = Monitor.this.schedulerFuture;
+                ac = Monitor.this.acc;
             }
-            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            PrivilegedAction<Void> action = new PrivilegedAction<Void>() {
                 public Void run() {
                     if (Monitor.this.isActive()) {
                         final int an[] = alreadyNotifieds;
@@ -1533,7 +1582,11 @@
                     }
                     return null;
                 }
-            }, Monitor.this.acc);
+            };
+            if (ac == null) {
+                throw new SecurityException("AccessControlContext cannot be null");
+            }
+            AccessController.doPrivileged(action, ac);
             synchronized (Monitor.this) {
                 if (Monitor.this.isActive() &&
                     Monitor.this.schedulerFuture == sf) {
@@ -1573,6 +1626,15 @@
             namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
         }
 
+        public DaemonThreadFactory(String poolName, ThreadGroup threadGroup) {
+            group = threadGroup;
+            namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
+        }
+
+        public ThreadGroup getThreadGroup() {
+            return group;
+        }
+
         public Thread newThread(Runnable r) {
             Thread t = new Thread(group,
                                   r,
--- a/src/share/classes/javax/management/monitor/StringMonitor.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/javax/management/monitor/StringMonitor.java	Thu Apr 16 21:08:04 2009 -0700
@@ -184,6 +184,7 @@
      * @return The derived gauge of the specified object.
      *
      */
+    @Override
     public synchronized String getDerivedGauge(ObjectName object) {
         return (String) super.getDerivedGauge(object);
     }
@@ -199,6 +200,7 @@
      * @return The derived gauge timestamp of the specified object.
      *
      */
+    @Override
     public synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
         return super.getDerivedGaugeTimeStamp(object);
     }
@@ -341,8 +343,9 @@
      * the Java class of the notification and the notification types sent by
      * the string monitor.
      */
+    @Override
     public MBeanNotificationInfo[] getNotificationInfo() {
-        return notifsInfo;
+        return notifsInfo.clone();
     }
 
     /*
--- a/src/share/classes/javax/print/attribute/standard/MediaSize.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/javax/print/attribute/standard/MediaSize.java	Thu Apr 16 21:08:04 2009 -0700
@@ -123,8 +123,10 @@
         if (x > y) {
             throw new IllegalArgumentException("X dimension > Y dimension");
         }
-        mediaName = media;
-        mediaMap.put(mediaName, this);
+        if (media != null && mediaMap.get(media) == null) {
+            mediaName = media;
+            mediaMap.put(mediaName, this);
+        }
         sizeVector.add(this);
     }
 
@@ -147,8 +149,10 @@
         if (x > y) {
             throw new IllegalArgumentException("X dimension > Y dimension");
         }
-        mediaName = media;
-        mediaMap.put(mediaName, this);
+        if (media != null && mediaMap.get(media) == null) {
+            mediaName = media;
+            mediaMap.put(mediaName, this);
+        }
         sizeVector.add(this);
     }
 
--- a/src/share/classes/sun/awt/image/GifImageDecoder.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/awt/image/GifImageDecoder.java	Thu Apr 16 21:08:04 2009 -0700
@@ -585,9 +585,16 @@
             System.out.print("Reading a " + width + " by " + height + " " +
                       (interlace ? "" : "non-") + "interlaced image...");
         }
-
+        int initCodeSize = ExtractByte(block, 9);
+        if (initCodeSize >= 12) {
+            if (verbose) {
+                System.out.println("Invalid initial code size: " +
+                                   initCodeSize);
+            }
+            return false;
+        }
         boolean ret = parseImage(x, y, width, height,
-                                 interlace, ExtractByte(block, 9),
+                                 interlace, initCodeSize,
                                  block, rasline, model);
 
         if (!ret) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/font/CreatedFontTracker.java	Thu Apr 16 21:08:04 2009 -0700
@@ -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	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/font/FileFont.java	Thu Apr 16 21:08:04 2009 -0700
@@ -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	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/font/FontManager.java	Thu Apr 16 21:08:04 2009 -0700
@@ -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) {
--- a/src/share/classes/sun/font/TrueTypeFont.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/font/TrueTypeFont.java	Thu Apr 16 21:08:04 2009 -0700
@@ -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);
     }
 
--- a/src/share/classes/sun/font/Type1Font.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/font/Type1Font.java	Thu Apr 16 21:08:04 2009 -0700
@@ -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 {
--- a/src/share/classes/sun/net/httpserver/Request.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/net/httpserver/Request.java	Thu Apr 16 21:08:04 2009 -0700
@@ -52,6 +52,9 @@
         os = rawout;
         do {
             startLine = readLine();
+            if (startLine == null) {
+                return;
+            }
             /* skip blank lines */
         } while (startLine == null ? false : startLine.equals (""));
     }
--- a/src/share/classes/sun/net/httpserver/ServerImpl.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/net/httpserver/ServerImpl.java	Thu Apr 16 21:08:04 2009 -0700
@@ -433,6 +433,7 @@
                         rawin = sslStreams.getInputStream();
                         rawout = sslStreams.getOutputStream();
                         engine = sslStreams.getSSLEngine();
+                        connection.sslStreams = sslStreams;
                     } else {
                         rawin = new BufferedInputStream(
                             new Request.ReadStream (
@@ -442,6 +443,8 @@
                             ServerImpl.this, chan
                         );
                     }
+                    connection.raw = rawin;
+                    connection.rawout = rawout;
                 }
                 Request req = new Request (rawin, rawout);
                 requestLine = req.requestLine();
--- a/src/share/classes/sun/security/krb5/KrbKdcReq.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/security/krb5/KrbKdcReq.java	Thu Apr 16 21:08:04 2009 -0700
@@ -274,27 +274,31 @@
                                + ",Attempt =" + i
                                + ", #bytes=" + obuf.length);
                     }
-                    /*
-                     * Send the data to the kdc.
-                     */
+                    try {
+                        /*
+                         * Send the data to the kdc.
+                         */
 
                     kdcClient.send(obuf);
 
-                    /*
-                     * And get a response.
-                     */
-                    try {
-                        ibuf = kdcClient.receive();
-                        break;
-                    } catch (SocketTimeoutException se) {
-                        if (DEBUG) {
-                            System.out.println ("SocketTimeOutException with " +
-                                                "attempt: " + i);
+                        /*
+                         * And get a response.
+                         */
+                        try {
+                            ibuf = kdcClient.receive();
+                            break;
+                        } catch (SocketTimeoutException se) {
+                            if (DEBUG) {
+                                System.out.println ("SocketTimeOutException with " +
+                                                    "attempt: " + i);
+                            }
+                            if (i == DEFAULT_KDC_RETRY_LIMIT) {
+                                ibuf = null;
+                                throw se;
+                            }
                         }
-                        if (i == DEFAULT_KDC_RETRY_LIMIT) {
-                            ibuf = null;
-                            throw se;
-                        }
+                    } finally {
+                        kdcClient.close();
                     }
                 }
             }
--- a/src/share/classes/sun/security/krb5/internal/UDPClient.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/security/krb5/internal/UDPClient.java	Thu Apr 16 21:08:04 2009 -0700
@@ -93,4 +93,7 @@
         return data;
     }
 
+    public void close() {
+        dgSocket.close();
+    }
 }
--- a/src/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java	Thu Apr 16 21:08:04 2009 -0700
@@ -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
@@ -38,6 +38,8 @@
 import sun.security.pkcs11.wrapper.*;
 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
 
+import sun.security.rsa.RSAKeyFactory;
+
 /**
  * KeyPairGenerator implementation class. This class currently supports
  * RSA, DSA, DH, and EC.
@@ -66,7 +68,7 @@
     private AlgorithmParameterSpec params;
 
     // for RSA, selected or default value of public exponent, always valid
-    private BigInteger rsaPublicExponent;
+    private BigInteger rsaPublicExponent = RSAKeyGenParameterSpec.F4;
 
     // SecureRandom instance, if specified in init
     private SecureRandom random;
@@ -88,19 +90,19 @@
     public void initialize(int keySize, SecureRandom random) {
         token.ensureValid();
         try {
-            checkKeySize(keySize);
+            checkKeySize(keySize, null);
         } catch (InvalidAlgorithmParameterException e) {
             throw new InvalidParameterException(e.getMessage());
         }
         this.keySize = keySize;
         this.params = null;
         this.random = random;
-        this.rsaPublicExponent = RSAKeyGenParameterSpec.F4;
         if (algorithm.equals("EC")) {
             params = P11ECKeyFactory.getECParameterSpec(keySize);
             if (params == null) {
-                throw new InvalidParameterException
-                ("No EC parameters available for key size " + keySize + " bits");
+                throw new InvalidParameterException(
+                    "No EC parameters available for key size "
+                    + keySize + " bits");
             }
         }
     }
@@ -115,8 +117,10 @@
                         ("DHParameterSpec required for Diffie-Hellman");
             }
             DHParameterSpec dhParams = (DHParameterSpec)params;
-            this.keySize = dhParams.getP().bitLength();
-            this.params = params;
+            int tmpKeySize = dhParams.getP().bitLength();
+            checkKeySize(tmpKeySize, dhParams);
+            this.keySize = tmpKeySize;
+            this.params = dhParams;
             // XXX sanity check params
         } else if (algorithm.equals("RSA")) {
             if (params instanceof RSAKeyGenParameterSpec == false) {
@@ -124,7 +128,9 @@
                         ("RSAKeyGenParameterSpec required for RSA");
             }
             RSAKeyGenParameterSpec rsaParams = (RSAKeyGenParameterSpec)params;
-            this.keySize = rsaParams.getKeysize();
+            int tmpKeySize = rsaParams.getKeysize();
+            checkKeySize(tmpKeySize, rsaParams);
+            this.keySize = tmpKeySize;
             this.params = null;
             this.rsaPublicExponent = rsaParams.getPublicExponent();
             // XXX sanity check params
@@ -134,13 +140,16 @@
                         ("DSAParameterSpec required for DSA");
             }
             DSAParameterSpec dsaParams = (DSAParameterSpec)params;
-            this.keySize = dsaParams.getP().bitLength();
-            this.params = params;
+            int tmpKeySize = dsaParams.getP().bitLength();
+            checkKeySize(tmpKeySize, dsaParams);
+            this.keySize = tmpKeySize;
+            this.params = dsaParams;
             // XXX sanity check params
         } else if (algorithm.equals("EC")) {
             ECParameterSpec ecParams;
             if (params instanceof ECParameterSpec) {
-                ecParams = P11ECKeyFactory.getECParameterSpec((ECParameterSpec)params);
+                ecParams = P11ECKeyFactory.getECParameterSpec(
+                    (ECParameterSpec)params);
                 if (ecParams == null) {
                     throw new InvalidAlgorithmParameterException
                         ("Unsupported curve: " + params);
@@ -156,16 +165,17 @@
                 throw new InvalidAlgorithmParameterException
                     ("ECParameterSpec or ECGenParameterSpec required for EC");
             }
-            this.keySize = ecParams.getCurve().getField().getFieldSize();
+            int tmpKeySize = ecParams.getCurve().getField().getFieldSize();
+            checkKeySize(tmpKeySize, ecParams);
+            this.keySize = tmpKeySize;
             this.params = ecParams;
         } else {
             throw new ProviderException("Unknown algorithm: " + algorithm);
         }
         this.random = random;
-        checkKeySize(keySize);
     }
 
-    private void checkKeySize(int keySize)
+    private void checkKeySize(int keySize, AlgorithmParameterSpec params)
             throws InvalidAlgorithmParameterException {
         if (algorithm.equals("EC")) {
             if (keySize < 112) {
@@ -178,13 +188,28 @@
                     ("Key size must be at most 2048 bit");
             }
             return;
+        } else if (algorithm.equals("RSA")) {
+            BigInteger tmpExponent = rsaPublicExponent;
+            if (params != null) {
+                // Already tested for instanceof RSAKeyGenParameterSpec above
+                tmpExponent =
+                    ((RSAKeyGenParameterSpec)params).getPublicExponent();
+            }
+            try {
+                // This provider supports 64K or less.
+                RSAKeyFactory.checkKeyLengths(keySize, tmpExponent,
+                    512, 64 * 1024);
+            } catch (InvalidKeyException e) {
+                throw new InvalidAlgorithmParameterException(e.getMessage());
+            }
+            return;
         }
+
         if (keySize < 512) {
             throw new InvalidAlgorithmParameterException
                 ("Key size must be at least 512 bit");
         }
-        if (algorithm.equals("RSA") ||
-                (algorithm.equals("DH") && (params != null))) {
+        if (algorithm.equals("DH") && (params != null)) {
             // sanity check, nobody really wants keys this large
             if (keySize > 64 * 1024) {
                 throw new InvalidAlgorithmParameterException
--- a/src/share/classes/sun/security/pkcs11/P11KeyStore.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/security/pkcs11/P11KeyStore.java	Thu Apr 16 21:08:04 2009 -0700
@@ -80,6 +80,8 @@
 import sun.security.pkcs11.wrapper.*;
 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
 
+import sun.security.rsa.RSAKeyFactory;
+
 final class P11KeyStore extends KeyStoreSpi {
 
     private static final CK_ATTRIBUTE ATTR_CLASS_CERT =
@@ -1328,6 +1330,15 @@
             BigInteger modulus = attrs[0].getBigInteger();
             keyLength = modulus.bitLength();
 
+            // This check will combine our "don't care" values here
+            // with the system-wide min/max values.
+            try {
+                RSAKeyFactory.checkKeyLengths(keyLength, null,
+                    -1, Integer.MAX_VALUE);
+            } catch (InvalidKeyException e) {
+                throw new KeyStoreException(e.getMessage());
+            }
+
             return P11Key.privateKey(session,
                                 oHandle,
                                 keyType,
--- a/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003 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
@@ -35,6 +35,8 @@
 import sun.security.pkcs11.wrapper.*;
 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
 
+import sun.security.rsa.RSAKeyFactory;
+
 /**
  * RSA KeyFactory implemenation.
  *
@@ -131,6 +133,9 @@
         } catch (PKCS11Exception e) {
             throw new InvalidKeySpecException
                 ("Could not create RSA public key", e);
+        } catch (InvalidKeyException e) {
+            throw new InvalidKeySpecException
+                ("Could not create RSA public key", e);
         }
     }
 
@@ -175,11 +180,15 @@
         } catch (PKCS11Exception e) {
             throw new InvalidKeySpecException
                 ("Could not create RSA private key", e);
+        } catch (InvalidKeyException e) {
+            throw new InvalidKeySpecException
+                ("Could not create RSA private key", e);
         }
     }
 
     private PublicKey generatePublic(BigInteger n, BigInteger e)
-            throws PKCS11Exception {
+            throws PKCS11Exception, InvalidKeyException {
+        RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);
         CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
             new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
             new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
@@ -200,7 +209,8 @@
     }
 
     private PrivateKey generatePrivate(BigInteger n, BigInteger d)
-            throws PKCS11Exception {
+            throws PKCS11Exception, InvalidKeyException {
+        RSAKeyFactory.checkKeyLengths(n.bitLength(), null, -1, 64 * 1024);
         CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
             new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
             new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
@@ -222,7 +232,9 @@
 
     private PrivateKey generatePrivate(BigInteger n, BigInteger e,
             BigInteger d, BigInteger p, BigInteger q, BigInteger pe,
-            BigInteger qe, BigInteger coeff) throws PKCS11Exception {
+            BigInteger qe, BigInteger coeff) throws PKCS11Exception,
+            InvalidKeyException {
+        RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);
         CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
             new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
             new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
--- a/src/share/classes/sun/security/pkcs11/SunPKCS11.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/security/pkcs11/SunPKCS11.java	Thu Apr 16 21:08:04 2009 -0700
@@ -120,11 +120,13 @@
     }
 
     /**
-     * @deprecated use new SunPKCS11(String) or new SunPKCS11(InputStream) instead
+     * @deprecated use new SunPKCS11(String) or new SunPKCS11(InputStream)
+     *         instead
      */
     @Deprecated
     public SunPKCS11(String configName, InputStream configStream) {
-        super("SunPKCS11-" + Config.getConfig(configName, configStream).getName(),
+        super("SunPKCS11-" +
+            Config.getConfig(configName, configStream).getName(),
             1.7d, Config.getConfig(configName, configStream).getDescription());
         this.configName = configName;
         this.config = Config.removeConfig(configName);
@@ -153,7 +155,8 @@
         //
         // If we are in Secmod mode and configured to use either the
         // nssKeyStore or the nssTrustAnchors module, we automatically
-        // switch to using the NSS trust attributes for trusted certs (KeyStore).
+        // switch to using the NSS trust attributes for trusted certs
+        // (KeyStore).
         //
 
         if (useSecmod) {
@@ -168,33 +171,40 @@
                 if (secmod.isInitialized()) {
                     if (nssSecmodDirectory != null) {
                         String s = secmod.getConfigDir();
-                        if ((s != null) && (s.equals(nssSecmodDirectory) == false)) {
+                        if ((s != null) &&
+                                (s.equals(nssSecmodDirectory) == false)) {
                             throw new ProviderException("Secmod directory "
                                 + nssSecmodDirectory
-                                + " invalid, NSS already initialized with " + s);
+                                + " invalid, NSS already initialized with "
+                                + s);
                         }
                     }
                     if (nssLibraryDirectory != null) {
                         String s = secmod.getLibDir();
-                        if ((s != null) && (s.equals(nssLibraryDirectory) == false)) {
+                        if ((s != null) &&
+                                (s.equals(nssLibraryDirectory) == false)) {
                             throw new ProviderException("NSS library directory "
                                 + nssLibraryDirectory
-                                + " invalid, NSS already initialized with " + s);
+                                + " invalid, NSS already initialized with "
+                                + s);
                         }
                     }
                 } else {
                     if (nssDbMode != DbMode.NO_DB) {
                         if (nssSecmodDirectory == null) {
-                            throw new ProviderException("Secmod not initialized and "
-                                + "nssSecmodDirectory not specified");
+                            throw new ProviderException(
+                                "Secmod not initialized and "
+                                 + "nssSecmodDirectory not specified");
                         }
                     } else {
                         if (nssSecmodDirectory != null) {
-                            throw new ProviderException
-                            ("nssSecmodDirectory must not be specified in noDb mode");
+                            throw new ProviderException(
+                                "nssSecmodDirectory must not be "
+                                + "specified in noDb mode");
                         }
                     }
-                    secmod.initialize(nssDbMode, nssSecmodDirectory, nssLibraryDirectory);
+                    secmod.initialize(nssDbMode, nssSecmodDirectory,
+                        nssLibraryDirectory);
                 }
             } catch (IOException e) {
                 // XXX which exception to throw
@@ -211,7 +221,8 @@
                 if (nssModule != null) {
                     moduleName = "fips";
                 } else {
-                    moduleName = (nssDbMode == DbMode.NO_DB) ? "crypto" : "keystore";
+                    moduleName = (nssDbMode == DbMode.NO_DB) ?
+                        "crypto" : "keystore";
                 }
             }
             if (moduleName.equals("fips")) {
@@ -253,10 +264,12 @@
                         + ": only " + k + " external NSS modules available");
                 }
             } else {
-                throw new ProviderException("Unknown NSS module: " + moduleName);
+                throw new ProviderException(
+                    "Unknown NSS module: " + moduleName);
             }
             if (nssModule == null) {
-                throw new ProviderException("NSS module not available: " + moduleName);
+                throw new ProviderException(
+                    "NSS module not available: " + moduleName);
             }
             if (nssModule.hasInitializedProvider()) {
                 throw new ProviderException("Secmod module already configured");
@@ -296,8 +309,9 @@
             initArgs.flags = CKF_OS_LOCKING_OK;
             PKCS11 tmpPKCS11;
             try {
-                tmpPKCS11 = PKCS11.getInstance
-                    (library, functionList, initArgs, config.getOmitInitialize());
+                tmpPKCS11 = PKCS11.getInstance(
+                    library, functionList, initArgs,
+                    config.getOmitInitialize());
             } catch (PKCS11Exception e) {
                 if (debug != null) {
                     debug.println("Multi-threaded initialization failed: " + e);
@@ -312,8 +326,8 @@
                 } else {
                     initArgs.flags = 0;
                 }
-                tmpPKCS11 = PKCS11.getInstance
-                    (library, functionList, initArgs, config.getOmitInitialize());
+                tmpPKCS11 = PKCS11.getInstance(library,
+                    functionList, initArgs, config.getOmitInitialize());
             }
             p11 = tmpPKCS11;
 
@@ -336,8 +350,10 @@
                     System.out.println("Slots with tokens: " + toString(slots));
                 }
                 if (slotID < 0) {
-                    if ((slotListIndex < 0) || (slotListIndex >= slots.length)) {
-                        throw new ProviderException("slotListIndex is " + slotListIndex
+                    if ((slotListIndex < 0)
+                            || (slotListIndex >= slots.length)) {
+                        throw new ProviderException("slotListIndex is "
+                            + slotListIndex
                             + " but token only has " + slots.length + " slots");
                     }
                     slotID = slots[slotListIndex];
@@ -575,12 +591,15 @@
         d(KF, "DH",             P11DHKeyFactory,        s("DiffieHellman"),
                 m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));
         d(KF, "EC",             P11DHKeyFactory,
-                m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE, CKM_ECDSA, CKM_ECDSA_SHA1));
+                m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
+                    CKM_ECDSA, CKM_ECDSA_SHA1));
 
         // AlgorithmParameters for EC.
         // Only needed until we have an EC implementation in the SUN provider.
-        d(AGP, "EC",            "sun.security.ec.ECParameters", s("1.2.840.10045.2.1"),
-                m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE, CKM_ECDSA, CKM_ECDSA_SHA1));
+        d(AGP, "EC",            "sun.security.ec.ECParameters",
+                                                s("1.2.840.10045.2.1"),
+                m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
+                    CKM_ECDSA, CKM_ECDSA_SHA1));
 
         d(KA, "DH",             P11KeyAgreement,        s("DiffieHellman"),
                 m(CKM_DH_PKCS_DERIVE));
@@ -654,12 +673,16 @@
         d(SIG, "SHA512withRSA", P11Signature,
                 m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
 
-        d(KG, "SunTlsRsaPremasterSecret", "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
+        d(KG, "SunTlsRsaPremasterSecret",
+                    "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
                 m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
-        d(KG, "SunTlsMasterSecret", "sun.security.pkcs11.P11TlsMasterSecretGenerator",
+        d(KG, "SunTlsMasterSecret",
+                    "sun.security.pkcs11.P11TlsMasterSecretGenerator",
                 m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,
-                    CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_MASTER_KEY_DERIVE_DH));
-        d(KG, "SunTlsKeyMaterial", "sun.security.pkcs11.P11TlsKeyMaterialGenerator",
+                    CKM_SSL3_MASTER_KEY_DERIVE_DH,
+                    CKM_TLS_MASTER_KEY_DERIVE_DH));
+        d(KG, "SunTlsKeyMaterial",
+                    "sun.security.pkcs11.P11TlsKeyMaterialGenerator",
                 m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));
         d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",
                 m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));
@@ -773,6 +796,13 @@
             System.out.println(token.tokenInfo);
         }
         long[] supportedMechanisms = p11.C_GetMechanismList(slotID);
+
+        // Create a map from the various Descriptors to the "most
+        // preferred" mechanism that was defined during the
+        // static initialization.  For example, DES/CBC/PKCS5Padding
+        // could be mapped to CKM_DES_CBC_PAD or CKM_DES_CBC.  Prefer
+        // the earliest entry.  When asked for "DES/CBC/PKCS5Padding", we
+        // return a CKM_DES_CBC_PAD.
         final Map<Descriptor,Integer> supportedAlgs =
                                         new HashMap<Descriptor,Integer>();
         for (int i = 0; i < supportedMechanisms.length; i++) {
@@ -807,6 +837,9 @@
                     supportedAlgs.put(d, integerMech);
                     continue;
                 }
+                // See if there is something "more preferred"
+                // than what we currently have in the supportedAlgs
+                // map.
                 int intOldMech = oldMech.intValue();
                 for (int j = 0; j < d.mechanisms.length; j++) {
                     int nextMech = d.mechanisms[j];
--- a/src/share/classes/sun/security/rsa/RSAKeyFactory.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/security/rsa/RSAKeyFactory.java	Thu Apr 16 21:08:04 2009 -0700
@@ -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
@@ -31,6 +31,8 @@
 import java.security.interfaces.*;
 import java.security.spec.*;
 
+import sun.security.action.GetPropertyAction;
+
 /**
  * KeyFactory for RSA keys. Keys must be instances of PublicKey or PrivateKey
  * and getAlgorithm() must return "RSA". For such keys, it supports conversion
@@ -68,6 +70,24 @@
     private final static Class<?> x509KeySpecClass  = X509EncodedKeySpec.class;
     private final static Class<?> pkcs8KeySpecClass = PKCS8EncodedKeySpec.class;
 
+    public final static int MIN_MODLEN = 512;
+    public final static int MAX_MODLEN = 16384;
+
+    /*
+     * If the modulus length is above this value, restrict the size of
+     * the exponent to something that can be reasonably computed.  We
+     * could simply hardcode the exp len to something like 64 bits, but
+     * this approach allows flexibility in case impls would like to use
+     * larger module and exponent values.
+     */
+    public final static int MAX_MODLEN_RESTRICT_EXP = 3072;
+    public final static int MAX_RESTRICTED_EXPLEN = 64;
+
+    private static final boolean restrictExpLen =
+        "true".equalsIgnoreCase(AccessController.doPrivileged(
+            new GetPropertyAction(
+                "sun.security.rsa.restrictRSAExponent", "true")));
+
     // instance used for static translateKey();
     private final static RSAKeyFactory INSTANCE = new RSAKeyFactory();
 
@@ -76,74 +96,79 @@
     }
 
     /**
-     * Static method to convert Key into a useable instance of
-     * RSAPublicKey or RSAPrivate(Crt)Key. Check the key and convert it
-     * to a SunRsaSign key if necessary. If the key is not an RSA key
-     * or cannot be used, throw an InvalidKeyException.
-     *
-     * The difference between this method and engineTranslateKey() is that
-     * we do not convert keys of other providers that are already an
-     * instance of RSAPublicKey or RSAPrivate(Crt)Key.
+     * Static method to convert Key into an instance of RSAPublicKeyImpl
+     * or RSAPrivate(Crt)KeyImpl. If the key is not an RSA key or cannot be
+     * used, throw an InvalidKeyException.
      *
      * Used by RSASignature and RSACipher.
      */
     public static RSAKey toRSAKey(Key key) throws InvalidKeyException {
-        if (key instanceof RSAKey) {
-            RSAKey rsaKey = (RSAKey)key;
-            checkKey(rsaKey);
-            return rsaKey;
+        if ((key instanceof RSAPrivateKeyImpl) ||
+            (key instanceof RSAPrivateCrtKeyImpl) ||
+            (key instanceof RSAPublicKeyImpl)) {
+            return (RSAKey)key;
         } else {
             return (RSAKey)INSTANCE.engineTranslateKey(key);
         }
     }
 
-    /**
-     * Check that the given RSA key is valid.
+    /*
+     * Single test entry point for all of the mechanisms in the SunRsaSign
+     * provider (RSA*KeyImpls).  All of the tests are the same.
+     *
+     * For compatibility, we round up to the nearest byte here:
+     * some Key impls might pass in a value within a byte of the
+     * real value.
      */
-    private static void checkKey(RSAKey key) throws InvalidKeyException {
-        // check for subinterfaces, omit additional checks for our keys
-        if (key instanceof RSAPublicKey) {
-            if (key instanceof RSAPublicKeyImpl) {
-                return;
-            }
-        } else if (key instanceof RSAPrivateKey) {
-            if ((key instanceof RSAPrivateCrtKeyImpl)
-                    || (key instanceof RSAPrivateKeyImpl)) {
-                return;
-            }
-        } else {
-            throw new InvalidKeyException("Neither a public nor a private key");
-        }
-        // RSAKey does not extend Key, so we need to do a cast
-        String keyAlg = ((Key)key).getAlgorithm();
-        if (keyAlg.equals("RSA") == false) {
-            throw new InvalidKeyException("Not an RSA key: " + keyAlg);
-        }
-        BigInteger modulus;
-        // some providers implement RSAKey for keys where the values are
-        // not accessible (although they should). Detect those here
-        // for a more graceful failure.
-        try {
-            modulus = key.getModulus();
-            if (modulus == null) {
-                throw new InvalidKeyException("Modulus is missing");
-            }
-        } catch (RuntimeException e) {
-            throw new InvalidKeyException(e);
-        }
-        checkKeyLength(modulus);
+    static void checkRSAProviderKeyLengths(int modulusLen, BigInteger exponent)
+            throws InvalidKeyException {
+        checkKeyLengths(((modulusLen + 7) & ~7), exponent,
+            RSAKeyFactory.MIN_MODLEN, Integer.MAX_VALUE);
     }
 
     /**
-     * Check the length of the modulus of an RSA key. We only support keys
-     * at least 505 bits long.
+     * Check the length of an RSA key modulus/exponent to make sure it
+     * is not too short or long.  Some impls have their own min and
+     * max key sizes that may or may not match with a system defined value.
+     *
+     * @param modulusLen the bit length of the RSA modulus.
+     * @param exponent the RSA exponent
+     * @param minModulusLen if > 0, check to see if modulusLen is at
+     *        least this long, otherwise unused.
+     * @param maxModulusLen caller will allow this max number of bits.
+     *        Allow the smaller of the system-defined maximum and this param.
+     *
+     * @throws InvalidKeyException if any of the values are unacceptable.
      */
-    static void checkKeyLength(BigInteger modulus) throws InvalidKeyException {
-        if (modulus.bitLength() < 505) {
-            // some providers may generate slightly shorter keys
-            // accept them if the encoding is at least 64 bytes long
-            throw new InvalidKeyException
-                ("RSA keys must be at least 512 bits long");
+     public static void checkKeyLengths(int modulusLen, BigInteger exponent,
+            int minModulusLen, int maxModulusLen) throws InvalidKeyException {
+
+        if ((minModulusLen > 0) && (modulusLen < (minModulusLen))) {
+            throw new InvalidKeyException( "RSA keys must be at least " +
+                minModulusLen + " bits long");
+        }
+
+        // Even though our policy file may allow this, we don't want
+        // either value (mod/exp) to be too big.
+
+        int maxLen = Math.min(maxModulusLen, MAX_MODLEN);
+
+        // If a RSAPrivateKey/RSAPublicKey, make sure the
+        // modulus len isn't too big.
+        if (modulusLen > maxLen) {
+            throw new InvalidKeyException(
+                "RSA keys must be no longer than " + maxLen + " bits");
+        }
+
+        // If a RSAPublicKey, make sure the exponent isn't too big.
+        if (restrictExpLen && (exponent != null) &&
+                (modulusLen > MAX_MODLEN_RESTRICT_EXP) &&
+                (exponent.bitLength() > MAX_RESTRICTED_EXPLEN)) {
+            throw new InvalidKeyException(
+                "RSA exponents can be no longer than " +
+                MAX_RESTRICTED_EXPLEN + " bits " +
+                " if modulus is greater than " +
+                MAX_MODLEN_RESTRICT_EXP + " bits");
         }
     }
 
--- a/src/share/classes/sun/security/rsa/RSAKeyPairGenerator.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/security/rsa/RSAKeyPairGenerator.java	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2004 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
@@ -47,7 +47,7 @@
     // public exponent to use
     private BigInteger publicExponent;
 
-    // size of the key to generate, >= 512
+    // size of the key to generate, >= RSAKeyFactory.MIN_MODLEN
     private int keySize;
 
     // PRNG to use
@@ -60,15 +60,16 @@
 
     // initialize the generator. See JCA doc
     public void initialize(int keySize, SecureRandom random) {
-        if (keySize < 512) {
-            throw new InvalidParameterException
-                ("Key size must be at least 512 bits");
+
+        // do not allow unreasonably small or large key sizes,
+        // probably user error
+        try {
+            RSAKeyFactory.checkKeyLengths(keySize, RSAKeyGenParameterSpec.F4,
+                512, 64 * 1024);
+        } catch (InvalidKeyException e) {
+            throw new InvalidParameterException(e.getMessage());
         }
-        if (keySize > 64 * 1024) {
-            // do not allow unreasonably large key sizes, probably user error
-            throw new InvalidParameterException
-                ("Key size must be 65536 bits or less");
-        }
+
         this.keySize = keySize;
         this.random = random;
         this.publicExponent = RSAKeyGenParameterSpec.F4;
@@ -77,35 +78,41 @@
     // second initialize method. See JCA doc.
     public void initialize(AlgorithmParameterSpec params, SecureRandom random)
             throws InvalidAlgorithmParameterException {
+
         if (params instanceof RSAKeyGenParameterSpec == false) {
             throw new InvalidAlgorithmParameterException
                 ("Params must be instance of RSAKeyGenParameterSpec");
         }
+
         RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params;
-        keySize = rsaSpec.getKeysize();
-        publicExponent = rsaSpec.getPublicExponent();
-        this.random = random;
-        if (keySize < 512) {
-            throw new InvalidAlgorithmParameterException
-                ("Key size must be at least 512 bits");
-        }
-        if (keySize > 64 * 1024) {
-            // do not allow unreasonably large key sizes, probably user error
-            throw new InvalidAlgorithmParameterException
-                ("Key size must be 65536 bits or less");
-        }
-        if (publicExponent == null) {
-            publicExponent = RSAKeyGenParameterSpec.F4;
+        int tmpKeySize = rsaSpec.getKeysize();
+        BigInteger tmpPublicExponent = rsaSpec.getPublicExponent();
+
+        if (tmpPublicExponent == null) {
+            tmpPublicExponent = RSAKeyGenParameterSpec.F4;
         } else {
-            if (publicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
+            if (tmpPublicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
                 throw new InvalidAlgorithmParameterException
                         ("Public exponent must be 3 or larger");
             }
-            if (publicExponent.bitLength() > keySize) {
+            if (tmpPublicExponent.bitLength() > tmpKeySize) {
                 throw new InvalidAlgorithmParameterException
                         ("Public exponent must be smaller than key size");
             }
         }
+
+        // do not allow unreasonably large key sizes, probably user error
+        try {
+            RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPublicExponent,
+                512, 64 * 1024);
+        } catch (InvalidKeyException e) {
+            throw new InvalidAlgorithmParameterException(
+                "Invalid key sizes", e);
+        }
+
+        this.keySize = tmpKeySize;
+        this.publicExponent = tmpPublicExponent;
+        this.random = random;
     }
 
     // generate the keypair. See JCA doc
--- a/src/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2005 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
@@ -89,7 +89,7 @@
      */
     RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException {
         decode(encoded);
-        RSAKeyFactory.checkKeyLength(n);
+        RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
     }
 
     /**
@@ -107,7 +107,8 @@
         this.pe = pe;
         this.qe = qe;
         this.coeff = coeff;
-        RSAKeyFactory.checkKeyLength(n);
+        RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
+
         // generate the encoding
         algid = rsaId;
         try {
--- a/src/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003 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
@@ -61,7 +61,7 @@
     RSAPrivateKeyImpl(BigInteger n, BigInteger d) throws InvalidKeyException {
         this.n = n;
         this.d = d;
-        RSAKeyFactory.checkKeyLength(n);
+        RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), null);
         // generate the encoding
         algid = RSAPrivateCrtKeyImpl.rsaId;
         try {
--- a/src/share/classes/sun/security/rsa/RSAPublicKeyImpl.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/classes/sun/security/rsa/RSAPublicKeyImpl.java	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2005 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
@@ -56,10 +56,11 @@
      * Construct a key from its components. Used by the
      * RSAKeyFactory and the RSAKeyPairGenerator.
      */
-    public RSAPublicKeyImpl(BigInteger n, BigInteger e) throws InvalidKeyException {
+    public RSAPublicKeyImpl(BigInteger n, BigInteger e)
+            throws InvalidKeyException {
         this.n = n;
         this.e = e;
-        RSAKeyFactory.checkKeyLength(n);
+        RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
         // generate the encoding
         algid = RSAPrivateCrtKeyImpl.rsaId;
         try {
@@ -80,7 +81,7 @@
      */
     public RSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException {
         decode(encoded);
-        RSAKeyFactory.checkKeyLength(n);
+        RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
     }
 
     // see JCA doc
--- a/src/share/lib/management/jmxremote.access	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/lib/management/jmxremote.access	Thu Apr 16 21:08:04 2009 -0700
@@ -8,7 +8,7 @@
 # passwords.  To be functional, a role must have an entry in
 # both the password and the access files.
 #
-# Default location of this file is $JRE/lib/management/jmxremote.access
+# The default location of this file is $JRE/lib/management/jmxremote.access
 # You can specify an alternate location by specifying a property in 
 # the management config file $JRE/lib/management/management.properties
 # (See that file for details)
@@ -16,7 +16,7 @@
 # The file format for password and access files is syntactically the same
 # as the Properties file format.  The syntax is described in the Javadoc
 # for java.util.Properties.load.
-# Typical access file has multiple  lines, where each line is blank,
+# A typical access file has multiple lines, where each line is blank,
 # a comment (like this one), or an access control entry.
 #
 # An access control entry consists of a role name, and an
@@ -29,10 +29,38 @@
 #                   role can read measurements but cannot perform any action
 #                   that changes the environment of the running program.
 #       "readwrite" grants access to read and write attributes of MBeans,
-#                   to invoke operations on them, and to create or remove them.
-#		    This access should be granted to only trusted clients, 
-#                   since they can potentially interfere with the smooth
-#		    operation of a running program 
+#                   to invoke operations on them, and optionally
+#                   to create or remove them. This access should be granted
+#                   only to trusted clients, since they can potentially
+#                   interfere with the smooth operation of a running program.
+#
+# The "readwrite" access level can optionally be followed by the "create" and/or
+# "unregister" keywords.  The "unregister" keyword grants access to unregister
+# (delete) MBeans.  The "create" keyword grants access to create MBeans of a
+# particular class or of any class matching a particular pattern.  Access
+# should only be granted to create MBeans of known and trusted classes.
+#
+# For example, the following entry would grant readwrite access
+# to "controlRole", as well as access to create MBeans of the class
+# javax.management.monitor.CounterMonitor and to unregister any MBean:
+#  controlRole readwrite \
+#              create javax.management.monitor.CounterMonitorMBean \
+#              unregister
+# or equivalently:
+#  controlRole readwrite unregister create javax.management.monitor.CounterMBean
+#
+# The following entry would grant readwrite access as well as access to create
+# MBeans of any class in the packages javax.management.monitor and
+# javax.management.timer:
+#  controlRole readwrite \
+#              create javax.management.monitor.*,javax.management.timer.* \
+#              unregister
+#
+# The \ character is defined in the Properties file syntax to allow continuation
+# lines as shown here.  A * in a class pattern matches a sequence of characters
+# other than dot (.), so javax.management.monitor.* matches
+# javax.management.monitor.CounterMonitor but not
+# javax.management.monitor.foo.Bar.
 #
 # A given role should have at most one entry in this file.  If a role
 # has no entry, it has no access.
@@ -42,7 +70,10 @@
 #
 # Default access control entries:
 # o The "monitorRole" role has readonly access.  
-# o The "controlRole" role has readwrite access.
+# o The "controlRole" role has readwrite access and can create the standard
+#   Timer and Monitor MBeans defined by the JMX API.
 
 monitorRole   readonly
-controlRole   readwrite
+controlRole   readwrite \
+              create javax.management.monitor.*,javax.management.timer.* \
+              unregister
--- a/src/share/native/com/sun/java/util/jar/pack/bands.cpp	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/com/sun/java/util/jar/pack/bands.cpp	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2009 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
@@ -94,6 +94,7 @@
       assert(!valc->isMalloc);
     }
     xvs.init(u->rp, u->rplimit, valc);
+    CHECK;
     int X = xvs.getInt();
     if (valc->S() != 0) {
       assert(valc->min <= -256);
@@ -117,6 +118,7 @@
     byte XB_byte = (byte) XB;
     byte* XB_ptr = &XB_byte;
     cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, null);
+    CHECK;
   } else {
     NOT_PRODUCT(byte* meta_rp0 = u->meta_rp);
     assert(u->meta_rp != null);
@@ -215,8 +217,19 @@
   if (length == 0)  return 0;
   if (total_memo > 0)  return total_memo-1;
   int total = getInt();
+  // overflow checks require that none of the addends are <0,
+  // and that the partial sums never overflow (wrap negative)
+  if (total < 0) {
+    abort("overflow detected");
+    return 0;
+  }
   for (int k = length-1; k > 0; k--) {
+    int prev_total = total;
     total += vs[0].getInt();
+    if (total < prev_total) {
+      abort("overflow detected");
+      return 0;
+    }
   }
   rewind();
   total_memo = total+1;
--- a/src/share/native/com/sun/java/util/jar/pack/bytes.cpp	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/com/sun/java/util/jar/pack/bytes.cpp	Thu Apr 16 21:08:04 2009 -0700
@@ -56,7 +56,7 @@
     return;
   }
   byte* oldptr = ptr;
-  ptr = (byte*)::realloc(ptr, len_+1);
+  ptr = (len_ >= PSIZE_MAX) ? null : (byte*)::realloc(ptr, len_+1);
   if (ptr != null)  {
     mtrace('r', oldptr, 0);
     mtrace('m', ptr, len_+1);
@@ -128,7 +128,7 @@
 // Make sure there are 'o' bytes beyond the fill pointer,
 // advance the fill pointer, and return the old fill pointer.
 byte* fillbytes::grow(size_t s) {
-  size_t nlen = b.len+s;
+  size_t nlen = add_size(b.len, s);
   if (nlen <= allocated) {
     b.len = nlen;
     return limit()-s;
--- a/src/share/native/com/sun/java/util/jar/pack/coding.cpp	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/com/sun/java/util/jar/pack/coding.cpp	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2009 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
@@ -814,6 +814,7 @@
     }
     band_rp = vs.rp;
   }
+  CHECK;
 
   // Get an accurate upper limit now.
   vs0.rplimit = band_rp;
--- a/src/share/native/com/sun/java/util/jar/pack/defines.h	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/com/sun/java/util/jar/pack/defines.h	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2001-2009 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
@@ -47,11 +47,13 @@
 #define NOT_PRODUCT(xxx)
 #define assert(p)
 #define PRINTCR(args)
+#define VERSION_STRING "%s version %s\n"
 #else
 #define IF_PRODUCT(xxx)
 #define NOT_PRODUCT(xxx) xxx
 #define assert(p) ((p) || assert_failed(#p))
 #define PRINTCR(args)  u->verbose && u->printcr_if_verbose args
+#define VERSION_STRING "%s version non-product %s\n"
 extern "C" void breakpoint();
 extern int assert_failed(const char*);
 #define BREAK (breakpoint())
@@ -79,9 +81,9 @@
 
 #define lengthof(array) (sizeof(array)/sizeof(array[0]))
 
-#define NEW(T, n)    (T*) must_malloc((int)(sizeof(T)*(n)))
-#define U_NEW(T, n)  (T*) u->alloc(sizeof(T)*(n))
-#define T_NEW(T, n)  (T*) u->temp_alloc(sizeof(T)*(n))
+#define NEW(T, n)    (T*) must_malloc((int)(scale_size(n, sizeof(T))))
+#define U_NEW(T, n)  (T*) u->alloc(scale_size(n, sizeof(T)))
+#define T_NEW(T, n)  (T*) u->temp_alloc(scale_size(n, sizeof(T)))
 
 
 // bytes and byte arrays
@@ -153,6 +155,8 @@
 #define CHECK_NULL_(y,p)        _CHECK_DO((p)==null, return y)
 #define CHECK_NULL_0(p)         _CHECK_DO((p)==null, return 0)
 
+#define CHECK_COUNT(t)          if (t < 0){abort("bad value count");} CHECK
+
 #define STR_TRUE   "true"
 #define STR_FALSE  "false"
 
--- a/src/share/native/com/sun/java/util/jar/pack/main.cpp	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/com/sun/java/util/jar/pack/main.cpp	Thu Apr 16 21:08:04 2009 -0700
@@ -299,7 +299,7 @@
     case 'J':  argp += 1; break;  // skip ignored -Jxxx parameter
 
     case 'V':
-      fprintf(u.errstrm, "%s version %s\n", nbasename(argv[0]), sccsver);
+      fprintf(u.errstrm, VERSION_STRING, nbasename(argv[0]), sccsver);
       exit(0);
 
     case 'h':
--- a/src/share/native/com/sun/java/util/jar/pack/unpack.cpp	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/com/sun/java/util/jar/pack/unpack.cpp	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2001-2009 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
@@ -523,15 +523,39 @@
   enum {
     MAGIC_BYTES = 4,
     AH_LENGTH_0 = 3,  //minver, majver, options are outside of archive_size
+    AH_LENGTH_0_MAX = AH_LENGTH_0 + 1,  // options might have 2 bytes
     AH_LENGTH   = 26, //maximum archive header length (w/ all fields)
     // Length contributions from optional header fields:
     AH_FILE_HEADER_LEN = 5, // sizehi/lo/next/modtime/files
+    AH_ARCHIVE_SIZE_LEN = 2, // sizehi/lo only; part of AH_FILE_HEADER_LEN
     AH_CP_NUMBER_LEN = 4,  // int/float/long/double
     AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers
     AH_LENGTH_MIN = AH_LENGTH
         -(AH_FILE_HEADER_LEN+AH_SPECIAL_FORMAT_LEN+AH_CP_NUMBER_LEN),
+    ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN),
     FIRST_READ  = MAGIC_BYTES + AH_LENGTH_MIN
   };
+
+  assert(AH_LENGTH_MIN    == 15); // # of UNSIGNED5 fields required after archive_magic
+  assert(ARCHIVE_SIZE_MIN == 10); // # of UNSIGNED5 fields required after archive_size
+  // An absolute minimum null archive is magic[4], {minver,majver,options}[3],
+  // archive_size[0], cp_counts[8], class_counts[4], for a total of 19 bytes.
+  // (Note that archive_size is optional; it may be 0..10 bytes in length.)
+  // The first read must capture everything up through the options field.
+  // This happens to work even if {minver,majver,options} is a pathological
+  // 15 bytes long.  Legal pack files limit those three fields to 1+1+2 bytes.
+  assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0 * B_MAX);
+
+  // Up through archive_size, the largest possible archive header is
+  // magic[4], {minver,majver,options}[4], archive_size[10].
+  // (Note only the low 12 bits of options are allowed to be non-zero.)
+  // In order to parse archive_size, we need at least this many bytes
+  // in the first read.  Of course, if archive_size_hi is more than
+  // a byte, we probably will fail to allocate the buffer, since it
+  // will be many gigabytes long.  This is a practical, not an
+  // architectural limit to Pack200 archive sizes.
+  assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0_MAX + 2*B_MAX);
+
   bool foreign_buf = (read_input_fn == null);
   byte initbuf[(int)FIRST_READ + (int)C_SLOP + 200];  // 200 is for JAR I/O
   if (foreign_buf) {
@@ -547,7 +571,7 @@
     // There is no way to tell the caller that we used only part of them.
     // Therefore, the caller must use only a bare minimum of read-ahead.
     if (inbytes.len > FIRST_READ) {
-      abort("too much pushback");
+      abort("too much read-ahead");
       return;
     }
     input.set(initbuf, sizeof(initbuf));
@@ -557,7 +581,7 @@
     rplimit += inbytes.len;
     bytes_read += inbytes.len;
   }
-  // Read only 19 bytes, which is certain to contain #archive_size fields,
+  // Read only 19 bytes, which is certain to contain #archive_options fields,
   // but is certain not to overflow past the archive_header.
   input.b.len = FIRST_READ;
   if (!ensure_input(FIRST_READ))
@@ -629,26 +653,25 @@
 #undef ORBIT
   if ((archive_options & ~OPTION_LIMIT) != 0) {
     fprintf(errstrm, "Warning: Illegal archive options 0x%x\n",
-            archive_options);
-    // Do not abort.  If the format really changes, version numbers will bump.
-    //abort("illegal archive options");
+        archive_options);
+    abort("illegal archive options");
+    return;
   }
 
   if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
     uint hi = hdr.getInt();
     uint lo = hdr.getInt();
-    archive_size = band::makeLong(hi, lo);
+    julong x = band::makeLong(hi, lo);
+    archive_size = (size_t) x;
+    if (archive_size != x) {
+      // Silly size specified; force overflow.
+      archive_size = PSIZE_MAX+1;
+    }
     hdrVals += 2;
   } else {
     hdrValsSkipped += 2;
   }
 
-  if (archive_size != (size_t)archive_size) {
-    // Silly size specified.
-    abort("archive too large");
-    return;
-  }
-
   // Now we can size the whole archive.
   // Read everything else into a mega-buffer.
   rp = hdr.rp;
@@ -662,9 +685,18 @@
       abort("EOF reading fixed input buffer");
       return;
     }
-  } else if (archive_size > 0) {
-    input.set(U_NEW(byte, (size_t)(header_size_0 + archive_size + C_SLOP)),
-              (size_t) header_size_0 + (size_t)archive_size);
+  } else if (archive_size != 0) {
+    if (archive_size < ARCHIVE_SIZE_MIN) {
+      abort("impossible archive size");  // bad input data
+      return;
+    }
+    if (archive_size < header_size_1) {
+      abort("too much read-ahead");  // somehow we pre-fetched too much?
+      return;
+    }
+    input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)),
+              (size_t) header_size_0 + archive_size);
+    CHECK;
     assert(input.limit()[0] == 0);
     // Move all the bytes we read initially into the real buffer.
     input.b.copyFrom(initbuf, header_size);
@@ -673,17 +705,17 @@
   } else {
     // It's more complicated and painful.
     // A zero archive_size means that we must read until EOF.
-    assert(archive_size == 0);
     input.init(CHUNK*2);
     CHECK;
     input.b.len = input.allocated;
     rp = rplimit = input.base();
     // Set up input buffer as if we already read the header:
     input.b.copyFrom(initbuf, header_size);
+    CHECK;
     rplimit += header_size;
     while (ensure_input(input.limit() - rp)) {
       size_t dataSoFar = input_remaining();
-      size_t nextSize = dataSoFar + CHUNK;
+      size_t nextSize = add_size(dataSoFar, CHUNK);
       input.ensureSize(nextSize);
       CHECK;
       input.b.len = input.allocated;
@@ -715,8 +747,10 @@
 
   if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
     archive_next_count = hdr.getInt();
+    CHECK_COUNT(archive_next_count);
     archive_modtime = hdr.getInt();
     file_count = hdr.getInt();
+    CHECK_COUNT(file_count);
     hdrVals += 3;
   } else {
     hdrValsSkipped += 3;
@@ -724,7 +758,9 @@
 
   if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0) {
     band_headers_size = hdr.getInt();
+    CHECK_COUNT(band_headers_size);
     attr_definition_count = hdr.getInt();
+    CHECK_COUNT(attr_definition_count);
     hdrVals += 2;
   } else {
     hdrValsSkipped += 2;
@@ -744,13 +780,16 @@
       }
     }
     cp_counts[k] = hdr.getInt();
+    CHECK_COUNT(cp_counts[k]);
     hdrVals += 1;
   }
 
   ic_count = hdr.getInt();
+  CHECK_COUNT(ic_count);
   default_class_minver = hdr.getInt();
   default_class_majver = hdr.getInt();
   class_count = hdr.getInt();
+  CHECK_COUNT(class_count);
   hdrVals += 4;
 
   // done with archive_header
@@ -807,7 +846,6 @@
   bytes::of(band_headers.limit(), C_SLOP).clear(_meta_error);
 }
 
-
 void unpacker::finish() {
   if (verbose >= 1) {
     fprintf(errstrm,
@@ -973,12 +1011,12 @@
   // First band:  Read lengths of shared prefixes.
   if (len > PREFIX_SKIP_2)
     cp_Utf8_prefix.readData(len - PREFIX_SKIP_2);
-  NOT_PRODUCT(else cp_Utf8_prefix.readData(0));  // for asserts
+    NOT_PRODUCT(else cp_Utf8_prefix.readData(0));  // for asserts
 
   // Second band:  Read lengths of unshared suffixes:
   if (len > SUFFIX_SKIP_1)
     cp_Utf8_suffix.readData(len - SUFFIX_SKIP_1);
-  NOT_PRODUCT(else cp_Utf8_suffix.readData(0));  // for asserts
+    NOT_PRODUCT(else cp_Utf8_suffix.readData(0));  // for asserts
 
   bytes* allsuffixes = T_NEW(bytes, len);
   CHECK;
@@ -2117,6 +2155,7 @@
 
   field_descr.readData(field_count);
   read_attrs(ATTR_CONTEXT_FIELD, field_count);
+  CHECK;
 
   method_descr.readData(method_count);
   read_attrs(ATTR_CONTEXT_METHOD, method_count);
@@ -2124,6 +2163,7 @@
   CHECK;
 
   read_attrs(ATTR_CONTEXT_CLASS, class_count);
+  CHECK;
 
   read_code_headers();
 
@@ -2150,10 +2190,12 @@
   assert(endsWith(xxx_flags_hi.name, "_flags_hi"));
   if (haveLongFlags)
     xxx_flags_hi.readData(obj_count);
+  CHECK;
 
   band& xxx_flags_lo = ad.xxx_flags_lo();
   assert(endsWith(xxx_flags_lo.name, "_flags_lo"));
   xxx_flags_lo.readData(obj_count);
+  CHECK;
 
   // pre-scan flags, counting occurrences of each index bit
   julong indexMask = ad.flagIndexMask();  // which flag bits are index bits?
@@ -2176,11 +2218,13 @@
   assert(endsWith(xxx_attr_count.name, "_attr_count"));
   // There is one count element for each 1<<16 bit set in flags:
   xxx_attr_count.readData(ad.predefCount(X_ATTR_OVERFLOW));
+  CHECK;
 
   band& xxx_attr_indexes = ad.xxx_attr_indexes();
   assert(endsWith(xxx_attr_indexes.name, "_attr_indexes"));
   int overflowIndexCount = xxx_attr_count.getIntTotal();
   xxx_attr_indexes.readData(overflowIndexCount);
+  CHECK;
   // pre-scan attr indexes, counting occurrences of each value
   for (i = 0; i < overflowIndexCount; i++) {
     idx = xxx_attr_indexes.getInt();
@@ -2211,6 +2255,7 @@
     }
   }
   ad.xxx_attr_calls().readData(backwardCounts);
+  CHECK;
 
   // Read built-in bands.
   // Mostly, these are hand-coded equivalents to readBandData().
@@ -2219,42 +2264,53 @@
 
     count = ad.predefCount(CLASS_ATTR_SourceFile);
     class_SourceFile_RUN.readData(count);
+    CHECK;
 
     count = ad.predefCount(CLASS_ATTR_EnclosingMethod);
     class_EnclosingMethod_RC.readData(count);
     class_EnclosingMethod_RDN.readData(count);
+    CHECK;
 
     count = ad.predefCount(X_ATTR_Signature);
     class_Signature_RS.readData(count);
+    CHECK;
 
     ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
     ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
 
     count = ad.predefCount(CLASS_ATTR_InnerClasses);
     class_InnerClasses_N.readData(count);
+    CHECK;
+
     count = class_InnerClasses_N.getIntTotal();
     class_InnerClasses_RC.readData(count);
     class_InnerClasses_F.readData(count);
+    CHECK;
     // Drop remaining columns wherever flags are zero:
     count -= class_InnerClasses_F.getIntCount(0);
     class_InnerClasses_outer_RCN.readData(count);
     class_InnerClasses_name_RUN.readData(count);
+    CHECK;
 
     count = ad.predefCount(CLASS_ATTR_ClassFile_version);
     class_ClassFile_version_minor_H.readData(count);
     class_ClassFile_version_major_H.readData(count);
+    CHECK;
     break;
 
   case ATTR_CONTEXT_FIELD:
 
     count = ad.predefCount(FIELD_ATTR_ConstantValue);
     field_ConstantValue_KQ.readData(count);
+    CHECK;
 
     count = ad.predefCount(X_ATTR_Signature);
     field_Signature_RS.readData(count);
+    CHECK;
 
     ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
     ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
+    CHECK;
     break;
 
   case ATTR_CONTEXT_METHOD:
@@ -2266,15 +2322,18 @@
     method_Exceptions_N.readData(count);
     count = method_Exceptions_N.getIntTotal();
     method_Exceptions_RC.readData(count);
+    CHECK;
 
     count = ad.predefCount(X_ATTR_Signature);
     method_Signature_RS.readData(count);
+    CHECK;
 
     ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
     ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
     ad.readBandData(METHOD_ATTR_RuntimeVisibleParameterAnnotations);
     ad.readBandData(METHOD_ATTR_RuntimeInvisibleParameterAnnotations);
     ad.readBandData(METHOD_ATTR_AnnotationDefault);
+    CHECK;
     break;
 
   case ATTR_CONTEXT_CODE:
@@ -2286,8 +2345,10 @@
       return;
     }
     code_StackMapTable_N.readData(count);
+    CHECK;
     count = code_StackMapTable_N.getIntTotal();
     code_StackMapTable_frame_T.readData(count);
+    CHECK;
     // the rest of it depends in a complicated way on frame tags
     {
       int fat_frame_count = 0;
@@ -2321,18 +2382,23 @@
       // deal completely with fat frames:
       offset_count += fat_frame_count;
       code_StackMapTable_local_N.readData(fat_frame_count);
+      CHECK;
       type_count += code_StackMapTable_local_N.getIntTotal();
       code_StackMapTable_stack_N.readData(fat_frame_count);
       type_count += code_StackMapTable_stack_N.getIntTotal();
+      CHECK;
       // read the rest:
       code_StackMapTable_offset.readData(offset_count);
       code_StackMapTable_T.readData(type_count);
+      CHECK;
       // (7) [RCH]
       count = code_StackMapTable_T.getIntCount(7);
       code_StackMapTable_RC.readData(count);
+      CHECK;
       // (8) [PH]
       count = code_StackMapTable_T.getIntCount(8);
       code_StackMapTable_P.readData(count);
+      CHECK;
     }
 
     count = ad.predefCount(CODE_ATTR_LineNumberTable);
@@ -2654,6 +2720,7 @@
   code_max_na_locals.readData();
   code_handler_count.readData();
   totalHandlerCount += code_handler_count.getIntTotal();
+  CHECK;
 
   // Read handler specifications.
   // Cf. PackageReader.readCodeHandlers.
@@ -2661,8 +2728,10 @@
   code_handler_end_PO.readData(totalHandlerCount);
   code_handler_catch_PO.readData(totalHandlerCount);
   code_handler_class_RCN.readData(totalHandlerCount);
+  CHECK;
 
   read_attrs(ATTR_CONTEXT_CODE, totalFlagsCount);
+  CHECK;
 }
 
 static inline bool is_in_range(uint n, uint min, uint max) {
--- a/src/share/native/com/sun/java/util/jar/pack/unpack.h	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/com/sun/java/util/jar/pack/unpack.h	Thu Apr 16 21:08:04 2009 -0700
@@ -204,7 +204,7 @@
 
   // archive header fields
   int      magic, minver, majver;
-  julong   archive_size;
+  size_t   archive_size;
   int      archive_next_count, archive_options, archive_modtime;
   int      band_headers_size;
   int      file_count, attr_definition_count, ic_count, class_count;
--- a/src/share/native/com/sun/java/util/jar/pack/utils.cpp	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/com/sun/java/util/jar/pack/utils.cpp	Thu Apr 16 21:08:04 2009 -0700
@@ -46,14 +46,13 @@
 
 #include "unpack.h"
 
-void* must_malloc(int size) {
-  int msize = size;
-  assert(size >= 0);
+void* must_malloc(size_t size) {
+  size_t msize = size;
   #ifdef USE_MTRACE
-  if (msize < sizeof(int))
+  if (msize >= 0 && msize < sizeof(int))
     msize = sizeof(int);  // see 0xbaadf00d below
   #endif
-  void* ptr = malloc(msize);
+  void* ptr = (msize > PSIZE_MAX) ? null : malloc(msize);
   if (ptr != null) {
     memset(ptr, 0, size);
   } else {
--- a/src/share/native/com/sun/java/util/jar/pack/utils.h	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/com/sun/java/util/jar/pack/utils.h	Thu Apr 16 21:08:04 2009 -0700
@@ -25,13 +25,31 @@
 
 //Definitions of our util functions
 
-void* must_malloc(int size);
+void* must_malloc(size_t size);
 #ifndef USE_MTRACE
 #define mtrace(c, ptr, size)
 #else
 void mtrace(char c, void* ptr, size_t size);
 #endif
 
+// overflow management
+#define OVERFLOW ((size_t)-1)
+#define PSIZE_MAX (OVERFLOW/2)  /* normal size limit */
+
+inline size_t scale_size(size_t size, size_t scale) {
+  return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
+}
+
+inline size_t add_size(size_t size1, size_t size2) {
+  return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX)
+    ? OVERFLOW
+    : size1 + size2;
+}
+
+inline size_t add_size(size_t size1, size_t size2, int size3) {
+  return add_size(add_size(size1, size2), size3);
+}
+
 // These may be expensive, because they have to go via Java TSD,
 // if the optional u argument is missing.
 struct unpacker;
--- a/src/share/native/sun/awt/giflib/dgif_lib.c	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/sun/awt/giflib/dgif_lib.c	Thu Apr 16 21:08:04 2009 -0700
@@ -722,6 +722,10 @@
     GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
 
     READ(GifFile, &CodeSize, 1);    /* Read Code size from file. */
+    if (CodeSize >= 12) {
+        /* Invalid initial code size: report failure */
+        return GIF_ERROR;
+    }
     BitsPerPixel = CodeSize;
 
     Private->Buf[0] = 0;    /* Input Buffer empty. */
@@ -964,10 +968,13 @@
 
     /* If code cannot fit into RunningBits bits, must raise its size. Note
      * however that codes above 4095 are used for special signaling.  */
-    if (++Private->RunningCode > Private->MaxCode1 &&
-        Private->RunningBits < LZ_BITS) {
-        Private->MaxCode1 <<= 1;
-        Private->RunningBits++;
+    if (++Private->RunningCode > Private->MaxCode1) {
+        if (Private->RunningBits < LZ_BITS) {
+            Private->MaxCode1 <<= 1;
+            Private->RunningBits++;
+        } else {
+            Private->RunningCode = Private->MaxCode1;
+        }
     }
     return GIF_OK;
 }
--- a/src/share/native/sun/awt/image/gif/gifdecoder.c	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/sun/awt/image/gif/gifdecoder.c	Thu Apr 16 21:08:04 2009 -0700
@@ -191,6 +191,11 @@
     int passht = passinc;
     int len;
 
+    /* We have verified the initial code size on the java layer.
+     * Here we just check bounds for particular indexes. */
+    if (freeCode >= 4096 || maxCode >= 4096) {
+        return 0;
+    }
     if (blockh == 0 || raslineh == 0
         || prefixh == 0 || suffixh == 0
         || outCodeh == 0)
--- a/src/share/native/sun/awt/medialib/awt_ImagingLib.c	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/sun/awt/medialib/awt_ImagingLib.c	Thu Apr 16 21:08:04 2009 -0700
@@ -216,6 +216,16 @@
 
 #endif /* ! DEBUG */
 
+static int
+getMlibEdgeHint(jint edgeHint) {
+    switch (edgeHint) {
+    case java_awt_image_ConvolveOp_EDGE_NO_OP:
+        return MLIB_EDGE_DST_COPY_SRC;
+    case java_awt_image_ConvolveOp_EDGE_ZERO_FILL:
+    default:
+        return MLIB_EDGE_DST_FILL_ZERO;
+    }
+}
 
 /***************************************************************************
  *                          External Functions                             *
@@ -400,22 +410,10 @@
         }
     }
 
-    if (edgeHint == java_awt_image_ConvolveOp_EDGE_NO_OP) {
-        int kw2 = kwidth>>1;
-        int kh2 = kheight>>1;
-        int bsize = mlib_ImageGetChannels(src)*
-            (mlib_ImageGetType(src) == MLIB_BYTE ? 1 : 2);
-
-        void *dstDataP = mlib_ImageGetData(dst);
-        void *srcDataP = mlib_ImageGetData(src);
-        /* REMIND: Copy a smaller area */
-        memcpy(dstDataP, srcDataP, dst->width*dst->height*bsize);
-    }
-
     cmask = (1<<src->channels)-1;
     status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
                                (w-1)/2, (h-1)/2, scale, cmask,
-                               MLIB_EDGE_DST_NO_WRITE);
+                               getMlibEdgeHint(edgeHint));
 
     if (status != MLIB_SUCCESS) {
         printMedialibError(status);
@@ -660,22 +658,10 @@
         }
     }
 
-    if (edgeHint == java_awt_image_ConvolveOp_EDGE_NO_OP) {
-        int kw2 = kwidth>>1;
-        int kh2 = kheight>>1;
-        int bsize = mlib_ImageGetChannels(src)*
-            (mlib_ImageGetType(src) == MLIB_BYTE ? 1 : 2);
-
-        void *dstDataP = mlib_ImageGetData(dst);
-        void *srcDataP = mlib_ImageGetData(src);
-        /* REMIND: Copy a smaller area */
-        memcpy(dstDataP, srcDataP, dst->width*dst->height*bsize);
-    }
-
     cmask = (1<<src->channels)-1;
     status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
                                (w-1)/2, (h-1)/2, scale, cmask,
-                               MLIB_EDGE_DST_NO_WRITE);
+                               getMlibEdgeHint(edgeHint));
 
     if (status != MLIB_SUCCESS) {
         printMedialibError(status);
--- a/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/sun/awt/splashscreen/splashscreen_gfx_impl.h	Thu Apr 16 21:08:04 2009 -0700
@@ -31,7 +31,7 @@
 /* here come some very simple macros */
 
 /* advance a pointer p by sizeof(type)*n bytes */
-#define INCPN(type,p,n) ((p) = (type*)(p)+n)
+#define INCPN(type,p,n) ((p) = (type*)(p)+(n))
 
 /* advance a pointer by sizeof(type) */
 #define INCP(type,p) INCPN(type,(p),1)
--- a/src/share/native/sun/awt/splashscreen/splashscreen_gif.c	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/sun/awt/splashscreen/splashscreen_gif.c	Thu Apr 16 21:08:04 2009 -0700
@@ -62,6 +62,15 @@
     return rc;
 }
 
+/* These macro help to ensure that we only take part of frame that fits into
+   logical screen. */
+
+/* Ensure that p belongs to [pmin, pmax) interval. Returns fixed point (if fix is needed) */
+#define FIX_POINT(p, pmin, pmax) ( ((p) < (pmin)) ? (pmin) : (((p) > (pmax)) ? (pmax) : (p)))
+/* Ensures that line starting at point p does not exceed boundary pmax.
+   Returns fixed length (if fix is needed) */
+#define FIX_LENGTH(p, len, pmax) ( ((p) + (len)) > (pmax) ? ((pmax) - (p)) : (len))
+
 int
 SplashDecodeGif(Splash * splash, GifFileType * gif)
 {
@@ -70,6 +79,7 @@
     byte_t *pBitmapBits, *pOldBitmapBits;
     int i, j;
     int imageIndex;
+    int cx, cy, cw, ch; /* clamped coordinates */
     const int interlacedOffset[] = { 0, 4, 2, 1, 0 };   /* The way Interlaced image should. */
     const int interlacedJumps[] = { 8, 8, 4, 2, 1 };    /* be read - offsets and jumps... */
 
@@ -79,14 +89,31 @@
 
     SplashCleanup(splash);
 
+    if (!SAFE_TO_ALLOC(gif->SWidth, splash->imageFormat.depthBytes)) {
+        return 0;
+    }
     stride = gif->SWidth * splash->imageFormat.depthBytes;
     if (splash->byteAlignment > 1)
         stride =
             (stride + splash->byteAlignment - 1) & ~(splash->byteAlignment - 1);
 
+    if (!SAFE_TO_ALLOC(gif->SHeight, stride)) {
+        return 0;
+    }
+
+    if (!SAFE_TO_ALLOC(gif->ImageCount, sizeof(SplashImage*))) {
+        return 0;
+    }
     bufferSize = stride * gif->SHeight;
     pBitmapBits = (byte_t *) malloc(bufferSize);
+    if (!pBitmapBits) {
+        return 0;
+    }
     pOldBitmapBits = (byte_t *) malloc(bufferSize);
+    if (!pOldBitmapBits) {
+        free(pBitmapBits);
+        return 0;
+    }
     memset(pBitmapBits, 0, bufferSize);
 
     splash->width = gif->SWidth;
@@ -94,6 +121,11 @@
     splash->frameCount = gif->ImageCount;
     splash->frames = (SplashImage *)
         malloc(sizeof(SplashImage) * gif->ImageCount);
+    if (!splash->frames) {
+      free(pBitmapBits);
+      free(pOldBitmapBits);
+      return 0;
+    }
     memset(splash->frames, 0, sizeof(SplashImage) * gif->ImageCount);
     splash->loopCount = 1;
 
@@ -109,6 +141,11 @@
         int colorCount = 0;
         rgbquad_t colorMapBuf[SPLASH_COLOR_MAP_SIZE];
 
+        cx = FIX_POINT(desc->Left, 0, gif->SWidth);
+        cy = FIX_POINT(desc->Top, 0, gif->SHeight);
+        cw = FIX_LENGTH(desc->Left, desc->Width, gif->SWidth);
+        ch = FIX_LENGTH(desc->Top, desc->Height, gif->SHeight);
+
         if (colorMap) {
             if (colorMap->ColorCount <= SPLASH_COLOR_MAP_SIZE) {
                 colorCount = colorMap->ColorCount;
@@ -195,13 +232,22 @@
             for (; pass < npass; ++pass) {
                 int jump = interlacedJumps[pass];
                 int ofs = interlacedOffset[pass];
-                int numLines = (desc->Height + jump - 1 - ofs) / jump;
+                /* Number of source lines for current pass */
+                int numPassLines = (desc->Height + jump - ofs - 1) / jump;
+                /* Number of lines that fits to dest buffer */
+                int numLines = (ch + jump - ofs - 1) / jump;
 
                 initRect(&srcRect, 0, 0, desc->Width, numLines, 1,
                     desc->Width, pSrc, &srcFormat);
-                initRect(&dstRect, desc->Left, desc->Top + ofs, desc->Width,
-                    numLines, jump, stride, pBitmapBits, &splash->imageFormat);
-                pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
+
+                if (numLines > 0) {
+                    initRect(&dstRect, cx, cy + ofs, cw,
+                             numLines , jump, stride, pBitmapBits, &splash->imageFormat);
+
+                    pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
+                }
+                // skip extra source data
+                pSrc += (numPassLines - numLines) * srcRect.stride;
             }
         }
 
@@ -209,6 +255,12 @@
 
         splash->frames[imageIndex].bitmapBits =
             (rgbquad_t *) malloc(bufferSize);
+        if (!splash->frames[imageIndex].bitmapBits) {
+            free(pBitmapBits);
+            free(pOldBitmapBits);
+            /* Assuming that callee will take care of splash frames we have already allocated */
+            return 0;
+        }
         memcpy(splash->frames[imageIndex].bitmapBits, pBitmapBits, bufferSize);
 
         SplashInitFrameShape(splash, imageIndex);
@@ -224,27 +276,29 @@
             {
                 ImageRect dstRect;
                 rgbquad_t fillColor = 0;                        // 0 is transparent
-                if (transparentColor < 0) {
+
+                if (transparentColor > 0) {
                     fillColor= MAKE_QUAD_GIF(
                         colorMap->Colors[gif->SBackGroundColor], 0xff);
                 }
-                initRect(&dstRect, desc->Left, desc->Top,
-                    desc->Width, desc->Height, 1, stride,
-                    pBitmapBits, &splash->imageFormat);
+                initRect(&dstRect,
+                         cx, cy, cw, ch,
+                         1, stride,
+                         pBitmapBits, &splash->imageFormat);
                 fillRect(fillColor, &dstRect);
             }
             break;
         case GIF_DISPOSE_RESTORE:
             {
-
-                int lineSize = desc->Width * splash->imageFormat.depthBytes;
-
-                for (j = 0; j < desc->Height; j++) {
-                    int lineIndex = stride * (j + desc->Top) +
-                        desc->Left * splash->imageFormat.depthBytes;
-
-                    memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
-                        lineSize);
+                int lineSize = cw * splash->imageFormat.depthBytes;
+                if (lineSize > 0) {
+                    int lineOffset = cx * splash->imageFormat.depthBytes;
+                    int lineIndex = cy * stride + lineOffset;
+                    for (j=0; j<ch; j++) {
+                        memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
+                               lineSize);
+                        lineIndex += stride;
+                    }
                 }
             }
             break;
--- a/src/share/native/sun/awt/splashscreen/splashscreen_impl.h	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/sun/awt/splashscreen/splashscreen_impl.h	Thu Apr 16 21:08:04 2009 -0700
@@ -155,6 +155,10 @@
 
 void SplashInitFrameShape(Splash * splash, int imageIndex);
 
+#define SAFE_TO_ALLOC(c, sz)                                               \
+    (((c) > 0) && ((sz) > 0) &&                                            \
+     ((0xffffffffu / ((unsigned int)(c))) > (unsigned int)(sz)))
+
 #define dbgprintf printf
 
 #endif
--- a/src/share/native/sun/awt/splashscreen/splashscreen_png.c	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/share/native/sun/awt/splashscreen/splashscreen_png.c	Thu Apr 16 21:08:04 2009 -0700
@@ -103,9 +103,17 @@
 
     rowbytes = png_get_rowbytes(png_ptr, info_ptr);
 
+    if (!SAFE_TO_ALLOC(rowbytes, height)) {
+        goto done;
+    }
+
     if ((image_data = (unsigned char *) malloc(rowbytes * height)) == NULL) {
         goto done;
     }
+
+    if (!SAFE_TO_ALLOC(height, sizeof(png_bytep))) {
+        goto done;
+    }
     if ((row_pointers = (png_bytepp) malloc(height * sizeof(png_bytep)))
             == NULL) {
         goto done;
@@ -121,13 +129,28 @@
     splash->width = width;
     splash->height = height;
 
+    if (!SAFE_TO_ALLOC(splash->width, splash->imageFormat.depthBytes)) {
+        goto done;
+    }
     stride = splash->width * splash->imageFormat.depthBytes;
 
+    if (!SAFE_TO_ALLOC(splash->height, stride)) {
+        goto done;
+    }
     splash->frameCount = 1;
     splash->frames = (SplashImage *)
         malloc(sizeof(SplashImage) * splash->frameCount);
+
+    if (splash->frames == NULL) {
+        goto done;
+    }
+
     splash->loopCount = 1;
     splash->frames[0].bitmapBits = malloc(stride * splash->height);
+    if (splash->frames[0].bitmapBits == NULL) {
+        free(splash->frames);
+        goto done;
+    }
     splash->frames[0].delay = 0;
 
     /* FIXME: sort out the real format */
--- a/src/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-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
@@ -31,6 +31,7 @@
 import java.security.spec.RSAKeyGenParameterSpec;
 
 import sun.security.jca.JCAUtil;
+import sun.security.rsa.RSAKeyFactory;
 
 /**
  * RSA keypair generator.
@@ -43,8 +44,8 @@
 public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
 
     // Supported by Microsoft Base, Strong and Enhanced Cryptographic Providers
-    private static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384
-    private static final int KEY_SIZE_MAX = 16384;
+    static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384
+    static final int KEY_SIZE_MAX = 16384;
     private static final int KEY_SIZE_DEFAULT = 1024;
 
     // size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
@@ -59,7 +60,14 @@
     // random is always ignored
     public void initialize(int keySize, SecureRandom random) {
 
-        checkKeySize(keySize);
+        try {
+            RSAKeyFactory.checkKeyLengths(keySize, null,
+                KEY_SIZE_MIN, KEY_SIZE_MAX);
+        } catch (InvalidKeyException e) {
+            throw new InvalidParameterException(e.getMessage());
+        }
+
+        this.keySize = keySize;
     }
 
     // second initialize method. See JCA doc
@@ -67,21 +75,31 @@
     public void initialize(AlgorithmParameterSpec params, SecureRandom random)
             throws InvalidAlgorithmParameterException {
 
+        int tmpSize;
         if (params == null) {
-            checkKeySize(KEY_SIZE_DEFAULT);
-
+            tmpSize = KEY_SIZE_DEFAULT;
         } else if (params instanceof RSAKeyGenParameterSpec) {
 
             if (((RSAKeyGenParameterSpec) params).getPublicExponent() != null) {
                 throw new InvalidAlgorithmParameterException
                     ("Exponent parameter is not supported");
             }
-            checkKeySize(((RSAKeyGenParameterSpec) params).getKeysize());
+            tmpSize = ((RSAKeyGenParameterSpec) params).getKeysize();
 
         } else {
             throw new InvalidAlgorithmParameterException
                 ("Params must be an instance of RSAKeyGenParameterSpec");
         }
+
+        try {
+            RSAKeyFactory.checkKeyLengths(tmpSize, null,
+                KEY_SIZE_MIN, KEY_SIZE_MAX);
+        } catch (InvalidKeyException e) {
+            throw new InvalidAlgorithmParameterException(
+                "Invalid Key sizes", e);
+        }
+
+        this.keySize = tmpSize;
     }
 
     // generate the keypair. See JCA doc
@@ -95,18 +113,6 @@
         return new KeyPair(keys.getPublic(), keys.getPrivate());
     }
 
-    private void checkKeySize(int keySize) throws InvalidParameterException {
-        if (keySize < KEY_SIZE_MIN) {
-            throw new InvalidParameterException
-                ("Key size must be at least " + KEY_SIZE_MIN + " bits");
-        }
-        if (keySize > KEY_SIZE_MAX) {
-            throw new InvalidParameterException
-                ("Key size must be " + KEY_SIZE_MAX + " bits or less");
-        }
-        this.keySize = keySize;
-    }
-
     private static native RSAKeyPair generateRSAKeyPair(int keySize,
         String keyContainerName);
 }
--- a/src/windows/classes/sun/security/mscapi/RSASignature.java	Sun Apr 12 20:21:43 2009 -0700
+++ b/src/windows/classes/sun/security/mscapi/RSASignature.java	Thu Apr 16 21:08:04 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-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
@@ -38,6 +38,9 @@
 import java.security.Signature;
 import java.security.SignatureSpi;
 import java.security.SignatureException;
+import java.math.BigInteger;
+
+import sun.security.rsa.RSAKeyFactory;
 
 /**
  * RSA signature implementation. Supports RSA signing using PKCS#1 v1.5 padding.
@@ -124,7 +127,16 @@
 
             // convert key to MSCAPI format
 
-            byte[] modulusBytes = rsaKey.getModulus().toByteArray();
+            BigInteger modulus = rsaKey.getModulus();
+            BigInteger exponent =  rsaKey.getPublicExponent();
+
+            // Check against the local and global values to make sure
+            // the sizes are ok.  Round up to the nearest byte.
+            RSAKeyFactory.checkKeyLengths(((modulus.bitLength() + 7) & ~7),
+                exponent, -1, RSAKeyPairGenerator.KEY_SIZE_MAX);
+
+            byte[] modulusBytes = modulus.toByteArray();
+            byte[] exponentBytes = exponent.toByteArray();
 
             // Adjust key length due to sign bit
             int keyBitLength = (modulusBytes[0] == 0)
@@ -132,8 +144,7 @@
                 : modulusBytes.length * 8;
 
             byte[] keyBlob = generatePublicKeyBlob(
-                keyBitLength, modulusBytes,
-                rsaKey.getPublicExponent().toByteArray());
+                keyBitLength, modulusBytes, exponentBytes);
 
             publicKey = importPublicKey(keyBlob, keyBitLength);
 
@@ -166,12 +177,11 @@
         }
         privateKey = (sun.security.mscapi.RSAPrivateKey) key;
 
-        // Determine byte length from bit length
-        int keySize = (privateKey.bitLength() + 7) >> 3;
-
-        if (keySize < 64)
-            throw new InvalidKeyException(
-                "RSA keys must be at least 512 bits long");
+        // Check against the local and global values to make sure
+        // the sizes are ok.  Round up to nearest byte.
+        RSAKeyFactory.checkKeyLengths(((privateKey.bitLength() + 7) & ~7),
+            null, RSAKeyPairGenerator.KEY_SIZE_MIN,
+            RSAKeyPairGenerator.KEY_SIZE_MAX);
 
         if (needsReset) {
             messageDigest.reset();
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	Thu Apr 16 21:08:04 2009 -0700
@@ -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	Thu Apr 16 21:08:04 2009 -0700
@@ -0,0 +1,89 @@
+/*
+ * 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, Font.TRUETYPE_FONT);
+        badRead(8193, Font.TRUETYPE_FONT);
+
+        badRead(-2, Font.TYPE1_FONT);
+        badRead(8193, Font.TYPE1_FONT);
+
+        // Make sure GC has a chance to clean up before we exit.
+        System.gc(); System.gc();
+    }
+
+    static void badRead(final int retval, int fontType) {
+        int num = 2;
+        byte[] buff = new byte[16*8192]; // Multiple of 8192 is important.
+        for (int ct=0; ct<num; ++ct) {
+            try {
+                Font.createFont(
+                    fontType,
+                    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	Thu Apr 16 21:08:04 2009 -0700
@@ -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	Thu Apr 16 21:08:04 2009 -0700
@@ -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	Thu Apr 16 21:08:04 2009 -0700
@@ -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.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/image/ConvolveOp/EdgeNoOpCrash.java	Thu Apr 16 21:08:04 2009 -0700
@@ -0,0 +1,95 @@
+/*
+ * 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     6726779
+ * @summary Test verifies that ConvolveOp with the EDGE_NO_OP edge condition
+ *          does not cause JVM crash if size of source raster elements is
+ *          greather than size of the destination raster element.
+ *
+ * @run     main EdgeNoOpCrash
+ */
+import java.awt.Point;
+import java.awt.image.ConvolveOp;
+import java.awt.image.DataBuffer;
+import java.awt.image.ImagingOpException;
+import java.awt.image.Kernel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.util.Arrays;
+
+public class EdgeNoOpCrash {
+    private static final int w = 3000;
+    private static final int h = 200;
+
+    public static void main(String[] args) {
+        crashTest();
+    }
+
+    private static void crashTest() {
+        Raster src = createSrcRaster();
+        WritableRaster dst = createDstRaster();
+        ConvolveOp op = createConvolveOp(ConvolveOp.EDGE_NO_OP);
+        try {
+            op.filter(src, dst);
+        } catch (ImagingOpException e) {
+            /*
+             * The test pair of source and destination rasters
+             * may cause failure of the medialib convolution routine,
+             * so this exception is expected.
+             *
+             * The JVM crash is the only manifestation of this
+             * test failure.
+             */
+        }
+        System.out.println("Test PASSED.");
+    }
+
+    private static Raster createSrcRaster() {
+        WritableRaster r = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT,
+                w, h, 4, new Point(0, 0));
+
+        return r;
+    }
+
+    private static WritableRaster createDstRaster() {
+        WritableRaster r = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+                w, h, 4, new Point(0, 0));
+
+        return r;
+    }
+
+    private static ConvolveOp createConvolveOp(int edgeHint) {
+        final int kw = 3;
+        final int kh = 3;
+        float[] kdata = new float[kw * kh];
+        float v = 1f / kdata.length;
+        Arrays.fill(kdata, v);
+
+        Kernel k = new Kernel(kw, kh, kdata);
+        ConvolveOp op = new ConvolveOp(k, edgeHint, null);
+
+        return op;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/print/attribute/MediaMappingsTest.java	Thu Apr 16 21:08:04 2009 -0700
@@ -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 6652463
+ * @summary Verify media size-> media mappings can't be altered
+ * @run main MediaMappingsTest
+*/
+
+import javax.print.attribute.standard.MediaSize;
+import javax.print.attribute.standard.MediaSizeName;
+
+public class MediaMappingsTest {
+
+    public static void main(String args[]) {
+        MediaSize sizeA = MediaSize.getMediaSizeForName(MediaSizeName.A);
+        new MediaSize(1.0f, 2.0f, MediaSize.MM, MediaSizeName.A);
+        if (!sizeA.equals(MediaSize.getMediaSizeForName(MediaSizeName.A))) {
+             throw new RuntimeException("mapping changed");
+        }
+        MediaSize sizeB = MediaSize.getMediaSizeForName(MediaSizeName.B);
+        new MediaSize(1, 2, MediaSize.MM, MediaSizeName.B);
+        if (!sizeB.equals(MediaSize.getMediaSizeForName(MediaSizeName.B))) {
+             throw new RuntimeException("mapping changed");
+        }
+    }
+}
--- a/test/tools/launcher/MultipleJRE.sh	Sun Apr 12 20:21:43 2009 -0700
+++ b/test/tools/launcher/MultipleJRE.sh	Thu Apr 16 21:08:04 2009 -0700
@@ -1,14 +1,14 @@
 # @test MultipleJRE.sh
-# @bug 4811102 4953711 4955505 4956301 4991229 4998210 5018605 6387069
+# @bug 4811102 4953711 4955505 4956301 4991229 4998210 5018605 6387069 6733959
 # @build PrintVersion
 # @build UglyPrintVersion
+# @build ZipMeUp
 # @run shell MultipleJRE.sh
 # @summary Verify Multiple JRE version support
 # @author Joseph E. Kowalski
 
-
 #
-# 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
@@ -49,11 +49,26 @@
   exit 1
 fi
 
+JAVAEXE="$TESTJAVA/bin/java"
 JAVA="$TESTJAVA/bin/java -classpath $TESTCLASSES"
 JAR="$TESTJAVA/bin/jar"
 OS=`uname -s`;
 
 #
+# Tests whether we are on windows (true) or not.
+#
+IsWindows() {
+    case "$OS" in
+        Windows* | CYGWIN* )
+            printf "true"
+	;;
+	* )
+            printf "false"
+	;;
+    esac
+}
+
+#
 # Shell routine to test for the proper rejection of syntactically incorrect
 # version specifications.
 #
@@ -139,7 +154,6 @@
 	    $PACKAGE/UglyPrintVersion.class
 }
 
-
 #
 # Constructs a jar file with a fair number of "zip directory" entries and
 # the MANIFEST.MF entry at or near the end of that directory to validate
@@ -262,6 +276,29 @@
 	fi
 }
 
+# Tests very long Main-Class attribute in the jar
+TestLongMainClass() {
+    JVER=$1
+    if [ "$JVER" = "mklink" ]; then
+        JVER=XX
+        JDKXX=jdk/j2re$JVER
+        rm -rf jdk
+        mkdir jdk
+        ln -s $TESTJAVA $JDKXX
+        JAVA_VERSION_PATH="`pwd`/jdk"
+        export JAVA_VERSION_PATH
+    fi
+    $JAVAEXE -cp $TESTCLASSES ZipMeUp UglyBetty.jar 4097 
+    message="`$JAVAEXE -version:$JVER -jar UglyBetty.jar 2>&1`"
+    echo $message | grep "Error: main-class: attribute exceeds system limits" > /dev/null 2>&1
+    if [ $? -ne 0 ]; then
+        printf "Long manifest test did not get expected error"
+        exit 1
+    fi
+    unset JAVA_VERSION_PATH
+    rm -rf jdk
+}
+
 #
 # Main test sequence starts here
 #
@@ -280,14 +317,11 @@
 LaunchVM "" "${RELEASE}"
 CreateJar "" "0"
 LaunchVM "" "${RELEASE}"
-case "$OS" in
-	Windows* | CYGWIN* )
-		MAXIMUM_PATH=255;
-	;;
-	*)
-		MAXIMUM_PATH=1024;
-	;;
-esac
+if [ `IsWindows` = "true" ]; then
+    MAXIMUM_PATH=255;
+else
+    MAXIMUM_PATH=1024;
+fi
 
 PATH_LENGTH=`printf "%s" "$UGLYCLASS" | wc -c`
 if [ ${PATH_LENGTH} -lt ${MAXIMUM_PATH} ]; then
@@ -346,7 +380,6 @@
 	LaunchVM "" "${RELEASE}"
 fi
 
-
 #
 # Throw some syntactically challenged (illegal) version specifiers at
 # the interface.  Failure (of the launcher) is success for the test.
@@ -357,15 +390,28 @@
 TestSyntax "1.2+.3"				# Embedded modifier
 TestSyntax "1.2.4+&1.2*&1++"			# Long and invalid
 
+# On windows we see if there is another jre installed, usually
+# there is, then we test using that, otherwise links are created
+# to get through to SelectVersion.
+if [ `IsWindows` = "false" ]; then
+   TestLongMainClass "mklink"
+else
+    $JAVAEXE -version:1.0+
+    if [ $? -eq 0 ]; then
+        TestLongMainClass "1.0+"
+    else
+        printf  "Warning: TestLongMainClass skipped as there is no"
+	printf  "viable MJRE installed.\n"
+    fi
+fi
+
 #
 # Because scribbling in the registry can be rather destructive, only a
 # subset of the tests are run on Windows.
 #
-case "$OS" in
-	Windows* | CYGWIN* )
-		exit 0;
-	;;
-esac
+if [ `IsWindows` = "true" ]; then
+    exit 0;
+fi
 
 #
 # Additional version specifiers containing spaces.  (Sigh, unable to
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/launcher/ZipMeUp.java	Thu Apr 16 21:08:04 2009 -0700
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+/**
+ * A simple class to create our erring Jar with a very long Main-Class
+ * attribute in the manifest.
+ */
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.zip.CRC32;
+import java.util.zip.CheckedOutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+public class ZipMeUp {
+
+    static final CRC32 crc = new CRC32();
+
+    private static String SOME_KLASS = ".Some";
+
+    static byte[] getManifestAsBytes(int nchars) throws IOException {
+        crc.reset();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        CheckedOutputStream cos = new CheckedOutputStream(baos, crc);
+        PrintStream ps = new PrintStream(cos);
+        ps.println("Manifest-Version: 1.0");
+        ps.print("Main-Class: ");
+        for (int i = 0 ; i < nchars - SOME_KLASS.length() ; i++) {
+            ps.print(i%10);
+        }
+        ps.println(SOME_KLASS);
+        cos.flush();
+        cos.close();
+        ps.close();
+        return baos.toByteArray();
+    }
+
+    /**
+     * The arguments are: filename_to_create length
+     * @param args
+     * @throws java.lang.Exception
+     */
+    public static void main(String...args) throws Exception  {
+        FileOutputStream fos = new FileOutputStream(args[0]);
+        ZipOutputStream zos = new ZipOutputStream(fos);
+        byte[] manifest = getManifestAsBytes(Integer.parseInt(args[1]));
+        ZipEntry ze = new ZipEntry("META-INF/MANIFEST.MF");
+        ze.setMethod(ZipEntry.STORED);
+        ze.setSize(manifest.length);
+        ze.setCompressedSize(manifest.length);
+        ze.setCrc(crc.getValue());
+        ze.setTime(System.currentTimeMillis());
+        zos.putNextEntry(ze);
+        zos.write(manifest);
+        zos.flush();
+
+        // add a zero length class
+        ze = new ZipEntry(SOME_KLASS + ".class");
+        ze.setMethod(ZipEntry.STORED);
+        ze.setSize(0);
+        ze.setCompressedSize(0);
+        ze.setCrc(0);
+        ze.setTime(System.currentTimeMillis());
+        zos.putNextEntry(ze);
+        zos.flush();
+        zos.closeEntry();
+        zos.close();
+        System.exit(0);
+    }
+}