This commit is contained in:
Tim Bell 2009-04-18 14:10:27 -07:00
commit f70e9b8dd9
126 changed files with 4939 additions and 8338 deletions

View file

@ -29,7 +29,6 @@ FILES_c = \
Deflater.c \ Deflater.c \
Inflater.c \ Inflater.c \
ZipFile.c \ ZipFile.c \
ZipEntry.c \
zadler32.c \ zadler32.c \
zcrc32.c \ zcrc32.c \
deflate.c \ deflate.c \

View file

@ -50,15 +50,17 @@ SUNWprivate_1.1 {
Java_java_util_zip_Inflater_initIDs; Java_java_util_zip_Inflater_initIDs;
Java_java_util_zip_Inflater_reset; Java_java_util_zip_Inflater_reset;
Java_java_util_zip_Inflater_setDictionary; Java_java_util_zip_Inflater_setDictionary;
Java_java_util_zip_ZipEntry_initFields;
Java_java_util_zip_ZipEntry_initIDs;
Java_java_util_zip_ZipFile_close; Java_java_util_zip_ZipFile_close;
Java_java_util_zip_ZipFile_freeEntry; Java_java_util_zip_ZipFile_freeEntry;
Java_java_util_zip_ZipFile_getCSize;
Java_java_util_zip_ZipFile_getEntry; Java_java_util_zip_ZipFile_getEntry;
Java_java_util_zip_ZipFile_getMethod; Java_java_util_zip_ZipFile_getEntryBytes;
Java_java_util_zip_ZipFile_getEntryCrc;
Java_java_util_zip_ZipFile_getEntryCSize;
Java_java_util_zip_ZipFile_getEntryFlag;
Java_java_util_zip_ZipFile_getEntryMethod;
Java_java_util_zip_ZipFile_getEntrySize;
Java_java_util_zip_ZipFile_getEntryTime;
Java_java_util_zip_ZipFile_getNextEntry; Java_java_util_zip_ZipFile_getNextEntry;
Java_java_util_zip_ZipFile_getSize;
Java_java_util_zip_ZipFile_getZipMessage; Java_java_util_zip_ZipFile_getZipMessage;
Java_java_util_zip_ZipFile_getTotal; Java_java_util_zip_ZipFile_getTotal;
Java_java_util_zip_ZipFile_initIDs; Java_java_util_zip_ZipFile_initIDs;

View file

@ -20,12 +20,14 @@ text: .text%Java_java_util_zip_ZipFile_initIDs;
text: .text%Java_java_util_zip_ZipFile_open; text: .text%Java_java_util_zip_ZipFile_open;
text: .text%Java_java_util_zip_ZipFile_getTotal; text: .text%Java_java_util_zip_ZipFile_getTotal;
text: .text%Java_java_util_zip_ZipFile_getEntry; text: .text%Java_java_util_zip_ZipFile_getEntry;
text: .text%Java_java_util_zip_ZipEntry_initIDs;
text: .text%Java_java_util_zip_ZipEntry_initFields;
text: .text%Java_java_util_zip_ZipFile_freeEntry; text: .text%Java_java_util_zip_ZipFile_freeEntry;
text: .text%Java_java_util_zip_ZipFile_getCSize; text: .text%Java_java_util_zip_ZipFile_getEntryTime;
text: .text%Java_java_util_zip_ZipFile_getSize; text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
text: .text%Java_java_util_zip_ZipFile_getMethod; text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
text: .text%Java_java_util_zip_ZipFile_getEntrySize;
text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
text: .text%Java_java_util_zip_Inflater_initIDs; text: .text%Java_java_util_zip_Inflater_initIDs;
text: .text%Java_java_util_zip_Inflater_init; text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_; text: .text%inflateInit2_;

View file

@ -19,12 +19,14 @@ text: .text%Java_java_util_zip_ZipFile_initIDs;
text: .text%Java_java_util_zip_ZipFile_open; text: .text%Java_java_util_zip_ZipFile_open;
text: .text%Java_java_util_zip_ZipFile_getTotal; text: .text%Java_java_util_zip_ZipFile_getTotal;
text: .text%Java_java_util_zip_ZipFile_getEntry; text: .text%Java_java_util_zip_ZipFile_getEntry;
text: .text%Java_java_util_zip_ZipEntry_initIDs;
text: .text%Java_java_util_zip_ZipEntry_initFields;
text: .text%Java_java_util_zip_ZipFile_freeEntry; text: .text%Java_java_util_zip_ZipFile_freeEntry;
text: .text%Java_java_util_zip_ZipFile_getCSize; text: .text%Java_java_util_zip_ZipFile_getEntryTime;
text: .text%Java_java_util_zip_ZipFile_getSize; text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
text: .text%Java_java_util_zip_ZipFile_getMethod; text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
text: .text%Java_java_util_zip_ZipFile_getEntrySize;
text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
text: .text%Java_java_util_zip_Inflater_initIDs; text: .text%Java_java_util_zip_Inflater_initIDs;
text: .text%Java_java_util_zip_Inflater_init; text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_; text: .text%inflateInit2_;

View file

@ -20,12 +20,14 @@ text: .text%Java_java_util_zip_ZipFile_initIDs;
text: .text%Java_java_util_zip_ZipFile_open; text: .text%Java_java_util_zip_ZipFile_open;
text: .text%Java_java_util_zip_ZipFile_getTotal; text: .text%Java_java_util_zip_ZipFile_getTotal;
text: .text%Java_java_util_zip_ZipFile_getEntry; text: .text%Java_java_util_zip_ZipFile_getEntry;
text: .text%Java_java_util_zip_ZipEntry_initIDs;
text: .text%Java_java_util_zip_ZipEntry_initFields;
text: .text%Java_java_util_zip_ZipFile_freeEntry; text: .text%Java_java_util_zip_ZipFile_freeEntry;
text: .text%Java_java_util_zip_ZipFile_getCSize; text: .text%Java_java_util_zip_ZipFile_getEntryTime;
text: .text%Java_java_util_zip_ZipFile_getSize; text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
text: .text%Java_java_util_zip_ZipFile_getMethod; text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
text: .text%Java_java_util_zip_ZipFile_getEntrySize;
text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
text: .text%Java_java_util_zip_Inflater_initIDs; text: .text%Java_java_util_zip_Inflater_initIDs;
text: .text%Java_java_util_zip_Inflater_init; text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_; text: .text%inflateInit2_;

View file

@ -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'"

View file

@ -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();

View file

@ -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;
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;
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 {
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 {
this.defaultClassLoader = defaultClassLoader; this.defaultClassLoader = defaultClassLoader;
this.executor = ex; this.executor = ex;
this.acc = AccessController.getContext();
} }
/** /**
@ -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 {
// 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 {
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

View file

@ -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
} }
/** /**
* 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
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
} }
/** /**
* 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
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
} }
/** /**
* 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
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
} }
/** /**
* 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
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
} }
/** /**
* 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
} }
/** /**
* 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);
} }

View file

@ -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;
* 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;
* 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
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
* #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
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
* #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
* 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
* @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
} }
} }
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
} }
}); });
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 void checkValues(Properties props) { private static boolean checkCreateAccess(Access access, String className) {
Collection<?> c = props.values(); for (String classNamePattern : access.createPatterns) {
for (Iterator<?> i = c.iterator(); i.hasNext(); ) { if (classNameMatch(classNamePattern, className))
final String accessLevel = (String) i.next(); return true;
if (!accessLevel.equals(READONLY) && }
!accessLevel.equals(READWRITE)) { return false;
throw new IllegalArgumentException( }
"Syntax error in access level entry [" + accessLevel + "]");
} private static boolean classNameMatch(String pattern, String className) {
// We studiously avoided regexes when parsing the properties file,
// because that is done whenever the VM is started with the
// appropriate -Dcom.sun.management options, even if nobody ever
// creates an MBean. We don't want to incur the overhead of loading
// all the regex code whenever those options are specified, but if we
// get as far as here then the VM is already running and somebody is
// doing the very unusual operation of remotely creating an MBean.
// Because that operation is so unusual, we don't try to optimize
// by hand-matching or by caching compiled Pattern objects.
StringBuilder sb = new StringBuilder();
StringTokenizer stok = new StringTokenizer(pattern, "*", true);
while (stok.hasMoreTokens()) {
String tok = stok.nextToken();
if (tok.equals("*"))
sb.append("[^.]*");
else
sb.append(Pattern.quote(tok));
}
return className.matches(sb.toString());
}
private void parseProperties(Properties props) {
this.accessMap = new HashMap<String, Access>();
for (Map.Entry<Object, Object> entry : props.entrySet()) {
String identity = (String) entry.getKey();
String accessString = (String) entry.getValue();
Access access = Parser.parseAccess(identity, accessString);
accessMap.put(identity, access);
} }
} }
private Properties props; private static class Parser {
private final static int EOS = -1; // pseudo-codepoint "end of string"
static {
assert !Character.isWhitespace(EOS);
}
private final String identity; // just for better error messages
private final String s; // the string we're parsing
private final int len; // s.length()
private int i;
private int c;
// At any point, either c is s.codePointAt(i), or i == len and
// c is EOS. We use int rather than char because it is conceivable
// (if unlikely) that a classname in a create clause might contain
// "supplementary characters", the ones that don't fit in the original
// 16 bits for Unicode.
private Parser(String identity, String s) {
this.identity = identity;
this.s = s;
this.len = s.length();
this.i = 0;
if (i < len)
this.c = s.codePointAt(i);
else
this.c = EOS;
}
static Access parseAccess(String identity, String s) {
return new Parser(identity, s).parseAccess();
}
private Access parseAccess() {
skipSpace();
String type = parseWord();
Access access;
if (type.equals(READONLY))
access = new Access(false, false, null);
else if (type.equals(READWRITE))
access = parseReadWrite();
else {
throw syntax("Expected " + READONLY + " or " + READWRITE +
": " + type);
}
if (c != EOS)
throw syntax("Extra text at end of line");
return access;
}
private Access parseReadWrite() {
List<String> createClasses = new ArrayList<String>();
boolean unregister = false;
while (true) {
skipSpace();
if (c == EOS)
break;
String type = parseWord();
if (type.equals(UNREGISTER))
unregister = true;
else if (type.equals(CREATE))
parseCreate(createClasses);
else
throw syntax("Unrecognized keyword " + type);
}
return new Access(true, unregister, createClasses);
}
private void parseCreate(List<String> createClasses) {
while (true) {
skipSpace();
createClasses.add(parseClassName());
skipSpace();
if (c == ',')
next();
else
break;
}
}
private String parseClassName() {
// We don't check that classname components begin with suitable
// characters (so we accept 1.2.3 for example). This means that
// there are only two states, which we can call dotOK and !dotOK
// according as a dot (.) is legal or not. Initially we're in
// !dotOK since a classname can't start with a dot; after a dot
// we're in !dotOK again; and after any other characters we're in
// dotOK. The classname is only accepted if we end in dotOK,
// so we reject an empty name or a name that ends with a dot.
final int start = i;
boolean dotOK = false;
while (true) {
if (c == '.') {
if (!dotOK)
throw syntax("Bad . in class name");
dotOK = false;
} else if (c == '*' || Character.isJavaIdentifierPart(c))
dotOK = true;
else
break;
next();
}
String className = s.substring(start, i);
if (!dotOK)
throw syntax("Bad class name " + className);
return className;
}
// Advance c and i to the next character, unless already at EOS.
private void next() {
if (c != EOS) {
i += Character.charCount(c);
if (i < len)
c = s.codePointAt(i);
else
c = EOS;
}
}
private void skipSpace() {
while (Character.isWhitespace(c))
next();
}
private String parseWord() {
skipSpace();
if (c == EOS)
throw syntax("Expected word at end of line");
final int start = i;
while (c != EOS && !Character.isWhitespace(c))
next();
String word = s.substring(start, i);
skipSpace();
return word;
}
private IllegalArgumentException syntax(String msg) {
return new IllegalArgumentException(
msg + " [" + identity + " " + s + "]");
}
}
private Map<String, Access> accessMap;
private Properties originalProps; private Properties originalProps;
private String accessFileName; private String accessFileName;
} }

View file

@ -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 {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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;
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;

View file

@ -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;
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
} }
/* 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
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
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() {
public Object run() {
File tFile = null;
FileOutputStream outStream = null;
try {
tFile = File.createTempFile("+~JF", ".tmp", null);
/* Temp file deleted by font shutdown hook */
BufferedInputStream inStream =
new BufferedInputStream(fStream);
outStream = new FileOutputStream(tFile);
int bytesRead = 0;
int bufSize = 8192;
byte [] buf = new byte[bufSize];
while (bytesRead != -1) {
try {
bytesRead = inStream.read(buf, 0, bufSize);
} catch (Throwable t) {
throw new IOException();
}
if (bytesRead != -1) {
outStream.write(buf, 0, bytesRead);
}
}
/* don't close the input stream */
outStream.close();
} catch (IOException e) {
if (outStream != null) {
try {
outStream.close();
} catch (Exception e1) {
}
}
if (tFile != null) {
try {
tFile.delete();
} catch (Exception e2) {
}
}
return e;
}
return tFile;
}
});
if (ret instanceof File) { try {
return new Font((File)ret, fontFormat, true); final File tFile = AccessController.doPrivileged(
} else if (ret instanceof IOException) { new PrivilegedExceptionAction<File>() {
throw (IOException)ret; public File run() throws IOException {
} else { return File.createTempFile("+~JF", ".tmp", null);
throw new FontFormatException("Couldn't access font stream"); }
}
);
int totalSize = 0;
CreatedFontTracker tracker = null;
try {
final OutputStream outStream =
AccessController.doPrivileged(
new PrivilegedExceptionAction<OutputStream>() {
public OutputStream run() throws IOException {
return new FileOutputStream(tFile);
}
}
);
if (!hasTempPermission()) {
tracker = CreatedFontTracker.getTracker();
}
try {
byte[] buf = new byte[8192];
for (;;) {
int bytesRead = fontStream.read(buf);
if (bytesRead < 0) {
break;
}
if (tracker != null) {
if (totalSize+bytesRead > tracker.MAX_FILE_SIZE) {
throw new IOException("File too big.");
}
if (totalSize+tracker.getNumBytes() >
tracker.MAX_TOTAL_BYTES)
{
throw new IOException("Total files too big.");
}
totalSize += bytesRead;
tracker.addBytes(bytesRead);
}
outStream.write(buf, 0, bytesRead);
}
/* don't close the input stream */
} finally {
outStream.close();
}
/* After all references to a Font2D are dropped, the file
* will be removed. To support long-lived AppContexts,
* we need to then decrement the byte count by the size
* of the file.
* If the data isn't a valid font, the implementation will
* delete the tmp file and decrement the byte count
* in the tracker object before returning from the
* constructor, so we can set 'copiedFontData' to true here
* without waiting for the results of that constructor.
*/
copiedFontData = true;
Font font = new Font(tFile, fontFormat, true, tracker);
return font;
} finally {
if (!copiedFontData) {
if (tracker != null) {
tracker.subBytes(totalSize);
}
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>() {
public Void run() {
tFile.delete();
return null;
}
}
);
}
}
} catch (Throwable t) {
if (t instanceof FontFormatException) {
throw (FontFormatException)t;
}
if (t instanceof IOException) {
throw (IOException)t;
}
Throwable cause = t.getCause();
if (cause instanceof FontFormatException) {
throw (FontFormatException)cause;
}
throw new IOException("Problem reading font data.");
} }
} }
@ -913,6 +979,9 @@ public 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
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);
} }
/** /**

View file

@ -41,14 +41,14 @@ class NoSuchFieldError extends IncompatibleClassChangeError {
private static final long serialVersionUID = -3456430195886129035L; private static final long serialVersionUID = -3456430195886129035L;
/** /**
* Constructs a <code>NoSuchFieldException</code> with no detail message. * Constructs a <code>NoSuchFieldError</code> with no detail message.
*/ */
public NoSuchFieldError() { public NoSuchFieldError() {
super(); super();
} }
/** /**
* Constructs a <code>NoSuchFieldException</code> with the specified * Constructs a <code>NoSuchFieldError</code> with the specified
* detail message. * detail message.
* *
* @param s the detail message. * @param s the detail message.

View file

@ -196,10 +196,12 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
if ((start < 0) || (end > len) || (start > end)) if ((start < 0) || (end > len) || (start > end))
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
int sublen = end - start; return new ByteBufferAsCharBuffer$RW$$BO$(bb,
int off = offset + ((pos + start) << $LG_BYTES_PER_VALUE$); -1,
assert (off >= 0); pos + start,
return new ByteBufferAsCharBuffer$RW$$BO$(bb, -1, 0, sublen, sublen, off); pos + end,
capacity(),
offset);
} }
#end[char] #end[char]

View file

@ -412,10 +412,12 @@ class Direct$Type$Buffer$RW$$BO$
if ((start < 0) || (end > len) || (start > end)) if ((start < 0) || (end > len) || (start > end))
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
int sublen = end - start; return new DirectCharBuffer$RW$$BO$(this,
int off = (pos + start) << $LG_BYTES_PER_VALUE$; -1,
assert (off >= 0); pos + start,
return new DirectCharBuffer$RW$$BO$(this, -1, 0, sublen, sublen, off); pos + end,
capacity(),
offset);
} }
#end[char] #end[char]

View file

@ -572,10 +572,13 @@ class Heap$Type$Buffer$RW$
|| (end > length()) || (end > length())
|| (start > end)) || (start > end))
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
int len = end - start; int pos = position();
return new HeapCharBuffer$RW$(hb, return new HeapCharBuffer$RW$(hb,
-1, 0, len, len, -1,
offset + position() + start); pos + start,
pos + end,
capacity(),
offset);
} }
#end[char] #end[char]

View file

@ -102,10 +102,12 @@ class StringCharBuffer // package-private
public final CharBuffer subSequence(int start, int end) { public final CharBuffer subSequence(int start, int end) {
try { try {
int pos = position(); int pos = position();
return new StringCharBuffer(str, -1, return new StringCharBuffer(str,
-1,
pos + checkIndex(start, pos), pos + checkIndex(start, pos),
pos + checkIndex(end, pos), pos + checkIndex(end, pos),
remaining(), offset); capacity(),
offset);
} catch (IllegalArgumentException x) { } catch (IllegalArgumentException x) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
} }

View file

@ -443,7 +443,7 @@ public abstract class AsynchronousDatagramChannel
* at least care must be taken to ensure that the buffer is not accessed * at least care must be taken to ensure that the buffer is not accessed
* while the channel remains open. * while the channel remains open.
* *
* <p> If there is a security manager installed and the the channel is not * <p> If there is a security manager installed and the channel is not
* connected then this method verifies that the target address and port number * connected then this method verifies that the target address and port number
* are permitted by the security manager's {@link SecurityManager#checkConnect * are permitted by the security manager's {@link SecurityManager#checkConnect
* checkConnect} method. The overhead of this security check can be avoided * checkConnect} method. The overhead of this security check can be avoided

View file

@ -494,7 +494,7 @@ public abstract class Path
* @throws IOException * @throws IOException
* if an I/O error occurs * if an I/O error occurs
* @throws SecurityException * @throws SecurityException
* In the case of the the default provider, and a security manager * In the case of the default provider, and a security manager
* is installed, it denies {@link LinkPermission}<tt>("symbolic")</tt> * is installed, it denies {@link LinkPermission}<tt>("symbolic")</tt>
* or its {@link SecurityManager#checkWrite(String) checkWrite} * or its {@link SecurityManager#checkWrite(String) checkWrite}
* method denies write access to the path of the symbolic link. * method denies write access to the path of the symbolic link.
@ -531,7 +531,7 @@ public abstract class Path
* @throws IOException * @throws IOException
* if an I/O error occurs * if an I/O error occurs
* @throws SecurityException * @throws SecurityException
* In the case of the the default provider, and a security manager * In the case of the default provider, and a security manager
* is installed, it denies {@link LinkPermission}<tt>("hard")</tt> * is installed, it denies {@link LinkPermission}<tt>("hard")</tt>
* or its {@link SecurityManager#checkWrite(String) checkWrite} * or its {@link SecurityManager#checkWrite(String) checkWrite}
* method denies write access to both this path and the path of the * method denies write access to both this path and the path of the
@ -560,7 +560,7 @@ public abstract class Path
* @throws IOException * @throws IOException
* if an I/O error occurs * if an I/O error occurs
* @throws SecurityException * @throws SecurityException
* In the case of the the default provider, and a security manager * In the case of the default provider, and a security manager
* is installed, it checks that {@code FilePermission} has been * is installed, it checks that {@code FilePermission} has been
* granted with the "{@code readlink}" action to read the link. * granted with the "{@code readlink}" action to read the link.
*/ */
@ -615,7 +615,7 @@ public abstract class Path
* obtained * obtained
* *
* @throws SecurityException * @throws SecurityException
* In the case of the the default provider, and a security manager * In the case of the default provider, and a security manager
* is installed, the {@link #toAbsolutePath toAbsolutePath} method * is installed, the {@link #toAbsolutePath toAbsolutePath} method
* throws a security exception. * throws a security exception.
*/ */
@ -636,7 +636,7 @@ public abstract class Path
* @throws IOError * @throws IOError
* if an I/O error occurs * if an I/O error occurs
* @throws SecurityException * @throws SecurityException
* In the case of the the default provider, and a security manager * In the case of the default provider, and a security manager
* is installed, its {@link SecurityManager#checkPropertyAccess(String) * is installed, its {@link SecurityManager#checkPropertyAccess(String)
* checkPropertyAccess} method is invoked to check access to the * checkPropertyAccess} method is invoked to check access to the
* system property {@code user.dir} * system property {@code user.dir}
@ -677,7 +677,7 @@ public abstract class Path
* @throws IOException * @throws IOException
* if the file does not exist or an I/O error occurs * if the file does not exist or an I/O error occurs
* @throws SecurityException * @throws SecurityException
* In the case of the the default provider, and a security manager * In the case of the default provider, and a security manager
* is installed, its {@link SecurityManager#checkRead(String) checkRead} * is installed, its {@link SecurityManager#checkRead(String) checkRead}
* method is invoked to check read access to the file, and where * method is invoked to check read access to the file, and where
* this path is not absolute, its {@link SecurityManager#checkPropertyAccess(String) * this path is not absolute, its {@link SecurityManager#checkPropertyAccess(String)

View file

@ -208,7 +208,7 @@ public abstract class SecureDirectoryStream
* @throws ClosedDirectoryStreamException * @throws ClosedDirectoryStreamException
* if the directory stream is closed * if the directory stream is closed
* @throws NoSuchFileException * @throws NoSuchFileException
* if the the directory does not exist <i>(optional specific exception)</i> * if the directory does not exist <i>(optional specific exception)</i>
* @throws DirectoryNotEmptyException * @throws DirectoryNotEmptyException
* if the directory could not otherwise be deleted because it is * if the directory could not otherwise be deleted because it is
* not empty <i>(optional specific exception)</i> * not empty <i>(optional specific exception)</i>

View file

@ -425,7 +425,7 @@ public final class AccessController {
* Performs the specified <code>PrivilegedExceptionAction</code> with * Performs the specified <code>PrivilegedExceptionAction</code> with
* privileges enabled and restricted by the specified * privileges enabled and restricted by the specified
* <code>AccessControlContext</code>. The action is performed with the * <code>AccessControlContext</code>. The action is performed with the
* intersection of the the permissions possessed by the caller's * intersection of the permissions possessed by the caller's
* protection domain, and those possessed by the domains represented by the * protection domain, and those possessed by the domains represented by the
* specified <code>AccessControlContext</code>. * specified <code>AccessControlContext</code>.
* <p> * <p>

View file

@ -102,7 +102,7 @@ public abstract class AlgorithmParametersSpi {
* parameters should be returned in an instance of the * parameters should be returned in an instance of the
* <code>DSAParameterSpec</code> class. * <code>DSAParameterSpec</code> class.
* *
* @param paramSpec the the specification class in which * @param paramSpec the specification class in which
* the parameters should be returned. * the parameters should be returned.
* *
* @return the parameter specification. * @return the parameter specification.

View file

@ -87,7 +87,7 @@ public class PrivilegedActionException extends Exception {
} }
/** /**
* Returns the the cause of this exception (the exception thrown by * Returns the cause of this exception (the exception thrown by
* the privileged computation that resulted in this * the privileged computation that resulted in this
* <code>PrivilegedActionException</code>). * <code>PrivilegedActionException</code>).
* *

View file

@ -501,7 +501,7 @@ public final class Security {
* <li> <i>&lt;crypto_service>.&lt;algorithm_or_type> * <li> <i>&lt;crypto_service>.&lt;algorithm_or_type>
* &lt;attribute_name>:&lt attribute_value></i> * &lt;attribute_name>:&lt attribute_value></i>
* <p> The cryptographic service name must not contain any dots. There * <p> The cryptographic service name must not contain any dots. There
* must be one or more space charaters between the the * must be one or more space charaters between the
* <i>&lt;algorithm_or_type></i> and the <i>&lt;attribute_name></i>. * <i>&lt;algorithm_or_type></i> and the <i>&lt;attribute_name></i>.
* <p> A provider satisfies this selection criterion iff the * <p> A provider satisfies this selection criterion iff the
* provider implements the specified algorithm or type for the specified * provider implements the specified algorithm or type for the specified

View file

@ -118,7 +118,7 @@ import java.util.StringTokenizer;
* <td>setProperty.{key}</td> * <td>setProperty.{key}</td>
* <td>Setting of the security property with the specified key</td> * <td>Setting of the security property with the specified key</td>
* <td>This could include setting a security provider or defining * <td>This could include setting a security provider or defining
* the location of the the system-wide security policy. Malicious * the location of the system-wide security policy. Malicious
* code that has permission to set a new security provider may * code that has permission to set a new security provider may
* set a rogue provider that steals confidential information such * set a rogue provider that steals confidential information such
* as cryptographic private keys. In addition, malicious code with * as cryptographic private keys. In addition, malicious code with

View file

@ -316,7 +316,7 @@ public abstract class SignatureSpi {
* overridden by a provider * overridden by a provider
* *
* @exception InvalidAlgorithmParameterException if this method is * @exception InvalidAlgorithmParameterException if this method is
* overridden by a provider and the the given parameters * overridden by a provider and the given parameters
* are inappropriate for this signature engine * are inappropriate for this signature engine
*/ */
protected void engineSetParameter(AlgorithmParameterSpec params) protected void engineSetParameter(AlgorithmParameterSpec params)

View file

@ -460,7 +460,7 @@ public class CertificateFactory {
* {@link java.io.InputStream#reset() reset}, this method will * {@link java.io.InputStream#reset() reset}, this method will
* consume the entire input stream. Otherwise, each call to this * consume the entire input stream. Otherwise, each call to this
* method consumes one CRL and the read position of the input stream * method consumes one CRL and the read position of the input stream
* is positioned to the next available byte after the the inherent * is positioned to the next available byte after the inherent
* end-of-CRL marker. If the data in the * end-of-CRL marker. If the data in the
* input stream does not contain an inherent end-of-CRL marker (other * input stream does not contain an inherent end-of-CRL marker (other
* than EOF) and there is trailing data after the CRL is parsed, a * than EOF) and there is trailing data after the CRL is parsed, a

View file

@ -88,7 +88,7 @@ public abstract class CertificateFactorySpi {
* {@link java.io.InputStream#reset() reset}, this method will * {@link java.io.InputStream#reset() reset}, this method will
* consume the entire input stream. Otherwise, each call to this * consume the entire input stream. Otherwise, each call to this
* method consumes one certificate and the read position of the input stream * method consumes one certificate and the read position of the input stream
* is positioned to the next available byte after the the inherent * is positioned to the next available byte after the inherent
* end-of-certificate marker. If the data in the * end-of-certificate marker. If the data in the
* input stream does not contain an inherent end-of-certificate marker (other * input stream does not contain an inherent end-of-certificate marker (other
* than EOF) and there is trailing data after the certificate is parsed, a * than EOF) and there is trailing data after the certificate is parsed, a
@ -261,7 +261,7 @@ public abstract class CertificateFactorySpi {
* {@link java.io.InputStream#reset() reset}, this method will * {@link java.io.InputStream#reset() reset}, this method will
* consume the entire input stream. Otherwise, each call to this * consume the entire input stream. Otherwise, each call to this
* method consumes one CRL and the read position of the input stream * method consumes one CRL and the read position of the input stream
* is positioned to the next available byte after the the inherent * is positioned to the next available byte after the inherent
* end-of-CRL marker. If the data in the * end-of-CRL marker. If the data in the
* input stream does not contain an inherent end-of-CRL marker (other * input stream does not contain an inherent end-of-CRL marker (other
* than EOF) and there is trailing data after the CRL is parsed, a * than EOF) and there is trailing data after the CRL is parsed, a

View file

@ -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
} }
} }
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
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
// 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;
} }
} }
} }

