提交 7b3c53a3 编写于 作者: A asaha

Merge

...@@ -50,6 +50,12 @@ ...@@ -50,6 +50,12 @@
#define JAR_ERROR2 "Error: Unable to access jarfile %s" #define JAR_ERROR2 "Error: Unable to access jarfile %s"
#define JAR_ERROR3 "Error: Invalid or corrupt 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_WARN1 "Warning: %s VM not supported; %s VM will be used"
#define CFG_WARN2 "Warning: No leading - on line %d of `%s'" #define CFG_WARN2 "Warning: No leading - on line %d of `%s'"
#define CFG_WARN3 "Warning: Missing VM type on line %d of `%s'" #define CFG_WARN3 "Warning: Missing VM type on line %d of `%s'"
......
...@@ -915,8 +915,14 @@ SelectVersion(int argc, char **argv, char **main_class) ...@@ -915,8 +915,14 @@ SelectVersion(int argc, char **argv, char **main_class)
* to avoid locating, expanding and parsing the manifest extra * to avoid locating, expanding and parsing the manifest extra
* times. * times.
*/ */
if (info.main_class != NULL) if (info.main_class != NULL) {
(void)JLI_StrCat(env_entry, info.main_class); 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); (void)putenv(env_entry);
ExecJRE(jre, new_argv); ExecJRE(jre, new_argv);
JLI_FreeManifest(); JLI_FreeManifest();
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
* CA 95054 USA or visit www.sun.com if you need additional information or * CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions. * have any questions.
*/ */
package com.sun.jmx.remote.internal; package com.sun.jmx.remote.internal;
import java.io.IOException; import java.io.IOException;
...@@ -34,6 +33,7 @@ import java.util.List; ...@@ -34,6 +33,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.security.AccessControlContext;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import javax.security.auth.Subject; import javax.security.auth.Subject;
...@@ -54,7 +54,10 @@ import com.sun.jmx.remote.util.EnvHelp; ...@@ -54,7 +54,10 @@ import com.sun.jmx.remote.util.EnvHelp;
public abstract class ClientNotifForwarder { public abstract class ClientNotifForwarder {
public ClientNotifForwarder(Map<String, ?> env) {
private final AccessControlContext acc;
public ClientNotifForwarder(Map env) {
this(null, env); this(null, env);
} }
...@@ -87,6 +90,8 @@ public abstract class ClientNotifForwarder { ...@@ -87,6 +90,8 @@ public abstract class ClientNotifForwarder {
this.command = command; this.command = command;
if (thread == null) { if (thread == null) {
thread = new Thread() { thread = new Thread() {
@Override
public void run() { public void run() {
while (true) { while (true) {
Runnable r; Runnable r;
...@@ -130,6 +135,7 @@ public abstract class ClientNotifForwarder { ...@@ -130,6 +135,7 @@ public abstract class ClientNotifForwarder {
this.defaultClassLoader = defaultClassLoader; this.defaultClassLoader = defaultClassLoader;
this.executor = ex; this.executor = ex;
this.acc = AccessController.getContext();
} }
/** /**
...@@ -380,28 +386,85 @@ public abstract class ClientNotifForwarder { ...@@ -380,28 +386,85 @@ public abstract class ClientNotifForwarder {
setState(TERMINATED); setState(TERMINATED);
} }
// -------------------------------------------------
// private classes // -------------------------------------------------
// ------------------------------------------------- // private classes
// -------------------------------------------------
// //
private class NotifFetcher implements Runnable { 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() { 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) { synchronized (ClientNotifForwarder.this) {
currentFetchThread = Thread.currentThread(); currentFetchThread = Thread.currentThread();
if (state == STARTING) if (state == STARTING) {
setState(STARTED); setState(STARTED);
}
} }
if (defaultClassLoader != null) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
Thread.currentThread().
setContextClassLoader(defaultClassLoader);
return null;
}
});
}
NotificationResult nr = null; NotificationResult nr = null;
if (!shouldStop() && (nr = fetchNotifs()) != null) { if (!shouldStop() && (nr = fetchNotifs()) != null) {
...@@ -434,8 +497,9 @@ public abstract class ClientNotifForwarder { ...@@ -434,8 +497,9 @@ public abstract class ClientNotifForwarder {
// check if an mbean unregistration notif // check if an mbean unregistration notif
if (!listenerID.equals(mbeanRemovedNotifID)) { if (!listenerID.equals(mbeanRemovedNotifID)) {
final ClientListenerInfo li = infoList.get(listenerID); final ClientListenerInfo li = infoList.get(listenerID);
if (li != null) if (li != null) {
listeners.put(listenerID,li); listeners.put(listenerID, li);
}
continue; continue;
} }
final Notification notif = tn.getNotification(); final Notification notif = tn.getNotification();
...@@ -799,9 +863,7 @@ public abstract class ClientNotifForwarder { ...@@ -799,9 +863,7 @@ public abstract class ClientNotifForwarder {
private long clientSequenceNumber = -1; private long clientSequenceNumber = -1;
private final int maxNotifications; private final int maxNotifications;
private final long timeout; private final long timeout;
private Integer mbeanRemovedNotifID = null; private Integer mbeanRemovedNotifID = null;
private Thread currentFetchThread; private Thread currentFetchThread;
// state // state
......
...@@ -111,6 +111,22 @@ public abstract class MBeanServerAccessController ...@@ -111,6 +111,22 @@ public abstract class MBeanServerAccessController
*/ */
protected abstract void checkWrite(); 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 @@ public abstract class MBeanServerAccessController ...@@ -148,7 +164,7 @@ public abstract class MBeanServerAccessController
} }
/** /**
* Call <code>checkWrite()</code>, then forward this method to the * Call <code>checkCreate(className)</code>, then forward this method to the
* wrapped object. * wrapped object.
*/ */
public ObjectInstance createMBean(String className, ObjectName name) public ObjectInstance createMBean(String className, ObjectName name)
...@@ -158,7 +174,7 @@ public abstract class MBeanServerAccessController ...@@ -158,7 +174,7 @@ public abstract class MBeanServerAccessController
MBeanRegistrationException, MBeanRegistrationException,
MBeanException, MBeanException,
NotCompliantMBeanException { NotCompliantMBeanException {
checkWrite(); checkCreate(className);
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm == null) { if (sm == null) {
Object object = getMBeanServer().instantiate(className); Object object = getMBeanServer().instantiate(className);
...@@ -170,7 +186,7 @@ public abstract class MBeanServerAccessController ...@@ -170,7 +186,7 @@ public abstract class MBeanServerAccessController
} }
/** /**
* Call <code>checkWrite()</code>, then forward this method to the * Call <code>checkCreate(className)</code>, then forward this method to the
* wrapped object. * wrapped object.
*/ */
public ObjectInstance createMBean(String className, ObjectName name, public ObjectInstance createMBean(String className, ObjectName name,
...@@ -181,7 +197,7 @@ public abstract class MBeanServerAccessController ...@@ -181,7 +197,7 @@ public abstract class MBeanServerAccessController
MBeanRegistrationException, MBeanRegistrationException,
MBeanException, MBeanException,
NotCompliantMBeanException { NotCompliantMBeanException {
checkWrite(); checkCreate(className);
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm == null) { if (sm == null) {
Object object = getMBeanServer().instantiate(className, Object object = getMBeanServer().instantiate(className,
...@@ -196,7 +212,7 @@ public abstract class MBeanServerAccessController ...@@ -196,7 +212,7 @@ public abstract class MBeanServerAccessController
} }
/** /**
* Call <code>checkWrite()</code>, then forward this method to the * Call <code>checkCreate(className)</code>, then forward this method to the
* wrapped object. * wrapped object.
*/ */
public ObjectInstance createMBean(String className, public ObjectInstance createMBean(String className,
...@@ -209,7 +225,7 @@ public abstract class MBeanServerAccessController ...@@ -209,7 +225,7 @@ public abstract class MBeanServerAccessController
MBeanException, MBeanException,
NotCompliantMBeanException, NotCompliantMBeanException,
InstanceNotFoundException { InstanceNotFoundException {
checkWrite(); checkCreate(className);
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm == null) { if (sm == null) {
Object object = getMBeanServer().instantiate(className, Object object = getMBeanServer().instantiate(className,
...@@ -222,7 +238,7 @@ public abstract class MBeanServerAccessController ...@@ -222,7 +238,7 @@ public abstract class MBeanServerAccessController
} }
/** /**
* Call <code>checkWrite()</code>, then forward this method to the * Call <code>checkCreate(className)</code>, then forward this method to the
* wrapped object. * wrapped object.
*/ */
public ObjectInstance createMBean(String className, public ObjectInstance createMBean(String className,
...@@ -237,7 +253,7 @@ public abstract class MBeanServerAccessController ...@@ -237,7 +253,7 @@ public abstract class MBeanServerAccessController
MBeanException, MBeanException,
NotCompliantMBeanException, NotCompliantMBeanException,
InstanceNotFoundException { InstanceNotFoundException {
checkWrite(); checkCreate(className);
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm == null) { if (sm == null) {
Object object = getMBeanServer().instantiate(className, Object object = getMBeanServer().instantiate(className,
...@@ -394,45 +410,45 @@ public abstract class MBeanServerAccessController ...@@ -394,45 +410,45 @@ public abstract class MBeanServerAccessController
} }
/** /**
* Call <code>checkWrite()</code>, then forward this method to the * Call <code>checkCreate(className)</code>, then forward this method to the
* wrapped object. * wrapped object.
*/ */
public Object instantiate(String className) public Object instantiate(String className)
throws ReflectionException, MBeanException { throws ReflectionException, MBeanException {
checkWrite(); checkCreate(className);
return getMBeanServer().instantiate(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. * wrapped object.
*/ */
public Object instantiate(String className, public Object instantiate(String className,
Object params[], Object params[],
String signature[]) String signature[])
throws ReflectionException, MBeanException { throws ReflectionException, MBeanException {
checkWrite(); checkCreate(className);
return getMBeanServer().instantiate(className, params, signature); 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. * wrapped object.
*/ */
public Object instantiate(String className, ObjectName loaderName) public Object instantiate(String className, ObjectName loaderName)
throws ReflectionException, MBeanException, InstanceNotFoundException { throws ReflectionException, MBeanException, InstanceNotFoundException {
checkWrite(); checkCreate(className);
return getMBeanServer().instantiate(className, loaderName); 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. * wrapped object.
*/ */
public Object instantiate(String className, ObjectName loaderName, public Object instantiate(String className, ObjectName loaderName,
Object params[], String signature[]) Object params[], String signature[])
throws ReflectionException, MBeanException, InstanceNotFoundException { throws ReflectionException, MBeanException, InstanceNotFoundException {
checkWrite(); checkCreate(className);
return getMBeanServer().instantiate(className, loaderName, return getMBeanServer().instantiate(className, loaderName,
params, signature); params, signature);
} }
...@@ -579,12 +595,12 @@ public abstract class MBeanServerAccessController ...@@ -579,12 +595,12 @@ public abstract class MBeanServerAccessController
} }
/** /**
* Call <code>checkWrite()</code>, then forward this method to the * Call <code>checkUnregister()</code>, then forward this method to the
* wrapped object. * wrapped object.
*/ */
public void unregisterMBean(ObjectName name) public void unregisterMBean(ObjectName name)
throws InstanceNotFoundException, MBeanRegistrationException { throws InstanceNotFoundException, MBeanRegistrationException {
checkWrite(); checkUnregister(name);
getMBeanServer().unregisterMBean(name); getMBeanServer().unregisterMBean(name);
} }
......
...@@ -31,11 +31,17 @@ import java.security.AccessControlContext; ...@@ -31,11 +31,17 @@ import java.security.AccessControlContext;
import java.security.AccessController; import java.security.AccessController;
import java.security.Principal; import java.security.Principal;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.Collection; import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import javax.management.MBeanServer; import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.security.auth.Subject; import javax.security.auth.Subject;
/** /**
...@@ -46,7 +52,8 @@ import javax.security.auth.Subject; ...@@ -46,7 +52,8 @@ import javax.security.auth.Subject;
* not allowed; in this case the request is not forwarded to the * not allowed; in this case the request is not forwarded to the
* wrapped object.</p> * 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 * 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 * 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 * filename which denotes a properties file on disk, or directly as an instance
...@@ -56,14 +63,50 @@ import javax.security.auth.Subject; ...@@ -56,14 +63,50 @@ import javax.security.auth.Subject;
* has exactly one access level. The same access level can be shared by several * has exactly one access level. The same access level can be shared by several
* usernames.</p> * usernames.</p>
* *
* <p>The supported access level values are <i>readonly</i> and * <p>The supported access level values are {@code readonly} and
* <i>readwrite</i>.</p> * {@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 public class MBeanServerFileAccessController
extends MBeanServerAccessController { extends MBeanServerAccessController {
public static final String READONLY = "readonly"; static final String READONLY = "readonly";
public static final String READWRITE = "readwrite"; 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 * <p>Create a new MBeanServerAccessController that forwards all the
...@@ -87,8 +130,8 @@ public class MBeanServerFileAccessController ...@@ -87,8 +130,8 @@ public class MBeanServerFileAccessController
throws IOException { throws IOException {
super(); super();
this.accessFileName = accessFileName; this.accessFileName = accessFileName;
props = propertiesFromFile(accessFileName); Properties props = propertiesFromFile(accessFileName);
checkValues(props); parseProperties(props);
} }
/** /**
...@@ -123,14 +166,14 @@ public class MBeanServerFileAccessController ...@@ -123,14 +166,14 @@ public class MBeanServerFileAccessController
* #setMBeanServer} method after doing access checks based on read and * #setMBeanServer} method after doing access checks based on read and
* write permissions.</p> * write permissions.</p>
* *
* <p>This instance is initialized from the specified properties instance. * <p>This instance is initialized from the specified properties
* This constructor makes a copy of the properties instance using its * instance. This constructor makes a copy of the properties
* <code>clone</code> method and it is the copy that is consulted to check * instance and it is the copy that is consulted to check the
* the username and access level of an incoming connection. The original * username and access level of an incoming connection. The
* properties object can be modified without affecting the copy. If the * original properties object can be modified without affecting
* {@link #refresh} method is then called, the * the copy. If the {@link #refresh} method is then called, the
* <code>MBeanServerFileAccessController</code> will make a new copy of the * <code>MBeanServerFileAccessController</code> will make a new
* properties object at that time.</p> * copy of the properties object at that time.</p>
* *
* @param accessFileProps properties list containing the username/access * @param accessFileProps properties list containing the username/access
* level entries. * level entries.
...@@ -145,8 +188,7 @@ public class MBeanServerFileAccessController ...@@ -145,8 +188,7 @@ public class MBeanServerFileAccessController
if (accessFileProps == null) if (accessFileProps == null)
throw new IllegalArgumentException("Null properties"); throw new IllegalArgumentException("Null properties");
originalProps = accessFileProps; originalProps = accessFileProps;
props = (Properties) accessFileProps.clone(); parseProperties(accessFileProps);
checkValues(props);
} }
/** /**
...@@ -155,14 +197,14 @@ public class MBeanServerFileAccessController ...@@ -155,14 +197,14 @@ public class MBeanServerFileAccessController
* #setMBeanServer} method after doing access checks based on read and * #setMBeanServer} method after doing access checks based on read and
* write permissions.</p> * write permissions.</p>
* *
* <p>This instance is initialized from the specified properties instance. * <p>This instance is initialized from the specified properties
* This constructor makes a copy of the properties instance using its * instance. This constructor makes a copy of the properties
* <code>clone</code> method and it is the copy that is consulted to check * instance and it is the copy that is consulted to check the
* the username and access level of an incoming connection. The original * username and access level of an incoming connection. The
* properties object can be modified without affecting the copy. If the * original properties object can be modified without affecting
* {@link #refresh} method is then called, the * the copy. If the {@link #refresh} method is then called, the
* <code>MBeanServerFileAccessController</code> will make a new copy of the * <code>MBeanServerFileAccessController</code> will make a new
* properties object at that time.</p> * copy of the properties object at that time.</p>
* *
* @param accessFileProps properties list containing the username/access * @param accessFileProps properties list containing the username/access
* level entries. * level entries.
...@@ -184,16 +226,36 @@ public class MBeanServerFileAccessController ...@@ -184,16 +226,36 @@ public class MBeanServerFileAccessController
* Check if the caller can do read operations. This method does * Check if the caller can do read operations. This method does
* nothing if so, otherwise throws SecurityException. * nothing if so, otherwise throws SecurityException.
*/ */
@Override
public void checkRead() { public void checkRead() {
checkAccessLevel(READONLY); checkAccess(AccessType.READ, null);
} }
/** /**
* Check if the caller can do write operations. This method does * Check if the caller can do write operations. This method does
* nothing if so, otherwise throws SecurityException. * nothing if so, otherwise throws SecurityException.
*/ */
@Override
public void checkWrite() { 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 @@ public class MBeanServerFileAccessController ...@@ -218,14 +280,13 @@ public class MBeanServerFileAccessController
* @exception IllegalArgumentException if any of the supplied access * @exception IllegalArgumentException if any of the supplied access
* level values differs from "readonly" or "readwrite". * level values differs from "readonly" or "readwrite".
*/ */
public void refresh() throws IOException { public synchronized void refresh() throws IOException {
synchronized (props) { Properties props;
if (accessFileName == null) if (accessFileName == null)
props = (Properties) originalProps.clone(); props = (Properties) originalProps;
else else
props = propertiesFromFile(accessFileName); props = propertiesFromFile(accessFileName);
checkValues(props); parseProperties(props);
}
} }
private static Properties propertiesFromFile(String fname) private static Properties propertiesFromFile(String fname)
...@@ -240,7 +301,7 @@ public class MBeanServerFileAccessController ...@@ -240,7 +301,7 @@ public class MBeanServerFileAccessController
} }
} }
private void checkAccessLevel(String accessLevel) { private synchronized void checkAccess(AccessType requiredAccess, String arg) {
final AccessControlContext acc = AccessController.getContext(); final AccessControlContext acc = AccessController.getContext();
final Subject s = final Subject s =
AccessController.doPrivileged(new PrivilegedAction<Subject>() { AccessController.doPrivileged(new PrivilegedAction<Subject>() {
...@@ -249,39 +310,235 @@ public class MBeanServerFileAccessController ...@@ -249,39 +310,235 @@ public class MBeanServerFileAccessController
} }
}); });
if (s == null) return; /* security has not been enabled */ if (s == null) return; /* security has not been enabled */
final Set<Principal> principals = s.getPrincipals(); final Set principals = s.getPrincipals();
for (Principal p : principals) { String newPropertyValue = null;
String grantedAccessLevel; for (Iterator i = principals.iterator(); i.hasNext(); ) {
synchronized (props) { final Principal p = (Principal) i.next();
grantedAccessLevel = props.getProperty(p.getName()); Access access = accessMap.get(p.getName());
} if (access != null) {
if (grantedAccessLevel != null) { boolean ok;
if (accessLevel.equals(READONLY) && switch (requiredAccess) {
(grantedAccessLevel.equals(READONLY) || case READ:
grantedAccessLevel.equals(READWRITE))) ok = true; // all access entries imply read
return; break;
if (accessLevel.equals(READWRITE) && case WRITE:
grantedAccessLevel.equals(READWRITE)) 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; return;
} }
} }
throw new SecurityException("Access denied! Invalid access level for " + SecurityException se = new SecurityException("Access denied! Invalid " +
"requested MBeanServer operation."); "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 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 void checkValues(Properties props) { private static class Parser {
Collection<?> c = props.values(); private final static int EOS = -1; // pseudo-codepoint "end of string"
for (Iterator<?> i = c.iterator(); i.hasNext(); ) { static {
final String accessLevel = (String) i.next(); assert !Character.isWhitespace(EOS);
if (!accessLevel.equals(READONLY) && }
!accessLevel.equals(READWRITE)) {
throw new IllegalArgumentException( private final String identity; // just for better error messages
"Syntax error in access level entry [" + accessLevel + "]"); 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 Properties props; private Map<String, Access> accessMap;
private Properties originalProps; private Properties originalProps;
private String accessFileName; private String accessFileName;
} }
...@@ -302,7 +302,16 @@ final public class LdapCtx extends ComponentDirContext ...@@ -302,7 +302,16 @@ final public class LdapCtx extends ComponentDirContext
schemaTrees = new Hashtable(11, 0.75f); schemaTrees = new Hashtable(11, 0.75f);
initEnv(); initEnv();
connect(false); try {
connect(false);
} catch (NamingException e) {
try {
close();
} catch (Exception e2) {
// Nothing
}
throw e;
}
} }
LdapCtx(LdapCtx existing, String newDN) throws NamingException { LdapCtx(LdapCtx existing, String newDN) throws NamingException {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -33,12 +33,33 @@ import java.security.PrivilegedAction; ...@@ -33,12 +33,33 @@ import java.security.PrivilegedAction;
final class VersionHelper12 extends VersionHelper { 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. VersionHelper12() {} // Disallow external from creating one of these.
ClassLoader getURLClassLoader(String[] url) ClassLoader getURLClassLoader(String[] url)
throws MalformedURLException { throws MalformedURLException {
ClassLoader parent = getContextClassLoader(); 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); return URLClassLoader.newInstance(getUrlArray(url), parent);
} else { } else {
return parent; return parent;
......
...@@ -37,6 +37,8 @@ import java.awt.geom.Rectangle2D; ...@@ -37,6 +37,8 @@ import java.awt.geom.Rectangle2D;
import java.awt.peer.FontPeer; import java.awt.peer.FontPeer;
import java.io.*; import java.io.*;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.text.AttributedCharacterIterator.Attribute; import java.text.AttributedCharacterIterator.Attribute;
import java.text.CharacterIterator; import java.text.CharacterIterator;
import java.text.StringCharacterIterator; import java.text.StringCharacterIterator;
...@@ -51,6 +53,7 @@ import sun.font.AttributeMap; ...@@ -51,6 +53,7 @@ import sun.font.AttributeMap;
import sun.font.AttributeValues; import sun.font.AttributeValues;
import sun.font.EAttribute; import sun.font.EAttribute;
import sun.font.CompositeFont; import sun.font.CompositeFont;
import sun.font.CreatedFontTracker;
import sun.font.Font2D; import sun.font.Font2D;
import sun.font.Font2DHandle; import sun.font.Font2DHandle;
import sun.font.FontManager; import sun.font.FontManager;
...@@ -575,14 +578,16 @@ public class Font implements java.io.Serializable ...@@ -575,14 +578,16 @@ public class Font implements java.io.Serializable
} }
/* used to implement Font.createFont */ /* 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 { throws FontFormatException {
this.createdFont = true; this.createdFont = true;
/* Font2D instances created by this method track their font file /* Font2D instances created by this method track their font file
* so that when the Font2D is GC'd it can also remove the file. * so that when the Font2D is GC'd it can also remove the file.
*/ */
this.font2DHandle = this.font2DHandle =
FontManager.createFont2D(fontFile, fontFormat, isCopy).handle; FontManager.createFont2D(fontFile, fontFormat,
isCopy, tracker).handle;
this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault()); this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
this.style = Font.PLAIN; this.style = Font.PLAIN;
this.size = 1; this.size = 1;
...@@ -787,6 +792,29 @@ public class Font implements java.io.Serializable ...@@ -787,6 +792,29 @@ public class Font implements java.io.Serializable
return new Font(attributes); return new Font(attributes);
} }
/**
* 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 * Returns a new <code>Font</code> using the specified font type
* and input data. The new <code>Font</code> is * and input data. The new <code>Font</code> is
...@@ -822,58 +850,96 @@ public class Font implements java.io.Serializable ...@@ -822,58 +850,96 @@ public class Font implements java.io.Serializable
fontFormat != Font.TYPE1_FONT) { fontFormat != Font.TYPE1_FONT) {
throw new IllegalArgumentException ("font format not recognized"); throw new IllegalArgumentException ("font format not recognized");
} }
final InputStream fStream = fontStream; boolean copiedFontData = false;
Object ret = java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() { try {
public Object run() { final File tFile = AccessController.doPrivileged(
File tFile = null; new PrivilegedExceptionAction<File>() {
FileOutputStream outStream = null; public File run() throws IOException {
try { return File.createTempFile("+~JF", ".tmp", null);
tFile = File.createTempFile("+~JF", ".tmp", null); }
/* Temp file deleted by font shutdown hook */ }
BufferedInputStream inStream = );
new BufferedInputStream(fStream);
outStream = new FileOutputStream(tFile); int totalSize = 0;
int bytesRead = 0; CreatedFontTracker tracker = null;
int bufSize = 8192; try {
byte [] buf = new byte[bufSize]; final OutputStream outStream =
while (bytesRead != -1) { AccessController.doPrivileged(
try { new PrivilegedExceptionAction<OutputStream>() {
bytesRead = inStream.read(buf, 0, bufSize); public OutputStream run() throws IOException {
} catch (Throwable t) { return new FileOutputStream(tFile);
throw new IOException(); }
} }
if (bytesRead != -1) { );
outStream.write(buf, 0, bytesRead); if (!hasTempPermission()) {
} tracker = CreatedFontTracker.getTracker();
} }
/* don't close the input stream */ try {
outStream.close(); byte[] buf = new byte[8192];
} catch (IOException e) { for (;;) {
if (outStream != null) { int bytesRead = fontStream.read(buf);
try { if (bytesRead < 0) {
outStream.close(); break;
} catch (Exception e1) { }
} if (tracker != null) {
} if (totalSize+bytesRead > tracker.MAX_FILE_SIZE) {
if (tFile != null) { throw new IOException("File too big.");
try { }
tFile.delete(); if (totalSize+tracker.getNumBytes() >
} catch (Exception e2) { tracker.MAX_TOTAL_BYTES)
} {
} throw new IOException("Total files too big.");
return e; }
} totalSize += bytesRead;
return tFile; tracker.addBytes(bytesRead);
} }
}); outStream.write(buf, 0, bytesRead);
}
if (ret instanceof File) { /* don't close the input stream */
return new Font((File)ret, fontFormat, true); } finally {
} else if (ret instanceof IOException) { outStream.close();
throw (IOException)ret; }
} else { /* After all references to a Font2D are dropped, the file
throw new FontFormatException("Couldn't access font stream"); * 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 class Font implements java.io.Serializable ...@@ -913,6 +979,9 @@ public class Font implements java.io.Serializable
*/ */
public static Font createFont(int fontFormat, File fontFile) public static Font createFont(int fontFormat, File fontFile)
throws java.awt.FontFormatException, java.io.IOException { throws java.awt.FontFormatException, java.io.IOException {
fontFile = new File(fontFile.getPath());
if (fontFormat != Font.TRUETYPE_FONT && if (fontFormat != Font.TRUETYPE_FONT &&
fontFormat != Font.TYPE1_FONT) { fontFormat != Font.TYPE1_FONT) {
throw new IllegalArgumentException ("font format not recognized"); throw new IllegalArgumentException ("font format not recognized");
...@@ -926,7 +995,7 @@ public class Font implements java.io.Serializable ...@@ -926,7 +995,7 @@ public class Font implements java.io.Serializable
if (!fontFile.canRead()) { if (!fontFile.canRead()) {
throw new IOException("Can't read " + fontFile); throw new IOException("Can't read " + fontFile);
} }
return new Font(fontFile, fontFormat, false); return new Font(fontFile, fontFormat, false, null);
} }
/** /**
......
...@@ -41,9 +41,14 @@ package java.util; ...@@ -41,9 +41,14 @@ package java.util;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable; import java.io.Serializable;
import java.security.AccessControlContext;
import java.security.AccessController; import java.security.AccessController;
import java.security.PermissionCollection;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.DateFormatSymbols; import java.text.DateFormatSymbols;
import sun.util.BuddhistCalendar; import sun.util.BuddhistCalendar;
...@@ -2628,6 +2633,18 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca ...@@ -2628,6 +2633,18 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
} }
} }
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). * Reconstitutes this object from a stream (i.e., deserialize it).
*/ */
...@@ -2657,17 +2674,30 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca ...@@ -2657,17 +2674,30 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
serialVersionOnStream = currentSerialVersion; serialVersionOnStream = currentSerialVersion;
// If there's a ZoneInfo object, use it for zone. // If there's a ZoneInfo object, use it for zone.
ZoneInfo zi = null;
try { try {
ZoneInfo zi = (ZoneInfo) AccessController.doPrivileged( zi = AccessController.doPrivileged(
new PrivilegedExceptionAction() { new PrivilegedExceptionAction<ZoneInfo>() {
public Object run() throws Exception { public ZoneInfo run() throws Exception {
return input.readObject(); return (ZoneInfo) input.readObject();
} }
}); },
if (zi != null) { CalendarAccessControlContext.INSTANCE);
zone = zi; } 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 // If the deserialized object has a SimpleTimeZone, try to
...@@ -2676,9 +2706,9 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca ...@@ -2676,9 +2706,9 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
// implementation as much as possible. // implementation as much as possible.
if (zone instanceof SimpleTimeZone) { if (zone instanceof SimpleTimeZone) {
String id = zone.getID(); String id = zone.getID();
TimeZone zi = TimeZone.getTimeZone(id); TimeZone tz = TimeZone.getTimeZone(id);
if (zi != null && zi.hasSameRules(zone) && zi.getID().equals(id)) { if (tz != null && tz.hasSameRules(zone) && tz.getID().equals(id)) {
zone = zi; zone = tz;
} }
} }
} }
......
...@@ -599,7 +599,7 @@ public class CounterMonitor extends Monitor implements CounterMonitorMBean { ...@@ -599,7 +599,7 @@ public class CounterMonitor extends Monitor implements CounterMonitorMBean {
*/ */
@Override @Override
public MBeanNotificationInfo[] getNotificationInfo() { public MBeanNotificationInfo[] getNotificationInfo() {
return notifsInfo; return notifsInfo.clone();
} }
/* /*
......
...@@ -481,7 +481,7 @@ public class GaugeMonitor extends Monitor implements GaugeMonitorMBean { ...@@ -481,7 +481,7 @@ public class GaugeMonitor extends Monitor implements GaugeMonitorMBean {
*/ */
@Override @Override
public MBeanNotificationInfo[] getNotificationInfo() { public MBeanNotificationInfo[] getNotificationInfo() {
return notifsInfo; return notifsInfo.clone();
} }
/* /*
......
...@@ -32,7 +32,10 @@ import java.io.IOException; ...@@ -32,7 +32,10 @@ import java.io.IOException;
import java.security.AccessControlContext; import java.security.AccessControlContext;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
...@@ -163,7 +166,10 @@ public abstract class Monitor ...@@ -163,7 +166,10 @@ public abstract class Monitor
/** /**
* AccessControlContext of the Monitor.start() caller. * 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. * Scheduler Service.
...@@ -173,14 +179,20 @@ public abstract class Monitor ...@@ -173,14 +179,20 @@ public abstract class Monitor
new DaemonThreadFactory("Scheduler")); new DaemonThreadFactory("Scheduler"));
/** /**
* Maximum Pool Size * Map containing the thread pool executor per thread group.
*/ */
private static final int maximumPoolSize; private static final Map<ThreadPoolExecutor, Void> executors =
new WeakHashMap<ThreadPoolExecutor, Void>();
/**
* Lock for executors map.
*/
private static final Object executorsLock = new Object();
/** /**
* Executor Service. * Maximum Pool Size
*/ */
private static final ThreadPoolExecutor executor; private static final int maximumPoolSize;
static { static {
final String maximumPoolSizeSysProp = "jmx.x.monitor.maximum.pool.size"; final String maximumPoolSizeSysProp = "jmx.x.monitor.maximum.pool.size";
final String maximumPoolSizeStr = AccessController.doPrivileged( final String maximumPoolSizeStr = AccessController.doPrivileged(
...@@ -210,21 +222,8 @@ public abstract class Monitor ...@@ -210,21 +222,8 @@ public abstract class Monitor
maximumPoolSize = maximumPoolSizeTmp; 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. * Future associated to the current monitor task.
*/ */
...@@ -233,7 +232,7 @@ public abstract class Monitor ...@@ -233,7 +232,7 @@ public abstract class Monitor
/** /**
* Scheduler task to be executed by the Scheduler Service. * 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. * ScheduledFuture associated to the current scheduler task.
...@@ -719,6 +718,7 @@ public abstract class Monitor ...@@ -719,6 +718,7 @@ public abstract class Monitor
// Start the scheduler. // Start the scheduler.
// //
cleanupFutures(); cleanupFutures();
schedulerTask.setMonitorTask(new MonitorTask());
schedulerFuture = scheduler.schedule(schedulerTask, schedulerFuture = scheduler.schedule(schedulerTask,
getGranularityPeriod(), getGranularityPeriod(),
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
...@@ -748,7 +748,7 @@ public abstract class Monitor ...@@ -748,7 +748,7 @@ public abstract class Monitor
// Reset the AccessControlContext. // Reset the AccessControlContext.
// //
acc = null; acc = noPermissionsACC;
// Reset the complex type attribute information // Reset the complex type attribute information
// such that it is recalculated again. // such that it is recalculated again.
...@@ -1467,7 +1467,7 @@ public abstract class Monitor ...@@ -1467,7 +1467,7 @@ public abstract class Monitor
*/ */
private class SchedulerTask implements Runnable { private class SchedulerTask implements Runnable {
private Runnable task = null; private MonitorTask task;
/* /*
* ------------------------------------------ * ------------------------------------------
...@@ -1475,7 +1475,16 @@ public abstract class Monitor ...@@ -1475,7 +1475,16 @@ public abstract class Monitor
* ------------------------------------------ * ------------------------------------------
*/ */
public SchedulerTask(Runnable task) { public SchedulerTask() {
}
/*
* ------------------------------------------
* GETTERS/SETTERS
* ------------------------------------------
*/
public void setMonitorTask(MonitorTask task) {
this.task = task; this.task = task;
} }
...@@ -1487,7 +1496,7 @@ public abstract class Monitor ...@@ -1487,7 +1496,7 @@ public abstract class Monitor
public void run() { public void run() {
synchronized (Monitor.this) { synchronized (Monitor.this) {
Monitor.this.monitorFuture = executor.submit(task); Monitor.this.monitorFuture = task.submit();
} }
} }
} }
...@@ -1500,6 +1509,8 @@ public abstract class Monitor ...@@ -1500,6 +1509,8 @@ public abstract class Monitor
*/ */
private class MonitorTask implements Runnable { private class MonitorTask implements Runnable {
private ThreadPoolExecutor executor;
/* /*
* ------------------------------------------ * ------------------------------------------
* CONSTRUCTORS * CONSTRUCTORS
...@@ -1507,6 +1518,38 @@ public abstract class Monitor ...@@ -1507,6 +1518,38 @@ public abstract class Monitor
*/ */
public MonitorTask() { 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 abstract class Monitor ...@@ -1515,12 +1558,18 @@ public abstract class Monitor
* ------------------------------------------ * ------------------------------------------
*/ */
public Future<?> submit() {
return executor.submit(this);
}
public void run() { public void run() {
final ScheduledFuture<?> sf; final ScheduledFuture<?> sf;
final AccessControlContext ac;
synchronized (Monitor.this) { synchronized (Monitor.this) {
sf = Monitor.this.schedulerFuture; sf = Monitor.this.schedulerFuture;
ac = Monitor.this.acc;
} }
AccessController.doPrivileged(new PrivilegedAction<Void>() { PrivilegedAction<Void> action = new PrivilegedAction<Void>() {
public Void run() { public Void run() {
if (Monitor.this.isActive()) { if (Monitor.this.isActive()) {
final int an[] = alreadyNotifieds; final int an[] = alreadyNotifieds;
...@@ -1533,7 +1582,11 @@ public abstract class Monitor ...@@ -1533,7 +1582,11 @@ public abstract class Monitor
} }
return null; return null;
} }
}, Monitor.this.acc); };
if (ac == null) {
throw new SecurityException("AccessControlContext cannot be null");
}
AccessController.doPrivileged(action, ac);
synchronized (Monitor.this) { synchronized (Monitor.this) {
if (Monitor.this.isActive() && if (Monitor.this.isActive() &&
Monitor.this.schedulerFuture == sf) { Monitor.this.schedulerFuture == sf) {
...@@ -1573,6 +1626,15 @@ public abstract class Monitor ...@@ -1573,6 +1626,15 @@ public abstract class Monitor
namePrefix = "JMX Monitor " + poolName + " Pool [Thread-"; 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) { public Thread newThread(Runnable r) {
Thread t = new Thread(group, Thread t = new Thread(group,
r, r,
......
...@@ -184,6 +184,7 @@ public class StringMonitor extends Monitor implements StringMonitorMBean { ...@@ -184,6 +184,7 @@ public class StringMonitor extends Monitor implements StringMonitorMBean {
* @return The derived gauge of the specified object. * @return The derived gauge of the specified object.
* *
*/ */
@Override
public synchronized String getDerivedGauge(ObjectName object) { public synchronized String getDerivedGauge(ObjectName object) {
return (String) super.getDerivedGauge(object); return (String) super.getDerivedGauge(object);
} }
...@@ -199,6 +200,7 @@ public class StringMonitor extends Monitor implements StringMonitorMBean { ...@@ -199,6 +200,7 @@ public class StringMonitor extends Monitor implements StringMonitorMBean {
* @return The derived gauge timestamp of the specified object. * @return The derived gauge timestamp of the specified object.
* *
*/ */
@Override
public synchronized long getDerivedGaugeTimeStamp(ObjectName object) { public synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
return super.getDerivedGaugeTimeStamp(object); return super.getDerivedGaugeTimeStamp(object);
} }
...@@ -341,8 +343,9 @@ public class StringMonitor extends Monitor implements StringMonitorMBean { ...@@ -341,8 +343,9 @@ public class StringMonitor extends Monitor implements StringMonitorMBean {
* the Java class of the notification and the notification types sent by * the Java class of the notification and the notification types sent by
* the string monitor. * the string monitor.
*/ */
@Override
public MBeanNotificationInfo[] getNotificationInfo() { public MBeanNotificationInfo[] getNotificationInfo() {
return notifsInfo; return notifsInfo.clone();
} }
/* /*
......
...@@ -123,8 +123,10 @@ public class MediaSize extends Size2DSyntax implements Attribute { ...@@ -123,8 +123,10 @@ public class MediaSize extends Size2DSyntax implements Attribute {
if (x > y) { if (x > y) {
throw new IllegalArgumentException("X dimension > Y dimension"); throw new IllegalArgumentException("X dimension > Y dimension");
} }
mediaName = media; if (media != null && mediaMap.get(media) == null) {
mediaMap.put(mediaName, this); mediaName = media;
mediaMap.put(mediaName, this);
}
sizeVector.add(this); sizeVector.add(this);
} }
...@@ -147,8 +149,10 @@ public class MediaSize extends Size2DSyntax implements Attribute { ...@@ -147,8 +149,10 @@ public class MediaSize extends Size2DSyntax implements Attribute {
if (x > y) { if (x > y) {
throw new IllegalArgumentException("X dimension > Y dimension"); throw new IllegalArgumentException("X dimension > Y dimension");
} }
mediaName = media; if (media != null && mediaMap.get(media) == null) {
mediaMap.put(mediaName, this); mediaName = media;
mediaMap.put(mediaName, this);
}
sizeVector.add(this); sizeVector.add(this);
} }
......
...@@ -585,9 +585,16 @@ public class GifImageDecoder extends ImageDecoder { ...@@ -585,9 +585,16 @@ public class GifImageDecoder extends ImageDecoder {
System.out.print("Reading a " + width + " by " + height + " " + System.out.print("Reading a " + width + " by " + height + " " +
(interlace ? "" : "non-") + "interlaced image..."); (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, boolean ret = parseImage(x, y, width, height,
interlace, ExtractByte(block, 9), interlace, initCodeSize,
block, rasline, model); block, rasline, model);
if (!ret) { if (!ret) {
......
/*
* 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;
}
}
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -125,9 +125,9 @@ public abstract class FileFont extends PhysicalFont { ...@@ -125,9 +125,9 @@ public abstract class FileFont extends PhysicalFont {
return true; return true;
} }
void setFileToRemove(File file) { void setFileToRemove(File file, CreatedFontTracker tracker) {
Disposer.addObjectRecord(this, Disposer.addObjectRecord(this,
new CreatedFontFileDisposerRecord(file)); new CreatedFontFileDisposerRecord(file, tracker));
} }
/* This is called when a font scaler is determined to /* This is called when a font scaler is determined to
...@@ -246,12 +246,16 @@ public abstract class FileFont extends PhysicalFont { ...@@ -246,12 +246,16 @@ public abstract class FileFont extends PhysicalFont {
return getScaler().getUnitsPerEm(); return getScaler().getUnitsPerEm();
} }
private static class CreatedFontFileDisposerRecord implements DisposerRecord { private static class CreatedFontFileDisposerRecord
implements DisposerRecord {
File fontFile = null; File fontFile = null;
CreatedFontTracker tracker;
private CreatedFontFileDisposerRecord(File file) { private CreatedFontFileDisposerRecord(File file,
CreatedFontTracker tracker) {
fontFile = file; fontFile = file;
this.tracker = tracker;
} }
public void dispose() { public void dispose() {
...@@ -260,6 +264,9 @@ public abstract class FileFont extends PhysicalFont { ...@@ -260,6 +264,9 @@ public abstract class FileFont extends PhysicalFont {
public Object run() { public Object run() {
if (fontFile != null) { if (fontFile != null) {
try { try {
if (tracker != null) {
tracker.subBytes((int)fontFile.length());
}
/* REMIND: is it possible that the file is /* REMIND: is it possible that the file is
* still open? It will be closed when the * still open? It will be closed when the
* font2D is disposed but could this code * font2D is disposed but could this code
......
...@@ -2348,19 +2348,21 @@ public final class FontManager { ...@@ -2348,19 +2348,21 @@ public final class FontManager {
static Vector<File> tmpFontFiles = null; static Vector<File> tmpFontFiles = null;
public static Font2D createFont2D(File fontFile, int fontFormat, public static Font2D createFont2D(File fontFile, int fontFormat,
boolean isCopy) boolean isCopy,
CreatedFontTracker tracker)
throws FontFormatException { throws FontFormatException {
String fontFilePath = fontFile.getPath(); String fontFilePath = fontFile.getPath();
FileFont font2D = null; FileFont font2D = null;
final File fFile = fontFile; final File fFile = fontFile;
final CreatedFontTracker _tracker = tracker;
try { try {
switch (fontFormat) { switch (fontFormat) {
case Font.TRUETYPE_FONT: case Font.TRUETYPE_FONT:
font2D = new TrueTypeFont(fontFilePath, null, 0, true); font2D = new TrueTypeFont(fontFilePath, null, 0, true);
break; break;
case Font.TYPE1_FONT: case Font.TYPE1_FONT:
font2D = new Type1Font(fontFilePath, null); font2D = new Type1Font(fontFilePath, null, isCopy);
break; break;
default: default:
throw new FontFormatException("Unrecognised Font Format"); throw new FontFormatException("Unrecognised Font Format");
...@@ -2370,6 +2372,9 @@ public final class FontManager { ...@@ -2370,6 +2372,9 @@ public final class FontManager {
java.security.AccessController.doPrivileged( java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() { new java.security.PrivilegedAction() {
public Object run() { public Object run() {
if (_tracker != null) {
_tracker.subBytes((int)fFile.length());
}
fFile.delete(); fFile.delete();
return null; return null;
} }
...@@ -2378,7 +2383,7 @@ public final class FontManager { ...@@ -2378,7 +2383,7 @@ public final class FontManager {
throw(e); throw(e);
} }
if (isCopy) { if (isCopy) {
font2D.setFileToRemove(fontFile); font2D.setFileToRemove(fontFile, tracker);
synchronized (FontManager.class) { synchronized (FontManager.class) {
if (tmpFontFiles == null) { if (tmpFontFiles == null) {
......
...@@ -175,8 +175,17 @@ public class TrueTypeFont extends FileFont { ...@@ -175,8 +175,17 @@ public class TrueTypeFont extends FileFont {
super(platname, nativeNames); super(platname, nativeNames);
useJavaRasterizer = javaRasterizer; useJavaRasterizer = javaRasterizer;
fontRank = Font2D.TTF_RANK; fontRank = Font2D.TTF_RANK;
verify(); try {
init(fIndex); 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); Disposer.addObjectRecord(this, disposerRecord);
} }
......
...@@ -39,6 +39,7 @@ import java.nio.BufferUnderflowException; ...@@ -39,6 +39,7 @@ import java.nio.BufferUnderflowException;
import java.nio.channels.ClosedChannelException; import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import sun.java2d.Disposer; import sun.java2d.Disposer;
import sun.java2d.DisposerRecord;
import java.util.HashSet; import java.util.HashSet;
import java.util.HashMap; import java.util.HashMap;
import java.awt.Font; import java.awt.Font;
...@@ -76,6 +77,27 @@ import java.awt.Font; ...@@ -76,6 +77,27 @@ import java.awt.Font;
*/ */
public class Type1Font extends FileFont { 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); WeakReference bufferRef = new WeakReference(null);
private String psName = null; private String psName = null;
...@@ -124,6 +146,17 @@ public class Type1Font extends FileFont { ...@@ -124,6 +146,17 @@ public class Type1Font extends FileFont {
} }
/**
* 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 * - does basic verification of the file
* - reads the names (full, family). * - reads the names (full, family).
...@@ -131,12 +164,25 @@ public class Type1Font extends FileFont { ...@@ -131,12 +164,25 @@ public class Type1Font extends FileFont {
* @throws FontFormatException - if the font can't be opened * @throws FontFormatException - if the font can't be opened
* or fails verification, or there's no usable cmap * 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 { throws FontFormatException {
super(platname, nativeNames); super(platname, nativeNames);
fontRank = Font2D.TYPE1_RANK; fontRank = Font2D.TYPE1_RANK;
checkedNatives = true; 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 { private synchronized ByteBuffer getBuffer() throws FontFormatException {
......
...@@ -52,6 +52,9 @@ class Request { ...@@ -52,6 +52,9 @@ class Request {
os = rawout; os = rawout;
do { do {
startLine = readLine(); startLine = readLine();
if (startLine == null) {
return;
}
/* skip blank lines */ /* skip blank lines */
} while (startLine == null ? false : startLine.equals ("")); } while (startLine == null ? false : startLine.equals (""));
} }
......
...@@ -433,6 +433,7 @@ class ServerImpl implements TimeSource { ...@@ -433,6 +433,7 @@ class ServerImpl implements TimeSource {
rawin = sslStreams.getInputStream(); rawin = sslStreams.getInputStream();
rawout = sslStreams.getOutputStream(); rawout = sslStreams.getOutputStream();
engine = sslStreams.getSSLEngine(); engine = sslStreams.getSSLEngine();
connection.sslStreams = sslStreams;
} else { } else {
rawin = new BufferedInputStream( rawin = new BufferedInputStream(
new Request.ReadStream ( new Request.ReadStream (
...@@ -442,6 +443,8 @@ class ServerImpl implements TimeSource { ...@@ -442,6 +443,8 @@ class ServerImpl implements TimeSource {
ServerImpl.this, chan ServerImpl.this, chan
); );
} }
connection.raw = rawin;
connection.rawout = rawout;
} }
Request req = new Request (rawin, rawout); Request req = new Request (rawin, rawout);
requestLine = req.requestLine(); requestLine = req.requestLine();
......
...@@ -274,27 +274,31 @@ public abstract class KrbKdcReq { ...@@ -274,27 +274,31 @@ public abstract class KrbKdcReq {
+ ",Attempt =" + i + ",Attempt =" + i
+ ", #bytes=" + obuf.length); + ", #bytes=" + obuf.length);
} }
/* try {
* Send the data to the kdc. /*
*/ * Send the data to the kdc.
*/
kdcClient.send(obuf); kdcClient.send(obuf);
/* /*
* And get a response. * And get a response.
*/ */
try { try {
ibuf = kdcClient.receive(); ibuf = kdcClient.receive();
break; break;
} catch (SocketTimeoutException se) { } catch (SocketTimeoutException se) {
if (DEBUG) { if (DEBUG) {
System.out.println ("SocketTimeOutException with " + System.out.println ("SocketTimeOutException with " +
"attempt: " + i); "attempt: " + i);
} }
if (i == DEFAULT_KDC_RETRY_LIMIT) { if (i == DEFAULT_KDC_RETRY_LIMIT) {
ibuf = null; ibuf = null;
throw se; throw se;
}
} }
} finally {
kdcClient.close();
} }
} }
} }
......
...@@ -93,4 +93,7 @@ public class UDPClient { ...@@ -93,4 +93,7 @@ public class UDPClient {
return data; return data;
} }
public void close() {
dgSocket.close();
}
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -38,6 +38,8 @@ import static sun.security.pkcs11.TemplateManager.*; ...@@ -38,6 +38,8 @@ import static sun.security.pkcs11.TemplateManager.*;
import sun.security.pkcs11.wrapper.*; import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import sun.security.rsa.RSAKeyFactory;
/** /**
* KeyPairGenerator implementation class. This class currently supports * KeyPairGenerator implementation class. This class currently supports
* RSA, DSA, DH, and EC. * RSA, DSA, DH, and EC.
...@@ -66,7 +68,7 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -66,7 +68,7 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
private AlgorithmParameterSpec params; private AlgorithmParameterSpec params;
// for RSA, selected or default value of public exponent, always valid // 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 // SecureRandom instance, if specified in init
private SecureRandom random; private SecureRandom random;
...@@ -88,19 +90,19 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -88,19 +90,19 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
public void initialize(int keySize, SecureRandom random) { public void initialize(int keySize, SecureRandom random) {
token.ensureValid(); token.ensureValid();
try { try {
checkKeySize(keySize); checkKeySize(keySize, null);
} catch (InvalidAlgorithmParameterException e) { } catch (InvalidAlgorithmParameterException e) {
throw new InvalidParameterException(e.getMessage()); throw new InvalidParameterException(e.getMessage());
} }
this.keySize = keySize; this.keySize = keySize;
this.params = null; this.params = null;
this.random = random; this.random = random;
this.rsaPublicExponent = RSAKeyGenParameterSpec.F4;
if (algorithm.equals("EC")) { if (algorithm.equals("EC")) {
params = P11ECKeyFactory.getECParameterSpec(keySize); params = P11ECKeyFactory.getECParameterSpec(keySize);
if (params == null) { if (params == null) {
throw new InvalidParameterException throw new InvalidParameterException(
("No EC parameters available for key size " + keySize + " bits"); "No EC parameters available for key size "
+ keySize + " bits");
} }
} }
} }
...@@ -115,8 +117,10 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -115,8 +117,10 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("DHParameterSpec required for Diffie-Hellman"); ("DHParameterSpec required for Diffie-Hellman");
} }
DHParameterSpec dhParams = (DHParameterSpec)params; DHParameterSpec dhParams = (DHParameterSpec)params;
this.keySize = dhParams.getP().bitLength(); int tmpKeySize = dhParams.getP().bitLength();
this.params = params; checkKeySize(tmpKeySize, dhParams);
this.keySize = tmpKeySize;
this.params = dhParams;
// XXX sanity check params // XXX sanity check params
} else if (algorithm.equals("RSA")) { } else if (algorithm.equals("RSA")) {
if (params instanceof RSAKeyGenParameterSpec == false) { if (params instanceof RSAKeyGenParameterSpec == false) {
...@@ -124,7 +128,9 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -124,7 +128,9 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("RSAKeyGenParameterSpec required for RSA"); ("RSAKeyGenParameterSpec required for RSA");
} }
RSAKeyGenParameterSpec rsaParams = (RSAKeyGenParameterSpec)params; RSAKeyGenParameterSpec rsaParams = (RSAKeyGenParameterSpec)params;
this.keySize = rsaParams.getKeysize(); int tmpKeySize = rsaParams.getKeysize();
checkKeySize(tmpKeySize, rsaParams);
this.keySize = tmpKeySize;
this.params = null; this.params = null;
this.rsaPublicExponent = rsaParams.getPublicExponent(); this.rsaPublicExponent = rsaParams.getPublicExponent();
// XXX sanity check params // XXX sanity check params
...@@ -134,13 +140,16 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -134,13 +140,16 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("DSAParameterSpec required for DSA"); ("DSAParameterSpec required for DSA");
} }
DSAParameterSpec dsaParams = (DSAParameterSpec)params; DSAParameterSpec dsaParams = (DSAParameterSpec)params;
this.keySize = dsaParams.getP().bitLength(); int tmpKeySize = dsaParams.getP().bitLength();
this.params = params; checkKeySize(tmpKeySize, dsaParams);
this.keySize = tmpKeySize;
this.params = dsaParams;
// XXX sanity check params // XXX sanity check params
} else if (algorithm.equals("EC")) { } else if (algorithm.equals("EC")) {
ECParameterSpec ecParams; ECParameterSpec ecParams;
if (params instanceof ECParameterSpec) { if (params instanceof ECParameterSpec) {
ecParams = P11ECKeyFactory.getECParameterSpec((ECParameterSpec)params); ecParams = P11ECKeyFactory.getECParameterSpec(
(ECParameterSpec)params);
if (ecParams == null) { if (ecParams == null) {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException
("Unsupported curve: " + params); ("Unsupported curve: " + params);
...@@ -156,16 +165,17 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -156,16 +165,17 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException
("ECParameterSpec or ECGenParameterSpec required for EC"); ("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; this.params = ecParams;
} else { } else {
throw new ProviderException("Unknown algorithm: " + algorithm); throw new ProviderException("Unknown algorithm: " + algorithm);
} }
this.random = random; this.random = random;
checkKeySize(keySize);
} }
private void checkKeySize(int keySize) private void checkKeySize(int keySize, AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException { throws InvalidAlgorithmParameterException {
if (algorithm.equals("EC")) { if (algorithm.equals("EC")) {
if (keySize < 112) { if (keySize < 112) {
...@@ -178,13 +188,28 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -178,13 +188,28 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("Key size must be at most 2048 bit"); ("Key size must be at most 2048 bit");
} }
return; 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) { if (keySize < 512) {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException
("Key size must be at least 512 bit"); ("Key size must be at least 512 bit");
} }
if (algorithm.equals("RSA") || if (algorithm.equals("DH") && (params != null)) {
(algorithm.equals("DH") && (params != null))) {
// sanity check, nobody really wants keys this large // sanity check, nobody really wants keys this large
if (keySize > 64 * 1024) { if (keySize > 64 * 1024) {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException
......
...@@ -80,6 +80,8 @@ import static sun.security.pkcs11.P11Util.*; ...@@ -80,6 +80,8 @@ import static sun.security.pkcs11.P11Util.*;
import sun.security.pkcs11.wrapper.*; import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import sun.security.rsa.RSAKeyFactory;
final class P11KeyStore extends KeyStoreSpi { final class P11KeyStore extends KeyStoreSpi {
private static final CK_ATTRIBUTE ATTR_CLASS_CERT = private static final CK_ATTRIBUTE ATTR_CLASS_CERT =
...@@ -1328,6 +1330,15 @@ final class P11KeyStore extends KeyStoreSpi { ...@@ -1328,6 +1330,15 @@ final class P11KeyStore extends KeyStoreSpi {
BigInteger modulus = attrs[0].getBigInteger(); BigInteger modulus = attrs[0].getBigInteger();
keyLength = modulus.bitLength(); 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, return P11Key.privateKey(session,
oHandle, oHandle,
keyType, keyType,
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -35,6 +35,8 @@ import static sun.security.pkcs11.TemplateManager.*; ...@@ -35,6 +35,8 @@ import static sun.security.pkcs11.TemplateManager.*;
import sun.security.pkcs11.wrapper.*; import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import sun.security.rsa.RSAKeyFactory;
/** /**
* RSA KeyFactory implemenation. * RSA KeyFactory implemenation.
* *
...@@ -131,6 +133,9 @@ final class P11RSAKeyFactory extends P11KeyFactory { ...@@ -131,6 +133,9 @@ final class P11RSAKeyFactory extends P11KeyFactory {
} catch (PKCS11Exception e) { } catch (PKCS11Exception e) {
throw new InvalidKeySpecException throw new InvalidKeySpecException
("Could not create RSA public key", e); ("Could not create RSA public key", e);
} catch (InvalidKeyException e) {
throw new InvalidKeySpecException
("Could not create RSA public key", e);
} }
} }
...@@ -175,11 +180,15 @@ final class P11RSAKeyFactory extends P11KeyFactory { ...@@ -175,11 +180,15 @@ final class P11RSAKeyFactory extends P11KeyFactory {
} catch (PKCS11Exception e) { } catch (PKCS11Exception e) {
throw new InvalidKeySpecException throw new InvalidKeySpecException
("Could not create RSA private key", e); ("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) 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[] { CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY), new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA), new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
...@@ -200,7 +209,8 @@ final class P11RSAKeyFactory extends P11KeyFactory { ...@@ -200,7 +209,8 @@ final class P11RSAKeyFactory extends P11KeyFactory {
} }
private PrivateKey generatePrivate(BigInteger n, BigInteger d) 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[] { CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY), new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA), new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
...@@ -222,7 +232,9 @@ final class P11RSAKeyFactory extends P11KeyFactory { ...@@ -222,7 +232,9 @@ final class P11RSAKeyFactory extends P11KeyFactory {
private PrivateKey generatePrivate(BigInteger n, BigInteger e, private PrivateKey generatePrivate(BigInteger n, BigInteger e,
BigInteger d, BigInteger p, BigInteger q, BigInteger pe, 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[] { CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY), new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA), new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
......
...@@ -120,11 +120,13 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -120,11 +120,13 @@ public final class SunPKCS11 extends AuthProvider {
} }
/** /**
* @deprecated use new SunPKCS11(String) or new SunPKCS11(InputStream) instead * @deprecated use new SunPKCS11(String) or new SunPKCS11(InputStream)
* instead
*/ */
@Deprecated @Deprecated
public SunPKCS11(String configName, InputStream configStream) { 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()); 1.7d, Config.getConfig(configName, configStream).getDescription());
this.configName = configName; this.configName = configName;
this.config = Config.removeConfig(configName); this.config = Config.removeConfig(configName);
...@@ -153,7 +155,8 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -153,7 +155,8 @@ public final class SunPKCS11 extends AuthProvider {
// //
// If we are in Secmod mode and configured to use either the // If we are in Secmod mode and configured to use either the
// nssKeyStore or the nssTrustAnchors module, we automatically // 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) { if (useSecmod) {
...@@ -168,33 +171,40 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -168,33 +171,40 @@ public final class SunPKCS11 extends AuthProvider {
if (secmod.isInitialized()) { if (secmod.isInitialized()) {
if (nssSecmodDirectory != null) { if (nssSecmodDirectory != null) {
String s = secmod.getConfigDir(); String s = secmod.getConfigDir();
if ((s != null) && (s.equals(nssSecmodDirectory) == false)) { if ((s != null) &&
(s.equals(nssSecmodDirectory) == false)) {
throw new ProviderException("Secmod directory " throw new ProviderException("Secmod directory "
+ nssSecmodDirectory + nssSecmodDirectory
+ " invalid, NSS already initialized with " + s); + " invalid, NSS already initialized with "
+ s);
} }
} }
if (nssLibraryDirectory != null) { if (nssLibraryDirectory != null) {
String s = secmod.getLibDir(); String s = secmod.getLibDir();
if ((s != null) && (s.equals(nssLibraryDirectory) == false)) { if ((s != null) &&
(s.equals(nssLibraryDirectory) == false)) {
throw new ProviderException("NSS library directory " throw new ProviderException("NSS library directory "
+ nssLibraryDirectory + nssLibraryDirectory
+ " invalid, NSS already initialized with " + s); + " invalid, NSS already initialized with "
+ s);
} }
} }
} else { } else {
if (nssDbMode != DbMode.NO_DB) { if (nssDbMode != DbMode.NO_DB) {
if (nssSecmodDirectory == null) { if (nssSecmodDirectory == null) {
throw new ProviderException("Secmod not initialized and " throw new ProviderException(
+ "nssSecmodDirectory not specified"); "Secmod not initialized and "
+ "nssSecmodDirectory not specified");
} }
} else { } else {
if (nssSecmodDirectory != null) { if (nssSecmodDirectory != null) {
throw new ProviderException throw new ProviderException(
("nssSecmodDirectory must not be specified in noDb mode"); "nssSecmodDirectory must not be "
+ "specified in noDb mode");
} }
} }
secmod.initialize(nssDbMode, nssSecmodDirectory, nssLibraryDirectory); secmod.initialize(nssDbMode, nssSecmodDirectory,
nssLibraryDirectory);
} }
} catch (IOException e) { } catch (IOException e) {
// XXX which exception to throw // XXX which exception to throw
...@@ -211,7 +221,8 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -211,7 +221,8 @@ public final class SunPKCS11 extends AuthProvider {
if (nssModule != null) { if (nssModule != null) {
moduleName = "fips"; moduleName = "fips";
} else { } else {
moduleName = (nssDbMode == DbMode.NO_DB) ? "crypto" : "keystore"; moduleName = (nssDbMode == DbMode.NO_DB) ?
"crypto" : "keystore";
} }
} }
if (moduleName.equals("fips")) { if (moduleName.equals("fips")) {
...@@ -253,10 +264,12 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -253,10 +264,12 @@ public final class SunPKCS11 extends AuthProvider {
+ ": only " + k + " external NSS modules available"); + ": only " + k + " external NSS modules available");
} }
} else { } else {
throw new ProviderException("Unknown NSS module: " + moduleName); throw new ProviderException(
"Unknown NSS module: " + moduleName);
} }
if (nssModule == null) { if (nssModule == null) {
throw new ProviderException("NSS module not available: " + moduleName); throw new ProviderException(
"NSS module not available: " + moduleName);
} }
if (nssModule.hasInitializedProvider()) { if (nssModule.hasInitializedProvider()) {
throw new ProviderException("Secmod module already configured"); throw new ProviderException("Secmod module already configured");
...@@ -296,8 +309,9 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -296,8 +309,9 @@ public final class SunPKCS11 extends AuthProvider {
initArgs.flags = CKF_OS_LOCKING_OK; initArgs.flags = CKF_OS_LOCKING_OK;
PKCS11 tmpPKCS11; PKCS11 tmpPKCS11;
try { try {
tmpPKCS11 = PKCS11.getInstance tmpPKCS11 = PKCS11.getInstance(
(library, functionList, initArgs, config.getOmitInitialize()); library, functionList, initArgs,
config.getOmitInitialize());
} catch (PKCS11Exception e) { } catch (PKCS11Exception e) {
if (debug != null) { if (debug != null) {
debug.println("Multi-threaded initialization failed: " + e); debug.println("Multi-threaded initialization failed: " + e);
...@@ -312,8 +326,8 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -312,8 +326,8 @@ public final class SunPKCS11 extends AuthProvider {
} else { } else {
initArgs.flags = 0; initArgs.flags = 0;
} }
tmpPKCS11 = PKCS11.getInstance tmpPKCS11 = PKCS11.getInstance(library,
(library, functionList, initArgs, config.getOmitInitialize()); functionList, initArgs, config.getOmitInitialize());
} }
p11 = tmpPKCS11; p11 = tmpPKCS11;
...@@ -336,8 +350,10 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -336,8 +350,10 @@ public final class SunPKCS11 extends AuthProvider {
System.out.println("Slots with tokens: " + toString(slots)); System.out.println("Slots with tokens: " + toString(slots));
} }
if (slotID < 0) { if (slotID < 0) {
if ((slotListIndex < 0) || (slotListIndex >= slots.length)) { if ((slotListIndex < 0)
throw new ProviderException("slotListIndex is " + slotListIndex || (slotListIndex >= slots.length)) {
throw new ProviderException("slotListIndex is "
+ slotListIndex
+ " but token only has " + slots.length + " slots"); + " but token only has " + slots.length + " slots");
} }
slotID = slots[slotListIndex]; slotID = slots[slotListIndex];
...@@ -575,12 +591,15 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -575,12 +591,15 @@ public final class SunPKCS11 extends AuthProvider {
d(KF, "DH", P11DHKeyFactory, s("DiffieHellman"), d(KF, "DH", P11DHKeyFactory, s("DiffieHellman"),
m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE)); m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));
d(KF, "EC", P11DHKeyFactory, 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. // AlgorithmParameters for EC.
// Only needed until we have an EC implementation in the SUN provider. // 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"), d(AGP, "EC", "sun.security.ec.ECParameters",
m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE, CKM_ECDSA, CKM_ECDSA_SHA1)); 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"), d(KA, "DH", P11KeyAgreement, s("DiffieHellman"),
m(CKM_DH_PKCS_DERIVE)); m(CKM_DH_PKCS_DERIVE));
...@@ -654,12 +673,16 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -654,12 +673,16 @@ public final class SunPKCS11 extends AuthProvider {
d(SIG, "SHA512withRSA", P11Signature, d(SIG, "SHA512withRSA", P11Signature,
m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509)); 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)); 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, m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,
CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_MASTER_KEY_DERIVE_DH)); CKM_SSL3_MASTER_KEY_DERIVE_DH,
d(KG, "SunTlsKeyMaterial", "sun.security.pkcs11.P11TlsKeyMaterialGenerator", 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)); m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));
d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator", d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",
m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL)); m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));
...@@ -773,6 +796,13 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -773,6 +796,13 @@ public final class SunPKCS11 extends AuthProvider {
System.out.println(token.tokenInfo); System.out.println(token.tokenInfo);
} }
long[] supportedMechanisms = p11.C_GetMechanismList(slotID); 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 = final Map<Descriptor,Integer> supportedAlgs =
new HashMap<Descriptor,Integer>(); new HashMap<Descriptor,Integer>();
for (int i = 0; i < supportedMechanisms.length; i++) { for (int i = 0; i < supportedMechanisms.length; i++) {
...@@ -807,6 +837,9 @@ public final class SunPKCS11 extends AuthProvider { ...@@ -807,6 +837,9 @@ public final class SunPKCS11 extends AuthProvider {
supportedAlgs.put(d, integerMech); supportedAlgs.put(d, integerMech);
continue; continue;
} }
// See if there is something "more preferred"
// than what we currently have in the supportedAlgs
// map.
int intOldMech = oldMech.intValue(); int intOldMech = oldMech.intValue();
for (int j = 0; j < d.mechanisms.length; j++) { for (int j = 0; j < d.mechanisms.length; j++) {
int nextMech = d.mechanisms[j]; int nextMech = d.mechanisms[j];
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -31,6 +31,8 @@ import java.security.*; ...@@ -31,6 +31,8 @@ import java.security.*;
import java.security.interfaces.*; import java.security.interfaces.*;
import java.security.spec.*; import java.security.spec.*;
import sun.security.action.GetPropertyAction;
/** /**
* KeyFactory for RSA keys. Keys must be instances of PublicKey or PrivateKey * KeyFactory for RSA keys. Keys must be instances of PublicKey or PrivateKey
* and getAlgorithm() must return "RSA". For such keys, it supports conversion * and getAlgorithm() must return "RSA". For such keys, it supports conversion
...@@ -68,6 +70,24 @@ public final class RSAKeyFactory extends KeyFactorySpi { ...@@ -68,6 +70,24 @@ public final class RSAKeyFactory extends KeyFactorySpi {
private final static Class<?> x509KeySpecClass = X509EncodedKeySpec.class; private final static Class<?> x509KeySpecClass = X509EncodedKeySpec.class;
private final static Class<?> pkcs8KeySpecClass = PKCS8EncodedKeySpec.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(); // instance used for static translateKey();
private final static RSAKeyFactory INSTANCE = new RSAKeyFactory(); private final static RSAKeyFactory INSTANCE = new RSAKeyFactory();
...@@ -76,74 +96,79 @@ public final class RSAKeyFactory extends KeyFactorySpi { ...@@ -76,74 +96,79 @@ public final class RSAKeyFactory extends KeyFactorySpi {
} }
/** /**
* Static method to convert Key into a useable instance of * Static method to convert Key into an instance of RSAPublicKeyImpl
* RSAPublicKey or RSAPrivate(Crt)Key. Check the key and convert it * or RSAPrivate(Crt)KeyImpl. If the key is not an RSA key or cannot be
* to a SunRsaSign key if necessary. If the key is not an RSA key * used, throw an InvalidKeyException.
* 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.
* *
* Used by RSASignature and RSACipher. * Used by RSASignature and RSACipher.
*/ */
public static RSAKey toRSAKey(Key key) throws InvalidKeyException { public static RSAKey toRSAKey(Key key) throws InvalidKeyException {
if (key instanceof RSAKey) { if ((key instanceof RSAPrivateKeyImpl) ||
RSAKey rsaKey = (RSAKey)key; (key instanceof RSAPrivateCrtKeyImpl) ||
checkKey(rsaKey); (key instanceof RSAPublicKeyImpl)) {
return rsaKey; return (RSAKey)key;
} else { } else {
return (RSAKey)INSTANCE.engineTranslateKey(key); 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 { static void checkRSAProviderKeyLengths(int modulusLen, BigInteger exponent)
// check for subinterfaces, omit additional checks for our keys throws InvalidKeyException {
if (key instanceof RSAPublicKey) { checkKeyLengths(((modulusLen + 7) & ~7), exponent,
if (key instanceof RSAPublicKeyImpl) { RSAKeyFactory.MIN_MODLEN, Integer.MAX_VALUE);
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);
} }
/** /**
* Check the length of the modulus of an RSA key. We only support keys * Check the length of an RSA key modulus/exponent to make sure it
* at least 505 bits long. * 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 { public static void checkKeyLengths(int modulusLen, BigInteger exponent,
if (modulus.bitLength() < 505) { int minModulusLen, int maxModulusLen) throws InvalidKeyException {
// some providers may generate slightly shorter keys
// accept them if the encoding is at least 64 bytes long if ((minModulusLen > 0) && (modulusLen < (minModulusLen))) {
throw new InvalidKeyException throw new InvalidKeyException( "RSA keys must be at least " +
("RSA keys must be at least 512 bits long"); 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");
} }
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -47,7 +47,7 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -47,7 +47,7 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// public exponent to use // public exponent to use
private BigInteger publicExponent; private BigInteger publicExponent;
// size of the key to generate, >= 512 // size of the key to generate, >= RSAKeyFactory.MIN_MODLEN
private int keySize; private int keySize;
// PRNG to use // PRNG to use
...@@ -60,15 +60,16 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -60,15 +60,16 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// initialize the generator. See JCA doc // initialize the generator. See JCA doc
public void initialize(int keySize, SecureRandom random) { public void initialize(int keySize, SecureRandom random) {
if (keySize < 512) {
throw new InvalidParameterException // do not allow unreasonably small or large key sizes,
("Key size must be at least 512 bits"); // probably user error
} try {
if (keySize > 64 * 1024) { RSAKeyFactory.checkKeyLengths(keySize, RSAKeyGenParameterSpec.F4,
// do not allow unreasonably large key sizes, probably user error 512, 64 * 1024);
throw new InvalidParameterException } catch (InvalidKeyException e) {
("Key size must be 65536 bits or less"); throw new InvalidParameterException(e.getMessage());
} }
this.keySize = keySize; this.keySize = keySize;
this.random = random; this.random = random;
this.publicExponent = RSAKeyGenParameterSpec.F4; this.publicExponent = RSAKeyGenParameterSpec.F4;
...@@ -77,35 +78,41 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -77,35 +78,41 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// second initialize method. See JCA doc. // second initialize method. See JCA doc.
public void initialize(AlgorithmParameterSpec params, SecureRandom random) public void initialize(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException { throws InvalidAlgorithmParameterException {
if (params instanceof RSAKeyGenParameterSpec == false) { if (params instanceof RSAKeyGenParameterSpec == false) {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException
("Params must be instance of RSAKeyGenParameterSpec"); ("Params must be instance of RSAKeyGenParameterSpec");
} }
RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params; RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params;
keySize = rsaSpec.getKeysize(); int tmpKeySize = rsaSpec.getKeysize();
publicExponent = rsaSpec.getPublicExponent(); BigInteger tmpPublicExponent = rsaSpec.getPublicExponent();
this.random = random;
if (keySize < 512) { if (tmpPublicExponent == null) {
throw new InvalidAlgorithmParameterException tmpPublicExponent = RSAKeyGenParameterSpec.F4;
("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;
} else { } else {
if (publicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) { if (tmpPublicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException
("Public exponent must be 3 or larger"); ("Public exponent must be 3 or larger");
} }
if (publicExponent.bitLength() > keySize) { if (tmpPublicExponent.bitLength() > tmpKeySize) {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException
("Public exponent must be smaller than key size"); ("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 // generate the keypair. See JCA doc
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -89,7 +89,7 @@ public final class RSAPrivateCrtKeyImpl ...@@ -89,7 +89,7 @@ public final class RSAPrivateCrtKeyImpl
*/ */
RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException { RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException {
decode(encoded); decode(encoded);
RSAKeyFactory.checkKeyLength(n); RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
} }
/** /**
...@@ -107,7 +107,8 @@ public final class RSAPrivateCrtKeyImpl ...@@ -107,7 +107,8 @@ public final class RSAPrivateCrtKeyImpl
this.pe = pe; this.pe = pe;
this.qe = qe; this.qe = qe;
this.coeff = coeff; this.coeff = coeff;
RSAKeyFactory.checkKeyLength(n); RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
// generate the encoding // generate the encoding
algid = rsaId; algid = rsaId;
try { try {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -61,7 +61,7 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey { ...@@ -61,7 +61,7 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey {
RSAPrivateKeyImpl(BigInteger n, BigInteger d) throws InvalidKeyException { RSAPrivateKeyImpl(BigInteger n, BigInteger d) throws InvalidKeyException {
this.n = n; this.n = n;
this.d = d; this.d = d;
RSAKeyFactory.checkKeyLength(n); RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), null);
// generate the encoding // generate the encoding
algid = RSAPrivateCrtKeyImpl.rsaId; algid = RSAPrivateCrtKeyImpl.rsaId;
try { try {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -56,10 +56,11 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey { ...@@ -56,10 +56,11 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
* Construct a key from its components. Used by the * Construct a key from its components. Used by the
* RSAKeyFactory and the RSAKeyPairGenerator. * RSAKeyFactory and the RSAKeyPairGenerator.
*/ */
public RSAPublicKeyImpl(BigInteger n, BigInteger e) throws InvalidKeyException { public RSAPublicKeyImpl(BigInteger n, BigInteger e)
throws InvalidKeyException {
this.n = n; this.n = n;
this.e = e; this.e = e;
RSAKeyFactory.checkKeyLength(n); RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
// generate the encoding // generate the encoding
algid = RSAPrivateCrtKeyImpl.rsaId; algid = RSAPrivateCrtKeyImpl.rsaId;
try { try {
...@@ -80,7 +81,7 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey { ...@@ -80,7 +81,7 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
*/ */
public RSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException { public RSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException {
decode(encoded); decode(encoded);
RSAKeyFactory.checkKeyLength(n); RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
} }
// see JCA doc // see JCA doc
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# passwords. To be functional, a role must have an entry in # passwords. To be functional, a role must have an entry in
# both the password and the access files. # 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 # You can specify an alternate location by specifying a property in
# the management config file $JRE/lib/management/management.properties # the management config file $JRE/lib/management/management.properties
# (See that file for details) # (See that file for details)
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
# The file format for password and access files is syntactically the same # The file format for password and access files is syntactically the same
# as the Properties file format. The syntax is described in the Javadoc # as the Properties file format. The syntax is described in the Javadoc
# for java.util.Properties.load. # 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. # a comment (like this one), or an access control entry.
# #
# An access control entry consists of a role name, and an # An access control entry consists of a role name, and an
...@@ -29,10 +29,38 @@ ...@@ -29,10 +29,38 @@
# role can read measurements but cannot perform any action # role can read measurements but cannot perform any action
# that changes the environment of the running program. # that changes the environment of the running program.
# "readwrite" grants access to read and write attributes of MBeans, # "readwrite" grants access to read and write attributes of MBeans,
# to invoke operations on them, and to create or remove them. # to invoke operations on them, and optionally
# This access should be granted to only trusted clients, # to create or remove them. This access should be granted
# since they can potentially interfere with the smooth # only to trusted clients, since they can potentially
# operation of a running program # 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 # A given role should have at most one entry in this file. If a role
# has no entry, it has no access. # has no entry, it has no access.
...@@ -42,7 +70,10 @@ ...@@ -42,7 +70,10 @@
# #
# Default access control entries: # Default access control entries:
# o The "monitorRole" role has readonly access. # 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 monitorRole readonly
controlRole readwrite controlRole readwrite \
create javax.management.monitor.*,javax.management.timer.* \
unregister
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -94,6 +94,7 @@ void band::readData(int expectedLength) { ...@@ -94,6 +94,7 @@ void band::readData(int expectedLength) {
assert(!valc->isMalloc); assert(!valc->isMalloc);
} }
xvs.init(u->rp, u->rplimit, valc); xvs.init(u->rp, u->rplimit, valc);
CHECK;
int X = xvs.getInt(); int X = xvs.getInt();
if (valc->S() != 0) { if (valc->S() != 0) {
assert(valc->min <= -256); assert(valc->min <= -256);
...@@ -117,6 +118,7 @@ void band::readData(int expectedLength) { ...@@ -117,6 +118,7 @@ void band::readData(int expectedLength) {
byte XB_byte = (byte) XB; byte XB_byte = (byte) XB;
byte* XB_ptr = &XB_byte; byte* XB_ptr = &XB_byte;
cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, null); cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, null);
CHECK;
} else { } else {
NOT_PRODUCT(byte* meta_rp0 = u->meta_rp); NOT_PRODUCT(byte* meta_rp0 = u->meta_rp);
assert(u->meta_rp != null); assert(u->meta_rp != null);
...@@ -215,8 +217,19 @@ int band::getIntTotal() { ...@@ -215,8 +217,19 @@ int band::getIntTotal() {
if (length == 0) return 0; if (length == 0) return 0;
if (total_memo > 0) return total_memo-1; if (total_memo > 0) return total_memo-1;
int total = getInt(); 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--) { for (int k = length-1; k > 0; k--) {
int prev_total = total;
total += vs[0].getInt(); total += vs[0].getInt();
if (total < prev_total) {
abort("overflow detected");
return 0;
}
} }
rewind(); rewind();
total_memo = total+1; total_memo = total+1;
......
...@@ -56,7 +56,7 @@ void bytes::realloc(size_t len_) { ...@@ -56,7 +56,7 @@ void bytes::realloc(size_t len_) {
return; return;
} }
byte* oldptr = ptr; byte* oldptr = ptr;
ptr = (byte*)::realloc(ptr, len_+1); ptr = (len_ >= PSIZE_MAX) ? null : (byte*)::realloc(ptr, len_+1);
if (ptr != null) { if (ptr != null) {
mtrace('r', oldptr, 0); mtrace('r', oldptr, 0);
mtrace('m', ptr, len_+1); mtrace('m', ptr, len_+1);
...@@ -128,7 +128,7 @@ const char* bytes::string() { ...@@ -128,7 +128,7 @@ const char* bytes::string() {
// Make sure there are 'o' bytes beyond the fill pointer, // Make sure there are 'o' bytes beyond the fill pointer,
// advance the fill pointer, and return the old fill pointer. // advance the fill pointer, and return the old fill pointer.
byte* fillbytes::grow(size_t s) { byte* fillbytes::grow(size_t s) {
size_t nlen = b.len+s; size_t nlen = add_size(b.len, s);
if (nlen <= allocated) { if (nlen <= allocated) {
b.len = nlen; b.len = nlen;
return limit()-s; return limit()-s;
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -814,6 +814,7 @@ void coding_method::init(byte* &band_rp, byte* band_limit, ...@@ -814,6 +814,7 @@ void coding_method::init(byte* &band_rp, byte* band_limit,
} }
band_rp = vs.rp; band_rp = vs.rp;
} }
CHECK;
// Get an accurate upper limit now. // Get an accurate upper limit now.
vs0.rplimit = band_rp; vs0.rplimit = band_rp;
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -47,11 +47,13 @@ ...@@ -47,11 +47,13 @@
#define NOT_PRODUCT(xxx) #define NOT_PRODUCT(xxx)
#define assert(p) #define assert(p)
#define PRINTCR(args) #define PRINTCR(args)
#define VERSION_STRING "%s version %s\n"
#else #else
#define IF_PRODUCT(xxx) #define IF_PRODUCT(xxx)
#define NOT_PRODUCT(xxx) xxx #define NOT_PRODUCT(xxx) xxx
#define assert(p) ((p) || assert_failed(#p)) #define assert(p) ((p) || assert_failed(#p))
#define PRINTCR(args) u->verbose && u->printcr_if_verbose args #define PRINTCR(args) u->verbose && u->printcr_if_verbose args
#define VERSION_STRING "%s version non-product %s\n"
extern "C" void breakpoint(); extern "C" void breakpoint();
extern int assert_failed(const char*); extern int assert_failed(const char*);
#define BREAK (breakpoint()) #define BREAK (breakpoint())
...@@ -79,9 +81,9 @@ extern int assert_failed(const char*); ...@@ -79,9 +81,9 @@ extern int assert_failed(const char*);
#define lengthof(array) (sizeof(array)/sizeof(array[0])) #define lengthof(array) (sizeof(array)/sizeof(array[0]))
#define NEW(T, n) (T*) must_malloc((int)(sizeof(T)*(n))) #define NEW(T, n) (T*) must_malloc((int)(scale_size(n, sizeof(T))))
#define U_NEW(T, n) (T*) u->alloc(sizeof(T)*(n)) #define U_NEW(T, n) (T*) u->alloc(scale_size(n, sizeof(T)))
#define T_NEW(T, n) (T*) u->temp_alloc(sizeof(T)*(n)) #define T_NEW(T, n) (T*) u->temp_alloc(scale_size(n, sizeof(T)))
// bytes and byte arrays // bytes and byte arrays
...@@ -153,6 +155,8 @@ enum { false, true }; ...@@ -153,6 +155,8 @@ enum { false, true };
#define CHECK_NULL_(y,p) _CHECK_DO((p)==null, return y) #define CHECK_NULL_(y,p) _CHECK_DO((p)==null, return y)
#define CHECK_NULL_0(p) _CHECK_DO((p)==null, return 0) #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_TRUE "true"
#define STR_FALSE "false" #define STR_FALSE "false"
......
...@@ -299,7 +299,7 @@ int unpacker::run(int argc, char **argv) { ...@@ -299,7 +299,7 @@ int unpacker::run(int argc, char **argv) {
case 'J': argp += 1; break; // skip ignored -Jxxx parameter case 'J': argp += 1; break; // skip ignored -Jxxx parameter
case 'V': case 'V':
fprintf(u.errstrm, "%s version %s\n", nbasename(argv[0]), sccsver); fprintf(u.errstrm, VERSION_STRING, nbasename(argv[0]), sccsver);
exit(0); exit(0);
case 'h': case 'h':
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -523,15 +523,39 @@ void unpacker::read_file_header() { ...@@ -523,15 +523,39 @@ void unpacker::read_file_header() {
enum { enum {
MAGIC_BYTES = 4, MAGIC_BYTES = 4,
AH_LENGTH_0 = 3, //minver, majver, options are outside of archive_size 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) AH_LENGTH = 26, //maximum archive header length (w/ all fields)
// Length contributions from optional header fields: // Length contributions from optional header fields:
AH_FILE_HEADER_LEN = 5, // sizehi/lo/next/modtime/files 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_CP_NUMBER_LEN = 4, // int/float/long/double
AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers
AH_LENGTH_MIN = AH_LENGTH AH_LENGTH_MIN = AH_LENGTH
-(AH_FILE_HEADER_LEN+AH_SPECIAL_FORMAT_LEN+AH_CP_NUMBER_LEN), -(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 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); bool foreign_buf = (read_input_fn == null);
byte initbuf[(int)FIRST_READ + (int)C_SLOP + 200]; // 200 is for JAR I/O byte initbuf[(int)FIRST_READ + (int)C_SLOP + 200]; // 200 is for JAR I/O
if (foreign_buf) { if (foreign_buf) {
...@@ -547,7 +571,7 @@ void unpacker::read_file_header() { ...@@ -547,7 +571,7 @@ void unpacker::read_file_header() {
// There is no way to tell the caller that we used only part of them. // 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. // Therefore, the caller must use only a bare minimum of read-ahead.
if (inbytes.len > FIRST_READ) { if (inbytes.len > FIRST_READ) {
abort("too much pushback"); abort("too much read-ahead");
return; return;
} }
input.set(initbuf, sizeof(initbuf)); input.set(initbuf, sizeof(initbuf));
...@@ -557,7 +581,7 @@ void unpacker::read_file_header() { ...@@ -557,7 +581,7 @@ void unpacker::read_file_header() {
rplimit += inbytes.len; rplimit += inbytes.len;
bytes_read += 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. // but is certain not to overflow past the archive_header.
input.b.len = FIRST_READ; input.b.len = FIRST_READ;
if (!ensure_input(FIRST_READ)) if (!ensure_input(FIRST_READ))
...@@ -629,26 +653,25 @@ void unpacker::read_file_header() { ...@@ -629,26 +653,25 @@ void unpacker::read_file_header() {
#undef ORBIT #undef ORBIT
if ((archive_options & ~OPTION_LIMIT) != 0) { if ((archive_options & ~OPTION_LIMIT) != 0) {
fprintf(errstrm, "Warning: Illegal archive options 0x%x\n", fprintf(errstrm, "Warning: Illegal archive options 0x%x\n",
archive_options); archive_options);
// Do not abort. If the format really changes, version numbers will bump. abort("illegal archive options");
//abort("illegal archive options"); return;
} }
if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) { if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
uint hi = hdr.getInt(); uint hi = hdr.getInt();
uint lo = 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; hdrVals += 2;
} else { } else {
hdrValsSkipped += 2; hdrValsSkipped += 2;
} }
if (archive_size != (size_t)archive_size) {
// Silly size specified.
abort("archive too large");
return;
}
// Now we can size the whole archive. // Now we can size the whole archive.
// Read everything else into a mega-buffer. // Read everything else into a mega-buffer.
rp = hdr.rp; rp = hdr.rp;
...@@ -662,9 +685,18 @@ void unpacker::read_file_header() { ...@@ -662,9 +685,18 @@ void unpacker::read_file_header() {
abort("EOF reading fixed input buffer"); abort("EOF reading fixed input buffer");
return; return;
} }
} else if (archive_size > 0) { } else if (archive_size != 0) {
input.set(U_NEW(byte, (size_t)(header_size_0 + archive_size + C_SLOP)), if (archive_size < ARCHIVE_SIZE_MIN) {
(size_t) header_size_0 + (size_t)archive_size); 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); assert(input.limit()[0] == 0);
// Move all the bytes we read initially into the real buffer. // Move all the bytes we read initially into the real buffer.
input.b.copyFrom(initbuf, header_size); input.b.copyFrom(initbuf, header_size);
...@@ -673,17 +705,17 @@ void unpacker::read_file_header() { ...@@ -673,17 +705,17 @@ void unpacker::read_file_header() {
} else { } else {
// It's more complicated and painful. // It's more complicated and painful.
// A zero archive_size means that we must read until EOF. // A zero archive_size means that we must read until EOF.
assert(archive_size == 0);
input.init(CHUNK*2); input.init(CHUNK*2);
CHECK; CHECK;
input.b.len = input.allocated; input.b.len = input.allocated;
rp = rplimit = input.base(); rp = rplimit = input.base();
// Set up input buffer as if we already read the header: // Set up input buffer as if we already read the header:
input.b.copyFrom(initbuf, header_size); input.b.copyFrom(initbuf, header_size);
CHECK;
rplimit += header_size; rplimit += header_size;
while (ensure_input(input.limit() - rp)) { while (ensure_input(input.limit() - rp)) {
size_t dataSoFar = input_remaining(); size_t dataSoFar = input_remaining();
size_t nextSize = dataSoFar + CHUNK; size_t nextSize = add_size(dataSoFar, CHUNK);
input.ensureSize(nextSize); input.ensureSize(nextSize);
CHECK; CHECK;
input.b.len = input.allocated; input.b.len = input.allocated;
...@@ -715,8 +747,10 @@ void unpacker::read_file_header() { ...@@ -715,8 +747,10 @@ void unpacker::read_file_header() {
if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) { if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
archive_next_count = hdr.getInt(); archive_next_count = hdr.getInt();
CHECK_COUNT(archive_next_count);
archive_modtime = hdr.getInt(); archive_modtime = hdr.getInt();
file_count = hdr.getInt(); file_count = hdr.getInt();
CHECK_COUNT(file_count);
hdrVals += 3; hdrVals += 3;
} else { } else {
hdrValsSkipped += 3; hdrValsSkipped += 3;
...@@ -724,7 +758,9 @@ void unpacker::read_file_header() { ...@@ -724,7 +758,9 @@ void unpacker::read_file_header() {
if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0) { if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0) {
band_headers_size = hdr.getInt(); band_headers_size = hdr.getInt();
CHECK_COUNT(band_headers_size);
attr_definition_count = hdr.getInt(); attr_definition_count = hdr.getInt();
CHECK_COUNT(attr_definition_count);
hdrVals += 2; hdrVals += 2;
} else { } else {
hdrValsSkipped += 2; hdrValsSkipped += 2;
...@@ -744,13 +780,16 @@ void unpacker::read_file_header() { ...@@ -744,13 +780,16 @@ void unpacker::read_file_header() {
} }
} }
cp_counts[k] = hdr.getInt(); cp_counts[k] = hdr.getInt();
CHECK_COUNT(cp_counts[k]);
hdrVals += 1; hdrVals += 1;
} }
ic_count = hdr.getInt(); ic_count = hdr.getInt();
CHECK_COUNT(ic_count);
default_class_minver = hdr.getInt(); default_class_minver = hdr.getInt();
default_class_majver = hdr.getInt(); default_class_majver = hdr.getInt();
class_count = hdr.getInt(); class_count = hdr.getInt();
CHECK_COUNT(class_count);
hdrVals += 4; hdrVals += 4;
// done with archive_header // done with archive_header
...@@ -807,7 +846,6 @@ void unpacker::read_file_header() { ...@@ -807,7 +846,6 @@ void unpacker::read_file_header() {
bytes::of(band_headers.limit(), C_SLOP).clear(_meta_error); bytes::of(band_headers.limit(), C_SLOP).clear(_meta_error);
} }
void unpacker::finish() { void unpacker::finish() {
if (verbose >= 1) { if (verbose >= 1) {
fprintf(errstrm, fprintf(errstrm,
...@@ -973,12 +1011,12 @@ void unpacker::read_Utf8_values(entry* cpMap, int len) { ...@@ -973,12 +1011,12 @@ void unpacker::read_Utf8_values(entry* cpMap, int len) {
// First band: Read lengths of shared prefixes. // First band: Read lengths of shared prefixes.
if (len > PREFIX_SKIP_2) if (len > PREFIX_SKIP_2)
cp_Utf8_prefix.readData(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: // Second band: Read lengths of unshared suffixes:
if (len > SUFFIX_SKIP_1) if (len > SUFFIX_SKIP_1)
cp_Utf8_suffix.readData(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); bytes* allsuffixes = T_NEW(bytes, len);
CHECK; CHECK;
...@@ -2117,6 +2155,7 @@ void unpacker::read_classes() { ...@@ -2117,6 +2155,7 @@ void unpacker::read_classes() {
field_descr.readData(field_count); field_descr.readData(field_count);
read_attrs(ATTR_CONTEXT_FIELD, field_count); read_attrs(ATTR_CONTEXT_FIELD, field_count);
CHECK;
method_descr.readData(method_count); method_descr.readData(method_count);
read_attrs(ATTR_CONTEXT_METHOD, method_count); read_attrs(ATTR_CONTEXT_METHOD, method_count);
...@@ -2124,6 +2163,7 @@ void unpacker::read_classes() { ...@@ -2124,6 +2163,7 @@ void unpacker::read_classes() {
CHECK; CHECK;
read_attrs(ATTR_CONTEXT_CLASS, class_count); read_attrs(ATTR_CONTEXT_CLASS, class_count);
CHECK;
read_code_headers(); read_code_headers();
...@@ -2150,10 +2190,12 @@ void unpacker::read_attrs(int attrc, int obj_count) { ...@@ -2150,10 +2190,12 @@ void unpacker::read_attrs(int attrc, int obj_count) {
assert(endsWith(xxx_flags_hi.name, "_flags_hi")); assert(endsWith(xxx_flags_hi.name, "_flags_hi"));
if (haveLongFlags) if (haveLongFlags)
xxx_flags_hi.readData(obj_count); xxx_flags_hi.readData(obj_count);
CHECK;
band& xxx_flags_lo = ad.xxx_flags_lo(); band& xxx_flags_lo = ad.xxx_flags_lo();
assert(endsWith(xxx_flags_lo.name, "_flags_lo")); assert(endsWith(xxx_flags_lo.name, "_flags_lo"));
xxx_flags_lo.readData(obj_count); xxx_flags_lo.readData(obj_count);
CHECK;
// pre-scan flags, counting occurrences of each index bit // pre-scan flags, counting occurrences of each index bit
julong indexMask = ad.flagIndexMask(); // which flag bits are index bits? julong indexMask = ad.flagIndexMask(); // which flag bits are index bits?
...@@ -2176,11 +2218,13 @@ void unpacker::read_attrs(int attrc, int obj_count) { ...@@ -2176,11 +2218,13 @@ void unpacker::read_attrs(int attrc, int obj_count) {
assert(endsWith(xxx_attr_count.name, "_attr_count")); assert(endsWith(xxx_attr_count.name, "_attr_count"));
// There is one count element for each 1<<16 bit set in flags: // There is one count element for each 1<<16 bit set in flags:
xxx_attr_count.readData(ad.predefCount(X_ATTR_OVERFLOW)); xxx_attr_count.readData(ad.predefCount(X_ATTR_OVERFLOW));
CHECK;
band& xxx_attr_indexes = ad.xxx_attr_indexes(); band& xxx_attr_indexes = ad.xxx_attr_indexes();
assert(endsWith(xxx_attr_indexes.name, "_attr_indexes")); assert(endsWith(xxx_attr_indexes.name, "_attr_indexes"));
int overflowIndexCount = xxx_attr_count.getIntTotal(); int overflowIndexCount = xxx_attr_count.getIntTotal();
xxx_attr_indexes.readData(overflowIndexCount); xxx_attr_indexes.readData(overflowIndexCount);
CHECK;
// pre-scan attr indexes, counting occurrences of each value // pre-scan attr indexes, counting occurrences of each value
for (i = 0; i < overflowIndexCount; i++) { for (i = 0; i < overflowIndexCount; i++) {
idx = xxx_attr_indexes.getInt(); idx = xxx_attr_indexes.getInt();
...@@ -2211,6 +2255,7 @@ void unpacker::read_attrs(int attrc, int obj_count) { ...@@ -2211,6 +2255,7 @@ void unpacker::read_attrs(int attrc, int obj_count) {
} }
} }
ad.xxx_attr_calls().readData(backwardCounts); ad.xxx_attr_calls().readData(backwardCounts);
CHECK;
// Read built-in bands. // Read built-in bands.
// Mostly, these are hand-coded equivalents to readBandData(). // Mostly, these are hand-coded equivalents to readBandData().
...@@ -2219,42 +2264,53 @@ void unpacker::read_attrs(int attrc, int obj_count) { ...@@ -2219,42 +2264,53 @@ void unpacker::read_attrs(int attrc, int obj_count) {
count = ad.predefCount(CLASS_ATTR_SourceFile); count = ad.predefCount(CLASS_ATTR_SourceFile);
class_SourceFile_RUN.readData(count); class_SourceFile_RUN.readData(count);
CHECK;
count = ad.predefCount(CLASS_ATTR_EnclosingMethod); count = ad.predefCount(CLASS_ATTR_EnclosingMethod);
class_EnclosingMethod_RC.readData(count); class_EnclosingMethod_RC.readData(count);
class_EnclosingMethod_RDN.readData(count); class_EnclosingMethod_RDN.readData(count);
CHECK;
count = ad.predefCount(X_ATTR_Signature); count = ad.predefCount(X_ATTR_Signature);
class_Signature_RS.readData(count); class_Signature_RS.readData(count);
CHECK;
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations); ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations); ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
count = ad.predefCount(CLASS_ATTR_InnerClasses); count = ad.predefCount(CLASS_ATTR_InnerClasses);
class_InnerClasses_N.readData(count); class_InnerClasses_N.readData(count);
CHECK;
count = class_InnerClasses_N.getIntTotal(); count = class_InnerClasses_N.getIntTotal();
class_InnerClasses_RC.readData(count); class_InnerClasses_RC.readData(count);
class_InnerClasses_F.readData(count); class_InnerClasses_F.readData(count);
CHECK;
// Drop remaining columns wherever flags are zero: // Drop remaining columns wherever flags are zero:
count -= class_InnerClasses_F.getIntCount(0); count -= class_InnerClasses_F.getIntCount(0);
class_InnerClasses_outer_RCN.readData(count); class_InnerClasses_outer_RCN.readData(count);
class_InnerClasses_name_RUN.readData(count); class_InnerClasses_name_RUN.readData(count);
CHECK;
count = ad.predefCount(CLASS_ATTR_ClassFile_version); count = ad.predefCount(CLASS_ATTR_ClassFile_version);
class_ClassFile_version_minor_H.readData(count); class_ClassFile_version_minor_H.readData(count);
class_ClassFile_version_major_H.readData(count); class_ClassFile_version_major_H.readData(count);
CHECK;
break; break;
case ATTR_CONTEXT_FIELD: case ATTR_CONTEXT_FIELD:
count = ad.predefCount(FIELD_ATTR_ConstantValue); count = ad.predefCount(FIELD_ATTR_ConstantValue);
field_ConstantValue_KQ.readData(count); field_ConstantValue_KQ.readData(count);
CHECK;
count = ad.predefCount(X_ATTR_Signature); count = ad.predefCount(X_ATTR_Signature);
field_Signature_RS.readData(count); field_Signature_RS.readData(count);
CHECK;
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations); ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations); ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
CHECK;
break; break;
case ATTR_CONTEXT_METHOD: case ATTR_CONTEXT_METHOD:
...@@ -2266,15 +2322,18 @@ void unpacker::read_attrs(int attrc, int obj_count) { ...@@ -2266,15 +2322,18 @@ void unpacker::read_attrs(int attrc, int obj_count) {
method_Exceptions_N.readData(count); method_Exceptions_N.readData(count);
count = method_Exceptions_N.getIntTotal(); count = method_Exceptions_N.getIntTotal();
method_Exceptions_RC.readData(count); method_Exceptions_RC.readData(count);
CHECK;
count = ad.predefCount(X_ATTR_Signature); count = ad.predefCount(X_ATTR_Signature);
method_Signature_RS.readData(count); method_Signature_RS.readData(count);
CHECK;
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations); ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations); ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
ad.readBandData(METHOD_ATTR_RuntimeVisibleParameterAnnotations); ad.readBandData(METHOD_ATTR_RuntimeVisibleParameterAnnotations);
ad.readBandData(METHOD_ATTR_RuntimeInvisibleParameterAnnotations); ad.readBandData(METHOD_ATTR_RuntimeInvisibleParameterAnnotations);
ad.readBandData(METHOD_ATTR_AnnotationDefault); ad.readBandData(METHOD_ATTR_AnnotationDefault);
CHECK;
break; break;
case ATTR_CONTEXT_CODE: case ATTR_CONTEXT_CODE:
...@@ -2286,8 +2345,10 @@ void unpacker::read_attrs(int attrc, int obj_count) { ...@@ -2286,8 +2345,10 @@ void unpacker::read_attrs(int attrc, int obj_count) {
return; return;
} }
code_StackMapTable_N.readData(count); code_StackMapTable_N.readData(count);
CHECK;
count = code_StackMapTable_N.getIntTotal(); count = code_StackMapTable_N.getIntTotal();
code_StackMapTable_frame_T.readData(count); code_StackMapTable_frame_T.readData(count);
CHECK;
// the rest of it depends in a complicated way on frame tags // the rest of it depends in a complicated way on frame tags
{ {
int fat_frame_count = 0; int fat_frame_count = 0;
...@@ -2321,18 +2382,23 @@ void unpacker::read_attrs(int attrc, int obj_count) { ...@@ -2321,18 +2382,23 @@ void unpacker::read_attrs(int attrc, int obj_count) {
// deal completely with fat frames: // deal completely with fat frames:
offset_count += fat_frame_count; offset_count += fat_frame_count;
code_StackMapTable_local_N.readData(fat_frame_count); code_StackMapTable_local_N.readData(fat_frame_count);
CHECK;
type_count += code_StackMapTable_local_N.getIntTotal(); type_count += code_StackMapTable_local_N.getIntTotal();
code_StackMapTable_stack_N.readData(fat_frame_count); code_StackMapTable_stack_N.readData(fat_frame_count);
type_count += code_StackMapTable_stack_N.getIntTotal(); type_count += code_StackMapTable_stack_N.getIntTotal();
CHECK;
// read the rest: // read the rest:
code_StackMapTable_offset.readData(offset_count); code_StackMapTable_offset.readData(offset_count);
code_StackMapTable_T.readData(type_count); code_StackMapTable_T.readData(type_count);
CHECK;
// (7) [RCH] // (7) [RCH]
count = code_StackMapTable_T.getIntCount(7); count = code_StackMapTable_T.getIntCount(7);
code_StackMapTable_RC.readData(count); code_StackMapTable_RC.readData(count);
CHECK;
// (8) [PH] // (8) [PH]
count = code_StackMapTable_T.getIntCount(8); count = code_StackMapTable_T.getIntCount(8);
code_StackMapTable_P.readData(count); code_StackMapTable_P.readData(count);
CHECK;
} }
count = ad.predefCount(CODE_ATTR_LineNumberTable); count = ad.predefCount(CODE_ATTR_LineNumberTable);
...@@ -2654,6 +2720,7 @@ void unpacker::read_code_headers() { ...@@ -2654,6 +2720,7 @@ void unpacker::read_code_headers() {
code_max_na_locals.readData(); code_max_na_locals.readData();
code_handler_count.readData(); code_handler_count.readData();
totalHandlerCount += code_handler_count.getIntTotal(); totalHandlerCount += code_handler_count.getIntTotal();
CHECK;
// Read handler specifications. // Read handler specifications.
// Cf. PackageReader.readCodeHandlers. // Cf. PackageReader.readCodeHandlers.
...@@ -2661,8 +2728,10 @@ void unpacker::read_code_headers() { ...@@ -2661,8 +2728,10 @@ void unpacker::read_code_headers() {
code_handler_end_PO.readData(totalHandlerCount); code_handler_end_PO.readData(totalHandlerCount);
code_handler_catch_PO.readData(totalHandlerCount); code_handler_catch_PO.readData(totalHandlerCount);
code_handler_class_RCN.readData(totalHandlerCount); code_handler_class_RCN.readData(totalHandlerCount);
CHECK;
read_attrs(ATTR_CONTEXT_CODE, totalFlagsCount); read_attrs(ATTR_CONTEXT_CODE, totalFlagsCount);
CHECK;
} }
static inline bool is_in_range(uint n, uint min, uint max) { static inline bool is_in_range(uint n, uint min, uint max) {
......
...@@ -204,7 +204,7 @@ struct unpacker { ...@@ -204,7 +204,7 @@ struct unpacker {
// archive header fields // archive header fields
int magic, minver, majver; int magic, minver, majver;
julong archive_size; size_t archive_size;
int archive_next_count, archive_options, archive_modtime; int archive_next_count, archive_options, archive_modtime;
int band_headers_size; int band_headers_size;
int file_count, attr_definition_count, ic_count, class_count; int file_count, attr_definition_count, ic_count, class_count;
......
...@@ -46,14 +46,13 @@ ...@@ -46,14 +46,13 @@
#include "unpack.h" #include "unpack.h"
void* must_malloc(int size) { void* must_malloc(size_t size) {
int msize = size; size_t msize = size;
assert(size >= 0);
#ifdef USE_MTRACE #ifdef USE_MTRACE
if (msize < sizeof(int)) if (msize >= 0 && msize < sizeof(int))
msize = sizeof(int); // see 0xbaadf00d below msize = sizeof(int); // see 0xbaadf00d below
#endif #endif
void* ptr = malloc(msize); void* ptr = (msize > PSIZE_MAX) ? null : malloc(msize);
if (ptr != null) { if (ptr != null) {
memset(ptr, 0, size); memset(ptr, 0, size);
} else { } else {
......
...@@ -25,13 +25,31 @@ ...@@ -25,13 +25,31 @@
//Definitions of our util functions //Definitions of our util functions
void* must_malloc(int size); void* must_malloc(size_t size);
#ifndef USE_MTRACE #ifndef USE_MTRACE
#define mtrace(c, ptr, size) #define mtrace(c, ptr, size)
#else #else
void mtrace(char c, void* ptr, size_t size); void mtrace(char c, void* ptr, size_t size);
#endif #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, // These may be expensive, because they have to go via Java TSD,
// if the optional u argument is missing. // if the optional u argument is missing.
struct unpacker; struct unpacker;
......
...@@ -722,6 +722,10 @@ DGifSetupDecompress(GifFileType * GifFile) { ...@@ -722,6 +722,10 @@ DGifSetupDecompress(GifFileType * GifFile) {
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
READ(GifFile, &CodeSize, 1); /* Read Code size from file. */ READ(GifFile, &CodeSize, 1); /* Read Code size from file. */
if (CodeSize >= 12) {
/* Invalid initial code size: report failure */
return GIF_ERROR;
}
BitsPerPixel = CodeSize; BitsPerPixel = CodeSize;
Private->Buf[0] = 0; /* Input Buffer empty. */ Private->Buf[0] = 0; /* Input Buffer empty. */
...@@ -964,10 +968,13 @@ DGifDecompressInput(GifFileType * GifFile, ...@@ -964,10 +968,13 @@ DGifDecompressInput(GifFileType * GifFile,
/* If code cannot fit into RunningBits bits, must raise its size. Note /* If code cannot fit into RunningBits bits, must raise its size. Note
* however that codes above 4095 are used for special signaling. */ * however that codes above 4095 are used for special signaling. */
if (++Private->RunningCode > Private->MaxCode1 && if (++Private->RunningCode > Private->MaxCode1) {
Private->RunningBits < LZ_BITS) { if (Private->RunningBits < LZ_BITS) {
Private->MaxCode1 <<= 1; Private->MaxCode1 <<= 1;
Private->RunningBits++; Private->RunningBits++;
} else {
Private->RunningCode = Private->MaxCode1;
}
} }
return GIF_OK; return GIF_OK;
} }
......
...@@ -191,6 +191,11 @@ Java_sun_awt_image_GifImageDecoder_parseImage(JNIEnv *env, ...@@ -191,6 +191,11 @@ Java_sun_awt_image_GifImageDecoder_parseImage(JNIEnv *env,
int passht = passinc; int passht = passinc;
int len; 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 if (blockh == 0 || raslineh == 0
|| prefixh == 0 || suffixh == 0 || prefixh == 0 || suffixh == 0
|| outCodeh == 0) || outCodeh == 0)
......
...@@ -216,6 +216,16 @@ printMedialibError(int status) { ...@@ -216,6 +216,16 @@ printMedialibError(int status) {
#endif /* ! DEBUG */ #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 * * External Functions *
...@@ -400,22 +410,10 @@ Java_sun_awt_image_ImagingLib_convolveBI(JNIEnv *env, jobject this, ...@@ -400,22 +410,10 @@ Java_sun_awt_image_ImagingLib_convolveBI(JNIEnv *env, jobject this,
} }
} }
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; cmask = (1<<src->channels)-1;
status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h, status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
(w-1)/2, (h-1)/2, scale, cmask, (w-1)/2, (h-1)/2, scale, cmask,
MLIB_EDGE_DST_NO_WRITE); getMlibEdgeHint(edgeHint));
if (status != MLIB_SUCCESS) { if (status != MLIB_SUCCESS) {
printMedialibError(status); printMedialibError(status);
...@@ -660,22 +658,10 @@ Java_sun_awt_image_ImagingLib_convolveRaster(JNIEnv *env, jobject this, ...@@ -660,22 +658,10 @@ Java_sun_awt_image_ImagingLib_convolveRaster(JNIEnv *env, jobject this,
} }
} }
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; cmask = (1<<src->channels)-1;
status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h, status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
(w-1)/2, (h-1)/2, scale, cmask, (w-1)/2, (h-1)/2, scale, cmask,
MLIB_EDGE_DST_NO_WRITE); getMlibEdgeHint(edgeHint));
if (status != MLIB_SUCCESS) { if (status != MLIB_SUCCESS) {
printMedialibError(status); printMedialibError(status);
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
/* here come some very simple macros */ /* here come some very simple macros */
/* advance a pointer p by sizeof(type)*n bytes */ /* 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) */ /* advance a pointer by sizeof(type) */
#define INCP(type,p) INCPN(type,(p),1) #define INCP(type,p) INCPN(type,(p),1)
......
...@@ -62,6 +62,15 @@ SplashStreamGifInputFunc(GifFileType * gif, GifByteType * buf, int n) ...@@ -62,6 +62,15 @@ SplashStreamGifInputFunc(GifFileType * gif, GifByteType * buf, int n)
return rc; 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 int
SplashDecodeGif(Splash * splash, GifFileType * gif) SplashDecodeGif(Splash * splash, GifFileType * gif)
{ {
...@@ -70,6 +79,7 @@ SplashDecodeGif(Splash * splash, GifFileType * gif) ...@@ -70,6 +79,7 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
byte_t *pBitmapBits, *pOldBitmapBits; byte_t *pBitmapBits, *pOldBitmapBits;
int i, j; int i, j;
int imageIndex; int imageIndex;
int cx, cy, cw, ch; /* clamped coordinates */
const int interlacedOffset[] = { 0, 4, 2, 1, 0 }; /* The way Interlaced image should. */ 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... */ const int interlacedJumps[] = { 8, 8, 4, 2, 1 }; /* be read - offsets and jumps... */
...@@ -79,14 +89,31 @@ SplashDecodeGif(Splash * splash, GifFileType * gif) ...@@ -79,14 +89,31 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
SplashCleanup(splash); SplashCleanup(splash);
if (!SAFE_TO_ALLOC(gif->SWidth, splash->imageFormat.depthBytes)) {
return 0;
}
stride = gif->SWidth * splash->imageFormat.depthBytes; stride = gif->SWidth * splash->imageFormat.depthBytes;
if (splash->byteAlignment > 1) if (splash->byteAlignment > 1)
stride = stride =
(stride + splash->byteAlignment - 1) & ~(splash->byteAlignment - 1); (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; bufferSize = stride * gif->SHeight;
pBitmapBits = (byte_t *) malloc(bufferSize); pBitmapBits = (byte_t *) malloc(bufferSize);
if (!pBitmapBits) {
return 0;
}
pOldBitmapBits = (byte_t *) malloc(bufferSize); pOldBitmapBits = (byte_t *) malloc(bufferSize);
if (!pOldBitmapBits) {
free(pBitmapBits);
return 0;
}
memset(pBitmapBits, 0, bufferSize); memset(pBitmapBits, 0, bufferSize);
splash->width = gif->SWidth; splash->width = gif->SWidth;
...@@ -94,6 +121,11 @@ SplashDecodeGif(Splash * splash, GifFileType * gif) ...@@ -94,6 +121,11 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
splash->frameCount = gif->ImageCount; splash->frameCount = gif->ImageCount;
splash->frames = (SplashImage *) splash->frames = (SplashImage *)
malloc(sizeof(SplashImage) * gif->ImageCount); malloc(sizeof(SplashImage) * gif->ImageCount);
if (!splash->frames) {
free(pBitmapBits);
free(pOldBitmapBits);
return 0;
}
memset(splash->frames, 0, sizeof(SplashImage) * gif->ImageCount); memset(splash->frames, 0, sizeof(SplashImage) * gif->ImageCount);
splash->loopCount = 1; splash->loopCount = 1;
...@@ -109,6 +141,11 @@ SplashDecodeGif(Splash * splash, GifFileType * gif) ...@@ -109,6 +141,11 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
int colorCount = 0; int colorCount = 0;
rgbquad_t colorMapBuf[SPLASH_COLOR_MAP_SIZE]; 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) {
if (colorMap->ColorCount <= SPLASH_COLOR_MAP_SIZE) { if (colorMap->ColorCount <= SPLASH_COLOR_MAP_SIZE) {
colorCount = colorMap->ColorCount; colorCount = colorMap->ColorCount;
...@@ -195,13 +232,22 @@ SplashDecodeGif(Splash * splash, GifFileType * gif) ...@@ -195,13 +232,22 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
for (; pass < npass; ++pass) { for (; pass < npass; ++pass) {
int jump = interlacedJumps[pass]; int jump = interlacedJumps[pass];
int ofs = interlacedOffset[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, initRect(&srcRect, 0, 0, desc->Width, numLines, 1,
desc->Width, pSrc, &srcFormat); desc->Width, pSrc, &srcFormat);
initRect(&dstRect, desc->Left, desc->Top + ofs, desc->Width,
numLines, jump, stride, pBitmapBits, &splash->imageFormat); if (numLines > 0) {
pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST); 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 @@ SplashDecodeGif(Splash * splash, GifFileType * gif) ...@@ -209,6 +255,12 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
splash->frames[imageIndex].bitmapBits = splash->frames[imageIndex].bitmapBits =
(rgbquad_t *) malloc(bufferSize); (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); memcpy(splash->frames[imageIndex].bitmapBits, pBitmapBits, bufferSize);
SplashInitFrameShape(splash, imageIndex); SplashInitFrameShape(splash, imageIndex);
...@@ -224,27 +276,29 @@ SplashDecodeGif(Splash * splash, GifFileType * gif) ...@@ -224,27 +276,29 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
{ {
ImageRect dstRect; ImageRect dstRect;
rgbquad_t fillColor = 0; // 0 is transparent rgbquad_t fillColor = 0; // 0 is transparent
if (transparentColor < 0) {
if (transparentColor > 0) {
fillColor= MAKE_QUAD_GIF( fillColor= MAKE_QUAD_GIF(
colorMap->Colors[gif->SBackGroundColor], 0xff); colorMap->Colors[gif->SBackGroundColor], 0xff);
} }
initRect(&dstRect, desc->Left, desc->Top, initRect(&dstRect,
desc->Width, desc->Height, 1, stride, cx, cy, cw, ch,
pBitmapBits, &splash->imageFormat); 1, stride,
pBitmapBits, &splash->imageFormat);
fillRect(fillColor, &dstRect); fillRect(fillColor, &dstRect);
} }
break; break;
case GIF_DISPOSE_RESTORE: case GIF_DISPOSE_RESTORE:
{ {
int lineSize = cw * splash->imageFormat.depthBytes;
int lineSize = desc->Width * splash->imageFormat.depthBytes; if (lineSize > 0) {
int lineOffset = cx * splash->imageFormat.depthBytes;
for (j = 0; j < desc->Height; j++) { int lineIndex = cy * stride + lineOffset;
int lineIndex = stride * (j + desc->Top) + for (j=0; j<ch; j++) {
desc->Left * splash->imageFormat.depthBytes; memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
lineSize);
memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex, lineIndex += stride;
lineSize); }
} }
} }
break; break;
......
...@@ -155,6 +155,10 @@ int BitmapToYXBandedRectangles(ImageRect * pSrcRect, RECT_T * out); ...@@ -155,6 +155,10 @@ int BitmapToYXBandedRectangles(ImageRect * pSrcRect, RECT_T * out);
void SplashInitFrameShape(Splash * splash, int imageIndex); 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 #define dbgprintf printf
#endif #endif
...@@ -103,9 +103,17 @@ SplashDecodePng(Splash * splash, png_rw_ptr read_func, void *io_ptr) ...@@ -103,9 +103,17 @@ SplashDecodePng(Splash * splash, png_rw_ptr read_func, void *io_ptr)
rowbytes = png_get_rowbytes(png_ptr, info_ptr); 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) { if ((image_data = (unsigned char *) malloc(rowbytes * height)) == NULL) {
goto done; goto done;
} }
if (!SAFE_TO_ALLOC(height, sizeof(png_bytep))) {
goto done;
}
if ((row_pointers = (png_bytepp) malloc(height * sizeof(png_bytep))) if ((row_pointers = (png_bytepp) malloc(height * sizeof(png_bytep)))
== NULL) { == NULL) {
goto done; goto done;
...@@ -121,13 +129,28 @@ SplashDecodePng(Splash * splash, png_rw_ptr read_func, void *io_ptr) ...@@ -121,13 +129,28 @@ SplashDecodePng(Splash * splash, png_rw_ptr read_func, void *io_ptr)
splash->width = width; splash->width = width;
splash->height = height; splash->height = height;
if (!SAFE_TO_ALLOC(splash->width, splash->imageFormat.depthBytes)) {
goto done;
}
stride = splash->width * splash->imageFormat.depthBytes; stride = splash->width * splash->imageFormat.depthBytes;
if (!SAFE_TO_ALLOC(splash->height, stride)) {
goto done;
}
splash->frameCount = 1; splash->frameCount = 1;
splash->frames = (SplashImage *) splash->frames = (SplashImage *)
malloc(sizeof(SplashImage) * splash->frameCount); malloc(sizeof(SplashImage) * splash->frameCount);
if (splash->frames == NULL) {
goto done;
}
splash->loopCount = 1; splash->loopCount = 1;
splash->frames[0].bitmapBits = malloc(stride * splash->height); splash->frames[0].bitmapBits = malloc(stride * splash->height);
if (splash->frames[0].bitmapBits == NULL) {
free(splash->frames);
goto done;
}
splash->frames[0].delay = 0; splash->frames[0].delay = 0;
/* FIXME: sort out the real format */ /* FIXME: sort out the real format */
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -31,6 +31,7 @@ import java.security.spec.AlgorithmParameterSpec; ...@@ -31,6 +31,7 @@ import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.RSAKeyGenParameterSpec;
import sun.security.jca.JCAUtil; import sun.security.jca.JCAUtil;
import sun.security.rsa.RSAKeyFactory;
/** /**
* RSA keypair generator. * RSA keypair generator.
...@@ -43,8 +44,8 @@ import sun.security.jca.JCAUtil; ...@@ -43,8 +44,8 @@ import sun.security.jca.JCAUtil;
public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi { public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// Supported by Microsoft Base, Strong and Enhanced Cryptographic Providers // Supported by Microsoft Base, Strong and Enhanced Cryptographic Providers
private static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384 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_MAX = 16384;
private static final int KEY_SIZE_DEFAULT = 1024; private static final int KEY_SIZE_DEFAULT = 1024;
// size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX // size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
...@@ -59,7 +60,14 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -59,7 +60,14 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// random is always ignored // random is always ignored
public void initialize(int keySize, SecureRandom random) { 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 // second initialize method. See JCA doc
...@@ -67,21 +75,31 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -67,21 +75,31 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
public void initialize(AlgorithmParameterSpec params, SecureRandom random) public void initialize(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException { throws InvalidAlgorithmParameterException {
int tmpSize;
if (params == null) { if (params == null) {
checkKeySize(KEY_SIZE_DEFAULT); tmpSize = KEY_SIZE_DEFAULT;
} else if (params instanceof RSAKeyGenParameterSpec) { } else if (params instanceof RSAKeyGenParameterSpec) {
if (((RSAKeyGenParameterSpec) params).getPublicExponent() != null) { if (((RSAKeyGenParameterSpec) params).getPublicExponent() != null) {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException
("Exponent parameter is not supported"); ("Exponent parameter is not supported");
} }
checkKeySize(((RSAKeyGenParameterSpec) params).getKeysize()); tmpSize = ((RSAKeyGenParameterSpec) params).getKeysize();
} else { } else {
throw new InvalidAlgorithmParameterException throw new InvalidAlgorithmParameterException
("Params must be an instance of RSAKeyGenParameterSpec"); ("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 // generate the keypair. See JCA doc
...@@ -95,18 +113,6 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi { ...@@ -95,18 +113,6 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
return new KeyPair(keys.getPublic(), keys.getPrivate()); 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, private static native RSAKeyPair generateRSAKeyPair(int keySize,
String keyContainerName); String keyContainerName);
} }
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -38,6 +38,9 @@ import java.security.SecureRandom; ...@@ -38,6 +38,9 @@ import java.security.SecureRandom;
import java.security.Signature; import java.security.Signature;
import java.security.SignatureSpi; import java.security.SignatureSpi;
import java.security.SignatureException; 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. * RSA signature implementation. Supports RSA signing using PKCS#1 v1.5 padding.
...@@ -124,7 +127,16 @@ abstract class RSASignature extends java.security.SignatureSpi ...@@ -124,7 +127,16 @@ abstract class RSASignature extends java.security.SignatureSpi
// convert key to MSCAPI format // 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 // Adjust key length due to sign bit
int keyBitLength = (modulusBytes[0] == 0) int keyBitLength = (modulusBytes[0] == 0)
...@@ -132,8 +144,7 @@ abstract class RSASignature extends java.security.SignatureSpi ...@@ -132,8 +144,7 @@ abstract class RSASignature extends java.security.SignatureSpi
: modulusBytes.length * 8; : modulusBytes.length * 8;
byte[] keyBlob = generatePublicKeyBlob( byte[] keyBlob = generatePublicKeyBlob(
keyBitLength, modulusBytes, keyBitLength, modulusBytes, exponentBytes);
rsaKey.getPublicExponent().toByteArray());
publicKey = importPublicKey(keyBlob, keyBitLength); publicKey = importPublicKey(keyBlob, keyBitLength);
...@@ -166,12 +177,11 @@ abstract class RSASignature extends java.security.SignatureSpi ...@@ -166,12 +177,11 @@ abstract class RSASignature extends java.security.SignatureSpi
} }
privateKey = (sun.security.mscapi.RSAPrivateKey) key; privateKey = (sun.security.mscapi.RSAPrivateKey) key;
// Determine byte length from bit length // Check against the local and global values to make sure
int keySize = (privateKey.bitLength() + 7) >> 3; // the sizes are ok. Round up to nearest byte.
RSAKeyFactory.checkKeyLengths(((privateKey.bitLength() + 7) & ~7),
if (keySize < 64) null, RSAKeyPairGenerator.KEY_SIZE_MIN,
throw new InvalidKeyException( RSAKeyPairGenerator.KEY_SIZE_MAX);
"RSA keys must be at least 512 bits long");
if (needsReset) { if (needsReset) {
messageDigest.reset(); messageDigest.reset();
......
/*
* 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");
}
}
}
/*
* 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();
}
}
}
}
# 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
<!--
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>
/*
* 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.");
}
}
}
/*
* 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
/*
* 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");
}
}
}
# @test MultipleJRE.sh # @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 PrintVersion
# @build UglyPrintVersion # @build UglyPrintVersion
# @build ZipMeUp
# @run shell MultipleJRE.sh # @run shell MultipleJRE.sh
# @summary Verify Multiple JRE version support # @summary Verify Multiple JRE version support
# @author Joseph E. Kowalski # @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. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -49,10 +49,25 @@ then ...@@ -49,10 +49,25 @@ then
exit 1 exit 1
fi fi
JAVAEXE="$TESTJAVA/bin/java"
JAVA="$TESTJAVA/bin/java -classpath $TESTCLASSES" JAVA="$TESTJAVA/bin/java -classpath $TESTCLASSES"
JAR="$TESTJAVA/bin/jar" JAR="$TESTJAVA/bin/jar"
OS=`uname -s`; 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 # Shell routine to test for the proper rejection of syntactically incorrect
# version specifications. # version specifications.
...@@ -139,7 +154,6 @@ CreateUglyJar() { ...@@ -139,7 +154,6 @@ CreateUglyJar() {
$PACKAGE/UglyPrintVersion.class $PACKAGE/UglyPrintVersion.class
} }
# #
# Constructs a jar file with a fair number of "zip directory" entries and # 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 # the MANIFEST.MF entry at or near the end of that directory to validate
...@@ -262,6 +276,29 @@ LaunchVM() { ...@@ -262,6 +276,29 @@ LaunchVM() {
fi 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 # Main test sequence starts here
# #
...@@ -280,14 +317,11 @@ CreateJar "" "" ...@@ -280,14 +317,11 @@ CreateJar "" ""
LaunchVM "" "${RELEASE}" LaunchVM "" "${RELEASE}"
CreateJar "" "0" CreateJar "" "0"
LaunchVM "" "${RELEASE}" LaunchVM "" "${RELEASE}"
case "$OS" in if [ `IsWindows` = "true" ]; then
Windows* | CYGWIN* ) MAXIMUM_PATH=255;
MAXIMUM_PATH=255; else
;; MAXIMUM_PATH=1024;
*) fi
MAXIMUM_PATH=1024;
;;
esac
PATH_LENGTH=`printf "%s" "$UGLYCLASS" | wc -c` PATH_LENGTH=`printf "%s" "$UGLYCLASS" | wc -c`
if [ ${PATH_LENGTH} -lt ${MAXIMUM_PATH} ]; then if [ ${PATH_LENGTH} -lt ${MAXIMUM_PATH} ]; then
...@@ -346,7 +380,6 @@ if [ -x /usr/bin/zipnote ]; then ...@@ -346,7 +380,6 @@ if [ -x /usr/bin/zipnote ]; then
LaunchVM "" "${RELEASE}" LaunchVM "" "${RELEASE}"
fi fi
# #
# Throw some syntactically challenged (illegal) version specifiers at # Throw some syntactically challenged (illegal) version specifiers at
# the interface. Failure (of the launcher) is success for the test. # the interface. Failure (of the launcher) is success for the test.
...@@ -357,15 +390,28 @@ TestSyntax "1.2.3-" # Ends with a separator ...@@ -357,15 +390,28 @@ TestSyntax "1.2.3-" # Ends with a separator
TestSyntax "1.2+.3" # Embedded modifier TestSyntax "1.2+.3" # Embedded modifier
TestSyntax "1.2.4+&1.2*&1++" # Long and invalid 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 # Because scribbling in the registry can be rather destructive, only a
# subset of the tests are run on Windows. # subset of the tests are run on Windows.
# #
case "$OS" in if [ `IsWindows` = "true" ]; then
Windows* | CYGWIN* ) exit 0;
exit 0; fi
;;
esac
# #
# Additional version specifiers containing spaces. (Sigh, unable to # Additional version specifiers containing spaces. (Sigh, unable to
......
/*
* 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);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册