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 \
Inflater.c \
ZipFile.c \
ZipEntry.c \
zadler32.c \
zcrc32.c \
deflate.c \

View File

@ -50,15 +50,17 @@ SUNWprivate_1.1 {
Java_java_util_zip_Inflater_initIDs;
Java_java_util_zip_Inflater_reset;
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_freeEntry;
Java_java_util_zip_ZipFile_getCSize;
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_getSize;
Java_java_util_zip_ZipFile_getZipMessage;
Java_java_util_zip_ZipFile_getTotal;
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_getTotal;
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_getCSize;
text: .text%Java_java_util_zip_ZipFile_getSize;
text: .text%Java_java_util_zip_ZipFile_getMethod;
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
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_init;
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_getTotal;
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_getCSize;
text: .text%Java_java_util_zip_ZipFile_getSize;
text: .text%Java_java_util_zip_ZipFile_getMethod;
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
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_init;
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_getTotal;
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_getCSize;
text: .text%Java_java_util_zip_ZipFile_getSize;
text: .text%Java_java_util_zip_ZipFile_getMethod;
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
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_init;
text: .text%inflateInit2_;

View File

@ -50,6 +50,12 @@
#define JAR_ERROR2 "Error: Unable to access jarfile %s"
#define JAR_ERROR3 "Error: Invalid or corrupt jarfile %s"
#define CLS_ERROR1 "Error: Could not find the main class %s.\n" JNI_ERROR
#define CLS_ERROR2 "Error: Failed to load Main Class: %s\n%s"
#define CLS_ERROR3 "Error: No main method found in specified class.\n" GEN_ERROR
#define CLS_ERROR4 "Error: Main method not public\n" GEN_ERROR
#define CLS_ERROR5 "Error: main-class: attribute exceeds system limits of %d bytes\n" GEN_ERROR
#define CFG_WARN1 "Warning: %s VM not supported; %s VM will be used"
#define CFG_WARN2 "Warning: No leading - on line %d of `%s'"
#define CFG_WARN3 "Warning: Missing VM type on line %d of `%s'"

View File

@ -915,8 +915,14 @@ SelectVersion(int argc, char **argv, char **main_class)
* to avoid locating, expanding and parsing the manifest extra
* times.
*/
if (info.main_class != NULL)
(void)JLI_StrCat(env_entry, info.main_class);
if (info.main_class != NULL) {
if (JLI_StrLen(info.main_class) <= MAXNAMELEN) {
(void)JLI_StrCat(env_entry, info.main_class);
} else {
JLI_ReportErrorMessage(CLS_ERROR5, MAXNAMELEN);
exit(1);
}
}
(void)putenv(env_entry);
ExecJRE(jre, new_argv);
JLI_FreeManifest();

View File

@ -22,7 +22,6 @@
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.remote.internal;
import java.io.IOException;
@ -34,6 +33,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.security.auth.Subject;
@ -54,7 +54,10 @@ import com.sun.jmx.remote.util.EnvHelp;
public abstract class ClientNotifForwarder {
public ClientNotifForwarder(Map<String, ?> env) {
private final AccessControlContext acc;
public ClientNotifForwarder(Map env) {
this(null, env);
}
@ -87,6 +90,8 @@ public abstract class ClientNotifForwarder {
this.command = command;
if (thread == null) {
thread = new Thread() {
@Override
public void run() {
while (true) {
Runnable r;
@ -130,6 +135,7 @@ public abstract class ClientNotifForwarder {
this.defaultClassLoader = defaultClassLoader;
this.executor = ex;
this.acc = AccessController.getContext();
}
/**
@ -380,28 +386,85 @@ public abstract class ClientNotifForwarder {
setState(TERMINATED);
}
// -------------------------------------------------
// private classes
// -------------------------------------------------
// -------------------------------------------------
// private classes
// -------------------------------------------------
//
private class NotifFetcher implements Runnable {
private volatile boolean alreadyLogged = false;
private void logOnce(String msg, SecurityException x) {
if (alreadyLogged) return;
// Log only once.
logger.config("setContextClassLoader",msg);
if (x != null) logger.fine("setContextClassLoader", x);
alreadyLogged = true;
}
// Set new context class loader, returns previous one.
private final ClassLoader setContextClassLoader(final ClassLoader loader) {
final AccessControlContext ctxt = ClientNotifForwarder.this.acc;
// if ctxt is null, log a config message and throw a
// SecurityException.
if (ctxt == null) {
logOnce("AccessControlContext must not be null.",null);
throw new SecurityException("AccessControlContext must not be null");
}
return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
try {
// get context class loader - may throw
// SecurityException - though unlikely.
final ClassLoader previous =
Thread.currentThread().getContextClassLoader();
// if nothing needs to be done, break here...
if (loader == previous) return previous;
// reset context class loader - may throw
// SecurityException
Thread.currentThread().setContextClassLoader(loader);
return previous;
} catch (SecurityException x) {
logOnce("Permission to set ContextClassLoader missing. " +
"Notifications will not be dispatched. " +
"Please check your Java policy configuration: " +
x, x);
throw x;
}
}
}, ctxt);
}
public void run() {
final ClassLoader previous;
if (defaultClassLoader != null) {
previous = setContextClassLoader(defaultClassLoader);
} else {
previous = null;
}
try {
doRun();
} finally {
if (defaultClassLoader != null) {
setContextClassLoader(previous);
}
}
}
private void doRun() {
synchronized (ClientNotifForwarder.this) {
currentFetchThread = Thread.currentThread();
if (state == STARTING)
if (state == STARTING) {
setState(STARTED);
}
}
if (defaultClassLoader != null) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
Thread.currentThread().
setContextClassLoader(defaultClassLoader);
return null;
}
});
}
NotificationResult nr = null;
if (!shouldStop() && (nr = fetchNotifs()) != null) {
@ -434,8 +497,9 @@ public abstract class ClientNotifForwarder {
// check if an mbean unregistration notif
if (!listenerID.equals(mbeanRemovedNotifID)) {
final ClientListenerInfo li = infoList.get(listenerID);
if (li != null)
listeners.put(listenerID,li);
if (li != null) {
listeners.put(listenerID, li);
}
continue;
}
final Notification notif = tn.getNotification();
@ -799,9 +863,7 @@ public abstract class ClientNotifForwarder {
private long clientSequenceNumber = -1;
private final int maxNotifications;
private final long timeout;
private Integer mbeanRemovedNotifID = null;
private Thread currentFetchThread;
// state

View File

@ -111,6 +111,22 @@ public abstract class MBeanServerAccessController
*/
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.
*/
public ObjectInstance createMBean(String className, ObjectName name)
@ -158,7 +174,7 @@ public abstract class MBeanServerAccessController
MBeanRegistrationException,
MBeanException,
NotCompliantMBeanException {
checkWrite();
checkCreate(className);
SecurityManager sm = System.getSecurityManager();
if (sm == null) {
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.
*/
public ObjectInstance createMBean(String className, ObjectName name,
@ -181,7 +197,7 @@ public abstract class MBeanServerAccessController
MBeanRegistrationException,
MBeanException,
NotCompliantMBeanException {
checkWrite();
checkCreate(className);
SecurityManager sm = System.getSecurityManager();
if (sm == null) {
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.
*/
public ObjectInstance createMBean(String className,
@ -209,7 +225,7 @@ public abstract class MBeanServerAccessController
MBeanException,
NotCompliantMBeanException,
InstanceNotFoundException {
checkWrite();
checkCreate(className);
SecurityManager sm = System.getSecurityManager();
if (sm == null) {
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.
*/
public ObjectInstance createMBean(String className,
@ -237,7 +253,7 @@ public abstract class MBeanServerAccessController
MBeanException,
NotCompliantMBeanException,
InstanceNotFoundException {
checkWrite();
checkCreate(className);
SecurityManager sm = System.getSecurityManager();
if (sm == null) {
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.
*/
public Object instantiate(String className)
throws ReflectionException, MBeanException {
checkWrite();
checkCreate(className);
return getMBeanServer().instantiate(className);
}
/**
* Call <code>checkWrite()</code>, then forward this method to the
* Call <code>checkCreate(className)</code>, then forward this method to the
* wrapped object.
*/
public Object instantiate(String className,
Object params[],
String signature[])
throws ReflectionException, MBeanException {
checkWrite();
checkCreate(className);
return getMBeanServer().instantiate(className, params, signature);
}
/**
* Call <code>checkWrite()</code>, then forward this method to the
* Call <code>checkCreate(className)</code>, then forward this method to the
* wrapped object.
*/
public Object instantiate(String className, ObjectName loaderName)
throws ReflectionException, MBeanException, InstanceNotFoundException {
checkWrite();
checkCreate(className);
return getMBeanServer().instantiate(className, loaderName);
}
/**
* Call <code>checkWrite()</code>, then forward this method to the
* Call <code>checkCreate(className)</code>, then forward this method to the
* wrapped object.
*/
public Object instantiate(String className, ObjectName loaderName,
Object params[], String signature[])
throws ReflectionException, MBeanException, InstanceNotFoundException {
checkWrite();
checkCreate(className);
return getMBeanServer().instantiate(className, loaderName,
params, signature);
}
@ -579,12 +595,12 @@ 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.
*/
public void unregisterMBean(ObjectName name)
throws InstanceNotFoundException, MBeanRegistrationException {
checkWrite();
checkUnregister(name);
getMBeanServer().unregisterMBean(name);
}

View File

@ -31,11 +31,17 @@ import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.security.auth.Subject;
/**
@ -46,7 +52,8 @@ import javax.security.auth.Subject;
* not allowed; in this case the request is not forwarded to the
* wrapped object.</p>
*
* <p>This class implements the {@link #checkRead()} and {@link #checkWrite()}
* <p>This class implements the {@link #checkRead()}, {@link #checkWrite()},
* {@link #checkCreate(String)}, and {@link #checkUnregister(ObjectName)}
* methods based on an access level properties file containing username/access
* level pairs. The set of username/access level pairs is passed either as a
* filename which denotes a properties file on disk, or directly as an instance
@ -56,14 +63,50 @@ import javax.security.auth.Subject;
* has exactly one access level. The same access level can be shared by several
* usernames.</p>
*
* <p>The supported access level values are <i>readonly</i> and
* <i>readwrite</i>.</p>
* <p>The supported access level values are {@code readonly} and
* {@code readwrite}. The {@code readwrite} access level can be
* qualified by one or more <i>clauses</i>, where each clause looks
* like <code>create <i>classNamePattern</i></code> or {@code
* unregister}. For example:</p>
*
* <pre>
* monitorRole readonly
* controlRole readwrite \
* create javax.management.timer.*,javax.management.monitor.* \
* unregister
* </pre>
*
* <p>(The continuation lines with {@code \} come from the parser for
* Properties files.)</p>
*/
public class MBeanServerFileAccessController
extends MBeanServerAccessController {
public static final String READONLY = "readonly";
public static final String READWRITE = "readwrite";
static final String READONLY = "readonly";
static final String READWRITE = "readwrite";
static final String CREATE = "create";
static final String UNREGISTER = "unregister";
private enum AccessType {READ, WRITE, CREATE, UNREGISTER};
private static class Access {
final boolean write;
final String[] createPatterns;
private boolean unregister;
Access(boolean write, boolean unregister, List<String> createPatternList) {
this.write = write;
int npats = (createPatternList == null) ? 0 : createPatternList.size();
if (npats == 0)
this.createPatterns = NO_STRINGS;
else
this.createPatterns = createPatternList.toArray(new String[npats]);
this.unregister = unregister;
}
private final String[] NO_STRINGS = new String[0];
}
/**
* <p>Create a new MBeanServerAccessController that forwards all the
@ -87,8 +130,8 @@ public class MBeanServerFileAccessController
throws IOException {
super();
this.accessFileName = accessFileName;
props = propertiesFromFile(accessFileName);
checkValues(props);
Properties props = propertiesFromFile(accessFileName);
parseProperties(props);
}
/**
@ -123,14 +166,14 @@ public class MBeanServerFileAccessController
* #setMBeanServer} method after doing access checks based on read and
* write permissions.</p>
*
* <p>This instance is initialized from the specified properties instance.
* This constructor makes a copy of the properties instance using its
* <code>clone</code> method and it is the copy that is consulted to check
* the username and access level of an incoming connection. The original
* properties object can be modified without affecting the copy. If the
* {@link #refresh} method is then called, the
* <code>MBeanServerFileAccessController</code> will make a new copy of the
* properties object at that time.</p>
* <p>This instance is initialized from the specified properties
* instance. This constructor makes a copy of the properties
* instance and it is the copy that is consulted to check the
* username and access level of an incoming connection. The
* original properties object can be modified without affecting
* the copy. If the {@link #refresh} method is then called, the
* <code>MBeanServerFileAccessController</code> will make a new
* copy of the properties object at that time.</p>
*
* @param accessFileProps properties list containing the username/access
* level entries.
@ -145,8 +188,7 @@ public class MBeanServerFileAccessController
if (accessFileProps == null)
throw new IllegalArgumentException("Null properties");
originalProps = accessFileProps;
props = (Properties) accessFileProps.clone();
checkValues(props);
parseProperties(accessFileProps);
}
/**
@ -155,14 +197,14 @@ public class MBeanServerFileAccessController
* #setMBeanServer} method after doing access checks based on read and
* write permissions.</p>
*
* <p>This instance is initialized from the specified properties instance.
* This constructor makes a copy of the properties instance using its
* <code>clone</code> method and it is the copy that is consulted to check
* the username and access level of an incoming connection. The original
* properties object can be modified without affecting the copy. If the
* {@link #refresh} method is then called, the
* <code>MBeanServerFileAccessController</code> will make a new copy of the
* properties object at that time.</p>
* <p>This instance is initialized from the specified properties
* instance. This constructor makes a copy of the properties
* instance and it is the copy that is consulted to check the
* username and access level of an incoming connection. The
* original properties object can be modified without affecting
* the copy. If the {@link #refresh} method is then called, the
* <code>MBeanServerFileAccessController</code> will make a new
* copy of the properties object at that time.</p>
*
* @param accessFileProps properties list containing the username/access
* level entries.
@ -184,16 +226,36 @@ public class MBeanServerFileAccessController
* Check if the caller can do read operations. This method does
* nothing if so, otherwise throws SecurityException.
*/
@Override
public void checkRead() {
checkAccessLevel(READONLY);
checkAccess(AccessType.READ, null);
}
/**
* Check if the caller can do write operations. This method does
* nothing if so, otherwise throws SecurityException.
*/
@Override
public void checkWrite() {
checkAccessLevel(READWRITE);
checkAccess(AccessType.WRITE, null);
}
/**
* Check if the caller can create MBeans or instances of the given class.
* This method does nothing if so, otherwise throws SecurityException.
*/
@Override
public void checkCreate(String className) {
checkAccess(AccessType.CREATE, className);
}
/**
* Check if the caller can do unregister operations. This method does
* nothing if so, otherwise throws SecurityException.
*/
@Override
public void checkUnregister(ObjectName name) {
checkAccess(AccessType.UNREGISTER, null);
}
/**
@ -218,14 +280,13 @@ public class MBeanServerFileAccessController
* @exception IllegalArgumentException if any of the supplied access
* level values differs from "readonly" or "readwrite".
*/
public void refresh() throws IOException {
synchronized (props) {
if (accessFileName == null)
props = (Properties) originalProps.clone();
else
props = propertiesFromFile(accessFileName);
checkValues(props);
}
public synchronized void refresh() throws IOException {
Properties props;
if (accessFileName == null)
props = (Properties) originalProps;
else
props = propertiesFromFile(accessFileName);
parseProperties(props);
}
private static Properties propertiesFromFile(String fname)
@ -240,7 +301,7 @@ public class MBeanServerFileAccessController
}
}
private void checkAccessLevel(String accessLevel) {
private synchronized void checkAccess(AccessType requiredAccess, String arg) {
final AccessControlContext acc = AccessController.getContext();
final Subject s =
AccessController.doPrivileged(new PrivilegedAction<Subject>() {
@ -249,39 +310,235 @@ public class MBeanServerFileAccessController
}
});
if (s == null) return; /* security has not been enabled */
final Set<Principal> principals = s.getPrincipals();
for (Principal p : principals) {
String grantedAccessLevel;
synchronized (props) {
grantedAccessLevel = props.getProperty(p.getName());
}
if (grantedAccessLevel != null) {
if (accessLevel.equals(READONLY) &&
(grantedAccessLevel.equals(READONLY) ||
grantedAccessLevel.equals(READWRITE)))
return;
if (accessLevel.equals(READWRITE) &&
grantedAccessLevel.equals(READWRITE))
final Set principals = s.getPrincipals();
String newPropertyValue = null;
for (Iterator i = principals.iterator(); i.hasNext(); ) {
final Principal p = (Principal) i.next();
Access access = accessMap.get(p.getName());
if (access != null) {
boolean ok;
switch (requiredAccess) {
case READ:
ok = true; // all access entries imply read
break;
case WRITE:
ok = access.write;
break;
case UNREGISTER:
ok = access.unregister;
if (!ok && access.write)
newPropertyValue = "unregister";
break;
case CREATE:
ok = checkCreateAccess(access, arg);
if (!ok && access.write)
newPropertyValue = "create " + arg;
break;
default:
throw new AssertionError();
}
if (ok)
return;
}
}
throw new SecurityException("Access denied! Invalid access level for " +
"requested MBeanServer operation.");
SecurityException se = new SecurityException("Access denied! Invalid " +
"access level for requested MBeanServer operation.");
// Add some more information to help people with deployments that
// worked before we required explicit create clauses. We're not giving
// any information to the bad guys, other than that the access control
// is based on a file, which they could have worked out from the stack
// trace anyway.
if (newPropertyValue != null) {
SecurityException se2 = new SecurityException("Access property " +
"for this identity should be similar to: " + READWRITE +
" " + newPropertyValue);
se.initCause(se2);
}
throw se;
}
private void checkValues(Properties props) {
Collection<?> c = props.values();
for (Iterator<?> i = c.iterator(); i.hasNext(); ) {
final String accessLevel = (String) i.next();
if (!accessLevel.equals(READONLY) &&
!accessLevel.equals(READWRITE)) {
throw new IllegalArgumentException(
"Syntax error in access level entry [" + accessLevel + "]");
}
private static boolean checkCreateAccess(Access access, String className) {
for (String classNamePattern : access.createPatterns) {
if (classNameMatch(classNamePattern, className))
return true;
}
return false;
}
private static boolean classNameMatch(String pattern, String className) {
// We studiously avoided regexes when parsing the properties file,
// because that is done whenever the VM is started with the
// appropriate -Dcom.sun.management options, even if nobody ever
// creates an MBean. We don't want to incur the overhead of loading
// all the regex code whenever those options are specified, but if we
// get as far as here then the VM is already running and somebody is
// doing the very unusual operation of remotely creating an MBean.
// Because that operation is so unusual, we don't try to optimize
// by hand-matching or by caching compiled Pattern objects.
StringBuilder sb = new StringBuilder();
StringTokenizer stok = new StringTokenizer(pattern, "*", true);
while (stok.hasMoreTokens()) {
String tok = stok.nextToken();
if (tok.equals("*"))
sb.append("[^.]*");
else
sb.append(Pattern.quote(tok));
}
return className.matches(sb.toString());
}
private void parseProperties(Properties props) {
this.accessMap = new HashMap<String, Access>();
for (Map.Entry<Object, Object> entry : props.entrySet()) {
String identity = (String) entry.getKey();
String accessString = (String) entry.getValue();
Access access = Parser.parseAccess(identity, accessString);
accessMap.put(identity, access);
}
}
private Properties props;
private static class Parser {
private final static int EOS = -1; // pseudo-codepoint "end of string"
static {
assert !Character.isWhitespace(EOS);
}
private final String identity; // just for better error messages
private final String s; // the string we're parsing
private final int len; // s.length()
private int i;
private int c;
// At any point, either c is s.codePointAt(i), or i == len and
// c is EOS. We use int rather than char because it is conceivable
// (if unlikely) that a classname in a create clause might contain
// "supplementary characters", the ones that don't fit in the original
// 16 bits for Unicode.
private Parser(String identity, String s) {
this.identity = identity;
this.s = s;
this.len = s.length();
this.i = 0;
if (i < len)
this.c = s.codePointAt(i);
else
this.c = EOS;
}
static Access parseAccess(String identity, String s) {
return new Parser(identity, s).parseAccess();
}
private Access parseAccess() {
skipSpace();
String type = parseWord();
Access access;
if (type.equals(READONLY))
access = new Access(false, false, null);
else if (type.equals(READWRITE))
access = parseReadWrite();
else {
throw syntax("Expected " + READONLY + " or " + READWRITE +
": " + type);
}
if (c != EOS)
throw syntax("Extra text at end of line");
return access;
}
private Access parseReadWrite() {
List<String> createClasses = new ArrayList<String>();
boolean unregister = false;
while (true) {
skipSpace();
if (c == EOS)
break;
String type = parseWord();
if (type.equals(UNREGISTER))
unregister = true;
else if (type.equals(CREATE))
parseCreate(createClasses);
else
throw syntax("Unrecognized keyword " + type);
}
return new Access(true, unregister, createClasses);
}
private void parseCreate(List<String> createClasses) {
while (true) {
skipSpace();
createClasses.add(parseClassName());
skipSpace();
if (c == ',')
next();
else
break;
}
}
private String parseClassName() {
// We don't check that classname components begin with suitable
// characters (so we accept 1.2.3 for example). This means that
// there are only two states, which we can call dotOK and !dotOK
// according as a dot (.) is legal or not. Initially we're in
// !dotOK since a classname can't start with a dot; after a dot
// we're in !dotOK again; and after any other characters we're in
// dotOK. The classname is only accepted if we end in dotOK,
// so we reject an empty name or a name that ends with a dot.
final int start = i;
boolean dotOK = false;
while (true) {
if (c == '.') {
if (!dotOK)
throw syntax("Bad . in class name");
dotOK = false;
} else if (c == '*' || Character.isJavaIdentifierPart(c))
dotOK = true;
else
break;
next();
}
String className = s.substring(start, i);
if (!dotOK)
throw syntax("Bad class name " + className);
return className;
}
// Advance c and i to the next character, unless already at EOS.
private void next() {
if (c != EOS) {
i += Character.charCount(c);
if (i < len)
c = s.codePointAt(i);
else
c = EOS;
}
}
private void skipSpace() {
while (Character.isWhitespace(c))
next();
}
private String parseWord() {
skipSpace();
if (c == EOS)
throw syntax("Expected word at end of line");
final int start = i;
while (c != EOS && !Character.isWhitespace(c))
next();
String word = s.substring(start, i);
skipSpace();
return word;
}
private IllegalArgumentException syntax(String msg) {
return new IllegalArgumentException(
msg + " [" + identity + " " + s + "]");
}
}
private Map<String, Access> accessMap;
private Properties originalProps;
private String accessFileName;
}

View File

@ -302,7 +302,16 @@ final public class LdapCtx extends ComponentDirContext
schemaTrees = new Hashtable(11, 0.75f);
initEnv();
connect(false);
try {
connect(false);
} catch (NamingException e) {
try {
close();
} catch (Exception e2) {
// Nothing
}
throw e;
}
}
LdapCtx(LdapCtx existing, String newDN) throws NamingException {

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.
*
* 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 {
// System property to control whether classes may be loaded from an
// arbitrary URL code base.
private static final String TRUST_URL_CODEBASE_PROPERTY =
"com.sun.jndi.ldap.object.trustURLCodebase";
// Determine whether classes may be loaded from an arbitrary URL code base.
private static final String trustURLCodebase =
AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
return System.getProperty(TRUST_URL_CODEBASE_PROPERTY,
"false");
}
}
);
VersionHelper12() {} // Disallow external from creating one of these.
ClassLoader getURLClassLoader(String[] url)
throws MalformedURLException {
ClassLoader parent = getContextClassLoader();
if (url != null) {
/*
* Classes may only be loaded from an arbitrary URL code base when
* the system property com.sun.jndi.ldap.object.trustURLCodebase
* has been set to "true".
*/
if (url != null && "true".equalsIgnoreCase(trustURLCodebase)) {
return URLClassLoader.newInstance(getUrlArray(url), parent);
} else {
return parent;

View File

@ -37,6 +37,8 @@ import java.awt.geom.Rectangle2D;
import java.awt.peer.FontPeer;
import java.io.*;
import java.lang.ref.SoftReference;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.text.AttributedCharacterIterator.Attribute;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
@ -51,6 +53,7 @@ import sun.font.AttributeMap;
import sun.font.AttributeValues;
import sun.font.EAttribute;
import sun.font.CompositeFont;
import sun.font.CreatedFontTracker;
import sun.font.Font2D;
import sun.font.Font2DHandle;
import sun.font.FontManager;
@ -575,14 +578,16 @@ public class Font implements java.io.Serializable
}
/* used to implement Font.createFont */
private Font(File fontFile, int fontFormat, boolean isCopy)
private Font(File fontFile, int fontFormat,
boolean isCopy, CreatedFontTracker tracker)
throws FontFormatException {
this.createdFont = true;
/* Font2D instances created by this method track their font file
* so that when the Font2D is GC'd it can also remove the file.
*/
this.font2DHandle =
FontManager.createFont2D(fontFile, fontFormat, isCopy).handle;
FontManager.createFont2D(fontFile, fontFormat,
isCopy, tracker).handle;
this.name = this.font2DHandle.font2D.getFontName(Locale.getDefault());
this.style = Font.PLAIN;
this.size = 1;
@ -787,6 +792,29 @@ public class Font implements java.io.Serializable
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
* and input data. The new <code>Font</code> is
@ -822,58 +850,96 @@ public class Font implements java.io.Serializable
fontFormat != Font.TYPE1_FONT) {
throw new IllegalArgumentException ("font format not recognized");
}
final InputStream fStream = fontStream;
Object ret = java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
File tFile = null;
FileOutputStream outStream = null;
try {
tFile = File.createTempFile("+~JF", ".tmp", null);
/* Temp file deleted by font shutdown hook */
BufferedInputStream inStream =
new BufferedInputStream(fStream);
outStream = new FileOutputStream(tFile);
int bytesRead = 0;
int bufSize = 8192;
byte [] buf = new byte[bufSize];
while (bytesRead != -1) {
try {
bytesRead = inStream.read(buf, 0, bufSize);
} catch (Throwable t) {
throw new IOException();
}
if (bytesRead != -1) {
outStream.write(buf, 0, bytesRead);
}
}
/* don't close the input stream */
outStream.close();
} catch (IOException e) {
if (outStream != null) {
try {
outStream.close();
} catch (Exception e1) {
}
}
if (tFile != null) {
try {
tFile.delete();
} catch (Exception e2) {
}
}
return e;
}
return tFile;
}
});
boolean copiedFontData = false;
if (ret instanceof File) {
return new Font((File)ret, fontFormat, true);
} else if (ret instanceof IOException) {
throw (IOException)ret;
} else {
throw new FontFormatException("Couldn't access font stream");
try {
final File tFile = AccessController.doPrivileged(
new PrivilegedExceptionAction<File>() {
public File run() throws IOException {
return File.createTempFile("+~JF", ".tmp", null);
}
}
);
int totalSize = 0;
CreatedFontTracker tracker = null;
try {
final OutputStream outStream =
AccessController.doPrivileged(
new PrivilegedExceptionAction<OutputStream>() {
public OutputStream run() throws IOException {
return new FileOutputStream(tFile);
}
}
);
if (!hasTempPermission()) {
tracker = CreatedFontTracker.getTracker();
}
try {
byte[] buf = new byte[8192];
for (;;) {
int bytesRead = fontStream.read(buf);
if (bytesRead < 0) {
break;
}
if (tracker != null) {
if (totalSize+bytesRead > tracker.MAX_FILE_SIZE) {
throw new IOException("File too big.");
}
if (totalSize+tracker.getNumBytes() >
tracker.MAX_TOTAL_BYTES)
{
throw new IOException("Total files too big.");
}
totalSize += bytesRead;
tracker.addBytes(bytesRead);
}
outStream.write(buf, 0, bytesRead);
}
/* don't close the input stream */
} finally {
outStream.close();
}
/* After all references to a Font2D are dropped, the file
* will be removed. To support long-lived AppContexts,
* we need to then decrement the byte count by the size
* of the file.
* If the data isn't a valid font, the implementation will
* delete the tmp file and decrement the byte count
* in the tracker object before returning from the
* constructor, so we can set 'copiedFontData' to true here
* without waiting for the results of that constructor.
*/
copiedFontData = true;
Font font = new Font(tFile, fontFormat, true, tracker);
return font;
} finally {
if (!copiedFontData) {
if (tracker != null) {
tracker.subBytes(totalSize);
}
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>() {
public Void run() {
tFile.delete();
return null;
}
}
);
}
}
} catch (Throwable t) {
if (t instanceof FontFormatException) {
throw (FontFormatException)t;
}
if (t instanceof IOException) {
throw (IOException)t;
}
Throwable cause = t.getCause();
if (cause instanceof FontFormatException) {
throw (FontFormatException)cause;
}
throw new IOException("Problem reading font data.");
}
}
@ -913,6 +979,9 @@ public class Font implements java.io.Serializable
*/
public static Font createFont(int fontFormat, File fontFile)
throws java.awt.FontFormatException, java.io.IOException {
fontFile = new File(fontFile.getPath());
if (fontFormat != Font.TRUETYPE_FONT &&
fontFormat != Font.TYPE1_FONT) {
throw new IllegalArgumentException ("font format not recognized");
@ -926,7 +995,7 @@ public class Font implements java.io.Serializable
if (!fontFile.canRead()) {
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;
/**
* Constructs a <code>NoSuchFieldException</code> with no detail message.
* Constructs a <code>NoSuchFieldError</code> with no detail message.
*/
public NoSuchFieldError() {
super();
}
/**
* Constructs a <code>NoSuchFieldException</code> with the specified
* Constructs a <code>NoSuchFieldError</code> with the specified
* 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))
throw new IndexOutOfBoundsException();
int sublen = end - start;
int off = offset + ((pos + start) << $LG_BYTES_PER_VALUE$);
assert (off >= 0);
return new ByteBufferAsCharBuffer$RW$$BO$(bb, -1, 0, sublen, sublen, off);
return new ByteBufferAsCharBuffer$RW$$BO$(bb,
-1,
pos + start,
pos + end,
capacity(),
offset);
}
#end[char]

View File

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

View File

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

View File

@ -102,10 +102,12 @@ class StringCharBuffer // package-private
public final CharBuffer subSequence(int start, int end) {
try {
int pos = position();
return new StringCharBuffer(str, -1,
return new StringCharBuffer(str,
-1,
pos + checkIndex(start, pos),
pos + checkIndex(end, pos),
remaining(), offset);
capacity(),
offset);
} catch (IllegalArgumentException x) {
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
* 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
* are permitted by the security manager's {@link SecurityManager#checkConnect
* checkConnect} method. The overhead of this security check can be avoided

View File

@ -494,7 +494,7 @@ public abstract class Path
* @throws IOException
* if an I/O error occurs
* @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>
* or its {@link SecurityManager#checkWrite(String) checkWrite}
* method denies write access to the path of the symbolic link.
@ -531,7 +531,7 @@ public abstract class Path
* @throws IOException
* if an I/O error occurs
* @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>
* or its {@link SecurityManager#checkWrite(String) checkWrite}
* method denies write access to both this path and the path of the
@ -560,7 +560,7 @@ public abstract class Path
* @throws IOException
* if an I/O error occurs
* @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
* granted with the "{@code readlink}" action to read the link.
*/
@ -615,7 +615,7 @@ public abstract class Path
* obtained
*
* @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
* throws a security exception.
*/
@ -636,7 +636,7 @@ public abstract class Path
* @throws IOError
* if an I/O error occurs
* @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)
* checkPropertyAccess} method is invoked to check access to the
* system property {@code user.dir}
@ -677,7 +677,7 @@ public abstract class Path
* @throws IOException
* if the file does not exist or an I/O error occurs
* @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}
* method is invoked to check read access to the file, and where
* this path is not absolute, its {@link SecurityManager#checkPropertyAccess(String)

View File

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

View File

@ -425,7 +425,7 @@ public final class AccessController {
* Performs the specified <code>PrivilegedExceptionAction</code> with
* privileges enabled and restricted by the specified
* <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
* specified <code>AccessControlContext</code>.
* <p>

View File

@ -102,7 +102,7 @@ public abstract class AlgorithmParametersSpi {
* parameters should be returned in an instance of the
* <code>DSAParameterSpec</code> class.
*
* @param paramSpec the the specification class in which
* @param paramSpec the specification class in which
* the parameters should be returned.
*
* @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
* <code>PrivilegedActionException</code>).
*

View File

@ -501,7 +501,7 @@ public final class Security {
* <li> <i>&lt;crypto_service>.&lt;algorithm_or_type>
* &lt;attribute_name>:&lt attribute_value></i>
* <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>.
* <p> A provider satisfies this selection criterion iff the
* 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>Setting of the security property with the specified key</td>
* <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
* set a rogue provider that steals confidential information such
* as cryptographic private keys. In addition, malicious code with

View File

@ -316,7 +316,7 @@ public abstract class SignatureSpi {
* overridden by a provider
*
* @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
*/
protected void engineSetParameter(AlgorithmParameterSpec params)

View File

@ -460,7 +460,7 @@ public class CertificateFactory {
* {@link java.io.InputStream#reset() reset}, this method will
* consume the entire input stream. Otherwise, each call to this
* 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
* 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

View File

@ -88,7 +88,7 @@ public abstract class CertificateFactorySpi {
* {@link java.io.InputStream#reset() reset}, this method will
* consume the entire input stream. Otherwise, each call to this
* 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
* 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
@ -261,7 +261,7 @@ public abstract class CertificateFactorySpi {
* {@link java.io.InputStream#reset() reset}, this method will
* consume the entire input stream. Otherwise, each call to this
* 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
* 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

View File

@ -41,9 +41,14 @@ package java.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PermissionCollection;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.text.DateFormat;
import java.text.DateFormatSymbols;
import sun.util.BuddhistCalendar;
@ -2628,6 +2633,18 @@ 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).
*/
@ -2657,17 +2674,30 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
serialVersionOnStream = currentSerialVersion;
// If there's a ZoneInfo object, use it for zone.
ZoneInfo zi = null;
try {
ZoneInfo zi = (ZoneInfo) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws Exception {
return input.readObject();
}
});
if (zi != null) {
zone = zi;
zi = AccessController.doPrivileged(
new PrivilegedExceptionAction<ZoneInfo>() {
public ZoneInfo run() throws Exception {
return (ZoneInfo) input.readObject();
}
},
CalendarAccessControlContext.INSTANCE);
} catch (PrivilegedActionException pae) {
Exception e = pae.getException();
if (!(e instanceof OptionalDataException)) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else if (e instanceof IOException) {
throw (IOException) e;
} else if (e instanceof ClassNotFoundException) {
throw (ClassNotFoundException) e;
}
throw new RuntimeException(e);
}
} catch (Exception e) {
}
if (zi != null) {
zone = zi;
}
// If the deserialized object has a SimpleTimeZone, try to
@ -2676,9 +2706,9 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
// implementation as much as possible.
if (zone instanceof SimpleTimeZone) {
String id = zone.getID();
TimeZone zi = TimeZone.getTimeZone(id);
if (zi != null && zi.hasSameRules(zone) && zi.getID().equals(id)) {
zone = zi;
TimeZone tz = TimeZone.getTimeZone(id);
if (tz != null && tz.hasSameRules(zone) && tz.getID().equals(id)) {
zone = tz;
}
}
}

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_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() {}
}

View File

@ -40,6 +40,7 @@ class ZipEntry implements ZipConstants, Cloneable {
long size = -1; // uncompressed size of entry data
long csize = -1; // compressed size of entry data
int method = -1; // compression method
int flag = 0; // general purpose flag
byte[] extra; // optional extra field data for entry
String comment; // optional comment string for entry
@ -53,13 +54,6 @@ class ZipEntry implements ZipConstants, Cloneable {
*/
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.
*
@ -90,28 +84,15 @@ class ZipEntry implements ZipConstants, Cloneable {
size = e.size;
csize = e.csize;
method = e.method;
flag = e.flag;
extra = e.extra;
comment = e.comment;
}
/*
* Creates a new zip entry for the given name with fields initialized
* from the specified jzentry data.
* Creates a new un-initialized zip entry
*/
ZipEntry(String name, long jzentry) {
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);
}
ZipEntry() {}
/**
* Returns the name of the entry.
@ -258,16 +239,16 @@ class ZipEntry implements ZipConstants, Cloneable {
/**
* 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
* @exception IllegalArgumentException if the length of the specified
* comment string is greater than 0xFFFF bytes
*
* @see #getComment()
*/
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;
}

View File

@ -29,9 +29,11 @@ import java.io.InputStream;
import java.io.IOException;
import java.io.EOFException;
import java.io.File;
import java.nio.charset.Charset;
import java.util.Vector;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import static java.util.zip.ZipConstants64.*;
/**
* 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.
*
* <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.
* <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.
*
* <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
* @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)
*/
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
* 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 mode the mode in which the file is to be opened
* @throws ZipException if a ZIP format error has occurred
@ -115,6 +123,59 @@ class ZipFile implements ZipConstants {
* @since 1.3
*/
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) ||
((mode & ~(OPEN_READ | OPEN_DELETE)) != 0)) {
throw new IllegalArgumentException("Illegal mode: 0x"+
@ -128,24 +189,61 @@ class ZipFile implements ZipConstants {
sm.checkDelete(name);
}
}
if (charset == null)
throw new NullPointerException("charset is null");
this.zc = ZipCoder.get(charset);
jzfile = open(name, mode, file.lastModified());
this.name = name;
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.
* @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
*
* @since 1.7
*/
public ZipFile(File file) throws ZipException, IOException {
this(file, OPEN_READ);
public ZipFile(File file, Charset charset) throws IOException
{
this(file, OPEN_READ, charset);
}
/**
@ -163,9 +261,9 @@ class ZipFile implements ZipConstants {
long jzentry = 0;
synchronized (this) {
ensureOpen();
jzentry = getEntry(jzfile, name, true);
jzentry = getEntry(jzfile, zc.getBytes(name), true);
if (jzentry != 0) {
ZipEntry ze = new ZipEntry(name, jzentry);
ZipEntry ze = getZipEntry(name, jzentry);
freeEntry(jzfile, jzentry);
return ze;
}
@ -173,7 +271,7 @@ class ZipFile implements ZipConstants {
return null;
}
private static native long getEntry(long jzfile, String name,
private static native long getEntry(long jzfile, byte[] name,
boolean addSlash);
// freeEntry releases the C jzentry struct.
@ -194,36 +292,30 @@ class ZipFile implements ZipConstants {
* @throws IllegalStateException if the zip file has been closed
*/
public InputStream getInputStream(ZipEntry entry) throws IOException {
return getInputStream(entry.name);
}
/**
* 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");
if (entry == null) {
throw new NullPointerException("entry");
}
long jzentry = 0;
ZipFileInputStream in = null;
synchronized (this) {
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) {
return null;
}
in = new ZipFileInputStream(jzentry);
}
final ZipFileInputStream zfin = in;
switch (getMethod(jzentry)) {
switch (getEntryMethod(jzentry)) {
case STORED:
return zfin;
case DEFLATED:
// 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 <= 0) size = 4096;
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
* a new one.
@ -343,7 +433,7 @@ class ZipFile implements ZipConstants {
",\n message = " + message
);
}
ZipEntry ze = new ZipEntry(jzentry);
ZipEntry ze = getZipEntry(null, jzentry);
freeEntry(jzfile, jzentry);
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);
/**
@ -443,8 +565,8 @@ class ZipFile implements ZipConstants {
ZipFileInputStream(long jzentry) {
pos = 0;
rem = getCSize(jzentry);
size = getSize(jzentry);
rem = getEntryCSize(jzentry);
size = getEntrySize(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,
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);
}

View File

@ -29,6 +29,7 @@ import java.io.InputStream;
import java.io.IOException;
import java.io.EOFException;
import java.io.PushbackInputStream;
import java.nio.charset.Charset;
import static java.util.zip.ZipConstants64.*;
/**
@ -54,6 +55,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
// one entry
private boolean entryEOF = false;
private ZipCoder zc;
/**
* 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.
*
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
* decode the entry names.
*
* @param in the actual input stream
*/
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);
usesDefaultInflater = true;
if(in == 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
* @return the actual number of bytes read, or -1 if the end of the
* entry is reached
* @exception NullPointerException If <code>b</code> is <code>null</code>.
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
* @exception NullPointerException if <code>b</code> is <code>null</code>.
* @exception IndexOutOfBoundsException if <code>off</code> is negative,
* <code>len</code> is negative, or <code>len</code> is greater than
* <code>b.length - off</code>
* @exception ZipException if a ZIP file error has occurred
@ -252,6 +280,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
if (get32(tmpbuf, 0) != LOCSIG) {
return null;
}
// get flag first, we need check EFS.
flag = get16(tmpbuf, LOCFLG);
// get the entry name and create the ZipEntry first
int len = get16(tmpbuf, LOCNAM);
int blen = b.length;
@ -262,9 +292,11 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
b = new byte[blen];
}
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
flag = get16(tmpbuf, LOCFLG);
if ((flag & 1) == 1) {
throw new ZipException("encrypted ZIP entry not supported");
}
@ -313,71 +345,6 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
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
* entry name.

View File

@ -27,6 +27,7 @@ package java.util.zip;
import java.io.OutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Vector;
import java.util.HashSet;
import static java.util.zip.ZipConstants64.*;
@ -44,19 +45,9 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
private static class XEntry {
public final ZipEntry entry;
public final long offset;
public final int flag;
public XEntry(ZipEntry entry, long offset) {
this.entry = entry;
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 long written = 0;
private long locoff = 0;
private String comment;
private byte[] comment;
private int method = DEFLATED;
private boolean finished;
private boolean closed = false;
private final ZipCoder zc;
private static int version(ZipEntry e) throws ZipException {
switch (e.method) {
case DEFLATED: return 20;
@ -100,10 +93,31 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
/**
* 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
*/
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));
if (charset == null)
throw new NullPointerException("charset is null");
this.zc = ZipCoder.get(charset);
usesDefaultDeflater = true;
}
@ -114,11 +128,11 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
* ZIP file comment is greater than 0xFFFF bytes
*/
public void setComment(String comment) {
if (comment != null && comment.length() > 0xffff/3
&& getUTF8Length(comment) > 0xffff) {
throw new IllegalArgumentException("ZIP file comment too long.");
if (comment != null) {
this.comment = zc.getBytes(comment);
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) {
e.method = method; // use default method
}
// store size, compressed size, and crc-32 in LOC header
e.flag = 0;
switch (e.method) {
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;
case STORED:
// 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)) {
throw new ZipException("duplicate entry: " + e.name);
}
if (zc.isUTF8())
e.flag |= EFS;
current = new XEntry(e, written);
xentries.add(current);
writeLOC(current);
@ -213,7 +236,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
while (!def.finished()) {
deflate();
}
if ((current.flag & 8) == 0) {
if ((e.flag & 8) == 0) {
// verify size, compressed size, and crc-32 settings
if (e.size != def.getBytesRead()) {
throw new ZipException(
@ -343,11 +366,11 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
*/
private void writeLOC(XEntry xentry) throws IOException {
ZipEntry e = xentry.entry;
int flag = xentry.flag;
int flag = e.flag;
int elen = (e.extra != null) ? e.extra.length : 0;
boolean hasZip64 = false;
writeInt(LOCSIG); // LOC header signature
writeInt(LOCSIG); // LOC header signature
if ((flag & 8) == 8) {
writeShort(version(e)); // version needed to extract
@ -380,7 +403,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
writeInt(e.size); // uncompressed size
}
}
byte[] nameBytes = getUTF8Bytes(e.name);
byte[] nameBytes = zc.getBytes(e.name);
writeShort(nameBytes.length);
writeShort(elen);
writeBytes(nameBytes, 0, nameBytes.length);
@ -417,7 +440,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
*/
private void writeCEN(XEntry xentry) throws IOException {
ZipEntry e = xentry.entry;
int flag = xentry.flag;
int flag = e.flag;
int version = version(e);
long csize = e.csize;
@ -454,7 +477,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
writeInt(e.crc); // crc-32
writeInt(csize); // compressed size
writeInt(size); // uncompressed size
byte[] nameBytes = getUTF8Bytes(e.name);
byte[] nameBytes = zc.getBytes(e.name);
writeShort(nameBytes.length);
if (hasZip64) {
// + headid(2) + datasize(2)
@ -464,8 +487,8 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
}
byte[] commentBytes;
if (e.comment != null) {
commentBytes = getUTF8Bytes(e.comment);
writeShort(commentBytes.length);
commentBytes = zc.getBytes(e.comment);
writeShort(Math.min(commentBytes.length, 0xffff));
} else {
commentBytes = null;
writeShort(0);
@ -489,7 +512,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
writeBytes(e.extra, 0, e.extra.length);
}
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(xoff); // offset of central directory
if (comment != null) { // zip file comment
byte[] b = getUTF8Bytes(comment);
writeShort(b.length);
writeBytes(b, 0, b.length);
writeShort(comment.length);
writeBytes(comment, 0, comment.length);
} else {
writeShort(0);
}
@ -594,60 +616,4 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
super.out.write(b, off, 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">
PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
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>
<li><a href="http://www.isi.edu/in-notes/rfc1950.txt">
ZLIB Compressed Data Format Specification version 3.3</a>

View File

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

View File

@ -481,7 +481,7 @@ public class GaugeMonitor extends Monitor implements GaugeMonitorMBean {
*/
@Override
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.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@ -163,7 +166,10 @@ public abstract class Monitor
/**
* 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.
@ -172,15 +178,21 @@ public abstract class Monitor
Executors.newSingleThreadScheduledExecutor(
new DaemonThreadFactory("Scheduler"));
/**
* Map containing the thread pool executor per thread group.
*/
private static final Map<ThreadPoolExecutor, Void> executors =
new WeakHashMap<ThreadPoolExecutor, Void>();
/**
* Lock for executors map.
*/
private static final Object executorsLock = new Object();
/**
* Maximum Pool Size
*/
private static final int maximumPoolSize;
/**
* Executor Service.
*/
private static final ThreadPoolExecutor executor;
static {
final String maximumPoolSizeSysProp = "jmx.x.monitor.maximum.pool.size";
final String maximumPoolSizeStr = AccessController.doPrivileged(
@ -210,21 +222,8 @@ public abstract class Monitor
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.
*/
@ -233,7 +232,7 @@ public abstract class Monitor
/**
* Scheduler task to be executed by the Scheduler Service.
*/
private final SchedulerTask schedulerTask = new SchedulerTask(monitorTask);
private final SchedulerTask schedulerTask = new SchedulerTask();
/**
* ScheduledFuture associated to the current scheduler task.
@ -719,6 +718,7 @@ public abstract class Monitor
// Start the scheduler.
//
cleanupFutures();
schedulerTask.setMonitorTask(new MonitorTask());
schedulerFuture = scheduler.schedule(schedulerTask,
getGranularityPeriod(),
TimeUnit.MILLISECONDS);
@ -748,7 +748,7 @@ public abstract class Monitor
// Reset the AccessControlContext.
//
acc = null;
acc = noPermissionsACC;
// Reset the complex type attribute information
// such that it is recalculated again.
@ -1467,7 +1467,7 @@ public abstract class Monitor
*/
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;
}
@ -1487,7 +1496,7 @@ public abstract class Monitor
public void run() {
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 ThreadPoolExecutor executor;
/*
* ------------------------------------------
* CONSTRUCTORS
@ -1507,6 +1518,38 @@ public abstract class Monitor
*/
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() {
final ScheduledFuture<?> sf;
final AccessControlContext ac;
synchronized (Monitor.this) {
sf = Monitor.this.schedulerFuture;
ac = Monitor.this.acc;
}
AccessController.doPrivileged(new PrivilegedAction<Void>() {
PrivilegedAction<Void> action = new PrivilegedAction<Void>() {
public Void run() {
if (Monitor.this.isActive()) {
final int an[] = alreadyNotifieds;
@ -1533,7 +1582,11 @@ public abstract class Monitor
}
return null;
}
}, Monitor.this.acc);
};
if (ac == null) {
throw new SecurityException("AccessControlContext cannot be null");
}
AccessController.doPrivileged(action, ac);
synchronized (Monitor.this) {
if (Monitor.this.isActive() &&
Monitor.this.schedulerFuture == sf) {
@ -1573,6 +1626,15 @@ public abstract class Monitor
namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
}
public DaemonThreadFactory(String poolName, ThreadGroup threadGroup) {
group = threadGroup;
namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
}
public ThreadGroup getThreadGroup() {
return group;
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group,
r,

View File

@ -184,6 +184,7 @@ public class StringMonitor extends Monitor implements StringMonitorMBean {
* @return The derived gauge of the specified object.
*
*/
@Override
public synchronized String getDerivedGauge(ObjectName 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.
*
*/
@Override
public synchronized long getDerivedGaugeTimeStamp(ObjectName 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 string monitor.
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return notifsInfo;
return notifsInfo.clone();
}
/*

View File

@ -123,8 +123,10 @@ public class MediaSize extends Size2DSyntax implements Attribute {
if (x > y) {
throw new IllegalArgumentException("X dimension > Y dimension");
}
mediaName = media;
mediaMap.put(mediaName, this);
if (media != null && mediaMap.get(media) == null) {
mediaName = media;
mediaMap.put(mediaName, this);
}
sizeVector.add(this);
}
@ -147,8 +149,10 @@ public class MediaSize extends Size2DSyntax implements Attribute {
if (x > y) {
throw new IllegalArgumentException("X dimension > Y dimension");
}
mediaName = media;
mediaMap.put(mediaName, this);
if (media != null && mediaMap.get(media) == null) {
mediaName = media;
mediaMap.put(mediaName, this);
}
sizeVector.add(this);
}

View File

@ -585,9 +585,16 @@ public class GifImageDecoder extends ImageDecoder {
System.out.print("Reading a " + width + " by " + height + " " +
(interlace ? "" : "non-") + "interlaced image...");
}
int initCodeSize = ExtractByte(block, 9);
if (initCodeSize >= 12) {
if (verbose) {
System.out.println("Invalid initial code size: " +
initCodeSize);
}
return false;
}
boolean ret = parseImage(x, y, width, height,
interlace, ExtractByte(block, 9),
interlace, initCodeSize,
block, rasline, model);
if (!ret) {

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.
*
* 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;
}
void setFileToRemove(File file) {
void setFileToRemove(File file, CreatedFontTracker tracker) {
Disposer.addObjectRecord(this,
new CreatedFontFileDisposerRecord(file));
new CreatedFontFileDisposerRecord(file, tracker));
}
/* This is called when a font scaler is determined to
@ -246,12 +246,16 @@ public abstract class FileFont extends PhysicalFont {
return getScaler().getUnitsPerEm();
}
private static class CreatedFontFileDisposerRecord implements DisposerRecord {
private static class CreatedFontFileDisposerRecord
implements DisposerRecord {
File fontFile = null;
CreatedFontTracker tracker;
private CreatedFontFileDisposerRecord(File file) {
private CreatedFontFileDisposerRecord(File file,
CreatedFontTracker tracker) {
fontFile = file;
this.tracker = tracker;
}
public void dispose() {
@ -260,6 +264,9 @@ public abstract class FileFont extends PhysicalFont {
public Object run() {
if (fontFile != null) {
try {
if (tracker != null) {
tracker.subBytes((int)fontFile.length());
}
/* REMIND: is it possible that the file is
* still open? It will be closed when the
* font2D is disposed but could this code

View File

@ -2357,19 +2357,21 @@ public final class FontManager {
static Vector<File> tmpFontFiles = null;
public static Font2D createFont2D(File fontFile, int fontFormat,
boolean isCopy)
boolean isCopy,
CreatedFontTracker tracker)
throws FontFormatException {
String fontFilePath = fontFile.getPath();
FileFont font2D = null;
final File fFile = fontFile;
final CreatedFontTracker _tracker = tracker;
try {
switch (fontFormat) {
case Font.TRUETYPE_FONT:
font2D = new TrueTypeFont(fontFilePath, null, 0, true);
break;
case Font.TYPE1_FONT:
font2D = new Type1Font(fontFilePath, null);
font2D = new Type1Font(fontFilePath, null, isCopy);
break;
default:
throw new FontFormatException("Unrecognised Font Format");
@ -2379,6 +2381,9 @@ public final class FontManager {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
if (_tracker != null) {
_tracker.subBytes((int)fFile.length());
}
fFile.delete();
return null;
}
@ -2387,7 +2392,7 @@ public final class FontManager {
throw(e);
}
if (isCopy) {
font2D.setFileToRemove(fontFile);
font2D.setFileToRemove(fontFile, tracker);
synchronized (FontManager.class) {
if (tmpFontFiles == null) {

View File

@ -175,8 +175,17 @@ public class TrueTypeFont extends FileFont {
super(platname, nativeNames);
useJavaRasterizer = javaRasterizer;
fontRank = Font2D.TTF_RANK;
verify();
init(fIndex);
try {
verify();
init(fIndex);
} catch (Throwable t) {
close();
if (t instanceof FontFormatException) {
throw (FontFormatException)t;
} else {
throw new FontFormatException("Unexpected runtime exception.");
}
}
Disposer.addObjectRecord(this, disposerRecord);
}

View File

@ -39,6 +39,7 @@ import java.nio.BufferUnderflowException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import sun.java2d.Disposer;
import sun.java2d.DisposerRecord;
import java.util.HashSet;
import java.util.HashMap;
import java.awt.Font;
@ -76,6 +77,27 @@ import java.awt.Font;
*/
public class Type1Font extends FileFont {
private static class T1DisposerRecord implements DisposerRecord {
String fileName = null;
T1DisposerRecord(String name) {
fileName = name;
}
public synchronized void dispose() {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
if (fileName != null) {
(new java.io.File(fileName)).delete();
}
return null;
}
});
}
}
WeakReference bufferRef = new WeakReference(null);
private String psName = null;
@ -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
* - reads the names (full, family).
@ -131,12 +164,25 @@ public class Type1Font extends FileFont {
* @throws FontFormatException - if the font can't be opened
* or fails verification, or there's no usable cmap
*/
public Type1Font(String platname, Object nativeNames)
public Type1Font(String platname, Object nativeNames, boolean createdCopy)
throws FontFormatException {
super(platname, nativeNames);
fontRank = Font2D.TYPE1_RANK;
checkedNatives = true;
verify();
try {
verify();
} catch (Throwable t) {
if (createdCopy) {
T1DisposerRecord ref = new T1DisposerRecord(platname);
Disposer.addObjectRecord(bufferRef, ref);
bufferRef = null;
}
if (t instanceof FontFormatException) {
throw (FontFormatException)t;
} else {
throw new FontFormatException("Unexpected runtime exception.");
}
}
}
private synchronized ByteBuffer getBuffer() throws FontFormatException {

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;
do {
startLine = readLine();
if (startLine == null) {
return;
}
/* skip blank lines */
} while (startLine == null ? false : startLine.equals (""));
}

View File

@ -433,6 +433,7 @@ class ServerImpl implements TimeSource {
rawin = sslStreams.getInputStream();
rawout = sslStreams.getOutputStream();
engine = sslStreams.getSSLEngine();
connection.sslStreams = sslStreams;
} else {
rawin = new BufferedInputStream(
new Request.ReadStream (
@ -442,6 +443,8 @@ class ServerImpl implements TimeSource {
ServerImpl.this, chan
);
}
connection.raw = rawin;
connection.rawout = rawout;
}
Request req = new Request (rawin, rawout);
requestLine = req.requestLine();

View File

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

View File

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

View File

@ -60,23 +60,12 @@ abstract class FileLockTable {
*/
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.
* <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.
@ -195,7 +184,7 @@ class SharedFileLockTable extends FileLockTable {
FileLockReference ref = list.get(index);
FileLock lock = ref.get();
if (lock == fl) {
assert (lock != null) && (lock.channel() == channel);
assert (lock != null) && (lock.acquiredBy() == channel);
ref.clear();
list.remove(index);
break;
@ -206,7 +195,8 @@ class SharedFileLockTable extends FileLockTable {
}
@Override
public void removeAll(Releaser releaser) throws IOException {
public List<FileLock> removeAll() {
List<FileLock> result = new ArrayList<FileLock>();
List<FileLockReference> list = lockMap.get(fileKey);
if (list != null) {
synchronized (list) {
@ -216,13 +206,13 @@ class SharedFileLockTable extends FileLockTable {
FileLock lock = ref.get();
// remove locks obtained by this channel
if (lock != null && lock.channel() == channel) {
// invoke the releaser to invalidate/release the lock
releaser.release(lock);
if (lock != null && lock.acquiredBy() == channel) {
// remove the lock from the list
ref.clear();
list.remove(index);
// add to result
result.add(lock);
} else {
index++;
}
@ -232,6 +222,7 @@ class SharedFileLockTable extends FileLockTable {
removeKeyIfEmpty(fileKey, list);
}
}
return result;
}
@Override

View File

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

View File

@ -736,6 +736,14 @@ public class Config {
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.
*/
@ -747,7 +755,7 @@ public class Config {
for (int j = 0; j < line.length(); j++) {
if (line.charAt(j) == '=') {
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);
break;
}
@ -820,7 +828,7 @@ public class Config {
} else {
nameVector = table.get(key);
}
nameVector.addElement((line.substring(j + 1)).trim());
nameVector.addElement(trimmed(line.substring(j + 1)));
table.put(key, nameVector);
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
+ ", #bytes=" + obuf.length);
}
/*
* Send the data to the kdc.
*/
try {
/*
* Send the data to the kdc.
*/
kdcClient.send(obuf);
/*
* And get a response.
*/
try {
ibuf = kdcClient.receive();
break;
} catch (SocketTimeoutException se) {
if (DEBUG) {
System.out.println ("SocketTimeOutException with " +
"attempt: " + i);
}
if (i == DEFAULT_KDC_RETRY_LIMIT) {
ibuf = null;
throw se;
/*
* And get a response.
*/
try {
ibuf = kdcClient.receive();
break;
} catch (SocketTimeoutException se) {
if (DEBUG) {
System.out.println ("SocketTimeOutException with " +
"attempt: " + i);
}
if (i == DEFAULT_KDC_RETRY_LIMIT) {
ibuf = null;
throw se;
}
}
} finally {
kdcClient.close();
}
}
}

View File

@ -93,4 +93,7 @@ public class UDPClient {
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.
*
* 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 static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import sun.security.rsa.RSAKeyFactory;
/**
* KeyPairGenerator implementation class. This class currently supports
* RSA, DSA, DH, and EC.
@ -66,7 +68,7 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
private AlgorithmParameterSpec params;
// for RSA, selected or default value of public exponent, always valid
private BigInteger rsaPublicExponent;
private BigInteger rsaPublicExponent = RSAKeyGenParameterSpec.F4;
// SecureRandom instance, if specified in init
private SecureRandom random;
@ -88,19 +90,19 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
public void initialize(int keySize, SecureRandom random) {
token.ensureValid();
try {
checkKeySize(keySize);
checkKeySize(keySize, null);
} catch (InvalidAlgorithmParameterException e) {
throw new InvalidParameterException(e.getMessage());
}
this.keySize = keySize;
this.params = null;
this.random = random;
this.rsaPublicExponent = RSAKeyGenParameterSpec.F4;
if (algorithm.equals("EC")) {
params = P11ECKeyFactory.getECParameterSpec(keySize);
if (params == null) {
throw new InvalidParameterException
("No EC parameters available for key size " + keySize + " bits");
throw new InvalidParameterException(
"No EC parameters available for key size "
+ keySize + " bits");
}
}
}
@ -115,8 +117,10 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("DHParameterSpec required for Diffie-Hellman");
}
DHParameterSpec dhParams = (DHParameterSpec)params;
this.keySize = dhParams.getP().bitLength();
this.params = params;
int tmpKeySize = dhParams.getP().bitLength();
checkKeySize(tmpKeySize, dhParams);
this.keySize = tmpKeySize;
this.params = dhParams;
// XXX sanity check params
} else if (algorithm.equals("RSA")) {
if (params instanceof RSAKeyGenParameterSpec == false) {
@ -124,7 +128,9 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("RSAKeyGenParameterSpec required for RSA");
}
RSAKeyGenParameterSpec rsaParams = (RSAKeyGenParameterSpec)params;
this.keySize = rsaParams.getKeysize();
int tmpKeySize = rsaParams.getKeysize();
checkKeySize(tmpKeySize, rsaParams);
this.keySize = tmpKeySize;
this.params = null;
this.rsaPublicExponent = rsaParams.getPublicExponent();
// XXX sanity check params
@ -134,13 +140,16 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("DSAParameterSpec required for DSA");
}
DSAParameterSpec dsaParams = (DSAParameterSpec)params;
this.keySize = dsaParams.getP().bitLength();
this.params = params;
int tmpKeySize = dsaParams.getP().bitLength();
checkKeySize(tmpKeySize, dsaParams);
this.keySize = tmpKeySize;
this.params = dsaParams;
// XXX sanity check params
} else if (algorithm.equals("EC")) {
ECParameterSpec ecParams;
if (params instanceof ECParameterSpec) {
ecParams = P11ECKeyFactory.getECParameterSpec((ECParameterSpec)params);
ecParams = P11ECKeyFactory.getECParameterSpec(
(ECParameterSpec)params);
if (ecParams == null) {
throw new InvalidAlgorithmParameterException
("Unsupported curve: " + params);
@ -156,16 +165,17 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
throw new InvalidAlgorithmParameterException
("ECParameterSpec or ECGenParameterSpec required for EC");
}
this.keySize = ecParams.getCurve().getField().getFieldSize();
int tmpKeySize = ecParams.getCurve().getField().getFieldSize();
checkKeySize(tmpKeySize, ecParams);
this.keySize = tmpKeySize;
this.params = ecParams;
} else {
throw new ProviderException("Unknown algorithm: " + algorithm);
}
this.random = random;
checkKeySize(keySize);
}
private void checkKeySize(int keySize)
private void checkKeySize(int keySize, AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException {
if (algorithm.equals("EC")) {
if (keySize < 112) {
@ -178,13 +188,28 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
("Key size must be at most 2048 bit");
}
return;
} else if (algorithm.equals("RSA")) {
BigInteger tmpExponent = rsaPublicExponent;
if (params != null) {
// Already tested for instanceof RSAKeyGenParameterSpec above
tmpExponent =
((RSAKeyGenParameterSpec)params).getPublicExponent();
}
try {
// This provider supports 64K or less.
RSAKeyFactory.checkKeyLengths(keySize, tmpExponent,
512, 64 * 1024);
} catch (InvalidKeyException e) {
throw new InvalidAlgorithmParameterException(e.getMessage());
}
return;
}
if (keySize < 512) {
throw new InvalidAlgorithmParameterException
("Key size must be at least 512 bit");
}
if (algorithm.equals("RSA") ||
(algorithm.equals("DH") && (params != null))) {
if (algorithm.equals("DH") && (params != null)) {
// sanity check, nobody really wants keys this large
if (keySize > 64 * 1024) {
throw new InvalidAlgorithmParameterException

View File

@ -80,6 +80,8 @@ import static sun.security.pkcs11.P11Util.*;
import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import sun.security.rsa.RSAKeyFactory;
final class P11KeyStore extends KeyStoreSpi {
private static final CK_ATTRIBUTE ATTR_CLASS_CERT =
@ -1328,6 +1330,15 @@ final class P11KeyStore extends KeyStoreSpi {
BigInteger modulus = attrs[0].getBigInteger();
keyLength = modulus.bitLength();
// This check will combine our "don't care" values here
// with the system-wide min/max values.
try {
RSAKeyFactory.checkKeyLengths(keyLength, null,
-1, Integer.MAX_VALUE);
} catch (InvalidKeyException e) {
throw new KeyStoreException(e.getMessage());
}
return P11Key.privateKey(session,
oHandle,
keyType,

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.
*
* 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 static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import sun.security.rsa.RSAKeyFactory;
/**
* RSA KeyFactory implemenation.
*
@ -131,6 +133,9 @@ final class P11RSAKeyFactory extends P11KeyFactory {
} catch (PKCS11Exception e) {
throw new InvalidKeySpecException
("Could not create RSA public key", e);
} catch (InvalidKeyException e) {
throw new InvalidKeySpecException
("Could not create RSA public key", e);
}
}
@ -175,11 +180,15 @@ final class P11RSAKeyFactory extends P11KeyFactory {
} catch (PKCS11Exception e) {
throw new InvalidKeySpecException
("Could not create RSA private key", e);
} catch (InvalidKeyException e) {
throw new InvalidKeySpecException
("Could not create RSA private key", e);
}
}
private PublicKey generatePublic(BigInteger n, BigInteger e)
throws PKCS11Exception {
throws PKCS11Exception, InvalidKeyException {
RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_CLASS, CKO_PUBLIC_KEY),
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
@ -200,7 +209,8 @@ final class P11RSAKeyFactory extends P11KeyFactory {
}
private PrivateKey generatePrivate(BigInteger n, BigInteger d)
throws PKCS11Exception {
throws PKCS11Exception, InvalidKeyException {
RSAKeyFactory.checkKeyLengths(n.bitLength(), null, -1, 64 * 1024);
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),
@ -222,7 +232,9 @@ final class P11RSAKeyFactory extends P11KeyFactory {
private PrivateKey generatePrivate(BigInteger n, BigInteger e,
BigInteger d, BigInteger p, BigInteger q, BigInteger pe,
BigInteger qe, BigInteger coeff) throws PKCS11Exception {
BigInteger qe, BigInteger coeff) throws PKCS11Exception,
InvalidKeyException {
RSAKeyFactory.checkKeyLengths(n.bitLength(), e, -1, 64 * 1024);
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_CLASS, CKO_PRIVATE_KEY),
new CK_ATTRIBUTE(CKA_KEY_TYPE, CKK_RSA),

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
public SunPKCS11(String configName, InputStream configStream) {
super("SunPKCS11-" + Config.getConfig(configName, configStream).getName(),
super("SunPKCS11-" +
Config.getConfig(configName, configStream).getName(),
1.7d, Config.getConfig(configName, configStream).getDescription());
this.configName = configName;
this.config = Config.removeConfig(configName);
@ -153,7 +155,8 @@ public final class SunPKCS11 extends AuthProvider {
//
// If we are in Secmod mode and configured to use either the
// nssKeyStore or the nssTrustAnchors module, we automatically
// switch to using the NSS trust attributes for trusted certs (KeyStore).
// switch to using the NSS trust attributes for trusted certs
// (KeyStore).
//
if (useSecmod) {
@ -168,33 +171,40 @@ public final class SunPKCS11 extends AuthProvider {
if (secmod.isInitialized()) {
if (nssSecmodDirectory != null) {
String s = secmod.getConfigDir();
if ((s != null) && (s.equals(nssSecmodDirectory) == false)) {
if ((s != null) &&
(s.equals(nssSecmodDirectory) == false)) {
throw new ProviderException("Secmod directory "
+ nssSecmodDirectory
+ " invalid, NSS already initialized with " + s);
+ " invalid, NSS already initialized with "
+ s);
}
}
if (nssLibraryDirectory != null) {
String s = secmod.getLibDir();
if ((s != null) && (s.equals(nssLibraryDirectory) == false)) {
if ((s != null) &&
(s.equals(nssLibraryDirectory) == false)) {
throw new ProviderException("NSS library directory "
+ nssLibraryDirectory
+ " invalid, NSS already initialized with " + s);
+ " invalid, NSS already initialized with "
+ s);
}
}
} else {
if (nssDbMode != DbMode.NO_DB) {
if (nssSecmodDirectory == null) {
throw new ProviderException("Secmod not initialized and "
+ "nssSecmodDirectory not specified");
throw new ProviderException(
"Secmod not initialized and "
+ "nssSecmodDirectory not specified");
}
} else {
if (nssSecmodDirectory != null) {
throw new ProviderException
("nssSecmodDirectory must not be specified in noDb mode");
throw new ProviderException(
"nssSecmodDirectory must not be "
+ "specified in noDb mode");
}
}
secmod.initialize(nssDbMode, nssSecmodDirectory, nssLibraryDirectory);
secmod.initialize(nssDbMode, nssSecmodDirectory,
nssLibraryDirectory);
}
} catch (IOException e) {
// XXX which exception to throw
@ -211,7 +221,8 @@ public final class SunPKCS11 extends AuthProvider {
if (nssModule != null) {
moduleName = "fips";
} else {
moduleName = (nssDbMode == DbMode.NO_DB) ? "crypto" : "keystore";
moduleName = (nssDbMode == DbMode.NO_DB) ?
"crypto" : "keystore";
}
}
if (moduleName.equals("fips")) {
@ -253,10 +264,12 @@ public final class SunPKCS11 extends AuthProvider {
+ ": only " + k + " external NSS modules available");
}
} else {
throw new ProviderException("Unknown NSS module: " + moduleName);
throw new ProviderException(
"Unknown NSS module: " + moduleName);
}
if (nssModule == null) {
throw new ProviderException("NSS module not available: " + moduleName);
throw new ProviderException(
"NSS module not available: " + moduleName);
}
if (nssModule.hasInitializedProvider()) {
throw new ProviderException("Secmod module already configured");
@ -296,8 +309,9 @@ public final class SunPKCS11 extends AuthProvider {
initArgs.flags = CKF_OS_LOCKING_OK;
PKCS11 tmpPKCS11;
try {
tmpPKCS11 = PKCS11.getInstance
(library, functionList, initArgs, config.getOmitInitialize());
tmpPKCS11 = PKCS11.getInstance(
library, functionList, initArgs,
config.getOmitInitialize());
} catch (PKCS11Exception e) {
if (debug != null) {
debug.println("Multi-threaded initialization failed: " + e);
@ -312,8 +326,8 @@ public final class SunPKCS11 extends AuthProvider {
} else {
initArgs.flags = 0;
}
tmpPKCS11 = PKCS11.getInstance
(library, functionList, initArgs, config.getOmitInitialize());
tmpPKCS11 = PKCS11.getInstance(library,
functionList, initArgs, config.getOmitInitialize());
}
p11 = tmpPKCS11;
@ -336,8 +350,10 @@ public final class SunPKCS11 extends AuthProvider {
System.out.println("Slots with tokens: " + toString(slots));
}
if (slotID < 0) {
if ((slotListIndex < 0) || (slotListIndex >= slots.length)) {
throw new ProviderException("slotListIndex is " + slotListIndex
if ((slotListIndex < 0)
|| (slotListIndex >= slots.length)) {
throw new ProviderException("slotListIndex is "
+ slotListIndex
+ " but token only has " + slots.length + " slots");
}
slotID = slots[slotListIndex];
@ -575,12 +591,15 @@ public final class SunPKCS11 extends AuthProvider {
d(KF, "DH", P11DHKeyFactory, s("DiffieHellman"),
m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));
d(KF, "EC", P11DHKeyFactory,
m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE, CKM_ECDSA, CKM_ECDSA_SHA1));
m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
CKM_ECDSA, CKM_ECDSA_SHA1));
// AlgorithmParameters for EC.
// Only needed until we have an EC implementation in the SUN provider.
d(AGP, "EC", "sun.security.ec.ECParameters", s("1.2.840.10045.2.1"),
m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE, CKM_ECDSA, CKM_ECDSA_SHA1));
d(AGP, "EC", "sun.security.ec.ECParameters",
s("1.2.840.10045.2.1"),
m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
CKM_ECDSA, CKM_ECDSA_SHA1));
d(KA, "DH", P11KeyAgreement, s("DiffieHellman"),
m(CKM_DH_PKCS_DERIVE));
@ -654,12 +673,16 @@ public final class SunPKCS11 extends AuthProvider {
d(SIG, "SHA512withRSA", P11Signature,
m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
d(KG, "SunTlsRsaPremasterSecret", "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
d(KG, "SunTlsRsaPremasterSecret",
"sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
d(KG, "SunTlsMasterSecret", "sun.security.pkcs11.P11TlsMasterSecretGenerator",
d(KG, "SunTlsMasterSecret",
"sun.security.pkcs11.P11TlsMasterSecretGenerator",
m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,
CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_MASTER_KEY_DERIVE_DH));
d(KG, "SunTlsKeyMaterial", "sun.security.pkcs11.P11TlsKeyMaterialGenerator",
CKM_SSL3_MASTER_KEY_DERIVE_DH,
CKM_TLS_MASTER_KEY_DERIVE_DH));
d(KG, "SunTlsKeyMaterial",
"sun.security.pkcs11.P11TlsKeyMaterialGenerator",
m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));
d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",
m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));
@ -773,6 +796,13 @@ public final class SunPKCS11 extends AuthProvider {
System.out.println(token.tokenInfo);
}
long[] supportedMechanisms = p11.C_GetMechanismList(slotID);
// Create a map from the various Descriptors to the "most
// preferred" mechanism that was defined during the
// static initialization. For example, DES/CBC/PKCS5Padding
// could be mapped to CKM_DES_CBC_PAD or CKM_DES_CBC. Prefer
// the earliest entry. When asked for "DES/CBC/PKCS5Padding", we
// return a CKM_DES_CBC_PAD.
final Map<Descriptor,Integer> supportedAlgs =
new HashMap<Descriptor,Integer>();
for (int i = 0; i < supportedMechanisms.length; i++) {
@ -807,6 +837,9 @@ public final class SunPKCS11 extends AuthProvider {
supportedAlgs.put(d, integerMech);
continue;
}
// See if there is something "more preferred"
// than what we currently have in the supportedAlgs
// map.
int intOldMech = oldMech.intValue();
for (int j = 0; j < d.mechanisms.length; j++) {
int nextMech = d.mechanisms[j];

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.
*
* 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.spec.*;
import sun.security.action.GetPropertyAction;
/**
* KeyFactory for RSA keys. Keys must be instances of PublicKey or PrivateKey
* and getAlgorithm() must return "RSA". For such keys, it supports conversion
@ -68,6 +70,24 @@ public final class RSAKeyFactory extends KeyFactorySpi {
private final static Class<?> x509KeySpecClass = X509EncodedKeySpec.class;
private final static Class<?> pkcs8KeySpecClass = PKCS8EncodedKeySpec.class;
public final static int MIN_MODLEN = 512;
public final static int MAX_MODLEN = 16384;
/*
* If the modulus length is above this value, restrict the size of
* the exponent to something that can be reasonably computed. We
* could simply hardcode the exp len to something like 64 bits, but
* this approach allows flexibility in case impls would like to use
* larger module and exponent values.
*/
public final static int MAX_MODLEN_RESTRICT_EXP = 3072;
public final static int MAX_RESTRICTED_EXPLEN = 64;
private static final boolean restrictExpLen =
"true".equalsIgnoreCase(AccessController.doPrivileged(
new GetPropertyAction(
"sun.security.rsa.restrictRSAExponent", "true")));
// instance used for static translateKey();
private final static RSAKeyFactory INSTANCE = new RSAKeyFactory();
@ -76,74 +96,79 @@ public final class RSAKeyFactory extends KeyFactorySpi {
}
/**
* Static method to convert Key into a useable instance of
* RSAPublicKey or RSAPrivate(Crt)Key. Check the key and convert it
* to a SunRsaSign key if necessary. If the key is not an RSA key
* or cannot be used, throw an InvalidKeyException.
*
* The difference between this method and engineTranslateKey() is that
* we do not convert keys of other providers that are already an
* instance of RSAPublicKey or RSAPrivate(Crt)Key.
* Static method to convert Key into an instance of RSAPublicKeyImpl
* or RSAPrivate(Crt)KeyImpl. If the key is not an RSA key or cannot be
* used, throw an InvalidKeyException.
*
* Used by RSASignature and RSACipher.
*/
public static RSAKey toRSAKey(Key key) throws InvalidKeyException {
if (key instanceof RSAKey) {
RSAKey rsaKey = (RSAKey)key;
checkKey(rsaKey);
return rsaKey;
if ((key instanceof RSAPrivateKeyImpl) ||
(key instanceof RSAPrivateCrtKeyImpl) ||
(key instanceof RSAPublicKeyImpl)) {
return (RSAKey)key;
} else {
return (RSAKey)INSTANCE.engineTranslateKey(key);
}
}
/**
* Check that the given RSA key is valid.
/*
* Single test entry point for all of the mechanisms in the SunRsaSign
* provider (RSA*KeyImpls). All of the tests are the same.
*
* For compatibility, we round up to the nearest byte here:
* some Key impls might pass in a value within a byte of the
* real value.
*/
private static void checkKey(RSAKey key) throws InvalidKeyException {
// check for subinterfaces, omit additional checks for our keys
if (key instanceof RSAPublicKey) {
if (key instanceof RSAPublicKeyImpl) {
return;
}
} else if (key instanceof RSAPrivateKey) {
if ((key instanceof RSAPrivateCrtKeyImpl)
|| (key instanceof RSAPrivateKeyImpl)) {
return;
}
} else {
throw new InvalidKeyException("Neither a public nor a private key");
}
// RSAKey does not extend Key, so we need to do a cast
String keyAlg = ((Key)key).getAlgorithm();
if (keyAlg.equals("RSA") == false) {
throw new InvalidKeyException("Not an RSA key: " + keyAlg);
}
BigInteger modulus;
// some providers implement RSAKey for keys where the values are
// not accessible (although they should). Detect those here
// for a more graceful failure.
try {
modulus = key.getModulus();
if (modulus == null) {
throw new InvalidKeyException("Modulus is missing");
}
} catch (RuntimeException e) {
throw new InvalidKeyException(e);
}
checkKeyLength(modulus);
static void checkRSAProviderKeyLengths(int modulusLen, BigInteger exponent)
throws InvalidKeyException {
checkKeyLengths(((modulusLen + 7) & ~7), exponent,
RSAKeyFactory.MIN_MODLEN, Integer.MAX_VALUE);
}
/**
* Check the length of the modulus of an RSA key. We only support keys
* at least 505 bits long.
* Check the length of an RSA key modulus/exponent to make sure it
* is not too short or long. Some impls have their own min and
* max key sizes that may or may not match with a system defined value.
*
* @param modulusLen the bit length of the RSA modulus.
* @param exponent the RSA exponent
* @param minModulusLen if > 0, check to see if modulusLen is at
* least this long, otherwise unused.
* @param maxModulusLen caller will allow this max number of bits.
* Allow the smaller of the system-defined maximum and this param.
*
* @throws InvalidKeyException if any of the values are unacceptable.
*/
static void checkKeyLength(BigInteger modulus) throws InvalidKeyException {
if (modulus.bitLength() < 505) {
// some providers may generate slightly shorter keys
// accept them if the encoding is at least 64 bytes long
throw new InvalidKeyException
("RSA keys must be at least 512 bits long");
public static void checkKeyLengths(int modulusLen, BigInteger exponent,
int minModulusLen, int maxModulusLen) throws InvalidKeyException {
if ((minModulusLen > 0) && (modulusLen < (minModulusLen))) {
throw new InvalidKeyException( "RSA keys must be at least " +
minModulusLen + " bits long");
}
// Even though our policy file may allow this, we don't want
// either value (mod/exp) to be too big.
int maxLen = Math.min(maxModulusLen, MAX_MODLEN);
// If a RSAPrivateKey/RSAPublicKey, make sure the
// modulus len isn't too big.
if (modulusLen > maxLen) {
throw new InvalidKeyException(
"RSA keys must be no longer than " + maxLen + " bits");
}
// If a RSAPublicKey, make sure the exponent isn't too big.
if (restrictExpLen && (exponent != null) &&
(modulusLen > MAX_MODLEN_RESTRICT_EXP) &&
(exponent.bitLength() > MAX_RESTRICTED_EXPLEN)) {
throw new InvalidKeyException(
"RSA exponents can be no longer than " +
MAX_RESTRICTED_EXPLEN + " bits " +
" if modulus is greater than " +
MAX_MODLEN_RESTRICT_EXP + " bits");
}
}

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.
*
* 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
private BigInteger publicExponent;
// size of the key to generate, >= 512
// size of the key to generate, >= RSAKeyFactory.MIN_MODLEN
private int keySize;
// PRNG to use
@ -60,15 +60,16 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// initialize the generator. See JCA doc
public void initialize(int keySize, SecureRandom random) {
if (keySize < 512) {
throw new InvalidParameterException
("Key size must be at least 512 bits");
}
if (keySize > 64 * 1024) {
// do not allow unreasonably large key sizes, probably user error
throw new InvalidParameterException
("Key size must be 65536 bits or less");
// do not allow unreasonably small or large key sizes,
// probably user error
try {
RSAKeyFactory.checkKeyLengths(keySize, RSAKeyGenParameterSpec.F4,
512, 64 * 1024);
} catch (InvalidKeyException e) {
throw new InvalidParameterException(e.getMessage());
}
this.keySize = keySize;
this.random = random;
this.publicExponent = RSAKeyGenParameterSpec.F4;
@ -77,35 +78,41 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// second initialize method. See JCA doc.
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException {
if (params instanceof RSAKeyGenParameterSpec == false) {
throw new InvalidAlgorithmParameterException
("Params must be instance of RSAKeyGenParameterSpec");
}
RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec)params;
keySize = rsaSpec.getKeysize();
publicExponent = rsaSpec.getPublicExponent();
this.random = random;
if (keySize < 512) {
throw new InvalidAlgorithmParameterException
("Key size must be at least 512 bits");
}
if (keySize > 64 * 1024) {
// do not allow unreasonably large key sizes, probably user error
throw new InvalidAlgorithmParameterException
("Key size must be 65536 bits or less");
}
if (publicExponent == null) {
publicExponent = RSAKeyGenParameterSpec.F4;
int tmpKeySize = rsaSpec.getKeysize();
BigInteger tmpPublicExponent = rsaSpec.getPublicExponent();
if (tmpPublicExponent == null) {
tmpPublicExponent = RSAKeyGenParameterSpec.F4;
} else {
if (publicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
if (tmpPublicExponent.compareTo(RSAKeyGenParameterSpec.F0) < 0) {
throw new InvalidAlgorithmParameterException
("Public exponent must be 3 or larger");
}
if (publicExponent.bitLength() > keySize) {
if (tmpPublicExponent.bitLength() > tmpKeySize) {
throw new InvalidAlgorithmParameterException
("Public exponent must be smaller than key size");
}
}
// do not allow unreasonably large key sizes, probably user error
try {
RSAKeyFactory.checkKeyLengths(tmpKeySize, tmpPublicExponent,
512, 64 * 1024);
} catch (InvalidKeyException e) {
throw new InvalidAlgorithmParameterException(
"Invalid key sizes", e);
}
this.keySize = tmpKeySize;
this.publicExponent = tmpPublicExponent;
this.random = random;
}
// generate the keypair. See JCA doc

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.
*
* 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 {
decode(encoded);
RSAKeyFactory.checkKeyLength(n);
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
}
/**
@ -107,7 +107,8 @@ public final class RSAPrivateCrtKeyImpl
this.pe = pe;
this.qe = qe;
this.coeff = coeff;
RSAKeyFactory.checkKeyLength(n);
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
// generate the encoding
algid = rsaId;
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.
*
* 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 {
this.n = n;
this.d = d;
RSAKeyFactory.checkKeyLength(n);
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), null);
// generate the encoding
algid = RSAPrivateCrtKeyImpl.rsaId;
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.
*
* 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
* RSAKeyFactory and the RSAKeyPairGenerator.
*/
public RSAPublicKeyImpl(BigInteger n, BigInteger e) throws InvalidKeyException {
public RSAPublicKeyImpl(BigInteger n, BigInteger e)
throws InvalidKeyException {
this.n = n;
this.e = e;
RSAKeyFactory.checkKeyLength(n);
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
// generate the encoding
algid = RSAPrivateCrtKeyImpl.rsaId;
try {
@ -80,7 +81,7 @@ public final class RSAPublicKeyImpl extends X509Key implements RSAPublicKey {
*/
public RSAPublicKeyImpl(byte[] encoded) throws InvalidKeyException {
decode(encoded);
RSAKeyFactory.checkKeyLength(n);
RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e);
}
// see JCA doc

View File

@ -26,7 +26,8 @@
package sun.security.util;
import java.io.*;
import java.math.BigInteger;
import java.util.Arrays;
/**
* Represent an ISO Object Identifier.
@ -44,105 +45,186 @@ import java.io.*;
* hierarchy, and other organizations can easily acquire the ability
* to assign such unique identifiers.
*
*
* @author David Brownell
* @author Amit Kapoor
* @author Hemma Prafullchandra
*/
final public
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 int maxFirstComponent = 2;
private static final int maxSecondComponent = 39;
/**
* Constructs an object identifier from a string. This string
* should be of the form 1.23.34.45.56 etc.
* Changed to Object
* @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
{
int ch = '.';
int start = 0;
int start = 0;
int end = 0;
// Calculate length of oid
componentLen = 0;
while ((end = oid.indexOf(ch,start)) != -1) {
start = end + 1;
componentLen += 1;
}
componentLen += 1;
components = new int[componentLen];
int pos = 0;
byte[] tmp = new byte[oid.length()];
int first = 0, second;
int count = 0;
start = 0;
int i = 0;
String comp = null;
try {
while ((end = oid.indexOf(ch,start)) != -1) {
comp = oid.substring(start,end);
components[i++] = Integer.valueOf(comp).intValue();
String comp = null;
do {
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;
}
comp = oid.substring(start);
components[i] = Integer.valueOf(comp).intValue();
count++;
} while (end != -1);
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) {
throw new IOException("ObjectIdentifier() -- Invalid format: "
+ e.toString(), e);
}
checkValidOid(components, componentLen);
this.stringForm = oid;
}
/**
* Check if the values make a legal OID. There must be at least 2
* components and they must be all non-negative. The first component
* 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.
* Constructor, from an array of integers.
* Validity check included.
*/
public ObjectIdentifier (int values []) throws IOException
{
checkValidOid(values, values.length);
components = values.clone();
componentLen = values.length;
checkCount(values.length);
checkFirstComponent(values[0]);
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.
* 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
* @exception IOException indicates a decoding error
*/
public ObjectIdentifier (DerInputStream in)
throws IOException
public ObjectIdentifier (DerInputStream in) throws IOException
{
byte type_id;
int bufferEnd;
@ -174,215 +255,67 @@ class ObjectIdentifier implements Serializable
+ " (tag = " + type_id + ")"
);
bufferEnd = in.available () - in.getLength () - 1;
if (bufferEnd < 0)
throw new IOException (
"ObjectIdentifier() -- not enough data");
initFromEncoding (in, bufferEnd);
encoding = new byte[in.getLength()];
in.getBytes(encoding);
check(encoding);
}
/*
* Build the OID from the rest of a DER input buffer; the tag
* and length have been removed/verified
* Constructor, from the rest of a DER input buffer;
* the tag and length have been removed/verified
* Validity check NOT included.
*/
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
* to avoid clash with the public constructor.
*/
private ObjectIdentifier(int[] components, boolean dummy) {
this.components = components;
this.componentLen = components.length;
}
/**
* Create a new ObjectIdentifier for internal use. The values are
* This method is kept for compatibility reasons. The new implementation
* does the check and conversion. All around the JDK, the method is called
* in static blocks to initialize pre-defined ObjectIdentifieies. No
* obvious performance hurt will be made after this change.
*
* Old doc: Create a new ObjectIdentifier for internal use. The values are
* neither checked nor cloned.
*/
public static ObjectIdentifier newInternal(int[] values) {
return new ObjectIdentifier(values, true);
}
/*
* Helper function -- get the OID from a stream, after tag and
* 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");
try {
return new ObjectIdentifier(values);
} catch (IOException ex) {
throw new RuntimeException(ex);
// Should not happen, internal calls always uses legal values.
}
}
/*
* n.b. the only public interface is DerOutputStream.putOID()
*/
void encode (DerOutputStream out) throws IOException
{
DerOutputStream bytes = new DerOutputStream ();
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;
out.write (DerValue.tag_ObjectId, encoding);
}
/**
@ -398,6 +331,7 @@ class ObjectIdentifier implements Serializable
*
* @return true iff the names are identical.
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
@ -406,23 +340,71 @@ class ObjectIdentifier implements Serializable
return false;
}
ObjectIdentifier other = (ObjectIdentifier)obj;
if (componentLen != other.componentLen) {
return false;
}
for (int i = 0; i < componentLen; i++) {
if (components[i] != other.components[i]) {
return false;
}
}
return true;
return Arrays.equals(encoding, other.encoding);
}
@Override
public int hashCode() {
int h = componentLen;
for (int i = 0; i < componentLen; i++) {
h += components[i] * 37;
return Arrays.hashCode(encoding);
}
/**
* 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
* will not be understood everywhere.
*/
@Override
public String toString() {
String s = stringForm;
if (s == null) {
StringBuffer sb = new StringBuffer(componentLen * 4);
for (int i = 0; i < componentLen; i++) {
if (i != 0) {
sb.append('.');
int length = encoding.length;
StringBuffer sb = new StringBuffer(length * 4);
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();
stringForm = s;
@ -447,15 +466,197 @@ class ObjectIdentifier implements Serializable
return s;
}
/*
* To simplify, we assume no individual component of an object ID is
* larger than 32 bits. Then we represent the path from the root as
* an array that's (usually) only filled at the beginning.
/**
* Repack all bits from input to output. On the both sides, only a portion
* (from the least significant bit) of the 8 bits in a byte is used. This
* 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 int componentLen; // how much is used.
private static byte[] pack(byte[] in, int ioffset, int ilength, int iw, int ow) {
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
# both the password and the access files.
#
# Default location of this file is $JRE/lib/management/jmxremote.access
# The default location of this file is $JRE/lib/management/jmxremote.access
# You can specify an alternate location by specifying a property in
# the management config file $JRE/lib/management/management.properties
# (See that file for details)
@ -16,7 +16,7 @@
# The file format for password and access files is syntactically the same
# as the Properties file format. The syntax is described in the Javadoc
# for java.util.Properties.load.
# Typical access file has multiple lines, where each line is blank,
# A typical access file has multiple lines, where each line is blank,
# a comment (like this one), or an access control entry.
#
# An access control entry consists of a role name, and an
@ -29,10 +29,38 @@
# role can read measurements but cannot perform any action
# that changes the environment of the running program.
# "readwrite" grants access to read and write attributes of MBeans,
# to invoke operations on them, and to create or remove them.
# This access should be granted to only trusted clients,
# since they can potentially interfere with the smooth
# operation of a running program
# to invoke operations on them, and optionally
# to create or remove them. This access should be granted
# only to trusted clients, since they can potentially
# interfere with the smooth operation of a running program.
#
# The "readwrite" access level can optionally be followed by the "create" and/or
# "unregister" keywords. The "unregister" keyword grants access to unregister
# (delete) MBeans. The "create" keyword grants access to create MBeans of a
# particular class or of any class matching a particular pattern. Access
# should only be granted to create MBeans of known and trusted classes.
#
# For example, the following entry would grant readwrite access
# to "controlRole", as well as access to create MBeans of the class
# javax.management.monitor.CounterMonitor and to unregister any MBean:
# controlRole readwrite \
# create javax.management.monitor.CounterMonitorMBean \
# unregister
# or equivalently:
# controlRole readwrite unregister create javax.management.monitor.CounterMBean
#
# The following entry would grant readwrite access as well as access to create
# MBeans of any class in the packages javax.management.monitor and
# javax.management.timer:
# controlRole readwrite \
# create javax.management.monitor.*,javax.management.timer.* \
# unregister
#
# The \ character is defined in the Properties file syntax to allow continuation
# lines as shown here. A * in a class pattern matches a sequence of characters
# other than dot (.), so javax.management.monitor.* matches
# javax.management.monitor.CounterMonitor but not
# javax.management.monitor.foo.Bar.
#
# A given role should have at most one entry in this file. If a role
# has no entry, it has no access.
@ -42,7 +70,10 @@
#
# Default access control entries:
# o The "monitorRole" role has readonly access.
# o The "controlRole" role has readwrite access.
# o The "controlRole" role has readwrite access and can create the standard
# Timer and Monitor MBeans defined by the JMX API.
monitorRole readonly
controlRole readwrite
controlRole readwrite \
create javax.management.monitor.*,javax.management.timer.* \
unregister

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.
*
* 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);
}
xvs.init(u->rp, u->rplimit, valc);
CHECK;
int X = xvs.getInt();
if (valc->S() != 0) {
assert(valc->min <= -256);
@ -117,6 +118,7 @@ void band::readData(int expectedLength) {
byte XB_byte = (byte) XB;
byte* XB_ptr = &XB_byte;
cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, null);
CHECK;
} else {
NOT_PRODUCT(byte* meta_rp0 = u->meta_rp);
assert(u->meta_rp != null);
@ -215,8 +217,19 @@ int band::getIntTotal() {
if (length == 0) return 0;
if (total_memo > 0) return total_memo-1;
int total = getInt();
// overflow checks require that none of the addends are <0,
// and that the partial sums never overflow (wrap negative)
if (total < 0) {
abort("overflow detected");
return 0;
}
for (int k = length-1; k > 0; k--) {
int prev_total = total;
total += vs[0].getInt();
if (total < prev_total) {
abort("overflow detected");
return 0;
}
}
rewind();
total_memo = total+1;

View File

@ -56,7 +56,7 @@ void bytes::realloc(size_t len_) {
return;
}
byte* oldptr = ptr;
ptr = (byte*)::realloc(ptr, len_+1);
ptr = (len_ >= PSIZE_MAX) ? null : (byte*)::realloc(ptr, len_+1);
if (ptr != null) {
mtrace('r', oldptr, 0);
mtrace('m', ptr, len_+1);
@ -128,7 +128,7 @@ const char* bytes::string() {
// Make sure there are 'o' bytes beyond the fill pointer,
// advance the fill pointer, and return the old fill pointer.
byte* fillbytes::grow(size_t s) {
size_t nlen = b.len+s;
size_t nlen = add_size(b.len, s);
if (nlen <= allocated) {
b.len = nlen;
return limit()-s;

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.
*
* 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;
}
CHECK;
// Get an accurate upper limit now.
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.
*
* This code is free software; you can redistribute it and/or modify it
@ -47,11 +47,13 @@
#define NOT_PRODUCT(xxx)
#define assert(p)
#define PRINTCR(args)
#define VERSION_STRING "%s version %s\n"
#else
#define IF_PRODUCT(xxx)
#define NOT_PRODUCT(xxx) xxx
#define assert(p) ((p) || assert_failed(#p))
#define PRINTCR(args) u->verbose && u->printcr_if_verbose args
#define VERSION_STRING "%s version non-product %s\n"
extern "C" void breakpoint();
extern int assert_failed(const char*);
#define BREAK (breakpoint())
@ -79,9 +81,9 @@ extern int assert_failed(const char*);
#define lengthof(array) (sizeof(array)/sizeof(array[0]))
#define NEW(T, n) (T*) must_malloc((int)(sizeof(T)*(n)))
#define U_NEW(T, n) (T*) u->alloc(sizeof(T)*(n))
#define T_NEW(T, n) (T*) u->temp_alloc(sizeof(T)*(n))
#define NEW(T, n) (T*) must_malloc((int)(scale_size(n, sizeof(T))))
#define U_NEW(T, n) (T*) u->alloc(scale_size(n, sizeof(T)))
#define T_NEW(T, n) (T*) u->temp_alloc(scale_size(n, sizeof(T)))
// bytes and byte arrays
@ -153,6 +155,8 @@ enum { false, true };
#define CHECK_NULL_(y,p) _CHECK_DO((p)==null, return y)
#define CHECK_NULL_0(p) _CHECK_DO((p)==null, return 0)
#define CHECK_COUNT(t) if (t < 0){abort("bad value count");} CHECK
#define STR_TRUE "true"
#define STR_FALSE "false"

View File

@ -299,7 +299,7 @@ int unpacker::run(int argc, char **argv) {
case 'J': argp += 1; break; // skip ignored -Jxxx parameter
case 'V':
fprintf(u.errstrm, "%s version %s\n", nbasename(argv[0]), sccsver);
fprintf(u.errstrm, VERSION_STRING, nbasename(argv[0]), sccsver);
exit(0);
case 'h':

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.
*
* This code is free software; you can redistribute it and/or modify it
@ -523,15 +523,39 @@ void unpacker::read_file_header() {
enum {
MAGIC_BYTES = 4,
AH_LENGTH_0 = 3, //minver, majver, options are outside of archive_size
AH_LENGTH_0_MAX = AH_LENGTH_0 + 1, // options might have 2 bytes
AH_LENGTH = 26, //maximum archive header length (w/ all fields)
// Length contributions from optional header fields:
AH_FILE_HEADER_LEN = 5, // sizehi/lo/next/modtime/files
AH_ARCHIVE_SIZE_LEN = 2, // sizehi/lo only; part of AH_FILE_HEADER_LEN
AH_CP_NUMBER_LEN = 4, // int/float/long/double
AH_SPECIAL_FORMAT_LEN = 2, // layouts/band-headers
AH_LENGTH_MIN = AH_LENGTH
-(AH_FILE_HEADER_LEN+AH_SPECIAL_FORMAT_LEN+AH_CP_NUMBER_LEN),
ARCHIVE_SIZE_MIN = AH_LENGTH_MIN - (AH_LENGTH_0 + AH_ARCHIVE_SIZE_LEN),
FIRST_READ = MAGIC_BYTES + AH_LENGTH_MIN
};
assert(AH_LENGTH_MIN == 15); // # of UNSIGNED5 fields required after archive_magic
assert(ARCHIVE_SIZE_MIN == 10); // # of UNSIGNED5 fields required after archive_size
// An absolute minimum null archive is magic[4], {minver,majver,options}[3],
// archive_size[0], cp_counts[8], class_counts[4], for a total of 19 bytes.
// (Note that archive_size is optional; it may be 0..10 bytes in length.)
// The first read must capture everything up through the options field.
// This happens to work even if {minver,majver,options} is a pathological
// 15 bytes long. Legal pack files limit those three fields to 1+1+2 bytes.
assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0 * B_MAX);
// Up through archive_size, the largest possible archive header is
// magic[4], {minver,majver,options}[4], archive_size[10].
// (Note only the low 12 bits of options are allowed to be non-zero.)
// In order to parse archive_size, we need at least this many bytes
// in the first read. Of course, if archive_size_hi is more than
// a byte, we probably will fail to allocate the buffer, since it
// will be many gigabytes long. This is a practical, not an
// architectural limit to Pack200 archive sizes.
assert(FIRST_READ >= MAGIC_BYTES + AH_LENGTH_0_MAX + 2*B_MAX);
bool foreign_buf = (read_input_fn == null);
byte initbuf[(int)FIRST_READ + (int)C_SLOP + 200]; // 200 is for JAR I/O
if (foreign_buf) {
@ -547,7 +571,7 @@ void unpacker::read_file_header() {
// There is no way to tell the caller that we used only part of them.
// Therefore, the caller must use only a bare minimum of read-ahead.
if (inbytes.len > FIRST_READ) {
abort("too much pushback");
abort("too much read-ahead");
return;
}
input.set(initbuf, sizeof(initbuf));
@ -557,7 +581,7 @@ void unpacker::read_file_header() {
rplimit += inbytes.len;
bytes_read += inbytes.len;
}
// Read only 19 bytes, which is certain to contain #archive_size fields,
// Read only 19 bytes, which is certain to contain #archive_options fields,
// but is certain not to overflow past the archive_header.
input.b.len = FIRST_READ;
if (!ensure_input(FIRST_READ))
@ -629,26 +653,25 @@ void unpacker::read_file_header() {
#undef ORBIT
if ((archive_options & ~OPTION_LIMIT) != 0) {
fprintf(errstrm, "Warning: Illegal archive options 0x%x\n",
archive_options);
// Do not abort. If the format really changes, version numbers will bump.
//abort("illegal archive options");
archive_options);
abort("illegal archive options");
return;
}
if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
uint hi = hdr.getInt();
uint lo = hdr.getInt();
archive_size = band::makeLong(hi, lo);
julong x = band::makeLong(hi, lo);
archive_size = (size_t) x;
if (archive_size != x) {
// Silly size specified; force overflow.
archive_size = PSIZE_MAX+1;
}
hdrVals += 2;
} else {
hdrValsSkipped += 2;
}
if (archive_size != (size_t)archive_size) {
// Silly size specified.
abort("archive too large");
return;
}
// Now we can size the whole archive.
// Read everything else into a mega-buffer.
rp = hdr.rp;
@ -662,9 +685,18 @@ void unpacker::read_file_header() {
abort("EOF reading fixed input buffer");
return;
}
} else if (archive_size > 0) {
input.set(U_NEW(byte, (size_t)(header_size_0 + archive_size + C_SLOP)),
(size_t) header_size_0 + (size_t)archive_size);
} else if (archive_size != 0) {
if (archive_size < ARCHIVE_SIZE_MIN) {
abort("impossible archive size"); // bad input data
return;
}
if (archive_size < header_size_1) {
abort("too much read-ahead"); // somehow we pre-fetched too much?
return;
}
input.set(U_NEW(byte, add_size(header_size_0, archive_size, C_SLOP)),
(size_t) header_size_0 + archive_size);
CHECK;
assert(input.limit()[0] == 0);
// Move all the bytes we read initially into the real buffer.
input.b.copyFrom(initbuf, header_size);
@ -673,17 +705,17 @@ void unpacker::read_file_header() {
} else {
// It's more complicated and painful.
// A zero archive_size means that we must read until EOF.
assert(archive_size == 0);
input.init(CHUNK*2);
CHECK;
input.b.len = input.allocated;
rp = rplimit = input.base();
// Set up input buffer as if we already read the header:
input.b.copyFrom(initbuf, header_size);
CHECK;
rplimit += header_size;
while (ensure_input(input.limit() - rp)) {
size_t dataSoFar = input_remaining();
size_t nextSize = dataSoFar + CHUNK;
size_t nextSize = add_size(dataSoFar, CHUNK);
input.ensureSize(nextSize);
CHECK;
input.b.len = input.allocated;
@ -715,8 +747,10 @@ void unpacker::read_file_header() {
if ((archive_options & AO_HAVE_FILE_HEADERS) != 0) {
archive_next_count = hdr.getInt();
CHECK_COUNT(archive_next_count);
archive_modtime = hdr.getInt();
file_count = hdr.getInt();
CHECK_COUNT(file_count);
hdrVals += 3;
} else {
hdrValsSkipped += 3;
@ -724,7 +758,9 @@ void unpacker::read_file_header() {
if ((archive_options & AO_HAVE_SPECIAL_FORMATS) != 0) {
band_headers_size = hdr.getInt();
CHECK_COUNT(band_headers_size);
attr_definition_count = hdr.getInt();
CHECK_COUNT(attr_definition_count);
hdrVals += 2;
} else {
hdrValsSkipped += 2;
@ -744,13 +780,16 @@ void unpacker::read_file_header() {
}
}
cp_counts[k] = hdr.getInt();
CHECK_COUNT(cp_counts[k]);
hdrVals += 1;
}
ic_count = hdr.getInt();
CHECK_COUNT(ic_count);
default_class_minver = hdr.getInt();
default_class_majver = hdr.getInt();
class_count = hdr.getInt();
CHECK_COUNT(class_count);
hdrVals += 4;
// done with archive_header
@ -807,7 +846,6 @@ void unpacker::read_file_header() {
bytes::of(band_headers.limit(), C_SLOP).clear(_meta_error);
}
void unpacker::finish() {
if (verbose >= 1) {
fprintf(errstrm,
@ -973,12 +1011,12 @@ void unpacker::read_Utf8_values(entry* cpMap, int len) {
// First band: Read lengths of shared prefixes.
if (len > PREFIX_SKIP_2)
cp_Utf8_prefix.readData(len - PREFIX_SKIP_2);
NOT_PRODUCT(else cp_Utf8_prefix.readData(0)); // for asserts
NOT_PRODUCT(else cp_Utf8_prefix.readData(0)); // for asserts
// Second band: Read lengths of unshared suffixes:
if (len > SUFFIX_SKIP_1)
cp_Utf8_suffix.readData(len - SUFFIX_SKIP_1);
NOT_PRODUCT(else cp_Utf8_suffix.readData(0)); // for asserts
NOT_PRODUCT(else cp_Utf8_suffix.readData(0)); // for asserts
bytes* allsuffixes = T_NEW(bytes, len);
CHECK;
@ -2117,6 +2155,7 @@ void unpacker::read_classes() {
field_descr.readData(field_count);
read_attrs(ATTR_CONTEXT_FIELD, field_count);
CHECK;
method_descr.readData(method_count);
read_attrs(ATTR_CONTEXT_METHOD, method_count);
@ -2124,6 +2163,7 @@ void unpacker::read_classes() {
CHECK;
read_attrs(ATTR_CONTEXT_CLASS, class_count);
CHECK;
read_code_headers();
@ -2150,10 +2190,12 @@ void unpacker::read_attrs(int attrc, int obj_count) {
assert(endsWith(xxx_flags_hi.name, "_flags_hi"));
if (haveLongFlags)
xxx_flags_hi.readData(obj_count);
CHECK;
band& xxx_flags_lo = ad.xxx_flags_lo();
assert(endsWith(xxx_flags_lo.name, "_flags_lo"));
xxx_flags_lo.readData(obj_count);
CHECK;
// pre-scan flags, counting occurrences of each index bit
julong indexMask = ad.flagIndexMask(); // which flag bits are index bits?
@ -2176,11 +2218,13 @@ void unpacker::read_attrs(int attrc, int obj_count) {
assert(endsWith(xxx_attr_count.name, "_attr_count"));
// There is one count element for each 1<<16 bit set in flags:
xxx_attr_count.readData(ad.predefCount(X_ATTR_OVERFLOW));
CHECK;
band& xxx_attr_indexes = ad.xxx_attr_indexes();
assert(endsWith(xxx_attr_indexes.name, "_attr_indexes"));
int overflowIndexCount = xxx_attr_count.getIntTotal();
xxx_attr_indexes.readData(overflowIndexCount);
CHECK;
// pre-scan attr indexes, counting occurrences of each value
for (i = 0; i < overflowIndexCount; i++) {
idx = xxx_attr_indexes.getInt();
@ -2211,6 +2255,7 @@ void unpacker::read_attrs(int attrc, int obj_count) {
}
}
ad.xxx_attr_calls().readData(backwardCounts);
CHECK;
// Read built-in bands.
// 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);
class_SourceFile_RUN.readData(count);
CHECK;
count = ad.predefCount(CLASS_ATTR_EnclosingMethod);
class_EnclosingMethod_RC.readData(count);
class_EnclosingMethod_RDN.readData(count);
CHECK;
count = ad.predefCount(X_ATTR_Signature);
class_Signature_RS.readData(count);
CHECK;
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
count = ad.predefCount(CLASS_ATTR_InnerClasses);
class_InnerClasses_N.readData(count);
CHECK;
count = class_InnerClasses_N.getIntTotal();
class_InnerClasses_RC.readData(count);
class_InnerClasses_F.readData(count);
CHECK;
// Drop remaining columns wherever flags are zero:
count -= class_InnerClasses_F.getIntCount(0);
class_InnerClasses_outer_RCN.readData(count);
class_InnerClasses_name_RUN.readData(count);
CHECK;
count = ad.predefCount(CLASS_ATTR_ClassFile_version);
class_ClassFile_version_minor_H.readData(count);
class_ClassFile_version_major_H.readData(count);
CHECK;
break;
case ATTR_CONTEXT_FIELD:
count = ad.predefCount(FIELD_ATTR_ConstantValue);
field_ConstantValue_KQ.readData(count);
CHECK;
count = ad.predefCount(X_ATTR_Signature);
field_Signature_RS.readData(count);
CHECK;
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
CHECK;
break;
case ATTR_CONTEXT_METHOD:
@ -2266,15 +2322,18 @@ void unpacker::read_attrs(int attrc, int obj_count) {
method_Exceptions_N.readData(count);
count = method_Exceptions_N.getIntTotal();
method_Exceptions_RC.readData(count);
CHECK;
count = ad.predefCount(X_ATTR_Signature);
method_Signature_RS.readData(count);
CHECK;
ad.readBandData(X_ATTR_RuntimeVisibleAnnotations);
ad.readBandData(X_ATTR_RuntimeInvisibleAnnotations);
ad.readBandData(METHOD_ATTR_RuntimeVisibleParameterAnnotations);
ad.readBandData(METHOD_ATTR_RuntimeInvisibleParameterAnnotations);
ad.readBandData(METHOD_ATTR_AnnotationDefault);
CHECK;
break;
case ATTR_CONTEXT_CODE:
@ -2286,8 +2345,10 @@ void unpacker::read_attrs(int attrc, int obj_count) {
return;
}
code_StackMapTable_N.readData(count);
CHECK;
count = code_StackMapTable_N.getIntTotal();
code_StackMapTable_frame_T.readData(count);
CHECK;
// the rest of it depends in a complicated way on frame tags
{
int fat_frame_count = 0;
@ -2321,18 +2382,23 @@ void unpacker::read_attrs(int attrc, int obj_count) {
// deal completely with fat frames:
offset_count += fat_frame_count;
code_StackMapTable_local_N.readData(fat_frame_count);
CHECK;
type_count += code_StackMapTable_local_N.getIntTotal();
code_StackMapTable_stack_N.readData(fat_frame_count);
type_count += code_StackMapTable_stack_N.getIntTotal();
CHECK;
// read the rest:
code_StackMapTable_offset.readData(offset_count);
code_StackMapTable_T.readData(type_count);
CHECK;
// (7) [RCH]
count = code_StackMapTable_T.getIntCount(7);
code_StackMapTable_RC.readData(count);
CHECK;
// (8) [PH]
count = code_StackMapTable_T.getIntCount(8);
code_StackMapTable_P.readData(count);
CHECK;
}
count = ad.predefCount(CODE_ATTR_LineNumberTable);
@ -2654,6 +2720,7 @@ void unpacker::read_code_headers() {
code_max_na_locals.readData();
code_handler_count.readData();
totalHandlerCount += code_handler_count.getIntTotal();
CHECK;
// Read handler specifications.
// Cf. PackageReader.readCodeHandlers.
@ -2661,8 +2728,10 @@ void unpacker::read_code_headers() {
code_handler_end_PO.readData(totalHandlerCount);
code_handler_catch_PO.readData(totalHandlerCount);
code_handler_class_RCN.readData(totalHandlerCount);
CHECK;
read_attrs(ATTR_CONTEXT_CODE, totalFlagsCount);
CHECK;
}
static inline bool is_in_range(uint n, uint min, uint max) {

View File

@ -204,7 +204,7 @@ struct unpacker {
// archive header fields
int magic, minver, majver;
julong archive_size;
size_t archive_size;
int archive_next_count, archive_options, archive_modtime;
int band_headers_size;
int file_count, attr_definition_count, ic_count, class_count;

View File

@ -46,14 +46,13 @@
#include "unpack.h"
void* must_malloc(int size) {
int msize = size;
assert(size >= 0);
void* must_malloc(size_t size) {
size_t msize = size;
#ifdef USE_MTRACE
if (msize < sizeof(int))
if (msize >= 0 && msize < sizeof(int))
msize = sizeof(int); // see 0xbaadf00d below
#endif
void* ptr = malloc(msize);
void* ptr = (msize > PSIZE_MAX) ? null : malloc(msize);
if (ptr != null) {
memset(ptr, 0, size);
} else {

View File

@ -25,13 +25,31 @@
//Definitions of our util functions
void* must_malloc(int size);
void* must_malloc(size_t size);
#ifndef USE_MTRACE
#define mtrace(c, ptr, size)
#else
void mtrace(char c, void* ptr, size_t size);
#endif
// overflow management
#define OVERFLOW ((size_t)-1)
#define PSIZE_MAX (OVERFLOW/2) /* normal size limit */
inline size_t scale_size(size_t size, size_t scale) {
return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
}
inline size_t add_size(size_t size1, size_t size2) {
return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX)
? OVERFLOW
: size1 + size2;
}
inline size_t add_size(size_t size1, size_t size2, int size3) {
return add_size(add_size(size1, size2), size3);
}
// These may be expensive, because they have to go via Java TSD,
// if the optional u argument is missing.
struct unpacker;

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
Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
jstring name, jboolean addSlash)
jbyteArray name, jboolean addSlash)
{
#define MAXNAME 1024
jzfile *zip = jlong_to_ptr(zfile);
jsize slen = (*env)->GetStringLength(env, name);
jsize ulen = (*env)->GetStringUTFLength(env, name);
jsize ulen = (*env)->GetArrayLength(env, name);
char buf[MAXNAME+2], *path;
jzentry *ze;
@ -159,7 +158,7 @@ Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
} else {
path = buf;
}
(*env)->GetStringUTFRegion(env, name, 0, slen, path);
(*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path);
path[ulen] = '\0';
if (addSlash == JNI_FALSE) {
ze = ZIP_GetEntry(zip, path, 0);
@ -186,34 +185,87 @@ Java_java_util_zip_ZipFile_getNextEntry(JNIEnv *env, jclass cls, jlong zfile,
jint n)
{
jzentry *ze = ZIP_GetNextEntry(jlong_to_ptr(zfile), n);
return ptr_to_jlong(ze);
}
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);
return ze->csize != 0 ? DEFLATED : STORED;
}
JNIEXPORT jlong JNICALL
Java_java_util_zip_ZipFile_getCSize(JNIEnv *env, jclass cls, jlong zentry)
JNIEXPORT jint JNICALL
Java_java_util_zip_ZipFile_getEntryFlag(JNIEnv *env, jclass cls, jlong 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;
}
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);
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
Java_java_util_zip_ZipFile_read(JNIEnv *env, jclass cls, jlong zfile,
jlong zentry, jlong pos, jbyteArray bytes,

View File

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

View File

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

View File

@ -722,6 +722,10 @@ DGifSetupDecompress(GifFileType * GifFile) {
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
READ(GifFile, &CodeSize, 1); /* Read Code size from file. */
if (CodeSize >= 12) {
/* Invalid initial code size: report failure */
return GIF_ERROR;
}
BitsPerPixel = CodeSize;
Private->Buf[0] = 0; /* Input Buffer empty. */
@ -964,10 +968,13 @@ DGifDecompressInput(GifFileType * GifFile,
/* If code cannot fit into RunningBits bits, must raise its size. Note
* however that codes above 4095 are used for special signaling. */
if (++Private->RunningCode > Private->MaxCode1 &&
Private->RunningBits < LZ_BITS) {
Private->MaxCode1 <<= 1;
Private->RunningBits++;
if (++Private->RunningCode > Private->MaxCode1) {
if (Private->RunningBits < LZ_BITS) {
Private->MaxCode1 <<= 1;
Private->RunningBits++;
} else {
Private->RunningCode = Private->MaxCode1;
}
}
return GIF_OK;
}

View File

@ -191,6 +191,11 @@ Java_sun_awt_image_GifImageDecoder_parseImage(JNIEnv *env,
int passht = passinc;
int len;
/* We have verified the initial code size on the java layer.
* Here we just check bounds for particular indexes. */
if (freeCode >= 4096 || maxCode >= 4096) {
return 0;
}
if (blockh == 0 || raslineh == 0
|| prefixh == 0 || suffixh == 0
|| outCodeh == 0)

View File

@ -216,6 +216,16 @@ printMedialibError(int status) {
#endif /* ! DEBUG */
static int
getMlibEdgeHint(jint edgeHint) {
switch (edgeHint) {
case java_awt_image_ConvolveOp_EDGE_NO_OP:
return MLIB_EDGE_DST_COPY_SRC;
case java_awt_image_ConvolveOp_EDGE_ZERO_FILL:
default:
return MLIB_EDGE_DST_FILL_ZERO;
}
}
/***************************************************************************
* External Functions *
@ -400,22 +410,10 @@ 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;
status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
(w-1)/2, (h-1)/2, scale, cmask,
MLIB_EDGE_DST_NO_WRITE);
getMlibEdgeHint(edgeHint));
if (status != MLIB_SUCCESS) {
printMedialibError(status);
@ -660,22 +658,10 @@ 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;
status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
(w-1)/2, (h-1)/2, scale, cmask,
MLIB_EDGE_DST_NO_WRITE);
getMlibEdgeHint(edgeHint));
if (status != MLIB_SUCCESS) {
printMedialibError(status);

View File

@ -31,7 +31,7 @@
/* here come some very simple macros */
/* advance a pointer p by sizeof(type)*n bytes */
#define INCPN(type,p,n) ((p) = (type*)(p)+n)
#define INCPN(type,p,n) ((p) = (type*)(p)+(n))
/* advance a pointer by sizeof(type) */
#define INCP(type,p) INCPN(type,(p),1)

View File

@ -62,6 +62,15 @@ SplashStreamGifInputFunc(GifFileType * gif, GifByteType * buf, int n)
return rc;
}
/* These macro help to ensure that we only take part of frame that fits into
logical screen. */
/* Ensure that p belongs to [pmin, pmax) interval. Returns fixed point (if fix is needed) */
#define FIX_POINT(p, pmin, pmax) ( ((p) < (pmin)) ? (pmin) : (((p) > (pmax)) ? (pmax) : (p)))
/* Ensures that line starting at point p does not exceed boundary pmax.
Returns fixed length (if fix is needed) */
#define FIX_LENGTH(p, len, pmax) ( ((p) + (len)) > (pmax) ? ((pmax) - (p)) : (len))
int
SplashDecodeGif(Splash * splash, GifFileType * gif)
{
@ -70,6 +79,7 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
byte_t *pBitmapBits, *pOldBitmapBits;
int i, j;
int imageIndex;
int cx, cy, cw, ch; /* clamped coordinates */
const int interlacedOffset[] = { 0, 4, 2, 1, 0 }; /* The way Interlaced image should. */
const int interlacedJumps[] = { 8, 8, 4, 2, 1 }; /* be read - offsets and jumps... */
@ -79,14 +89,31 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
SplashCleanup(splash);
if (!SAFE_TO_ALLOC(gif->SWidth, splash->imageFormat.depthBytes)) {
return 0;
}
stride = gif->SWidth * splash->imageFormat.depthBytes;
if (splash->byteAlignment > 1)
stride =
(stride + splash->byteAlignment - 1) & ~(splash->byteAlignment - 1);
if (!SAFE_TO_ALLOC(gif->SHeight, stride)) {
return 0;
}
if (!SAFE_TO_ALLOC(gif->ImageCount, sizeof(SplashImage*))) {
return 0;
}
bufferSize = stride * gif->SHeight;
pBitmapBits = (byte_t *) malloc(bufferSize);
if (!pBitmapBits) {
return 0;
}
pOldBitmapBits = (byte_t *) malloc(bufferSize);
if (!pOldBitmapBits) {
free(pBitmapBits);
return 0;
}
memset(pBitmapBits, 0, bufferSize);
splash->width = gif->SWidth;
@ -94,6 +121,11 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
splash->frameCount = gif->ImageCount;
splash->frames = (SplashImage *)
malloc(sizeof(SplashImage) * gif->ImageCount);
if (!splash->frames) {
free(pBitmapBits);
free(pOldBitmapBits);
return 0;
}
memset(splash->frames, 0, sizeof(SplashImage) * gif->ImageCount);
splash->loopCount = 1;
@ -109,6 +141,11 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
int colorCount = 0;
rgbquad_t colorMapBuf[SPLASH_COLOR_MAP_SIZE];
cx = FIX_POINT(desc->Left, 0, gif->SWidth);
cy = FIX_POINT(desc->Top, 0, gif->SHeight);
cw = FIX_LENGTH(desc->Left, desc->Width, gif->SWidth);
ch = FIX_LENGTH(desc->Top, desc->Height, gif->SHeight);
if (colorMap) {
if (colorMap->ColorCount <= SPLASH_COLOR_MAP_SIZE) {
colorCount = colorMap->ColorCount;
@ -195,13 +232,22 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
for (; pass < npass; ++pass) {
int jump = interlacedJumps[pass];
int ofs = interlacedOffset[pass];
int numLines = (desc->Height + jump - 1 - ofs) / jump;
/* Number of source lines for current pass */
int numPassLines = (desc->Height + jump - ofs - 1) / jump;
/* Number of lines that fits to dest buffer */
int numLines = (ch + jump - ofs - 1) / jump;
initRect(&srcRect, 0, 0, desc->Width, numLines, 1,
desc->Width, pSrc, &srcFormat);
initRect(&dstRect, desc->Left, desc->Top + ofs, desc->Width,
numLines, jump, stride, pBitmapBits, &splash->imageFormat);
pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
if (numLines > 0) {
initRect(&dstRect, cx, cy + ofs, cw,
numLines , jump, stride, pBitmapBits, &splash->imageFormat);
pSrc += convertRect(&srcRect, &dstRect, CVT_ALPHATEST);
}
// skip extra source data
pSrc += (numPassLines - numLines) * srcRect.stride;
}
}
@ -209,6 +255,12 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
splash->frames[imageIndex].bitmapBits =
(rgbquad_t *) malloc(bufferSize);
if (!splash->frames[imageIndex].bitmapBits) {
free(pBitmapBits);
free(pOldBitmapBits);
/* Assuming that callee will take care of splash frames we have already allocated */
return 0;
}
memcpy(splash->frames[imageIndex].bitmapBits, pBitmapBits, bufferSize);
SplashInitFrameShape(splash, imageIndex);
@ -224,27 +276,29 @@ SplashDecodeGif(Splash * splash, GifFileType * gif)
{
ImageRect dstRect;
rgbquad_t fillColor = 0; // 0 is transparent
if (transparentColor < 0) {
if (transparentColor > 0) {
fillColor= MAKE_QUAD_GIF(
colorMap->Colors[gif->SBackGroundColor], 0xff);
}
initRect(&dstRect, desc->Left, desc->Top,
desc->Width, desc->Height, 1, stride,
pBitmapBits, &splash->imageFormat);
initRect(&dstRect,
cx, cy, cw, ch,
1, stride,
pBitmapBits, &splash->imageFormat);
fillRect(fillColor, &dstRect);
}
break;
case GIF_DISPOSE_RESTORE:
{
int lineSize = desc->Width * splash->imageFormat.depthBytes;
for (j = 0; j < desc->Height; j++) {
int lineIndex = stride * (j + desc->Top) +
desc->Left * splash->imageFormat.depthBytes;
memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
lineSize);
int lineSize = cw * splash->imageFormat.depthBytes;
if (lineSize > 0) {
int lineOffset = cx * splash->imageFormat.depthBytes;
int lineIndex = cy * stride + lineOffset;
for (j=0; j<ch; j++) {
memcpy(pBitmapBits + lineIndex, pOldBitmapBits + lineIndex,
lineSize);
lineIndex += stride;
}
}
}
break;

View File

@ -155,6 +155,10 @@ int BitmapToYXBandedRectangles(ImageRect * pSrcRect, RECT_T * out);
void SplashInitFrameShape(Splash * splash, int imageIndex);
#define SAFE_TO_ALLOC(c, sz) \
(((c) > 0) && ((sz) > 0) && \
((0xffffffffu / ((unsigned int)(c))) > (unsigned int)(sz)))
#define dbgprintf printf
#endif

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);
if (!SAFE_TO_ALLOC(rowbytes, height)) {
goto done;
}
if ((image_data = (unsigned char *) malloc(rowbytes * height)) == NULL) {
goto done;
}
if (!SAFE_TO_ALLOC(height, sizeof(png_bytep))) {
goto done;
}
if ((row_pointers = (png_bytepp) malloc(height * sizeof(png_bytep)))
== NULL) {
goto done;
@ -121,13 +129,28 @@ SplashDecodePng(Splash * splash, png_rw_ptr read_func, void *io_ptr)
splash->width = width;
splash->height = height;
if (!SAFE_TO_ALLOC(splash->width, splash->imageFormat.depthBytes)) {
goto done;
}
stride = splash->width * splash->imageFormat.depthBytes;
if (!SAFE_TO_ALLOC(splash->height, stride)) {
goto done;
}
splash->frameCount = 1;
splash->frames = (SplashImage *)
malloc(sizeof(SplashImage) * splash->frameCount);
if (splash->frames == NULL) {
goto done;
}
splash->loopCount = 1;
splash->frames[0].bitmapBits = malloc(stride * splash->height);
if (splash->frames[0].bitmapBits == NULL) {
free(splash->frames);
goto done;
}
splash->frames[0].delay = 0;
/* FIXME: sort out the real format */

View File

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

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.
*
* 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 sun.security.jca.JCAUtil;
import sun.security.rsa.RSAKeyFactory;
/**
* RSA keypair generator.
@ -43,8 +44,8 @@ import sun.security.jca.JCAUtil;
public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// Supported by Microsoft Base, Strong and Enhanced Cryptographic Providers
private static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384
private static final int KEY_SIZE_MAX = 16384;
static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384
static final int KEY_SIZE_MAX = 16384;
private static final int KEY_SIZE_DEFAULT = 1024;
// size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
@ -59,7 +60,14 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
// random is always ignored
public void initialize(int keySize, SecureRandom random) {
checkKeySize(keySize);
try {
RSAKeyFactory.checkKeyLengths(keySize, null,
KEY_SIZE_MIN, KEY_SIZE_MAX);
} catch (InvalidKeyException e) {
throw new InvalidParameterException(e.getMessage());
}
this.keySize = keySize;
}
// second initialize method. See JCA doc
@ -67,21 +75,31 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException {
int tmpSize;
if (params == null) {
checkKeySize(KEY_SIZE_DEFAULT);
tmpSize = KEY_SIZE_DEFAULT;
} else if (params instanceof RSAKeyGenParameterSpec) {
if (((RSAKeyGenParameterSpec) params).getPublicExponent() != null) {
throw new InvalidAlgorithmParameterException
("Exponent parameter is not supported");
}
checkKeySize(((RSAKeyGenParameterSpec) params).getKeysize());
tmpSize = ((RSAKeyGenParameterSpec) params).getKeysize();
} else {
throw new InvalidAlgorithmParameterException
("Params must be an instance of RSAKeyGenParameterSpec");
}
try {
RSAKeyFactory.checkKeyLengths(tmpSize, null,
KEY_SIZE_MIN, KEY_SIZE_MAX);
} catch (InvalidKeyException e) {
throw new InvalidAlgorithmParameterException(
"Invalid Key sizes", e);
}
this.keySize = tmpSize;
}
// generate the keypair. See JCA doc
@ -95,18 +113,6 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi {
return new KeyPair(keys.getPublic(), keys.getPrivate());
}
private void checkKeySize(int keySize) throws InvalidParameterException {
if (keySize < KEY_SIZE_MIN) {
throw new InvalidParameterException
("Key size must be at least " + KEY_SIZE_MIN + " bits");
}
if (keySize > KEY_SIZE_MAX) {
throw new InvalidParameterException
("Key size must be " + KEY_SIZE_MAX + " bits or less");
}
this.keySize = keySize;
}
private static native RSAKeyPair generateRSAKeyPair(int keySize,
String keyContainerName);
}

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.
*
* 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.SignatureSpi;
import java.security.SignatureException;
import java.math.BigInteger;
import sun.security.rsa.RSAKeyFactory;
/**
* RSA signature implementation. Supports RSA signing using PKCS#1 v1.5 padding.
@ -124,7 +127,16 @@ abstract class RSASignature extends java.security.SignatureSpi
// convert key to MSCAPI format
byte[] modulusBytes = rsaKey.getModulus().toByteArray();
BigInteger modulus = rsaKey.getModulus();
BigInteger exponent = rsaKey.getPublicExponent();
// Check against the local and global values to make sure
// the sizes are ok. Round up to the nearest byte.
RSAKeyFactory.checkKeyLengths(((modulus.bitLength() + 7) & ~7),
exponent, -1, RSAKeyPairGenerator.KEY_SIZE_MAX);
byte[] modulusBytes = modulus.toByteArray();
byte[] exponentBytes = exponent.toByteArray();
// Adjust key length due to sign bit
int keyBitLength = (modulusBytes[0] == 0)
@ -132,8 +144,7 @@ abstract class RSASignature extends java.security.SignatureSpi
: modulusBytes.length * 8;
byte[] keyBlob = generatePublicKeyBlob(
keyBitLength, modulusBytes,
rsaKey.getPublicExponent().toByteArray());
keyBitLength, modulusBytes, exponentBytes);
publicKey = importPublicKey(keyBlob, keyBitLength);
@ -166,12 +177,11 @@ abstract class RSASignature extends java.security.SignatureSpi
}
privateKey = (sun.security.mscapi.RSAPrivateKey) key;
// Determine byte length from bit length
int keySize = (privateKey.bitLength() + 7) >> 3;
if (keySize < 64)
throw new InvalidKeyException(
"RSA keys must be at least 512 bits long");
// Check against the local and global values to make sure
// the sizes are ok. Round up to nearest byte.
RSAKeyFactory.checkKeyLengths(((privateKey.bitLength() + 7) & ~7),
null, RSAKeyPairGenerator.KEY_SIZE_MIN,
RSAKeyPairGenerator.KEY_SIZE_MAX);
if (needsReset) {
messageDigest.reset();

View File

@ -414,7 +414,7 @@ Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this,
o.Offset = lowPos;
o.OffsetHigh = highPos;
result = UnlockFileEx(h, 0, lowNumBytes, highNumBytes, &o);
if (result == 0) {
if (result == 0 && GetLastError() != ERROR_NOT_LOCKED) {
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.
*
* 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
*
*/
BOOL native_debug = 0;
BOOL PackageConnectLookup(PHANDLE,PULONG);
@ -113,208 +114,221 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
jclass cls;
JNIEnv *env;
jfieldID fldDEBUG;
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {
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");
if (cls == NULL) {
printf("Couldn't find Ticket\n");
printf("LSA: Couldn't find Ticket\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found Ticket\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found Ticket\n");
}
ticketClass = (*env)->NewWeakGlobalRef(env,cls);
if (ticketClass == NULL) {
return JNI_ERR;
}
#ifdef DEBUG
printf("Made NewWeakGlobalRef\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
cls = (*env)->FindClass(env, "sun/security/krb5/PrincipalName");
if (cls == NULL) {
printf("Couldn't find PrincipalName\n");
printf("LSA: Couldn't find PrincipalName\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found PrincipalName\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found PrincipalName\n");
}
principalNameClass = (*env)->NewWeakGlobalRef(env,cls);
if (principalNameClass == NULL) {
return JNI_ERR;
}
#ifdef DEBUG
printf("Made NewWeakGlobalRef\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
cls = (*env)->FindClass(env,"sun/security/util/DerValue");
if (cls == NULL) {
printf("Couldn't find DerValue\n");
printf("LSA: Couldn't find DerValue\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found DerValue\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found DerValue\n");
}
derValueClass = (*env)->NewWeakGlobalRef(env,cls);
if (derValueClass == NULL) {
return JNI_ERR;
}
#ifdef DEBUG
printf("Made NewWeakGlobalRef\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
cls = (*env)->FindClass(env,"sun/security/krb5/EncryptionKey");
if (cls == NULL) {
printf("Couldn't find EncryptionKey\n");
printf("LSA: Couldn't find EncryptionKey\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found EncryptionKey\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found EncryptionKey\n");
}
encryptionKeyClass = (*env)->NewWeakGlobalRef(env,cls);
if (encryptionKeyClass == NULL) {
return JNI_ERR;
}
#ifdef DEBUG
printf("Made NewWeakGlobalRef\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
cls = (*env)->FindClass(env,"sun/security/krb5/internal/TicketFlags");
if (cls == NULL) {
printf("Couldn't find TicketFlags\n");
printf("LSA: Couldn't find TicketFlags\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found TicketFlags\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found TicketFlags\n");
}
ticketFlagsClass = (*env)->NewWeakGlobalRef(env,cls);
if (ticketFlagsClass == NULL) {
return JNI_ERR;
}
#ifdef DEBUG
printf("Made NewWeakGlobalRef\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
cls = (*env)->FindClass(env,"sun/security/krb5/internal/KerberosTime");
if (cls == NULL) {
printf("Couldn't find KerberosTime\n");
printf("LSA: Couldn't find KerberosTime\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found KerberosTime\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found KerberosTime\n");
}
kerberosTimeClass = (*env)->NewWeakGlobalRef(env,cls);
if (kerberosTimeClass == NULL) {
return JNI_ERR;
}
#ifdef DEBUG
printf("Made NewWeakGlobalRef\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
cls = (*env)->FindClass(env,"java/lang/String");
if (cls == NULL) {
printf("Couldn't find String\n");
printf("LSA: Couldn't find String\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found String\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found String\n");
}
javaLangStringClass = (*env)->NewWeakGlobalRef(env,cls);
if (javaLangStringClass == NULL) {
return JNI_ERR;
}
#ifdef DEBUG
printf("Made NewWeakGlobalRef\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Made NewWeakGlobalRef\n");
}
derValueConstructor = (*env)->GetMethodID(env, derValueClass,
"<init>", "([B)V");
if (derValueConstructor == 0) {
printf("Couldn't find DerValue constructor\n");
printf("LSA: Couldn't find DerValue constructor\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found DerValue constructor\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found DerValue constructor\n");
}
ticketConstructor = (*env)->GetMethodID(env, ticketClass,
"<init>", "(Lsun/security/util/DerValue;)V");
if (ticketConstructor == 0) {
printf("Couldn't find Ticket constructor\n");
printf("LSA: Couldn't find Ticket constructor\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found Ticket constructor\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found Ticket constructor\n");
}
principalNameConstructor = (*env)->GetMethodID(env, principalNameClass,
"<init>", "([Ljava/lang/String;)V");
if (principalNameConstructor == 0) {
printf("Couldn't find PrincipalName constructor\n");
printf("LSA: Couldn't find PrincipalName constructor\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found PrincipalName constructor\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found PrincipalName constructor\n");
}
encryptionKeyConstructor = (*env)->GetMethodID(env, encryptionKeyClass,
"<init>", "(I[B)V");
if (encryptionKeyConstructor == 0) {
printf("Couldn't find EncryptionKey constructor\n");
printf("LSA: Couldn't find EncryptionKey constructor\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found EncryptionKey constructor\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found EncryptionKey constructor\n");
}
ticketFlagsConstructor = (*env)->GetMethodID(env, ticketFlagsClass,
"<init>", "(I[B)V");
if (ticketFlagsConstructor == 0) {
printf("Couldn't find TicketFlags constructor\n");
printf("LSA: Couldn't find TicketFlags constructor\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found TicketFlags constructor\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found TicketFlags constructor\n");
}
kerberosTimeConstructor = (*env)->GetMethodID(env, kerberosTimeClass,
"<init>", "(Ljava/lang/String;)V");
if (kerberosTimeConstructor == 0) {
printf("Couldn't find KerberosTime constructor\n");
printf("LSA: Couldn't find KerberosTime constructor\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Found KerberosTime constructor\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Found KerberosTime constructor\n");
}
// load the setRealm method in PrincipalName
setRealmMethod = (*env)->GetMethodID(env, principalNameClass,
"setRealm", "(Ljava/lang/String;)V");
if (setRealmMethod == 0) {
printf("Couldn't find setRealm in PrincipalName\n");
printf("LSA: Couldn't find setRealm in PrincipalName\n");
return JNI_ERR;
}
#ifdef DEBUG
printf("Finished OnLoad processing\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Finished OnLoad processing\n");
}
return JNI_VERSION_1_2;
}
@ -389,16 +403,25 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
if (krbcredsConstructor == 0) {
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) {
printf("Couldn't find sun.security.krb5.Credentials constructor\n");
printf("LSA: Couldn't find sun.security.krb5.Credentials constructor\n");
break;
}
}
#ifdef DEBUG
printf("Found KrbCreds constructor\n");
#endif
if (native_debug) {
printf("LSA: Found KrbCreds constructor\n");
}
//
// 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))
break;
#ifdef DEBUG
printf("Got handle to Kerberos package\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Got handle to Kerberos package\n");
}
// Get the MS TGT from cache
CacheRequest.MessageType = KerbRetrieveTicketMessage;
@ -426,9 +449,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
&SubStatus
);
#ifdef DEBUG
printf("Response size is %d\n", rspSize);
#endif
if (native_debug) {
printf("LSA: Response size is %d\n", rspSize);
}
if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
if (!LSA_SUCCESS(Status)) {
@ -467,9 +490,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
}
if (ignore_cache) {
#ifdef DEBUG
printf("MS TGT in cache is invalid/not supported; request new ticket\n");
#endif /* DEBUG */
if (native_debug) {
printf("LSA: MS TGT in cache is invalid/not supported; request new ticket\n");
}
// use domain to request Ticket
Status = ConstructTicketRequest(msticket->TargetDomainName,
@ -493,9 +516,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
&SubStatus
);
#ifdef DEBUG
printf("Response size is %d\n", responseSize);
#endif /* DEBUG */
if (native_debug) {
printf("LSA: Response size is %d\n", responseSize);
}
if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
if (!LSA_SUCCESS(Status)) {
@ -788,7 +811,9 @@ ShowLastError(
static WCHAR szMsgBuf[MAX_MSG_SIZE];
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 (
FORMAT_MESSAGE_FROM_SYSTEM,
@ -798,11 +823,13 @@ ShowLastError(
szMsgBuf,
MAX_MSG_SIZE,
NULL);
if (0 == dwRes) {
printf("FormatMessage failed with %d\n", GetLastError());
// ExitProcess(EXIT_FAILURE);
} else {
printf("%S",szMsgBuf);
if (native_debug) {
if (0 == dwRes) {
printf("LSA: FormatMessage failed with %d\n", GetLastError());
// ExitProcess(EXIT_FAILURE);
} else {
printf("LSA: %S",szMsgBuf);
}
}
}
@ -896,17 +923,19 @@ jobject BuildPrincipal(JNIEnv *env, PKERB_EXTERNAL_NAME principalName,
((domainName.Length)*sizeof(WCHAR) + sizeof(UNICODE_NULL)));
wcsncpy(realm, domainName.Buffer, domainName.Length/sizeof(WCHAR));
#ifdef DEBUG
printf("Principal domain is %S\n", realm);
printf("Name type is %x\n", principalName->NameType);
printf("Name count is %x\n", principalName->NameCount);
#endif
if (native_debug) {
printf("LSA: Principal domain is %S\n", realm);
printf("LSA: Name type is %x\n", principalName->NameType);
printf("LSA: Name count is %x\n", principalName->NameCount);
}
nameCount = principalName->NameCount;
stringArray = (*env)->NewObjectArray(env, nameCount,
javaLangStringClass, 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);
return principal;
}
@ -941,6 +970,17 @@ jobject BuildEncryptionKey(JNIEnv *env, PKERB_CRYPTO_KEY cryptoKey) {
// First, need to build a byte array
jbyteArray ary;
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);
(*env)->SetByteArrayRegion(env, ary, (jsize) 0, cryptoKey->Length,
@ -1005,9 +1045,9 @@ jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime) {
hour,
minute,
second );
#ifdef DEBUG
printf("%S\n", (wchar_t *)timeString);
#endif /* DEBUG */
if (native_debug) {
printf("LSA: %S\n", (wchar_t *)timeString);
}
stringTime = (*env)->NewString(env, timeString,
(sizeof(timeString)/sizeof(WCHAR))-1);
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