View file

@ -0,0 +1,139 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 java.util.zip;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.util.Arrays;
/**
* Utility class for zipfile name and comment decoding and encoding
*/
final class ZipCoder {
String toString(byte[] ba, int length) {
CharsetDecoder cd = decoder().reset();
int len = (int)(length * cd.maxCharsPerByte());
char[] ca = new char[len];
if (len == 0)
return new String(ca);
ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
CharBuffer cb = CharBuffer.wrap(ca);
CoderResult cr = cd.decode(bb, cb, true);
if (!cr.isUnderflow())
throw new IllegalArgumentException(cr.toString());
cr = cd.flush(cb);
if (!cr.isUnderflow())
throw new IllegalArgumentException(cr.toString());
return new String(ca, 0, cb.position());
}
String toString(byte[] ba) {
return toString(ba, ba.length);
}
byte[] getBytes(String s) {
CharsetEncoder ce = encoder().reset();
char[] ca = s.toCharArray();
int len = (int)(ca.length * ce.maxBytesPerChar());
byte[] ba = new byte[len];
if (len == 0)
return ba;
ByteBuffer bb = ByteBuffer.wrap(ba);
CharBuffer cb = CharBuffer.wrap(ca);
CoderResult cr = ce.encode(cb, bb, true);
if (!cr.isUnderflow())
throw new IllegalArgumentException(cr.toString());
cr = ce.flush(bb);
if (!cr.isUnderflow())
throw new IllegalArgumentException(cr.toString());
if (bb.position() == ba.length) // defensive copy?
return ba;
else
return Arrays.copyOf(ba, bb.position());
}
// assume invoked only if "this" is not utf8
byte[] getBytesUTF8(String s) {
if (isutf8)
return getBytes(s);
if (utf8 == null)
utf8 = new ZipCoder(Charset.forName("UTF-8"));
return utf8.getBytes(s);
}
String toStringUTF8(byte[] ba, int len) {
if (isutf8)
return toString(ba, len);
if (utf8 == null)
utf8 = new ZipCoder(Charset.forName("UTF-8"));
return utf8.toString(ba, len);
}
boolean isUTF8() {
return isutf8;
}
private Charset cs;
private CharsetDecoder dec;
private CharsetEncoder enc;
private boolean isutf8;
private ZipCoder utf8;
private ZipCoder(Charset cs) {
this.cs = cs;
this.isutf8 = cs.name().equals("UTF-8");
}
static ZipCoder get(Charset charset) {
return new ZipCoder(charset);
}
private CharsetDecoder decoder() {
if (dec == null) {
dec = cs.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT);
}
return dec;
}
private CharsetEncoder encoder() {
if (enc == null) {
enc = cs.newEncoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT);
}
return enc;
}
}

View file

@ -73,5 +73,12 @@ class ZipConstants64 {
static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte
/*
* Language encoding flag EFS
*/
static final int EFS = 0x800; // If this bit is set the filename and
// comment fields for this file must be
// encoded using UTF-8.
private ZipConstants64() {} private ZipConstants64() {}
} }

View file

@ -40,6 +40,7 @@ class ZipEntry implements ZipConstants, Cloneable {
long size = -1; // uncompressed size of entry data long size = -1; // uncompressed size of entry data
long csize = -1; // compressed size of entry data long csize = -1; // compressed size of entry data
int method = -1; // compression method int method = -1; // compression method
int flag = 0; // general purpose flag
byte[] extra; // optional extra field data for entry byte[] extra; // optional extra field data for entry
String comment; // optional comment string for entry String comment; // optional comment string for entry
@ -53,13 +54,6 @@ class ZipEntry implements ZipConstants, Cloneable {
*/ */
public static final int DEFLATED = 8; public static final int DEFLATED = 8;
static {
/* Zip library is loaded from System.initializeSystemClass */
initIDs();
}
private static native void initIDs();
/** /**
* Creates a new zip entry with the specified name. * Creates a new zip entry with the specified name.
* *
@ -90,28 +84,15 @@ class ZipEntry implements ZipConstants, Cloneable {
size = e.size; size = e.size;
csize = e.csize; csize = e.csize;
method = e.method; method = e.method;
flag = e.flag;
extra = e.extra; extra = e.extra;
comment = e.comment; comment = e.comment;
} }
/* /*
* Creates a new zip entry for the given name with fields initialized * Creates a new un-initialized zip entry
* from the specified jzentry data.
*/ */
ZipEntry(String name, long jzentry) { ZipEntry() {}
this.name = name;
initFields(jzentry);
}
private native void initFields(long jzentry);
/*
* Creates a new zip entry with fields initialized from the specified
* jzentry data.
*/
ZipEntry(long jzentry) {
initFields(jzentry);
}
/** /**
* Returns the name of the entry. * Returns the name of the entry.
@ -258,16 +239,16 @@ class ZipEntry implements ZipConstants, Cloneable {
/** /**
* Sets the optional comment string for the entry. * Sets the optional comment string for the entry.
*
* <p>ZIP entry comments have maximum length of 0xffff. If the length of the
* specified comment string is greater than 0xFFFF bytes after encoding, only
* the first 0xFFFF bytes are output to the ZIP file entry.
*
* @param comment the comment string * @param comment the comment string
* @exception IllegalArgumentException if the length of the specified *
* comment string is greater than 0xFFFF bytes
* @see #getComment() * @see #getComment()
*/ */
public void setComment(String comment) { public void setComment(String comment) {
if (comment != null && comment.length() > 0xffff/3
&& ZipOutputStream.getUTF8Length(comment) > 0xffff) {
throw new IllegalArgumentException("invalid entry comment length");
}
this.comment = comment; this.comment = comment;
} }

View file

@ -29,9 +29,11 @@ import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.EOFException; import java.io.EOFException;
import java.io.File; import java.io.File;
import java.nio.charset.Charset;
import java.util.Vector; import java.util.Vector;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import static java.util.zip.ZipConstants64.*;
/** /**
* This class is used to read entries from a zip file. * This class is used to read entries from a zip file.
@ -76,16 +78,19 @@ class ZipFile implements ZipConstants {
/** /**
* Opens a zip file for reading. * Opens a zip file for reading.
* *
* <p>First, if there is a security * <p>First, if there is a security manager, its <code>checkRead</code>
* manager, its <code>checkRead</code> method * method is called with the <code>name</code> argument as its argument
* is called with the <code>name</code> argument * to ensure the read is allowed.
* as its argument to ensure the read is allowed. *
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
* decode the entry names and comments.
* *
* @param name the name of the zip file * @param name the name of the zip file
* @throws ZipException if a ZIP format error has occurred * @throws ZipException if a ZIP format error has occurred
* @throws IOException if an I/O error has occurred * @throws IOException if an I/O error has occurred
* @throws SecurityException if a security manager exists and its * @throws SecurityException if a security manager exists and its
* <code>checkRead</code> method doesn't allow read access to the file. * <code>checkRead</code> method doesn't allow read access to the file.
*
* @see SecurityManager#checkRead(java.lang.String) * @see SecurityManager#checkRead(java.lang.String)
*/ */
public ZipFile(String name) throws IOException { public ZipFile(String name) throws IOException {
@ -101,6 +106,9 @@ class ZipFile implements ZipConstants {
* method is called with the <code>name</code> argument as its argument to * method is called with the <code>name</code> argument as its argument to
* ensure the read is allowed. * ensure the read is allowed.
* *
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
* decode the entry names and comments
*
* @param file the ZIP file to be opened for reading * @param file the ZIP file to be opened for reading
* @param mode the mode in which the file is to be opened * @param mode the mode in which the file is to be opened
* @throws ZipException if a ZIP format error has occurred * @throws ZipException if a ZIP format error has occurred
@ -115,6 +123,59 @@ class ZipFile implements ZipConstants {
* @since 1.3 * @since 1.3
*/ */
public ZipFile(File file, int mode) throws IOException { public ZipFile(File file, int mode) throws IOException {
this(file, mode, Charset.forName("UTF-8"));
}
/**
* Opens a ZIP file for reading given the specified File object.
*
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
* decode the entry names and comments.
*
* @param file the ZIP file to be opened for reading
* @throws ZipException if a ZIP format error has occurred
* @throws IOException if an I/O error has occurred
*/
public ZipFile(File file) throws ZipException, IOException {
this(file, OPEN_READ);
}
private ZipCoder zc;
/**
* Opens a new <code>ZipFile</code> to read from the specified
* <code>File</code> object in the specified mode. The mode argument
* must be either <tt>OPEN_READ</tt> or <tt>OPEN_READ | OPEN_DELETE</tt>.
*
* <p>First, if there is a security manager, its <code>checkRead</code>
* method is called with the <code>name</code> argument as its argument to
* ensure the read is allowed.
*
* @param file the ZIP file to be opened for reading
* @param mode the mode in which the file is to be opened
* @param charset
* the {@link java.nio.charset.Charset {@code charset}} to
* be used to decode the ZIP entry name and comment that are not
* encoded by using UTF-8 encoding (indicated by entry's general
* purpose flag).
*
* @throws ZipException if a ZIP format error has occurred
* @throws IOException if an I/O error has occurred
*
* @throws SecurityException
* if a security manager exists and its <code>checkRead</code>
* method doesn't allow read access to the file,or its
* <code>checkDelete</code> method doesn't allow deleting the
* file when the <tt>OPEN_DELETE</tt> flag is set
*
* @throws IllegalArgumentException if the <tt>mode</tt> argument is invalid
*
* @see SecurityManager#checkRead(java.lang.String)
*
* @since 1.7
*/
public ZipFile(File file, int mode, Charset charset) throws IOException
{
if (((mode & OPEN_READ) == 0) || if (((mode & OPEN_READ) == 0) ||
((mode & ~(OPEN_READ | OPEN_DELETE)) != 0)) { ((mode & ~(OPEN_READ | OPEN_DELETE)) != 0)) {
throw new IllegalArgumentException("Illegal mode: 0x"+ throw new IllegalArgumentException("Illegal mode: 0x"+
@ -128,24 +189,61 @@ class ZipFile implements ZipConstants {
sm.checkDelete(name); sm.checkDelete(name);
} }
} }
if (charset == null)
throw new NullPointerException("charset is null");
this.zc = ZipCoder.get(charset);
jzfile = open(name, mode, file.lastModified()); jzfile = open(name, mode, file.lastModified());
this.name = name; this.name = name;
this.total = getTotal(jzfile); this.total = getTotal(jzfile);
} }
private static native long open(String name, int mode, long lastModified); /**
private static native int getTotal(long jzfile); * Opens a zip file for reading.
*
* <p>First, if there is a security manager, its <code>checkRead</code>
* method is called with the <code>name</code> argument as its argument
* to ensure the read is allowed.
*
* @param name the name of the zip file
* @param charset
* the {@link java.nio.charset.Charset {@code charset}} to
* be used to decode the ZIP entry name and comment that are not
* encoded by using UTF-8 encoding (indicated by entry's general
* purpose flag).
*
* @throws ZipException if a ZIP format error has occurred
* @throws IOException if an I/O error has occurred
* @throws SecurityException
* if a security manager exists and its <code>checkRead</code>
* method doesn't allow read access to the file
*
* @see SecurityManager#checkRead(java.lang.String)
*
* @since 1.7
*/
public ZipFile(String name, Charset charset) throws IOException
{
this(new File(name), OPEN_READ, charset);
}
/** /**
* Opens a ZIP file for reading given the specified File object. * Opens a ZIP file for reading given the specified File object.
* @param file the ZIP file to be opened for reading * @param file the ZIP file to be opened for reading
* @throws ZipException if a ZIP error has occurred * @param charset
* The {@link java.nio.charset.Charset {@code charset}} to be
* used to decode the ZIP entry name and comment (ignored if
* the <a href="package-summary.html#lang_encoding"> language
* encoding bit</a> of the ZIP entry's general purpose bit
* flag is set).
*
* @throws ZipException if a ZIP format error has occurred
* @throws IOException if an I/O error has occurred * @throws IOException if an I/O error has occurred
*
* @since 1.7
*/ */
public ZipFile(File file) throws ZipException, IOException { public ZipFile(File file, Charset charset) throws IOException
this(file, OPEN_READ); {
this(file, OPEN_READ, charset);
} }
/** /**
@ -163,9 +261,9 @@ class ZipFile implements ZipConstants {
long jzentry = 0; long jzentry = 0;
synchronized (this) { synchronized (this) {
ensureOpen(); ensureOpen();
jzentry = getEntry(jzfile, name, true); jzentry = getEntry(jzfile, zc.getBytes(name), true);
if (jzentry != 0) { if (jzentry != 0) {
ZipEntry ze = new ZipEntry(name, jzentry); ZipEntry ze = getZipEntry(name, jzentry);
freeEntry(jzfile, jzentry); freeEntry(jzfile, jzentry);
return ze; return ze;
} }
@ -173,7 +271,7 @@ class ZipFile implements ZipConstants {
return null; return null;
} }
private static native long getEntry(long jzfile, String name, private static native long getEntry(long jzfile, byte[] name,
boolean addSlash); boolean addSlash);
// freeEntry releases the C jzentry struct. // freeEntry releases the C jzentry struct.
@ -194,36 +292,30 @@ class ZipFile implements ZipConstants {
* @throws IllegalStateException if the zip file has been closed * @throws IllegalStateException if the zip file has been closed
*/ */
public InputStream getInputStream(ZipEntry entry) throws IOException { public InputStream getInputStream(ZipEntry entry) throws IOException {
return getInputStream(entry.name); if (entry == null) {
} throw new NullPointerException("entry");
/**
* Returns an input stream for reading the contents of the specified
* entry, or null if the entry was not found.
*/
private InputStream getInputStream(String name) throws IOException {
if (name == null) {
throw new NullPointerException("name");
} }
long jzentry = 0; long jzentry = 0;
ZipFileInputStream in = null; ZipFileInputStream in = null;
synchronized (this) { synchronized (this) {
ensureOpen(); ensureOpen();
jzentry = getEntry(jzfile, name, false); if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
jzentry = getEntry(jzfile, zc.getBytesUTF8(entry.name), false);
} else {
jzentry = getEntry(jzfile, zc.getBytes(entry.name), false);
}
if (jzentry == 0) { if (jzentry == 0) {
return null; return null;
} }
in = new ZipFileInputStream(jzentry); in = new ZipFileInputStream(jzentry);
} }
final ZipFileInputStream zfin = in; final ZipFileInputStream zfin = in;
switch (getMethod(jzentry)) { switch (getEntryMethod(jzentry)) {
case STORED: case STORED:
return zfin; return zfin;
case DEFLATED: case DEFLATED:
// MORE: Compute good size for inflater stream: // MORE: Compute good size for inflater stream:
long size = getSize(jzentry) + 2; // Inflater likes a bit of slack long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack
if (size > 65536) size = 8192; if (size > 65536) size = 8192;
if (size <= 0) size = 4096; if (size <= 0) size = 4096;
return new InflaterInputStream(zfin, getInflater(), (int)size) { return new InflaterInputStream(zfin, getInflater(), (int)size) {
@ -267,8 +359,6 @@ class ZipFile implements ZipConstants {
} }
} }
private static native int getMethod(long jzentry);
/* /*
* Gets an inflater from the list of available inflaters or allocates * Gets an inflater from the list of available inflaters or allocates
* a new one. * a new one.
@ -343,7 +433,7 @@ class ZipFile implements ZipConstants {
",\n message = " + message ",\n message = " + message
); );
} }
ZipEntry ze = new ZipEntry(jzentry); ZipEntry ze = getZipEntry(null, jzentry);
freeEntry(jzfile, jzentry); freeEntry(jzfile, jzentry);
return ze; return ze;
} }
@ -351,6 +441,38 @@ class ZipFile implements ZipConstants {
}; };
} }
private ZipEntry getZipEntry(String name, long jzentry) {
ZipEntry e = new ZipEntry();
e.flag = getEntryFlag(jzentry); // get the flag first
if (name != null) {
e.name = name;
} else {
byte[] bname = getEntryBytes(jzentry, JZENTRY_NAME);
if (!zc.isUTF8() && (e.flag & EFS) != 0) {
e.name = zc.toStringUTF8(bname, bname.length);
} else {
e.name = zc.toString(bname, bname.length);
}
}
e.time = getEntryTime(jzentry);
e.crc = getEntryCrc(jzentry);
e.size = getEntrySize(jzentry);
e. csize = getEntryCSize(jzentry);
e.method = getEntryMethod(jzentry);
e.extra = getEntryBytes(jzentry, JZENTRY_EXTRA);
byte[] bcomm = getEntryBytes(jzentry, JZENTRY_COMMENT);
if (bcomm == null) {
e.comment = null;
} else {
if (!zc.isUTF8() && (e.flag & EFS) != 0) {
e.comment = zc.toStringUTF8(bcomm, bcomm.length);
} else {
e.comment = zc.toString(bcomm, bcomm.length);
}
}
return e;
}
private static native long getNextEntry(long jzfile, int i); private static native long getNextEntry(long jzfile, int i);
/** /**
@ -443,8 +565,8 @@ class ZipFile implements ZipConstants {
ZipFileInputStream(long jzentry) { ZipFileInputStream(long jzentry) {
pos = 0; pos = 0;
rem = getCSize(jzentry); rem = getEntryCSize(jzentry);
size = getSize(jzentry); size = getEntrySize(jzentry);
this.jzentry = jzentry; this.jzentry = jzentry;
} }
@ -514,13 +636,25 @@ class ZipFile implements ZipConstants {
} }
private static native long open(String name, int mode, long lastModified)
throws IOException;
private static native int getTotal(long jzfile);
private static native int read(long jzfile, long jzentry, private static native int read(long jzfile, long jzentry,
long pos, byte[] b, int off, int len); long pos, byte[] b, int off, int len);
private static native long getCSize(long jzentry); // access to the native zentry object
private static native long getEntryTime(long jzentry);
private static native long getEntryCrc(long jzentry);
private static native long getEntryCSize(long jzentry);
private static native long getEntrySize(long jzentry);
private static native int getEntryMethod(long jzentry);
private static native int getEntryFlag(long jzentry);
private static native long getSize(long jzentry); private static final int JZENTRY_NAME = 0;
private static final int JZENTRY_EXTRA = 1;
private static final int JZENTRY_COMMENT = 2;
private static native byte[] getEntryBytes(long jzentry, int type);
// Temporary add on for bug troubleshooting
private static native String getZipMessage(long jzfile); private static native String getZipMessage(long jzfile);
} }

View file

@ -29,6 +29,7 @@ import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.EOFException; import java.io.EOFException;
import java.io.PushbackInputStream; import java.io.PushbackInputStream;
import java.nio.charset.Charset;
import static java.util.zip.ZipConstants64.*; import static java.util.zip.ZipConstants64.*;
/** /**
@ -54,6 +55,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
// one entry // one entry
private boolean entryEOF = false; private boolean entryEOF = false;
private ZipCoder zc;
/** /**
* Check to make sure that this stream has not been closed * Check to make sure that this stream has not been closed
*/ */
@ -65,14 +68,39 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
/** /**
* Creates a new ZIP input stream. * Creates a new ZIP input stream.
*
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
* decode the entry names.
*
* @param in the actual input stream * @param in the actual input stream
*/ */
public ZipInputStream(InputStream in) { public ZipInputStream(InputStream in) {
this(in, Charset.forName("UTF-8"));
}
/**
* Creates a new ZIP input stream.
*
* @param in the actual input stream
*
* @param charset
* The {@link java.nio.charset.Charset {@code charset}} to be
* used to decode the ZIP entry name (ignored if the
* <a href="package-summary.html#lang_encoding"> language
* encoding bit</a> of the ZIP entry's general purpose bit
* flag is set).
*
* @since 1.7
*/
public ZipInputStream(InputStream in, Charset charset) {
super(new PushbackInputStream(in, 512), new Inflater(true), 512); super(new PushbackInputStream(in, 512), new Inflater(true), 512);
usesDefaultInflater = true; usesDefaultInflater = true;
if(in == null) { if(in == null) {
throw new NullPointerException("in is null"); throw new NullPointerException("in is null");
} }
if (charset == null)
throw new NullPointerException("charset is null");
this.zc = ZipCoder.get(charset);
} }
/** /**
@ -141,8 +169,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
* @param len the maximum number of bytes read * @param len the maximum number of bytes read
* @return the actual number of bytes read, or -1 if the end of the * @return the actual number of bytes read, or -1 if the end of the
* entry is reached * entry is reached
* @exception NullPointerException If <code>b</code> is <code>null</code>. * @exception NullPointerException if <code>b</code> is <code>null</code>.
* @exception IndexOutOfBoundsException If <code>off</code> is negative, * @exception IndexOutOfBoundsException if <code>off</code> is negative,
* <code>len</code> is negative, or <code>len</code> is greater than * <code>len</code> is negative, or <code>len</code> is greater than
* <code>b.length - off</code> * <code>b.length - off</code>
* @exception ZipException if a ZIP file error has occurred * @exception ZipException if a ZIP file error has occurred
@ -252,6 +280,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
if (get32(tmpbuf, 0) != LOCSIG) { if (get32(tmpbuf, 0) != LOCSIG) {
return null; return null;
} }
// get flag first, we need check EFS.
flag = get16(tmpbuf, LOCFLG);
// get the entry name and create the ZipEntry first // get the entry name and create the ZipEntry first
int len = get16(tmpbuf, LOCNAM); int len = get16(tmpbuf, LOCNAM);
int blen = b.length; int blen = b.length;
@ -262,9 +292,11 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
b = new byte[blen]; b = new byte[blen];
} }
readFully(b, 0, len); readFully(b, 0, len);
ZipEntry e = createZipEntry(getUTF8String(b, 0, len)); // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
ZipEntry e = createZipEntry(((flag & EFS) != 0)
? zc.toStringUTF8(b, len)
: zc.toString(b, len));
// now get the remaining fields for the entry // now get the remaining fields for the entry
flag = get16(tmpbuf, LOCFLG);
if ((flag & 1) == 1) { if ((flag & 1) == 1) {
throw new ZipException("encrypted ZIP entry not supported"); throw new ZipException("encrypted ZIP entry not supported");
} }
@ -313,71 +345,6 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
return e; return e;
} }
/*
* Fetches a UTF8-encoded String from the specified byte array.
*/
private static String getUTF8String(byte[] b, int off, int len) {
// First, count the number of characters in the sequence
int count = 0;
int max = off + len;
int i = off;
while (i < max) {
int c = b[i++] & 0xff;
switch (c >> 4) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
count++;
break;
case 12: case 13:
// 110xxxxx 10xxxxxx
if ((b[i++] & 0xc0) != 0x80) {
throw new IllegalArgumentException();
}
count++;
break;
case 14:
// 1110xxxx 10xxxxxx 10xxxxxx
if (((b[i++] & 0xc0) != 0x80) ||
((b[i++] & 0xc0) != 0x80)) {
throw new IllegalArgumentException();
}
count++;
break;
default:
// 10xxxxxx, 1111xxxx
throw new IllegalArgumentException();
}
}
if (i != max) {
throw new IllegalArgumentException();
}
// Now decode the characters...
char[] cs = new char[count];
i = 0;
while (off < max) {
int c = b[off++] & 0xff;
switch (c >> 4) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
cs[i++] = (char)c;
break;
case 12: case 13:
// 110xxxxx 10xxxxxx
cs[i++] = (char)(((c & 0x1f) << 6) | (b[off++] & 0x3f));
break;
case 14:
// 1110xxxx 10xxxxxx 10xxxxxx
int t = (b[off++] & 0x3f) << 6;
cs[i++] = (char)(((c & 0x0f) << 12) | t | (b[off++] & 0x3f));
break;
default:
// 10xxxxxx, 1111xxxx
throw new IllegalArgumentException();
}
}
return new String(cs, 0, count);
}
/** /**
* Creates a new <code>ZipEntry</code> object for the specified * Creates a new <code>ZipEntry</code> object for the specified
* entry name. * entry name.

View file

@ -27,6 +27,7 @@ package java.util.zip;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Vector; import java.util.Vector;
import java.util.HashSet; import java.util.HashSet;
import static java.util.zip.ZipConstants64.*; import static java.util.zip.ZipConstants64.*;
@ -44,19 +45,9 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
private static class XEntry { private static class XEntry {
public final ZipEntry entry; public final ZipEntry entry;
public final long offset; public final long offset;
public final int flag;
public XEntry(ZipEntry entry, long offset) { public XEntry(ZipEntry entry, long offset) {
this.entry = entry; this.entry = entry;
this.offset = offset; this.offset = offset;
this.flag = (entry.method == DEFLATED &&
(entry.size == -1 ||
entry.csize == -1 ||
entry.crc == -1))
// store size, compressed size, and crc-32 in data descriptor
// immediately following the compressed entry data
? 8
// store size, compressed size, and crc-32 in LOC header
: 0;
} }
} }
@ -66,12 +57,14 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
private CRC32 crc = new CRC32(); private CRC32 crc = new CRC32();
private long written = 0; private long written = 0;
private long locoff = 0; private long locoff = 0;
private String comment; private byte[] comment;
private int method = DEFLATED; private int method = DEFLATED;
private boolean finished; private boolean finished;
private boolean closed = false; private boolean closed = false;
private final ZipCoder zc;
private static int version(ZipEntry e) throws ZipException { private static int version(ZipEntry e) throws ZipException {
switch (e.method) { switch (e.method) {
case DEFLATED: return 20; case DEFLATED: return 20;
@ -100,10 +93,31 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
/** /**
* Creates a new ZIP output stream. * Creates a new ZIP output stream.
*
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used
* to encode the entry names and comments.
*
* @param out the actual output stream * @param out the actual output stream
*/ */
public ZipOutputStream(OutputStream out) { public ZipOutputStream(OutputStream out) {
this(out, Charset.forName("UTF-8"));
}
/**
* Creates a new ZIP output stream.
*
* @param out the actual output stream
*
* @param charset the {@link java.nio.charset.Charset </code>charset<code>}
* to be used to encode the entry names and comments
*
* @since 1.7
*/
public ZipOutputStream(OutputStream out, Charset charset) {
super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true)); super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
if (charset == null)
throw new NullPointerException("charset is null");
this.zc = ZipCoder.get(charset);
usesDefaultDeflater = true; usesDefaultDeflater = true;
} }
@ -114,11 +128,11 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
* ZIP file comment is greater than 0xFFFF bytes * ZIP file comment is greater than 0xFFFF bytes
*/ */
public void setComment(String comment) { public void setComment(String comment) {
if (comment != null && comment.length() > 0xffff/3 if (comment != null) {
&& getUTF8Length(comment) > 0xffff) { this.comment = zc.getBytes(comment);
throw new IllegalArgumentException("ZIP file comment too long."); if (this.comment.length > 0xffff)
throw new IllegalArgumentException("ZIP file comment too long.");
} }
this.comment = comment;
} }
/** /**
@ -167,8 +181,15 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
if (e.method == -1) { if (e.method == -1) {
e.method = method; // use default method e.method = method; // use default method
} }
// store size, compressed size, and crc-32 in LOC header
e.flag = 0;
switch (e.method) { switch (e.method) {
case DEFLATED: case DEFLATED:
// store size, compressed size, and crc-32 in data descriptor
// immediately following the compressed entry data
if (e.size == -1 || e.csize == -1 || e.crc == -1)
e.flag = 8;
break; break;
case STORED: case STORED:
// compressed size, uncompressed size, and crc-32 must all be // compressed size, uncompressed size, and crc-32 must all be
@ -192,6 +213,8 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
if (! names.add(e.name)) { if (! names.add(e.name)) {
throw new ZipException("duplicate entry: " + e.name); throw new ZipException("duplicate entry: " + e.name);
} }
if (zc.isUTF8())
e.flag |= EFS;
current = new XEntry(e, written); current = new XEntry(e, written);
xentries.add(current); xentries.add(current);
writeLOC(current); writeLOC(current);
@ -213,7 +236,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
while (!def.finished()) { while (!def.finished()) {
deflate(); deflate();
} }
if ((current.flag & 8) == 0) { if ((e.flag & 8) == 0) {
// verify size, compressed size, and crc-32 settings // verify size, compressed size, and crc-32 settings
if (e.size != def.getBytesRead()) { if (e.size != def.getBytesRead()) {
throw new ZipException( throw new ZipException(
@ -343,11 +366,11 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
*/ */
private void writeLOC(XEntry xentry) throws IOException { private void writeLOC(XEntry xentry) throws IOException {
ZipEntry e = xentry.entry; ZipEntry e = xentry.entry;
int flag = xentry.flag; int flag = e.flag;
int elen = (e.extra != null) ? e.extra.length : 0; int elen = (e.extra != null) ? e.extra.length : 0;
boolean hasZip64 = false; boolean hasZip64 = false;
writeInt(LOCSIG); // LOC header signature writeInt(LOCSIG); // LOC header signature
if ((flag & 8) == 8) { if ((flag & 8) == 8) {
writeShort(version(e)); // version needed to extract writeShort(version(e)); // version needed to extract
@ -380,7 +403,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
writeInt(e.size); // uncompressed size writeInt(e.size); // uncompressed size
} }
} }
byte[] nameBytes = getUTF8Bytes(e.name); byte[] nameBytes = zc.getBytes(e.name);
writeShort(nameBytes.length); writeShort(nameBytes.length);
writeShort(elen); writeShort(elen);
writeBytes(nameBytes, 0, nameBytes.length); writeBytes(nameBytes, 0, nameBytes.length);
@ -417,7 +440,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
*/ */
private void writeCEN(XEntry xentry) throws IOException { private void writeCEN(XEntry xentry) throws IOException {
ZipEntry e = xentry.entry; ZipEntry e = xentry.entry;
int flag = xentry.flag; int flag = e.flag;
int version = version(e); int version = version(e);
long csize = e.csize; long csize = e.csize;
@ -454,7 +477,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
writeInt(e.crc); // crc-32 writeInt(e.crc); // crc-32
writeInt(csize); // compressed size writeInt(csize); // compressed size
writeInt(size); // uncompressed size writeInt(size); // uncompressed size
byte[] nameBytes = getUTF8Bytes(e.name); byte[] nameBytes = zc.getBytes(e.name);
writeShort(nameBytes.length); writeShort(nameBytes.length);
if (hasZip64) { if (hasZip64) {
// + headid(2) + datasize(2) // + headid(2) + datasize(2)
@ -464,8 +487,8 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
} }
byte[] commentBytes; byte[] commentBytes;
if (e.comment != null) { if (e.comment != null) {
commentBytes = getUTF8Bytes(e.comment); commentBytes = zc.getBytes(e.comment);
writeShort(commentBytes.length); writeShort(Math.min(commentBytes.length, 0xffff));
} else { } else {
commentBytes = null; commentBytes = null;
writeShort(0); writeShort(0);
@ -489,7 +512,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
writeBytes(e.extra, 0, e.extra.length); writeBytes(e.extra, 0, e.extra.length);
} }
if (commentBytes != null) { if (commentBytes != null) {
writeBytes(commentBytes, 0, commentBytes.length); writeBytes(commentBytes, 0, Math.min(commentBytes.length, 0xffff));
} }
} }
@ -541,9 +564,8 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
writeInt(xlen); // length of central directory writeInt(xlen); // length of central directory
writeInt(xoff); // offset of central directory writeInt(xoff); // offset of central directory
if (comment != null) { // zip file comment if (comment != null) { // zip file comment
byte[] b = getUTF8Bytes(comment); writeShort(comment.length);
writeShort(b.length); writeBytes(comment, 0, comment.length);
writeBytes(b, 0, b.length);
} else { } else {
writeShort(0); writeShort(0);
} }
@ -594,60 +616,4 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
super.out.write(b, off, len); super.out.write(b, off, len);
written += len; written += len;
} }
/*
* Returns the length of String's UTF8 encoding.
*/
static int getUTF8Length(String s) {
int count = 0;
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (ch <= 0x7f) {
count++;
} else if (ch <= 0x7ff) {
count += 2;
} else {
count += 3;
}
}
return count;
}
/*
* Returns an array of bytes representing the UTF8 encoding
* of the specified String.
*/
private static byte[] getUTF8Bytes(String s) {
char[] c = s.toCharArray();
int len = c.length;
// Count the number of encoded bytes...
int count = 0;
for (int i = 0; i < len; i++) {
int ch = c[i];
if (ch <= 0x7f) {
count++;
} else if (ch <= 0x7ff) {
count += 2;
} else {
count += 3;
}
}
// Now return the encoded bytes...
byte[] b = new byte[count];
int off = 0;
for (int i = 0; i < len; i++) {
int ch = c[i];
if (ch <= 0x7f) {
b[off++] = (byte)ch;
} else if (ch <= 0x7ff) {
b[off++] = (byte)((ch >> 6) | 0xc0);
b[off++] = (byte)((ch & 0x3f) | 0x80);
} else {
b[off++] = (byte)((ch >> 12) | 0xe0);
b[off++] = (byte)(((ch >> 6) & 0x3f) | 0x80);
b[off++] = (byte)((ch & 0x3f) | 0x80);
}
}
return b;
}
} }

View file

@ -52,6 +52,11 @@ input streams.
<a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT"> <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
are used to overcome the size limitations of the original ZIP format. are used to overcome the size limitations of the original ZIP format.
<p>
<a name="lang_encoding">
<li>APPENDIX D of <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
PKWARE ZIP File Format Specification</a> - Language Encoding Flag (EFS) to
encode ZIP entry filename and comment fields using UTF-8.
<p> <p>
<li><a href="http://www.isi.edu/in-notes/rfc1950.txt"> <li><a href="http://www.isi.edu/in-notes/rfc1950.txt">
ZLIB Compressed Data Format Specification version 3.3</a> ZLIB Compressed Data Format Specification version 3.3</a>

View file

@ -599,7 +599,7 @@ public class CounterMonitor extends Monitor implements CounterMonitorMBean {
*/ */
@Override @Override
public MBeanNotificationInfo[] getNotificationInfo() { public MBeanNotificationInfo[] getNotificationInfo() {
return notifsInfo; return notifsInfo.clone();
} }
/* /*

View file

@ -481,7 +481,7 @@ public class GaugeMonitor extends Monitor implements GaugeMonitorMBean {
*/ */
@Override @Override
public MBeanNotificationInfo[] getNotificationInfo() { public MBeanNotificationInfo[] getNotificationInfo() {
return notifsInfo; return notifsInfo.clone();
} }
/* /*

View file

@ -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
/** /**
* 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.
@ -172,15 +178,21 @@ public abstract class Monitor
Executors.newSingleThreadScheduledExecutor( Executors.newSingleThreadScheduledExecutor(
new DaemonThreadFactory("Scheduler")); new DaemonThreadFactory("Scheduler"));
/**
* Map containing the thread pool executor per thread group.
*/
private static final Map<ThreadPoolExecutor, Void> executors =
new WeakHashMap<ThreadPoolExecutor, Void>();
/**
* Lock for executors map.
*/
private static final Object executorsLock = new Object();
/** /**
* Maximum Pool Size * Maximum Pool Size
*/ */
private static final int maximumPoolSize; private static final int maximumPoolSize;
/**
* Executor Service.
*/
private static final ThreadPoolExecutor executor;
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
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
/** /**
* 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
// 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
// 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
*/ */
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
* ------------------------------------------ * ------------------------------------------
*/ */
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
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
*/ */
private class MonitorTask implements Runnable { private class MonitorTask implements Runnable {
private ThreadPoolExecutor executor;
/* /*
* ------------------------------------------ * ------------------------------------------
* CONSTRUCTORS * CONSTRUCTORS
@ -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
* ------------------------------------------ * ------------------------------------------
*/ */
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
} }
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
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,

View file

@ -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 {
* @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 {
* 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();
} }
/* /*

View file

@ -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 {
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);
} }

View file

@ -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) {

View file

@ -0,0 +1,54 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.font;
public class CreatedFontTracker {
public static final int MAX_FILE_SIZE = 32 * 1024 * 1024;
public static final int MAX_TOTAL_BYTES = 10 * MAX_FILE_SIZE;
static int numBytes;
static CreatedFontTracker tracker;
public static synchronized CreatedFontTracker getTracker() {
if (tracker == null) {
tracker = new CreatedFontTracker();
}
return tracker;
}
public synchronized int getNumBytes() {
return numBytes;
}
public synchronized void addBytes(int sz) {
numBytes += sz;
}
public synchronized void subBytes(int sz) {
numBytes -= sz;
}
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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 {
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 {
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 {
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

View file

@ -2357,19 +2357,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");
@ -2379,6 +2381,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;
} }
@ -2387,7 +2392,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) {

View file

@ -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);
} }

View file

@ -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;
*/ */
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 {
} }
/**
* 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 {
* @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 {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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 (""));
} }

View file

@ -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 {
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();

View file

@ -113,16 +113,16 @@ abstract class AsynchronousFileChannelImpl
} }
} }
final void invalidateAllLocks() { final void invalidateAllLocks() throws IOException {
if (fileLockTable != null) { if (fileLockTable != null) {
try { for (FileLock fl: fileLockTable.removeAll()) {
fileLockTable.removeAll( new FileLockTable.Releaser() { synchronized (fl) {
public void release(FileLock fl) { if (fl.isValid()) {
((FileLockImpl)fl).invalidate(); FileLockImpl fli = (FileLockImpl)fl;
implRelease(fli);
fli.invalidate();
} }
}); }
} catch (IOException e) {
throw new AssertionError(e);
} }
} }
} }
@ -158,7 +158,21 @@ abstract class AsynchronousFileChannelImpl
} }
/** /**
* Invoked by FileLockImpl to release lock acquired by this channel. * Releases the given file lock.
*/ */
abstract void release(FileLockImpl fli) throws IOException; protected abstract void implRelease(FileLockImpl fli) throws IOException;
/**
* Invoked by FileLockImpl to release the given file lock and remove it
* from the lock table.
*/
final void release(FileLockImpl fli) throws IOException {
try {
begin();
implRelease(fli);
removeFromFileLockTable(fli);
} finally {
end();
}
}
} }

View file

@ -33,8 +33,6 @@ import java.nio.BufferPoolMXBean;
import java.nio.channels.*; import java.nio.channels.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Iterator;
import java.lang.reflect.Field;
import java.security.AccessController; import java.security.AccessController;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.management.MalformedObjectNameException; import javax.management.MalformedObjectNameException;
@ -95,14 +93,16 @@ public class FileChannelImpl
// -- Standard channel operations -- // -- Standard channel operations --
protected void implCloseChannel() throws IOException { protected void implCloseChannel() throws IOException {
// Invalidate and release any locks that we still hold // Release and invalidate any locks that we still hold
if (fileLockTable != null) { if (fileLockTable != null) {
fileLockTable.removeAll( new FileLockTable.Releaser() { for (FileLock fl: fileLockTable.removeAll()) {
public void release(FileLock fl) throws IOException { synchronized (fl) {
((FileLockImpl)fl).invalidate(); if (fl.isValid()) {
nd.release(fd, fl.position(), fl.size()); nd.release(fd, fl.position(), fl.size());
((FileLockImpl)fl).invalidate();
}
} }
}); }
} }
nd.preClose(fd); nd.preClose(fd);
@ -912,32 +912,33 @@ public class FileChannelImpl
FileLockImpl fli = new FileLockImpl(this, position, size, shared); FileLockImpl fli = new FileLockImpl(this, position, size, shared);
FileLockTable flt = fileLockTable(); FileLockTable flt = fileLockTable();
flt.add(fli); flt.add(fli);
boolean i = true; boolean completed = false;
int ti = -1; int ti = -1;
try { try {
begin(); begin();
ti = threads.add(); ti = threads.add();
if (!isOpen()) if (!isOpen())
return null; return null;
int result = nd.lock(fd, true, position, size, shared); int n;
if (result == FileDispatcher.RET_EX_LOCK) { do {
assert shared; n = nd.lock(fd, true, position, size, shared);
FileLockImpl fli2 = new FileLockImpl(this, position, size, } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
false); if (isOpen()) {
flt.replace(fli, fli2); if (n == FileDispatcher.RET_EX_LOCK) {
return fli2; assert shared;
FileLockImpl fli2 = new FileLockImpl(this, position, size,
false);
flt.replace(fli, fli2);
fli = fli2;
}
completed = true;
} }
if (result == FileDispatcher.INTERRUPTED || result == FileDispatcher.NO_LOCK) {
flt.remove(fli);
i = false;
}
} catch (IOException e) {
flt.remove(fli);
throw e;
} finally { } finally {
if (!completed)
flt.remove(fli);
threads.remove(ti); threads.remove(ti);
try { try {
end(i); end(completed);
} catch (ClosedByInterruptException e) { } catch (ClosedByInterruptException e) {
throw new FileLockInterruptionException(); throw new FileLockInterruptionException();
} }
@ -985,7 +986,6 @@ public class FileChannelImpl
} }
void release(FileLockImpl fli) throws IOException { void release(FileLockImpl fli) throws IOException {
ensureOpen();
int ti = threads.add(); int ti = threads.add();
try { try {
ensureOpen(); ensureOpen();
@ -1005,7 +1005,7 @@ public class FileChannelImpl
*/ */
private static class SimpleFileLockTable extends FileLockTable { private static class SimpleFileLockTable extends FileLockTable {
// synchronize on list for access // synchronize on list for access
private List<FileLock> lockList = new ArrayList<FileLock>(2); private final List<FileLock> lockList = new ArrayList<FileLock>(2);
public SimpleFileLockTable() { public SimpleFileLockTable() {
} }
@ -1034,14 +1034,11 @@ public class FileChannelImpl
} }
} }
public void removeAll(Releaser releaser) throws IOException { public List<FileLock> removeAll() {
synchronized(lockList) { synchronized(lockList) {
Iterator<FileLock> i = lockList.iterator(); List<FileLock> result = new ArrayList<FileLock>(lockList);
while (i.hasNext()) { lockList.clear();
FileLock fl = i.next(); return result;
releaser.release(fl);
i.remove();
}
} }
} }

View file

@ -31,25 +31,24 @@ import java.nio.channels.*;
public class FileLockImpl public class FileLockImpl
extends FileLock extends FileLock
{ {
boolean valid; private volatile boolean valid = true;
FileLockImpl(FileChannel channel, long position, long size, boolean shared) FileLockImpl(FileChannel channel, long position, long size, boolean shared)
{ {
super(channel, position, size, shared); super(channel, position, size, shared);
this.valid = true;
} }
FileLockImpl(AsynchronousFileChannel channel, long position, long size, boolean shared) FileLockImpl(AsynchronousFileChannel channel, long position, long size, boolean shared)
{ {
super(channel, position, size, shared); super(channel, position, size, shared);
this.valid = true;
} }
public synchronized boolean isValid() { public boolean isValid() {
return valid; return valid;
} }
synchronized void invalidate() { void invalidate() {
assert Thread.holdsLock(this);
valid = false; valid = false;
} }
@ -66,5 +65,4 @@ public class FileLockImpl
valid = false; valid = false;
} }
} }
} }

View file

@ -60,23 +60,12 @@ abstract class FileLockTable {
*/ */
public abstract void remove(FileLock fl); public abstract void remove(FileLock fl);
/**
* An implementation of this interface releases a given file lock.
* Used with removeAll.
*/
public abstract interface Releaser {
void release(FileLock fl) throws IOException;
}
/** /**
* Removes all file locks from the table. * Removes all file locks from the table.
* <p>
* The Releaser#release method is invoked for each file lock before
* it is removed.
* *
* @throws IOException if the release method throws IOException * @return The list of file locks removed
*/ */
public abstract void removeAll(Releaser r) throws IOException; public abstract List<FileLock> removeAll();
/** /**
* Replaces an existing file lock in the table. * Replaces an existing file lock in the table.
@ -195,7 +184,7 @@ class SharedFileLockTable extends FileLockTable {
FileLockReference ref = list.get(index); FileLockReference ref = list.get(index);
FileLock lock = ref.get(); FileLock lock = ref.get();
if (lock == fl) { if (lock == fl) {
assert (lock != null) && (lock.channel() == channel); assert (lock != null) && (lock.acquiredBy() == channel);
ref.clear(); ref.clear();
list.remove(index); list.remove(index);
break; break;
@ -206,7 +195,8 @@ class SharedFileLockTable extends FileLockTable {
} }
@Override @Override
public void removeAll(Releaser releaser) throws IOException { public List<FileLock> removeAll() {
List<FileLock> result = new ArrayList<FileLock>();
List<FileLockReference> list = lockMap.get(fileKey); List<FileLockReference> list = lockMap.get(fileKey);
if (list != null) { if (list != null) {
synchronized (list) { synchronized (list) {
@ -216,13 +206,13 @@ class SharedFileLockTable extends FileLockTable {
FileLock lock = ref.get(); FileLock lock = ref.get();
// remove locks obtained by this channel // remove locks obtained by this channel
if (lock != null && lock.channel() == channel) { if (lock != null && lock.acquiredBy() == channel) {
// invoke the releaser to invalidate/release the lock
releaser.release(lock);
// remove the lock from the list // remove the lock from the list
ref.clear(); ref.clear();
list.remove(index); list.remove(index);
// add to result
result.add(lock);
} else { } else {
index++; index++;
} }
@ -232,6 +222,7 @@ class SharedFileLockTable extends FileLockTable {
removeKeyIfEmpty(fileKey, list); removeKeyIfEmpty(fileKey, list);
} }
} }
return result;
} }
@Override @Override

View file

@ -97,6 +97,9 @@ public class SimpleAsynchronousFileChannelImpl
// then it will throw ClosedChannelException // then it will throw ClosedChannelException
} }
// Invalidate and release any locks that we still hold
invalidateAllLocks();
// signal any threads blocked on this channel // signal any threads blocked on this channel
nd.preClose(fdObj); nd.preClose(fdObj);
threads.signalAndWait(); threads.signalAndWait();
@ -109,9 +112,6 @@ public class SimpleAsynchronousFileChannelImpl
closeLock.writeLock().unlock(); closeLock.writeLock().unlock();
} }
// Invalidate and release any locks that we still hold
invalidateAllLocks();
// close file // close file
nd.close(fdObj); nd.close(fdObj);
@ -226,11 +226,9 @@ public class SimpleAsynchronousFileChannelImpl
do { do {
n = nd.lock(fdObj, true, position, size, shared); n = nd.lock(fdObj, true, position, size, shared);
} while ((n == FileDispatcher.INTERRUPTED) && isOpen()); } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
if (n == FileDispatcher.LOCKED) { if (n == FileDispatcher.LOCKED && isOpen()) {
result.setResult(fli); result.setResult(fli);
} else { } else {
if (n != FileDispatcher.INTERRUPTED)
throw new AssertionError();
throw new AsynchronousCloseException(); throw new AsynchronousCloseException();
} }
} catch (IOException x) { } catch (IOException x) {
@ -279,16 +277,16 @@ public class SimpleAsynchronousFileChannelImpl
do { do {
n = nd.lock(fdObj, false, position, size, shared); n = nd.lock(fdObj, false, position, size, shared);
} while ((n == FileDispatcher.INTERRUPTED) && isOpen()); } while ((n == FileDispatcher.INTERRUPTED) && isOpen());
if (n != FileDispatcher.LOCKED) { if (n == FileDispatcher.LOCKED && isOpen()) {
if (n == FileDispatcher.NO_LOCK) gotLock = true;
return null; // locked by someone else return fli; // lock acquired
if (n == FileDispatcher.INTERRUPTED)
throw new AsynchronousCloseException();
// should not get here
throw new AssertionError();
} }
gotLock = true; if (n == FileDispatcher.NO_LOCK)
return fli; return null; // locked by someone else
if (n == FileDispatcher.INTERRUPTED)
throw new AsynchronousCloseException();
// should not get here
throw new AssertionError();
} finally { } finally {
if (!gotLock) if (!gotLock)
removeFromFileLockTable(fli); removeFromFileLockTable(fli);
@ -298,14 +296,8 @@ public class SimpleAsynchronousFileChannelImpl
} }
@Override @Override
void release(FileLockImpl fli) throws IOException { protected void implRelease(FileLockImpl fli) throws IOException {
try { nd.release(fdObj, fli.position(), fli.size());
begin();
nd.release(fdObj, fli.position(), fli.size());
removeFromFileLockTable(fli);
} finally {
end();
}
} }
@Override @Override

View file

@ -736,6 +736,14 @@ public class Config {
return name; return name;
} }
private static String trimmed(String s) {
s = s.trim();
if (s.charAt(0) == '"' && s.charAt(s.length()-1) == '"' ||
s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\'') {
s = s.substring(1, s.length()-1).trim();
}
return s;
}
/** /**
* Parses key-value pairs under a stanza name. * Parses key-value pairs under a stanza name.
*/ */
@ -747,7 +755,7 @@ public class Config {
for (int j = 0; j < line.length(); j++) { for (int j = 0; j < line.length(); j++) {
if (line.charAt(j) == '=') { if (line.charAt(j) == '=') {
String key = (line.substring(0, j)).trim(); String key = (line.substring(0, j)).trim();
String value = (line.substring(j + 1)).trim(); String value = trimmed(line.substring(j + 1));
table.put(key, value); table.put(key, value);
break; break;
} }
@ -820,7 +828,7 @@ public class Config {
} else { } else {
nameVector = table.get(key); nameVector = table.get(key);
} }
nameVector.addElement((line.substring(j + 1)).trim()); nameVector.addElement(trimmed(line.substring(j + 1)));
table.put(key, nameVector); table.put(key, nameVector);
break; break;
} }
@ -1263,4 +1271,32 @@ public class Config {
} }
} }
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
toStringIndented("", stanzaTable, sb);
return sb.toString();
}
private static void toStringIndented(String prefix, Object obj,
StringBuffer sb) {
if (obj instanceof String) {
sb.append(prefix);
sb.append(obj);
sb.append('\n');
} else if (obj instanceof Hashtable) {
Hashtable tab = (Hashtable)obj;
for (Object o: tab.keySet()) {
sb.append(prefix);
sb.append(o);
sb.append(" = {\n");
toStringIndented(prefix + " ", tab.get(o), sb);
sb.append(prefix + "}\n");
}
} else if (obj instanceof Vector) {
Vector v = (Vector)obj;
for (Object o: v.toArray()) {
toStringIndented(prefix + " ", o, sb);
}
}
}
} }

View file

@ -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();
} }
} }
} }

View file

@ -93,4 +93,7 @@ public class UDPClient {
return data; return data;
} }
public void close() {
dgSocket.close();
}
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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.*;
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 {
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 {
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 {
("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 {
("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 {
("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 {
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 {
("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

View file

@ -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 {
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,

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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.*;
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 {
} 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 {
} 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 {
} }
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 {
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),

View file

@ -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 {
// //
// 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 {
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 {
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 {
+ ": 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 {
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 {
} 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 {
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 {
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 {
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 {
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 {
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];

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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.*;
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 {
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 {
} }
/** /**
* 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");
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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 {
// 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 {
// 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 {
// 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

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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
*/ */
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
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 {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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 {
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 {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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 {
* 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 {
*/ */
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

View file

@ -26,7 +26,8 @@
package sun.security.util; package sun.security.util;
import java.io.*; import java.io.*;
import java.math.BigInteger;
import java.util.Arrays;
/** /**
* Represent an ISO Object Identifier. * Represent an ISO Object Identifier.
@ -44,105 +45,186 @@ import java.io.*;
* hierarchy, and other organizations can easily acquire the ability * hierarchy, and other organizations can easily acquire the ability
* to assign such unique identifiers. * to assign such unique identifiers.
* *
*
* @author David Brownell * @author David Brownell
* @author Amit Kapoor * @author Amit Kapoor
* @author Hemma Prafullchandra * @author Hemma Prafullchandra
*/ */
final public final public
class ObjectIdentifier implements Serializable class ObjectIdentifier implements Serializable
{ {
/** use serialVersionUID from JDK 1.1. for interoperability */ /**
* We use the DER value (no tag, no length) as the internal format
* @serial
*/
private byte[] encoding = null;
private transient volatile String stringForm;
/*
* IMPORTANT NOTES FOR CODE CHANGES (bug 4811968) IN JDK 1.7.0
* ===========================================================
*
* (Almost) serialization compatibility with old versions:
*
* serialVersionUID is unchanged. Old field "component" is changed to
* type Object so that "poison" (unknown object type for old versions)
* can be put inside if there are huge components that cannot be saved
* as integers.
*
* New version use the new filed "encoding" only.
*
* Below are all 4 cases in a serialization/deserialization process:
*
* 1. old -> old: Not covered here
* 2. old -> new: There's no "encoding" field, new readObject() reads
* "components" and "componentLen" instead and inits correctly.
* 3. new -> new: "encoding" field exists, new readObject() uses it
* (ignoring the other 2 fields) and inits correctly.
* 4. new -> old: old readObject() only recognizes "components" and
* "componentLen" fields. If no huge components are involved, they
* are serialized as legal values and old object can init correctly.
* Otherwise, old object cannot recognize the form (component not int[])
* and throw a ClassNotFoundException at deserialization time.
*
* Therfore, for the first 3 cases, exact compatibility is preserved. In
* the 4th case, non-huge OID is still supportable in old versions, while
* huge OID is not.
*/
private static final long serialVersionUID = 8697030238860181294L; private static final long serialVersionUID = 8697030238860181294L;
private static final int maxFirstComponent = 2;
private static final int maxSecondComponent = 39;
/** /**
* Constructs an object identifier from a string. This string * Changed to Object
* should be of the form 1.23.34.45.56 etc. * @serial
*/
private Object components = null; // path from root
/**
* @serial
*/
private int componentLen = -1; // how much is used.
// Is the components field calculated?
transient private boolean componentsCalculated = false;
private void readObject(ObjectInputStream is)
throws IOException, ClassNotFoundException {
is.defaultReadObject();
if (encoding == null) { // from an old version
init((int[])components, componentLen);
}
}
private void writeObject(ObjectOutputStream os)
throws IOException {
if (!componentsCalculated) {
int[] comps = toIntArray();
if (comps != null) { // every one understands this
components = comps;
componentLen = comps.length;
} else {
components = HugeOidNotSupportedByOldJDK.theOne;
}
componentsCalculated = true;
}
os.defaultWriteObject();
}
static class HugeOidNotSupportedByOldJDK implements Serializable {
private static final long serialVersionUID = 1L;
static HugeOidNotSupportedByOldJDK theOne = new HugeOidNotSupportedByOldJDK();
}
/**
* Constructs, from a string. This string should be of the form 1.23.56.
* Validity check included.
*/ */
public ObjectIdentifier (String oid) throws IOException public ObjectIdentifier (String oid) throws IOException
{ {
int ch = '.'; int ch = '.';
int start = 0; int start = 0;
int end = 0; int end = 0;
// Calculate length of oid int pos = 0;
componentLen = 0; byte[] tmp = new byte[oid.length()];
while ((end = oid.indexOf(ch,start)) != -1) { int first = 0, second;
start = end + 1; int count = 0;
componentLen += 1;
}
componentLen += 1;
components = new int[componentLen];
start = 0;
int i = 0;
String comp = null;
try { try {
while ((end = oid.indexOf(ch,start)) != -1) { String comp = null;
comp = oid.substring(start,end); do {
components[i++] = Integer.valueOf(comp).intValue(); int length = 0; // length of one section
end = oid.indexOf(ch,start);
if (end == -1) {
comp = oid.substring(start);
length = oid.length() - start;
} else {
comp = oid.substring(start,end);
length = end - start;
}
if (length > 9) {
BigInteger bignum = new BigInteger(comp);
if (count == 0) {
checkFirstComponent(bignum);
first = bignum.intValue();
} else {
if (count == 1) {
checkSecondComponent(first, bignum);
bignum = bignum.add(BigInteger.valueOf(40*first));
} else {
checkOtherComponent(count, bignum);
}
pos += pack7Oid(bignum, tmp, pos);
}
} else {
int num = Integer.parseInt(comp);
if (count == 0) {
checkFirstComponent(num);
first = num;
} else {
if (count == 1) {
checkSecondComponent(first, num);
num += 40 * first;
} else {
checkOtherComponent(count, num);
}
pos += pack7Oid(num, tmp, pos);
}
}
start = end + 1; start = end + 1;
} count++;
comp = oid.substring(start); } while (end != -1);
components[i] = Integer.valueOf(comp).intValue();
checkCount(count);
encoding = new byte[pos];
System.arraycopy(tmp, 0, encoding, 0, pos);
this.stringForm = oid;
} catch (IOException ioe) { // already detected by checkXXX
throw ioe;
} catch (Exception e) { } catch (Exception e) {
throw new IOException("ObjectIdentifier() -- Invalid format: " throw new IOException("ObjectIdentifier() -- Invalid format: "
+ e.toString(), e); + e.toString(), e);
} }
checkValidOid(components, componentLen);
this.stringForm = oid;
} }
/** /**
* Check if the values make a legal OID. There must be at least 2 * Constructor, from an array of integers.
* components and they must be all non-negative. The first component * Validity check included.
* should be 0,1 or 2. When the first component is 0 or 1, the
* second component should be less than or equal to 39
*
* @param values the components that will make the OID
* @param len the number of components to check. Note that the allocation
* size of <code>values</code> may be longer than <code>len</code>.
* In this case, only the first <code>len</code> items are checked.
* @exception IOException if this is not a legal OID
*/
private void checkValidOid(int[] values, int len) throws IOException {
if (values == null || len < 2) {
throw new IOException("ObjectIdentifier() -- " +
"Must be at least two oid components ");
}
for (int i=0; i<len; i++) {
if (values[i] < 0) {
throw new IOException("ObjectIdentifier() -- " +
"oid component #" + (i+1) + " must be non-negative ");
}
}
if (values[0] > maxFirstComponent) {
throw new IOException("ObjectIdentifier() -- " +
"First oid component is invalid ");
}
if (values[0] < 2 && values[1] > maxSecondComponent) {
throw new IOException("ObjectIdentifier() -- " +
"Second oid component is invalid ");
}
}
/**
* Constructs an object ID from an array of integers. This
* is used to construct constant object IDs.
*/ */
public ObjectIdentifier (int values []) throws IOException public ObjectIdentifier (int values []) throws IOException
{ {
checkValidOid(values, values.length); checkCount(values.length);
components = values.clone(); checkFirstComponent(values[0]);
componentLen = values.length; checkSecondComponent(values[0], values[1]);
for (int i=2; i<values.length; i++)
checkOtherComponent(i, values[i]);
init(values, values.length);
} }
/** /**
* Constructs an object ID from an ASN.1 encoded input stream. * Constructor, from an ASN.1 encoded input stream.
* Validity check NOT included.
* The encoding of the ID in the stream uses "DER", a BER/1 subset. * The encoding of the ID in the stream uses "DER", a BER/1 subset.
* In this case, that means a triple { typeId, length, data }. * In this case, that means a triple { typeId, length, data }.
* *
@ -152,8 +234,7 @@ class ObjectIdentifier implements Serializable
* @param in DER-encoded data holding an object ID * @param in DER-encoded data holding an object ID
* @exception IOException indicates a decoding error * @exception IOException indicates a decoding error
*/ */
public ObjectIdentifier (DerInputStream in) public ObjectIdentifier (DerInputStream in) throws IOException
throws IOException
{ {
byte type_id; byte type_id;
int bufferEnd; int bufferEnd;
@ -174,215 +255,67 @@ class ObjectIdentifier implements Serializable
+ " (tag = " + type_id + ")" + " (tag = " + type_id + ")"
); );
bufferEnd = in.available () - in.getLength () - 1; encoding = new byte[in.getLength()];
if (bufferEnd < 0) in.getBytes(encoding);
throw new IOException ( check(encoding);
"ObjectIdentifier() -- not enough data");
initFromEncoding (in, bufferEnd);
} }
/* /*
* Build the OID from the rest of a DER input buffer; the tag * Constructor, from the rest of a DER input buffer;
* and length have been removed/verified * the tag and length have been removed/verified
* Validity check NOT included.
*/ */
ObjectIdentifier (DerInputBuffer buf) throws IOException ObjectIdentifier (DerInputBuffer buf) throws IOException
{ {
initFromEncoding (new DerInputStream (buf), 0); DerInputStream in = new DerInputStream(buf);
encoding = new byte[in.available()];
in.getBytes(encoding);
check(encoding);
}
private void init(int[] components, int length) {
int pos = 0;
byte[] tmp = new byte[length*5+1]; // +1 for empty input
if (components[1] < Integer.MAX_VALUE - components[0]*40)
pos += pack7Oid(components[0]*40+components[1], tmp, pos);
else {
BigInteger big = BigInteger.valueOf(components[1]);
big = big.add(BigInteger.valueOf(components[0]*40));
pos += pack7Oid(big, tmp, pos);
}
for (int i=2; i<length; i++) {
pos += pack7Oid(components[i], tmp, pos);
}
encoding = new byte[pos];
System.arraycopy(tmp, 0, encoding, 0, pos);
} }
/** /**
* Private constructor for use by newInternal(). Dummy argument * This method is kept for compatibility reasons. The new implementation
* to avoid clash with the public constructor. * does the check and conversion. All around the JDK, the method is called
*/ * in static blocks to initialize pre-defined ObjectIdentifieies. No
private ObjectIdentifier(int[] components, boolean dummy) { * obvious performance hurt will be made after this change.
this.components = components; *
this.componentLen = components.length; * Old doc: Create a new ObjectIdentifier for internal use. The values are
}
/**
* Create a new ObjectIdentifier for internal use. The values are
* neither checked nor cloned. * neither checked nor cloned.
*/ */
public static ObjectIdentifier newInternal(int[] values) { public static ObjectIdentifier newInternal(int[] values) {
return new ObjectIdentifier(values, true); try {
} return new ObjectIdentifier(values);
} catch (IOException ex) {
/* throw new RuntimeException(ex);
* Helper function -- get the OID from a stream, after tag and // Should not happen, internal calls always uses legal values.
* length are verified.
*/
private void initFromEncoding (DerInputStream in, int bufferEnd)
throws IOException
{
/*
* Now get the components ("sub IDs") one at a time. We fill a
* temporary buffer, resizing it as needed.
*/
int component;
boolean first_subid = true;
for (components = new int [allocationQuantum], componentLen = 0;
in.available () > bufferEnd;
) {
component = getComponent (in);
if (component < 0) {
throw new IOException(
"ObjectIdentifier() -- " +
"component values must be nonnegative");
}
if (first_subid) {
int X, Y;
/*
* NOTE: the allocation quantum is large enough that we know
* we don't have to reallocate here!
*/
if (component < 40)
X = 0;
else if (component < 80)
X = 1;
else
X = 2;
Y = component - ( X * 40);
components [0] = X;
components [1] = Y;
componentLen = 2;
first_subid = false;
} else {
/*
* Other components are encoded less exotically. The only
* potential trouble is the need to grow the array.
*/
if (componentLen >= components.length) {
int tmp_components [];
tmp_components = new int [components.length
+ allocationQuantum];
System.arraycopy (components, 0, tmp_components, 0,
components.length);
components = tmp_components;
}
components [componentLen++] = component;
}
}
checkValidOid(components, componentLen);
/*
* Final sanity check -- if we didn't use exactly the number of bytes
* specified, something's quite wrong.
*/
if (in.available () != bufferEnd) {
throw new IOException (
"ObjectIdentifier() -- malformed input data");
} }
} }
/* /*
* n.b. the only public interface is DerOutputStream.putOID() * n.b. the only public interface is DerOutputStream.putOID()
*/ */
void encode (DerOutputStream out) throws IOException void encode (DerOutputStream out) throws IOException
{ {
DerOutputStream bytes = new DerOutputStream (); out.write (DerValue.tag_ObjectId, encoding);
int i;
// According to ISO X.660, when the 1st component is 0 or 1, the 2nd
// component is restricted to be less than or equal to 39, thus make
// it small enough to be encoded into one single byte.
if (components[0] < 2) {
bytes.write ((components [0] * 40) + components [1]);
} else {
putComponent(bytes, (components [0] * 40) + components [1]);
}
for (i = 2; i < componentLen; i++)
putComponent (bytes, components [i]);
/*
* Now that we've constructed the component, encode
* it in the stream we were given.
*/
out.write (DerValue.tag_ObjectId, bytes);
}
/*
* Tricky OID component parsing technique ... note that one bit
* per octet is lost, this returns at most 28 bits of component.
* Also, notice this parses in big-endian format.
*/
private static int getComponent (DerInputStream in)
throws IOException
{
int retval, i, tmp;
for (i = 0, retval = 0; i < 4; i++) {
retval <<= 7;
tmp = in.getByte ();
retval |= (tmp & 0x07f);
if ((tmp & 0x080) == 0)
return retval;
}
throw new IOException ("ObjectIdentifier() -- component value too big");
}
/*
* Reverse of the above routine. Notice it needs to emit in
* big-endian form, so it buffers the output until it's ready.
* (Minimum length encoding is a DER requirement.)
*/
private static void putComponent (DerOutputStream out, int val)
throws IOException
{
int i;
// TODO: val must be <128*128*128*128 here, otherwise, 4 bytes is not
// enough to hold it. Will address this later.
byte buf [] = new byte [4] ;
for (i = 0; i < 4; i++) {
buf [i] = (byte) (val & 0x07f);
val >>>= 7;
if (val == 0)
break;
}
for ( ; i > 0; --i)
out.write (buf [i] | 0x080);
out.write (buf [0]);
}
// XXX this API should probably facilitate the JDK sort utility
/**
* Compares this identifier with another, for sorting purposes.
* An identifier does not precede itself.
*
* @param other identifer that may precede this one.
* @return true iff <em>other</em> precedes this one
* in a particular sorting order.
*/
public boolean precedes (ObjectIdentifier other)
{
int i;
// shorter IDs go first
if (other == this || componentLen < other.componentLen)
return false;
if (other.componentLen < componentLen)
return true;
// for each component, the lesser component goes first
for (i = 0; i < componentLen; i++) {
if (other.components [i] < components [i])
return true;
}
// identical IDs don't precede each other
return false;
} }
/** /**
@ -398,6 +331,7 @@ class ObjectIdentifier implements Serializable
* *
* @return true iff the names are identical. * @return true iff the names are identical.
*/ */
@Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;
@ -406,23 +340,71 @@ class ObjectIdentifier implements Serializable
return false; return false;
} }
ObjectIdentifier other = (ObjectIdentifier)obj; ObjectIdentifier other = (ObjectIdentifier)obj;
if (componentLen != other.componentLen) { return Arrays.equals(encoding, other.encoding);
return false;
}
for (int i = 0; i < componentLen; i++) {
if (components[i] != other.components[i]) {
return false;
}
}
return true;
} }
@Override
public int hashCode() { public int hashCode() {
int h = componentLen; return Arrays.hashCode(encoding);
for (int i = 0; i < componentLen; i++) { }
h += components[i] * 37;
/**
* Private helper method for serialization. To be compatible with old
* versions of JDK.
* @return components in an int array, if all the components are less than
* Integer.MAX_VALUE. Otherwise, null.
*/
private int[] toIntArray() {
int length = encoding.length;
int[] result = new int[20];
int which = 0;
int fromPos = 0;
for (int i = 0; i < length; i++) {
if ((encoding[i] & 0x80) == 0) {
// one section [fromPos..i]
if (i - fromPos + 1 > 4) {
BigInteger big = new BigInteger(pack(encoding, fromPos, i-fromPos+1, 7, 8));
if (fromPos == 0) {
result[which++] = 2;
BigInteger second = big.subtract(BigInteger.valueOf(80));
if (second.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) {
return null;
} else {
result[which++] = second.intValue();
}
} else {
if (big.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) == 1) {
return null;
} else {
result[which++] = big.intValue();
}
}
} else {
int retval = 0;
for (int j = fromPos; j <= i; j++) {
retval <<= 7;
byte tmp = encoding[j];
retval |= (tmp & 0x07f);
}
if (fromPos == 0) {
if (retval < 80) {
result[which++] = retval / 40;
result[which++] = retval % 40;
} else {
result[which++] = 2;
result[which++] = retval - 80;
}
} else {
result[which++] = retval;
}
}
fromPos = i+1;
}
if (which >= result.length) {
result = Arrays.copyOf(result, which + 10);
}
} }
return h; return Arrays.copyOf(result, which);
} }
/** /**
@ -431,15 +413,52 @@ class ObjectIdentifier implements Serializable
* user-friendly descriptive strings, since those strings * user-friendly descriptive strings, since those strings
* will not be understood everywhere. * will not be understood everywhere.
*/ */
@Override
public String toString() { public String toString() {
String s = stringForm; String s = stringForm;
if (s == null) { if (s == null) {
StringBuffer sb = new StringBuffer(componentLen * 4); int length = encoding.length;
for (int i = 0; i < componentLen; i++) { StringBuffer sb = new StringBuffer(length * 4);
if (i != 0) {
sb.append('.'); int fromPos = 0;
for (int i = 0; i < length; i++) {
if ((encoding[i] & 0x80) == 0) {
// one section [fromPos..i]
if (fromPos != 0) { // not the first segment
sb.append('.');
}
if (i - fromPos + 1 > 4) { // maybe big integer
BigInteger big = new BigInteger(pack(encoding, fromPos, i-fromPos+1, 7, 8));
if (fromPos == 0) {
// first section encoded with more than 4 bytes,
// must be 2.something
sb.append("2.");
sb.append(big.subtract(BigInteger.valueOf(80)));
} else {
sb.append(big);
}
} else { // small integer
int retval = 0;
for (int j = fromPos; j <= i; j++) {
retval <<= 7;
byte tmp = encoding[j];
retval |= (tmp & 0x07f);
}
if (fromPos == 0) {
if (retval < 80) {
sb.append(retval/40);
sb.append('.');
sb.append(retval%40);
} else {
sb.append("2.");
sb.append(retval - 80);
}
} else {
sb.append(retval);
}
}
fromPos = i+1;
} }
sb.append(components[i]);
} }
s = sb.toString(); s = sb.toString();
stringForm = s; stringForm = s;
@ -447,15 +466,197 @@ class ObjectIdentifier implements Serializable
return s; return s;
} }
/* /**
* To simplify, we assume no individual component of an object ID is * Repack all bits from input to output. On the both sides, only a portion
* larger than 32 bits. Then we represent the path from the root as * (from the least significant bit) of the 8 bits in a byte is used. This
* an array that's (usually) only filled at the beginning. * number is defined as the number of useful bits (NUB) for the array. All the
* used bits from the input byte array and repacked into the output in the
* exactly same order. The output bits are aligned so that the final bit of
* the input (the least significant bit in the last byte), when repacked as
* the final bit of the output, is still at the least significant position.
* Zeroes will be padded on the left side of the first output byte if
* necessary. All unused bits in the output are also zeroed.
*
* For example: if the input is 01001100 with NUB 8, the output which
* has a NUB 6 will look like:
* 00000001 00001100
* The first 2 bits of the output bytes are unused bits. The other bits
* turn out to be 000001 001100. While the 8 bits on the right are from
* the input, the left 4 zeroes are padded to fill the 6 bits space.
*
* @param in the input byte array
* @param ioffset start point inside <code>in</code>
* @param ilength number of bytes to repack
* @param iw NUB for input
* @param ow NUB for output
* @return the repacked bytes
*/ */
private int components []; // path from root private static byte[] pack(byte[] in, int ioffset, int ilength, int iw, int ow) {
private int componentLen; // how much is used. assert (iw > 0 && iw <= 8): "input NUB must be between 1 and 8";
assert (ow > 0 && ow <= 8): "output NUB must be between 1 and 8";
private transient volatile String stringForm; if (iw == ow) {
return in.clone();
}
private static final int allocationQuantum = 5; // >= 2 int bits = ilength * iw; // number of all used bits
byte[] out = new byte[(bits+ow-1)/ow];
// starting from the 0th bit in the input
int ipos = 0;
// the number of padding 0's needed in the output, skip them
int opos = (bits+ow-1)/ow*ow-bits;
while(ipos < bits) {
int count = iw - ipos%iw; // unpacked bits in current input byte
if (count > ow - opos%ow) { // free space available in output byte
count = ow - opos%ow; // choose the smaller number
}
// and move them!
out[opos/ow] |= // paste!
(((in[ioffset+ipos/iw]+256) // locate the byte (+256 so that it's never negative)
>> (iw-ipos%iw-count)) // move to the end of a byte
& ((1 << (count))-1)) // zero out all other bits
<< (ow-opos%ow-count); // move to the output position
ipos += count; // advance
opos += count; // advance
}
return out;
}
/**
* Repack from NUB 8 to a NUB 7 OID sub-identifier, remove all
* unnecessary 0 headings, set the first bit of all non-tail
* output bytes to 1 (as ITU-T Rec. X.690 8.19.2 says), and
* paste it into an existing byte array.
* @param out the existing array to be pasted into
* @param ooffset the starting position to paste
* @return the number of bytes pasted
*/
private static int pack7Oid(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) {
byte[] pack = pack(in, ioffset, ilength, 8, 7);
int firstNonZero = pack.length-1; // paste at least one byte
for (int i=pack.length-2; i>=0; i--) {
if (pack[i] != 0) {
firstNonZero = i;
}
pack[i] |= 0x80;
}
System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero);
return pack.length-firstNonZero;
}
/**
* Repack from NUB 7 to NUB 8, remove all unnecessary 0
* headings, and paste it into an existing byte array.
* @param out the existing array to be pasted into
* @param ooffset the starting position to paste
* @return the number of bytes pasted
*/
private static int pack8(byte[] in, int ioffset, int ilength, byte[] out, int ooffset) {
byte[] pack = pack(in, ioffset, ilength, 7, 8);
int firstNonZero = pack.length-1; // paste at least one byte
for (int i=pack.length-2; i>=0; i--) {
if (pack[i] != 0) {
firstNonZero = i;
}
}
System.arraycopy(pack, firstNonZero, out, ooffset, pack.length-firstNonZero);
return pack.length-firstNonZero;
}
/**
* Pack the int into a OID sub-identifier DER encoding
*/
private static int pack7Oid(int input, byte[] out, int ooffset) {
byte[] b = new byte[4];
b[0] = (byte)(input >> 24);
b[1] = (byte)(input >> 16);
b[2] = (byte)(input >> 8);
b[3] = (byte)(input);
return pack7Oid(b, 0, 4, out, ooffset);
}
/**
* Pack the BigInteger into a OID subidentifier DER encoding
*/
private static int pack7Oid(BigInteger input, byte[] out, int ooffset) {
byte[] b = input.toByteArray();
return pack7Oid(b, 0, b.length, out, ooffset);
}
/**
* Private methods to check validity of OID. They must be --
* 1. at least 2 components
* 2. all components must be non-negative
* 3. the first must be 0, 1 or 2
* 4. if the first is 0 or 1, the second must be <40
*/
/**
* Check the DER encoding. Since DER encoding defines that the integer bits
* are unsigned, so there's no need to check the MSB.
*/
private static void check(byte[] encoding) throws IOException {
int length = encoding.length;
if (length < 1 || // too short
(encoding[length - 1] & 0x80) != 0) { // not ended
throw new IOException("ObjectIdentifier() -- " +
"Invalid DER encoding, not ended");
}
for (int i=0; i<length; i++) {
// 0x80 at the beginning of a subidentifier
if (encoding[i] == (byte)0x80 &&
(i==0 || (encoding[i-1] & 0x80) == 0)) {
throw new IOException("ObjectIdentifier() -- " +
"Invalid DER encoding, useless extra octet detected");
}
}
}
private static void checkCount(int count) throws IOException {
if (count < 2) {
throw new IOException("ObjectIdentifier() -- " +
"Must be at least two oid components ");
}
}
private static void checkFirstComponent(int first) throws IOException {
if (first < 0 || first > 2) {
throw new IOException("ObjectIdentifier() -- " +
"First oid component is invalid ");
}
}
private static void checkFirstComponent(BigInteger first) throws IOException {
if (first.signum() == -1 ||
first.compareTo(BigInteger.valueOf(2)) == 1) {
throw new IOException("ObjectIdentifier() -- " +
"First oid component is invalid ");
}
}
private static void checkSecondComponent(int first, int second) throws IOException {
if (second < 0 || first != 2 && second > 39) {
throw new IOException("ObjectIdentifier() -- " +
"Second oid component is invalid ");
}
}
private static void checkSecondComponent(int first, BigInteger second) throws IOException {
if (second.signum() == -1 ||
first != 2 &&
second.compareTo(BigInteger.valueOf(39)) == 1) {
throw new IOException("ObjectIdentifier() -- " +
"Second oid component is invalid ");
}
}
private static void checkOtherComponent(int i, int num) throws IOException {
if (num < 0) {
throw new IOException("ObjectIdentifier() -- " +
"oid component #" + (i+1) + " must be non-negative ");
}
}
private static void checkOtherComponent(int i, BigInteger num) throws IOException {
if (num.signum() == -1) {
throw new IOException("ObjectIdentifier() -- " +
"oid component #" + (i+1) + " must be non-negative ");
}
}
} }

View file

@ -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 @@
# 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 @@
# 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 @@
# #
# 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

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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) {
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) {
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() {
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;

View file

@ -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() {
// 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;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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,
} }
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;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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 @@
#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*);
#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 };
#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"

View file

@ -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':

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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() {
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() {
// 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() {
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() {
#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() {
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() {
} 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() {
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() {
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() {
} }
} }
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() {
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) {
// 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() {
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() {
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) {
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) {
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) {
} }
} }
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) {
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) {
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) {
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) {
// 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() {
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() {
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) {

View file

@ -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;

View file

@ -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 {

View file

@ -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;

View file

@ -1,105 +0,0 @@
/*
* Copyright 1998 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.
*/
/*
* Native method support for java.util.zip.ZipEntry
*/
#include <stdio.h>
#include <stdlib.h>
#include "jlong.h"
#include "jvm.h"
#include "jni.h"
#include "jni_util.h"
#include "zip_util.h"
#include "java_util_zip_ZipEntry.h"
#define DEFLATED 8
#define STORED 0
static jfieldID nameID;
static jfieldID timeID;
static jfieldID crcID;
static jfieldID sizeID;
static jfieldID csizeID;
static jfieldID methodID;
static jfieldID extraID;
static jfieldID commentID;
JNIEXPORT void JNICALL
Java_java_util_zip_ZipEntry_initIDs(JNIEnv *env, jclass cls)
{
nameID = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");
timeID = (*env)->GetFieldID(env, cls, "time", "J");
crcID = (*env)->GetFieldID(env, cls, "crc", "J");
sizeID = (*env)->GetFieldID(env, cls, "size", "J");
csizeID = (*env)->GetFieldID(env, cls, "csize", "J");
methodID = (*env)->GetFieldID(env, cls, "method", "I");
extraID = (*env)->GetFieldID(env, cls, "extra", "[B");
commentID = (*env)->GetFieldID(env, cls, "comment", "Ljava/lang/String;");
}
JNIEXPORT void JNICALL
Java_java_util_zip_ZipEntry_initFields(JNIEnv *env, jobject obj, jlong zentry)
{
jzentry *ze = jlong_to_ptr(zentry);
jstring name = (*env)->GetObjectField(env, obj, nameID);
if (name == 0) {
name = (*env)->NewStringUTF(env, ze->name);
if (name == 0) {
return;
}
(*env)->SetObjectField(env, obj, nameID, name);
}
(*env)->SetLongField(env, obj, timeID, (jlong)ze->time & 0xffffffffUL);
(*env)->SetLongField(env, obj, crcID, (jlong)ze->crc & 0xffffffffUL);
(*env)->SetLongField(env, obj, sizeID, (jlong)ze->size);
if (ze->csize == 0) {
(*env)->SetLongField(env, obj, csizeID, (jlong)ze->size);
(*env)->SetIntField(env, obj, methodID, STORED);
} else {
(*env)->SetLongField(env, obj, csizeID, (jlong)ze->csize);
(*env)->SetIntField(env, obj, methodID, DEFLATED);
}
if (ze->extra != 0) {
unsigned char *bp = (unsigned char *)&ze->extra[0];
jsize len = (bp[0] | (bp[1] << 8));
jbyteArray extra = (*env)->NewByteArray(env, len);
if (extra == 0) {
return;
}
(*env)->SetByteArrayRegion(env, extra, 0, len, &ze->extra[2]);
(*env)->SetObjectField(env, obj, extraID, extra);
}
if (ze->comment != 0) {
jstring comment = (*env)->NewStringUTF(env, ze->comment);
if (comment == 0) {
return;
}
(*env)->SetObjectField(env, obj, commentID, comment);
}
}

View file

@ -141,12 +141,11 @@ Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile)
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile, Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
jstring name, jboolean addSlash) jbyteArray name, jboolean addSlash)
{ {
#define MAXNAME 1024 #define MAXNAME 1024
jzfile *zip = jlong_to_ptr(zfile); jzfile *zip = jlong_to_ptr(zfile);
jsize slen = (*env)->GetStringLength(env, name); jsize ulen = (*env)->GetArrayLength(env, name);
jsize ulen = (*env)->GetStringUTFLength(env, name);
char buf[MAXNAME+2], *path; char buf[MAXNAME+2], *path;
jzentry *ze; jzentry *ze;
@ -159,7 +158,7 @@ Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
} else { } else {
path = buf; path = buf;
} }
(*env)->GetStringUTFRegion(env, name, 0, slen, path); (*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path);
path[ulen] = '\0'; path[ulen] = '\0';
if (addSlash == JNI_FALSE) { if (addSlash == JNI_FALSE) {
ze = ZIP_GetEntry(zip, path, 0); ze = ZIP_GetEntry(zip, path, 0);
@ -186,34 +185,87 @@ Java_java_util_zip_ZipFile_getNextEntry(JNIEnv *env, jclass cls, jlong zfile,
jint n) jint n)
{ {
jzentry *ze = ZIP_GetNextEntry(jlong_to_ptr(zfile), n); jzentry *ze = ZIP_GetNextEntry(jlong_to_ptr(zfile), n);
return ptr_to_jlong(ze); return ptr_to_jlong(ze);
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_java_util_zip_ZipFile_getMethod(JNIEnv *env, jclass cls, jlong zentry) Java_java_util_zip_ZipFile_getEntryMethod(JNIEnv *env, jclass cls, jlong zentry)
{ {
jzentry *ze = jlong_to_ptr(zentry); jzentry *ze = jlong_to_ptr(zentry);
return ze->csize != 0 ? DEFLATED : STORED; return ze->csize != 0 ? DEFLATED : STORED;
} }
JNIEXPORT jlong JNICALL JNIEXPORT jint JNICALL
Java_java_util_zip_ZipFile_getCSize(JNIEnv *env, jclass cls, jlong zentry) Java_java_util_zip_ZipFile_getEntryFlag(JNIEnv *env, jclass cls, jlong zentry)
{ {
jzentry *ze = jlong_to_ptr(zentry); jzentry *ze = jlong_to_ptr(zentry);
return ze->flag;
}
JNIEXPORT jlong JNICALL
Java_java_util_zip_ZipFile_getEntryCSize(JNIEnv *env, jclass cls, jlong zentry)
{
jzentry *ze = jlong_to_ptr(zentry);
return ze->csize != 0 ? ze->csize : ze->size; return ze->csize != 0 ? ze->csize : ze->size;
} }
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_java_util_zip_ZipFile_getSize(JNIEnv *env, jclass cls, jlong zentry) Java_java_util_zip_ZipFile_getEntrySize(JNIEnv *env, jclass cls, jlong zentry)
{ {
jzentry *ze = jlong_to_ptr(zentry); jzentry *ze = jlong_to_ptr(zentry);
return ze->size; return ze->size;
} }
JNIEXPORT jlong JNICALL
Java_java_util_zip_ZipFile_getEntryTime(JNIEnv *env, jclass cls, jlong zentry)
{
jzentry *ze = jlong_to_ptr(zentry);
return (jlong)ze->time & 0xffffffffUL;
}
JNIEXPORT jlong JNICALL
Java_java_util_zip_ZipFile_getEntryCrc(JNIEnv *env, jclass cls, jlong zentry)
{
jzentry *ze = jlong_to_ptr(zentry);
return (jlong)ze->crc & 0xffffffffUL;
}
JNIEXPORT jbyteArray JNICALL
Java_java_util_zip_ZipFile_getEntryBytes(JNIEnv *env, jclass cls, jlong zentry, jint type)
{
jzentry *ze = jlong_to_ptr(zentry);
int len = 0;
jbyteArray jba = NULL;
switch (type) {
case java_util_zip_ZipFile_JZENTRY_NAME:
if (ze->name != 0) {
len = (int)strlen(ze->name);
if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
break;
(*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte *)ze->name);
}
break;
case java_util_zip_ZipFile_JZENTRY_EXTRA:
if (ze->extra != 0) {
unsigned char *bp = (unsigned char *)&ze->extra[0];
len = (bp[0] | (bp[1] << 8));
if (len <= 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
break;
(*env)->SetByteArrayRegion(env, jba, 0, len, &ze->extra[2]);
}
break;
case java_util_zip_ZipFile_JZENTRY_COMMENT:
if (ze->comment != 0) {
len = (int)strlen(ze->comment);
if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
break;
(*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte*)ze->comment);
}
break;
}
return jba;
}
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_java_util_zip_ZipFile_read(JNIEnv *env, jclass cls, jlong zfile, Java_java_util_zip_ZipFile_read(JNIEnv *env, jclass cls, jlong zfile,
jlong zentry, jlong pos, jbyteArray bytes, jlong zentry, jlong pos, jbyteArray bytes,

View file

@ -512,7 +512,6 @@ readCEN(jzfile *zip, jint knownTotal)
/* Clear previous zip error */ /* Clear previous zip error */
zip->msg = NULL; zip->msg = NULL;
/* Get position of END header */ /* Get position of END header */
if ((endpos = findEND(zip, endbuf)) == -1) if ((endpos = findEND(zip, endbuf)) == -1)
return -1; /* no END header or system error */ return -1; /* no END header or system error */
@ -520,7 +519,6 @@ readCEN(jzfile *zip, jint knownTotal)
if (endpos == 0) return 0; /* only END header present */ if (endpos == 0) return 0; /* only END header present */
freeCEN(zip); freeCEN(zip);
/* Get position and length of central directory */ /* Get position and length of central directory */
cenlen = ENDSIZ(endbuf); cenlen = ENDSIZ(endbuf);
cenoff = ENDOFF(endbuf); cenoff = ENDOFF(endbuf);
@ -935,6 +933,7 @@ newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
ze->crc = CENCRC(cen); ze->crc = CENCRC(cen);
locoff = CENOFF(cen); locoff = CENOFF(cen);
ze->pos = -(zip->locpos + locoff); ze->pos = -(zip->locpos + locoff);
ze->flag = CENFLG(cen);
if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch; if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
memcpy(ze->name, cen + CENHDR, nlen); memcpy(ze->name, cen + CENHDR, nlen);

View file

@ -168,6 +168,7 @@ typedef struct jzentry { /* Zip file entry */
char *comment; /* optional zip file comment */ char *comment; /* optional zip file comment */
jbyte *extra; /* optional extra data */ jbyte *extra; /* optional extra data */
jlong pos; /* position of LOC header or entry data */ jlong pos; /* position of LOC header or entry data */
jint flag; /* general purpose flag */
} jzentry; } jzentry;
/* /*

View file

@ -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,
/* 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;
} }

View file

@ -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)

View file

@ -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,
} }
} }
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,
} }
} }
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);

View file

@ -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)

View file

@ -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)
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)
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)
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)
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)
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)
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)
{ {
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;

View file

@ -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

View file

@ -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)
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 */

View file

@ -354,16 +354,9 @@ public class WindowsAsynchronousFileChannelImpl
} }
} }
// invoke by FileFileImpl to release lock
@Override @Override
void release(FileLockImpl fli) throws IOException { protected void implRelease(FileLockImpl fli) throws IOException {
try { nd.release(fdObj, fli.position(), fli.size());
begin();
nd.release(fdObj, fli.position(), fli.size());
removeFromFileLockTable(fli);
} finally {
end();
}
} }
/** /**

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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;
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;
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 {
// 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 {
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 {
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);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * 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;
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
// 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
: 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
} }
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();

View file

@ -414,7 +414,7 @@ Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this,
o.Offset = lowPos; o.Offset = lowPos;
o.OffsetHigh = highPos; o.OffsetHigh = highPos;
result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o); result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o);
if (result == 0) { if (result == 0 && GetLastError() != ERROR_NOT_LOCKED) {
JNU_ThrowIOExceptionWithLastError(env, "Release failed"); JNU_ThrowIOExceptionWithLastError(env, "Release failed");
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Portions Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. * Portions Copyright 2000-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
@ -73,6 +73,7 @@ jmethodID setRealmMethod = 0;
* Function prototypes for internal routines * Function prototypes for internal routines
* *
*/ */
BOOL native_debug = 0;
BOOL PackageConnectLookup(PHANDLE,PULONG); BOOL PackageConnectLookup(PHANDLE,PULONG);
@ -113,208 +114,221 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
jclass cls; jclass cls;
JNIEnv *env; JNIEnv *env;
jfieldID fldDEBUG;
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) { if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {
return JNI_EVERSION; /* JNI version not supported */ return JNI_EVERSION; /* JNI version not supported */
} }
cls = (*env)->FindClass(env,"sun/security/krb5/internal/Krb5");
if (cls == NULL) {
printf("LSA: Couldn't find Krb5\n");
return JNI_ERR;
}
fldDEBUG = (*env)->GetStaticFieldID(env, cls, "DEBUG", "Z");
if (fldDEBUG == NULL) {
printf("LSA: Krb5 has no DEBUG field\n");
return JNI_ERR;
}
native_debug = (*env)->GetStaticBooleanField(env, cls, fldDEBUG);
cls = (*env)->FindClass(env,"sun/security/krb5/internal/Ticket"); cls = (*env)->FindClass(env,"sun/security/krb5/internal/Ticket");
if (cls == NULL) { if (cls == NULL) {
printf("Couldn't find Ticket\n"); printf("LSA: Couldn't find Ticket\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found Ticket\n"); printf("LSA: Found Ticket\n");
#endif /* DEBUG */ }
ticketClass = (*env)->NewWeakGlobalRef(env,cls); ticketClass = (*env)->NewWeakGlobalRef(env,cls);
if (ticketClass == NULL) { if (ticketClass == NULL) {
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Made NewWeakGlobalRef\n"); printf("LSA: Made NewWeakGlobalRef\n");
#endif /* DEBUG */ }
cls = (*env)->FindClass(env, "sun/security/krb5/PrincipalName"); cls = (*env)->FindClass(env, "sun/security/krb5/PrincipalName");
if (cls == NULL) { if (cls == NULL) {
printf("Couldn't find PrincipalName\n"); printf("LSA: Couldn't find PrincipalName\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found PrincipalName\n"); printf("LSA: Found PrincipalName\n");
#endif /* DEBUG */ }
principalNameClass = (*env)->NewWeakGlobalRef(env,cls); principalNameClass = (*env)->NewWeakGlobalRef(env,cls);
if (principalNameClass == NULL) { if (principalNameClass == NULL) {
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Made NewWeakGlobalRef\n"); printf("LSA: Made NewWeakGlobalRef\n");
#endif /* DEBUG */ }
cls = (*env)->FindClass(env,"sun/security/util/DerValue"); cls = (*env)->FindClass(env,"sun/security/util/DerValue");
if (cls == NULL) { if (cls == NULL) {
printf("Couldn't find DerValue\n"); printf("LSA: Couldn't find DerValue\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found DerValue\n"); printf("LSA: Found DerValue\n");
#endif /* DEBUG */ }
derValueClass = (*env)->NewWeakGlobalRef(env,cls); derValueClass = (*env)->NewWeakGlobalRef(env,cls);
if (derValueClass == NULL) { if (derValueClass == NULL) {
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Made NewWeakGlobalRef\n"); printf("LSA: Made NewWeakGlobalRef\n");
#endif /* DEBUG */ }
cls = (*env)->FindClass(env,"sun/security/krb5/EncryptionKey"); cls = (*env)->FindClass(env,"sun/security/krb5/EncryptionKey");
if (cls == NULL) { if (cls == NULL) {
printf("Couldn't find EncryptionKey\n"); printf("LSA: Couldn't find EncryptionKey\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found EncryptionKey\n"); printf("LSA: Found EncryptionKey\n");
#endif /* DEBUG */ }
encryptionKeyClass = (*env)->NewWeakGlobalRef(env,cls); encryptionKeyClass = (*env)->NewWeakGlobalRef(env,cls);
if (encryptionKeyClass == NULL) { if (encryptionKeyClass == NULL) {
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Made NewWeakGlobalRef\n"); printf("LSA: Made NewWeakGlobalRef\n");
#endif /* DEBUG */ }
cls = (*env)->FindClass(env,"sun/security/krb5/internal/TicketFlags"); cls = (*env)->FindClass(env,"sun/security/krb5/internal/TicketFlags");
if (cls == NULL) { if (cls == NULL) {
printf("Couldn't find TicketFlags\n"); printf("LSA: Couldn't find TicketFlags\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found TicketFlags\n"); printf("LSA: Found TicketFlags\n");
#endif /* DEBUG */ }
ticketFlagsClass = (*env)->NewWeakGlobalRef(env,cls); ticketFlagsClass = (*env)->NewWeakGlobalRef(env,cls);
if (ticketFlagsClass == NULL) { if (ticketFlagsClass == NULL) {
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Made NewWeakGlobalRef\n"); printf("LSA: Made NewWeakGlobalRef\n");
#endif /* DEBUG */ }
cls = (*env)->FindClass(env,"sun/security/krb5/internal/KerberosTime"); cls = (*env)->FindClass(env,"sun/security/krb5/internal/KerberosTime");
if (cls == NULL) { if (cls == NULL) {
printf("Couldn't find KerberosTime\n"); printf("LSA: Couldn't find KerberosTime\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found KerberosTime\n"); printf("LSA: Found KerberosTime\n");
#endif /* DEBUG */ }
kerberosTimeClass = (*env)->NewWeakGlobalRef(env,cls); kerberosTimeClass = (*env)->NewWeakGlobalRef(env,cls);
if (kerberosTimeClass == NULL) { if (kerberosTimeClass == NULL) {
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Made NewWeakGlobalRef\n"); printf("LSA: Made NewWeakGlobalRef\n");
#endif /* DEBUG */ }
cls = (*env)->FindClass(env,"java/lang/String"); cls = (*env)->FindClass(env,"java/lang/String");
if (cls == NULL) { if (cls == NULL) {
printf("Couldn't find String\n"); printf("LSA: Couldn't find String\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found String\n"); printf("LSA: Found String\n");
#endif /* DEBUG */ }
javaLangStringClass = (*env)->NewWeakGlobalRef(env,cls); javaLangStringClass = (*env)->NewWeakGlobalRef(env,cls);
if (javaLangStringClass == NULL) { if (javaLangStringClass == NULL) {
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Made NewWeakGlobalRef\n"); printf("LSA: Made NewWeakGlobalRef\n");
#endif /* DEBUG */ }
derValueConstructor = (*env)->GetMethodID(env, derValueClass, derValueConstructor = (*env)->GetMethodID(env, derValueClass,
"<init>", "([B)V"); "<init>", "([B)V");
if (derValueConstructor == 0) { if (derValueConstructor == 0) {
printf("Couldn't find DerValue constructor\n"); printf("LSA: Couldn't find DerValue constructor\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found DerValue constructor\n"); printf("LSA: Found DerValue constructor\n");
#endif /* DEBUG */ }
ticketConstructor = (*env)->GetMethodID(env, ticketClass, ticketConstructor = (*env)->GetMethodID(env, ticketClass,
"<init>", "(Lsun/security/util/DerValue;)V"); "<init>", "(Lsun/security/util/DerValue;)V");
if (ticketConstructor == 0) { if (ticketConstructor == 0) {
printf("Couldn't find Ticket constructor\n"); printf("LSA: Couldn't find Ticket constructor\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found Ticket constructor\n"); printf("LSA: Found Ticket constructor\n");
#endif /* DEBUG */ }
principalNameConstructor = (*env)->GetMethodID(env, principalNameClass, principalNameConstructor = (*env)->GetMethodID(env, principalNameClass,
"<init>", "([Ljava/lang/String;)V"); "<init>", "([Ljava/lang/String;)V");
if (principalNameConstructor == 0) { if (principalNameConstructor == 0) {
printf("Couldn't find PrincipalName constructor\n"); printf("LSA: Couldn't find PrincipalName constructor\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found PrincipalName constructor\n"); printf("LSA: Found PrincipalName constructor\n");
#endif /* DEBUG */ }
encryptionKeyConstructor = (*env)->GetMethodID(env, encryptionKeyClass, encryptionKeyConstructor = (*env)->GetMethodID(env, encryptionKeyClass,
"<init>", "(I[B)V"); "<init>", "(I[B)V");
if (encryptionKeyConstructor == 0) { if (encryptionKeyConstructor == 0) {
printf("Couldn't find EncryptionKey constructor\n"); printf("LSA: Couldn't find EncryptionKey constructor\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found EncryptionKey constructor\n"); printf("LSA: Found EncryptionKey constructor\n");
#endif /* DEBUG */ }
ticketFlagsConstructor = (*env)->GetMethodID(env, ticketFlagsClass, ticketFlagsConstructor = (*env)->GetMethodID(env, ticketFlagsClass,
"<init>", "(I[B)V"); "<init>", "(I[B)V");
if (ticketFlagsConstructor == 0) { if (ticketFlagsConstructor == 0) {
printf("Couldn't find TicketFlags constructor\n"); printf("LSA: Couldn't find TicketFlags constructor\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found TicketFlags constructor\n"); printf("LSA: Found TicketFlags constructor\n");
#endif /* DEBUG */ }
kerberosTimeConstructor = (*env)->GetMethodID(env, kerberosTimeClass, kerberosTimeConstructor = (*env)->GetMethodID(env, kerberosTimeClass,
"<init>", "(Ljava/lang/String;)V"); "<init>", "(Ljava/lang/String;)V");
if (kerberosTimeConstructor == 0) { if (kerberosTimeConstructor == 0) {
printf("Couldn't find KerberosTime constructor\n"); printf("LSA: Couldn't find KerberosTime constructor\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Found KerberosTime constructor\n"); printf("LSA: Found KerberosTime constructor\n");
#endif /* DEBUG */ }
// load the setRealm method in PrincipalName // load the setRealm method in PrincipalName
setRealmMethod = (*env)->GetMethodID(env, principalNameClass, setRealmMethod = (*env)->GetMethodID(env, principalNameClass,
"setRealm", "(Ljava/lang/String;)V"); "setRealm", "(Ljava/lang/String;)V");
if (setRealmMethod == 0) { if (setRealmMethod == 0) {
printf("Couldn't find setRealm in PrincipalName\n"); printf("LSA: Couldn't find setRealm in PrincipalName\n");
return JNI_ERR; return JNI_ERR;
} }
#ifdef DEBUG if (native_debug) {
printf("Finished OnLoad processing\n"); printf("LSA: Finished OnLoad processing\n");
#endif /* DEBUG */ }
return JNI_VERSION_1_2; return JNI_VERSION_1_2;
} }
@ -389,16 +403,25 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
if (krbcredsConstructor == 0) { if (krbcredsConstructor == 0) {
krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>", krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>",
"(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V"); "(Lsun/security/krb5/internal/Ticket;"
"Lsun/security/krb5/PrincipalName;"
"Lsun/security/krb5/PrincipalName;"
"Lsun/security/krb5/EncryptionKey;"
"Lsun/security/krb5/internal/TicketFlags;"
"Lsun/security/krb5/internal/KerberosTime;"
"Lsun/security/krb5/internal/KerberosTime;"
"Lsun/security/krb5/internal/KerberosTime;"
"Lsun/security/krb5/internal/KerberosTime;"
"Lsun/security/krb5/internal/HostAddresses;)V");
if (krbcredsConstructor == 0) { if (krbcredsConstructor == 0) {
printf("Couldn't find sun.security.krb5.Credentials constructor\n"); printf("LSA: Couldn't find sun.security.krb5.Credentials constructor\n");
break; break;
} }
} }
#ifdef DEBUG if (native_debug) {
printf("Found KrbCreds constructor\n"); printf("LSA: Found KrbCreds constructor\n");
#endif }
// //
// Get the logon handle and package ID from the // Get the logon handle and package ID from the
@ -407,9 +430,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
if (!PackageConnectLookup(&LogonHandle, &PackageId)) if (!PackageConnectLookup(&LogonHandle, &PackageId))
break; break;
#ifdef DEBUG if (native_debug) {
printf("Got handle to Kerberos package\n"); printf("LSA: Got handle to Kerberos package\n");
#endif /* DEBUG */ }
// Get the MS TGT from cache // Get the MS TGT from cache
CacheRequest.MessageType = KerbRetrieveTicketMessage; CacheRequest.MessageType = KerbRetrieveTicketMessage;
@ -426,9 +449,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
&SubStatus &SubStatus
); );
#ifdef DEBUG if (native_debug) {
printf("Response size is %d\n", rspSize); printf("LSA: Response size is %d\n", rspSize);
#endif }
if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) { if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
if (!LSA_SUCCESS(Status)) { if (!LSA_SUCCESS(Status)) {
@ -467,9 +490,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
} }
if (ignore_cache) { if (ignore_cache) {
#ifdef DEBUG if (native_debug) {
printf("MS TGT in cache is invalid/not supported; request new ticket\n"); printf("LSA: MS TGT in cache is invalid/not supported; request new ticket\n");
#endif /* DEBUG */ }
// use domain to request Ticket // use domain to request Ticket
Status = ConstructTicketRequest(msticket->TargetDomainName, Status = ConstructTicketRequest(msticket->TargetDomainName,
@ -493,9 +516,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
&SubStatus &SubStatus
); );
#ifdef DEBUG if (native_debug) {
printf("Response size is %d\n", responseSize); printf("LSA: Response size is %d\n", responseSize);
#endif /* DEBUG */ }
if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) { if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
if (!LSA_SUCCESS(Status)) { if (!LSA_SUCCESS(Status)) {
@ -788,7 +811,9 @@ ShowLastError(
static WCHAR szMsgBuf[MAX_MSG_SIZE]; static WCHAR szMsgBuf[MAX_MSG_SIZE];
DWORD dwRes; DWORD dwRes;
printf("Error calling function %s: %lu\n", szAPI, dwError); if (native_debug) {
printf("LSA: Error calling function %s: %lu\n", szAPI, dwError);
}
dwRes = FormatMessage ( dwRes = FormatMessage (
FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_FROM_SYSTEM,
@ -798,11 +823,13 @@ ShowLastError(
szMsgBuf, szMsgBuf,
MAX_MSG_SIZE, MAX_MSG_SIZE,
NULL); NULL);
if (0 == dwRes) { if (native_debug) {
printf("FormatMessage failed with %d\n", GetLastError()); if (0 == dwRes) {
// ExitProcess(EXIT_FAILURE); printf("LSA: FormatMessage failed with %d\n", GetLastError());
} else { // ExitProcess(EXIT_FAILURE);
printf("%S",szMsgBuf); } else {
printf("LSA: %S",szMsgBuf);
}
} }
} }
@ -896,17 +923,19 @@ jobject BuildPrincipal(JNIEnv *env, PKERB_EXTERNAL_NAME principalName,
((domainName.Length)*sizeof(WCHAR) + sizeof(UNICODE_NULL))); ((domainName.Length)*sizeof(WCHAR) + sizeof(UNICODE_NULL)));
wcsncpy(realm, domainName.Buffer, domainName.Length/sizeof(WCHAR)); wcsncpy(realm, domainName.Buffer, domainName.Length/sizeof(WCHAR));
#ifdef DEBUG if (native_debug) {
printf("Principal domain is %S\n", realm); printf("LSA: Principal domain is %S\n", realm);
printf("Name type is %x\n", principalName->NameType); printf("LSA: Name type is %x\n", principalName->NameType);
printf("Name count is %x\n", principalName->NameCount); printf("LSA: Name count is %x\n", principalName->NameCount);
#endif }
nameCount = principalName->NameCount; nameCount = principalName->NameCount;
stringArray = (*env)->NewObjectArray(env, nameCount, stringArray = (*env)->NewObjectArray(env, nameCount,
javaLangStringClass, NULL); javaLangStringClass, NULL);
if (stringArray == NULL) { if (stringArray == NULL) {
printf("Can't allocate String array for Principal\n"); if (native_debug) {
printf("LSA: Can't allocate String array for Principal\n");
}
LocalFree(realm); LocalFree(realm);
return principal; return principal;
} }
@ -941,6 +970,17 @@ jobject BuildEncryptionKey(JNIEnv *env, PKERB_CRYPTO_KEY cryptoKey) {
// First, need to build a byte array // First, need to build a byte array
jbyteArray ary; jbyteArray ary;
jobject encryptionKey = NULL; jobject encryptionKey = NULL;
unsigned int i;
for (i=0; i<cryptoKey->Length; i++) {
if (cryptoKey->Value[i]) break;
}
if (i == cryptoKey->Length) {
if (native_debug) {
printf("LSA: Session key all zero. Stop.\n");
}
return NULL;
}
ary = (*env)->NewByteArray(env,cryptoKey->Length); ary = (*env)->NewByteArray(env,cryptoKey->Length);
(*env)->SetByteArrayRegion(env, ary, (jsize) 0, cryptoKey->Length, (*env)->SetByteArrayRegion(env, ary, (jsize) 0, cryptoKey->Length,
@ -1005,9 +1045,9 @@ jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime) {
hour, hour,
minute, minute,
second ); second );
#ifdef DEBUG if (native_debug) {
printf("%S\n", (wchar_t *)timeString); printf("LSA: %S\n", (wchar_t *)timeString);
#endif /* DEBUG */ }
stringTime = (*env)->NewString(env, timeString, stringTime = (*env)->NewString(env, timeString,
(sizeof(timeString)/sizeof(WCHAR))-1); (sizeof(timeString)/sizeof(WCHAR))-1);
if (stringTime != NULL) { // everything's OK so far if (stringTime != NULL) { // everything's OK so far

Binary file not shown.

View file

@ -0,0 +1,139 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
import java.applet.*;
import java.awt.*;
import java.io.*;
import java.net.*;
public class BigFont extends Applet {
static private class SizedInputStream extends InputStream {
int size;
int cnt = 0;
SizedInputStream(int size) {
this.size = size;
}
public int read() {
if (cnt < size) {
cnt++;
return 0;
} else {
return -1;
}
}
public int getCurrentSize() {
return cnt;
}
}
String id;
String fileName;
public void init() {
id = getParameter("number");
fileName = getParameter("font");
System.out.println("Applet " + id + " "+
Thread.currentThread().getThreadGroup());
// Larger than size for a single font.
int fontSize = 64 * 1000 * 1000;
SizedInputStream sis = new SizedInputStream(fontSize);
try {
Font font = Font.createFont(Font.TRUETYPE_FONT, sis);
} catch (Throwable t) {
if (t instanceof FontFormatException ||
fontSize <= sis.getCurrentSize())
{
System.out.println(sis.getCurrentSize());
System.out.println(t);
throw new RuntimeException("Allowed file to be too large.");
}
}
// The following part of the test was verified manually but
// is impractical to enable because it requires a fairly large
// valid font to be part of the test, and we can't easily include
// that, nor dependably reference one from the applet environment.
/*
if (fileName == null) {
return;
}
int size = getFileSize(fileName);
if (size == 0) {
return;
}
int fontCnt = 1000 * 1000 * 1000 / size;
loadMany(size, fontCnt, fileName);
System.gc(); System.gc();
fontCnt = fontCnt / 2;
System.out.println("Applet " + id + " load more.");
loadMany(size, fontCnt, fileName);
*/
System.out.println("Applet " + id + " finished.");
}
int getFileSize(String fileName) {
try {
URL url = new URL(getCodeBase(), fileName);
InputStream inStream = url.openStream();
BufferedInputStream fontStream = new BufferedInputStream(inStream);
int size = 0;
while (fontStream.read() != -1) {
size++;
}
fontStream.close();
return size;
} catch (IOException e) {
return 0;
}
}
void loadMany(int oneFont, int fontCnt, String fileName) {
System.out.println("fontcnt= " + fontCnt);
Font[] fonts = new Font[fontCnt];
int totalSize = 0;
boolean gotException = false;
for (int i=0; i<fontCnt; i++) {
try {
URL url = new URL(getCodeBase(), fileName);
InputStream inStream = url.openStream();
BufferedInputStream fontStream =
new BufferedInputStream(inStream);
fonts[i] = Font.createFont(Font.TRUETYPE_FONT, fontStream);
totalSize += oneFont;
fontStream.close();
} catch (Throwable t) {
gotException = true;
System.out.println("Applet " + id + " " + t);
}
}
if (!gotException) {
throw new RuntimeException("No expected exception");
}
}
}

View file

@ -0,0 +1,89 @@
/*
* Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
import java.io.*;
import java.awt.*;
public class DeleteFont {
public static void main(String args[]) throws Exception {
String font = "A.ttf";
String sep = System.getProperty("file.separator");
String testSrc = System.getenv("TESTSRC");
if (testSrc != null) {
font = testSrc + sep + font;
}
System.out.println("Using font file: " + font);
FileInputStream fis = new FileInputStream(font);
Font f = Font.createFont(Font.TRUETYPE_FONT, fis);
f.toString();
f.deriveFont(Font.BOLD);
f.canDisplay('X');
InputStream in = new InputStream() {
public int read() {
throw new RuntimeException();
}
};
boolean gotException = false;
try {
Font.createFont(java.awt.Font.TRUETYPE_FONT, in);
} catch (IOException e) {
gotException = true;
}
if (!gotException) {
throw new RuntimeException("No expected IOException");
}
badRead(-2, Font.TRUETYPE_FONT);
badRead(8193, Font.TRUETYPE_FONT);
badRead(-2, Font.TYPE1_FONT);
badRead(8193, Font.TYPE1_FONT);
// Make sure GC has a chance to clean up before we exit.
System.gc(); System.gc();
}
static void badRead(final int retval, int fontType) {
int num = 2;
byte[] buff = new byte[16*8192]; // Multiple of 8192 is important.
for (int ct=0; ct<num; ++ct) {
try {
Font.createFont(
fontType,
new ByteArrayInputStream(buff) {
@Override
public int read(byte[] buff, int off, int len) {
int read = super.read(buff, off, len);
return read<0 ? retval : read;
}
}
);
} catch (Throwable exc) {
//exc.printStackTrace();
}
}
}
}

View file

@ -0,0 +1,66 @@
# Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
# @test
# @bug 6189812 6380357 6632886
# @summary Verify that temporary font files are deleted on exit.
if [ -z "${TESTSRC}" ]; then
echo "TESTSRC undefined: defaulting to ."
TESTSRC=.
fi
if [ -z "${TESTCLASSES}" ]; then
echo "TESTCLASSES undefined: defaulting to ."
TESTCLASSES=.
fi
if [ -z "${TESTJAVA}" ]; then
echo "TESTJAVA undefined: can't continue."
exit 1
fi
echo "TESTJAVA=${TESTJAVA}"
echo "TESTSRC=${TESTSRC}"
echo "TESTCLASSES=${TESTCLASSES}"
cd ${TESTSRC}
${TESTJAVA}/bin/javac -d ${TESTCLASSES} DeleteFont.java
cd ${TESTCLASSES}
numfiles0=`ls ${TESTCLASSES} | wc -l`
${TESTJAVA}/bin/java -Djava.io.tmpdir=${TESTCLASSES} DeleteFont
if [ $? -ne 0 ]
then
echo "Test fails: exception thrown!"
exit 1
fi
numfiles1=`ls ${TESTCLASSES} | wc -l`
if [ $numfiles0 -ne $numfiles1 ]
then
echo "Test fails: tmp file exists!"
ls ${TESTCLASSES}
exit 1
fi
exit 0

Some files were not shown because too many files have changed in this diff Show more