提交 78919f1d 编写于 作者: T tbell

Merge

......@@ -29,7 +29,6 @@ FILES_c = \
Deflater.c \
Inflater.c \
ZipFile.c \
ZipEntry.c \
zadler32.c \
zcrc32.c \
deflate.c \
......
......@@ -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;
......
......@@ -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_;
......
......@@ -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_;
......
......@@ -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_;
......
......@@ -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'"
......
......@@ -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();
......
......@@ -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
......
......@@ -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);
}
......
......@@ -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 static boolean checkCreateAccess(Access access, String className) {
for (String classNamePattern : access.createPatterns) {
if (classNameMatch(classNamePattern, className))
return true;
}
return false;
}
private static boolean classNameMatch(String pattern, String className) {
// We studiously avoided regexes when parsing the properties file,
// because that is done whenever the VM is started with the
// appropriate -Dcom.sun.management options, even if nobody ever
// creates an MBean. We don't want to incur the overhead of loading
// all the regex code whenever those options are specified, but if we
// get as far as here then the VM is already running and somebody is
// doing the very unusual operation of remotely creating an MBean.
// Because that operation is so unusual, we don't try to optimize
// by hand-matching or by caching compiled Pattern objects.
StringBuilder sb = new StringBuilder();
StringTokenizer stok = new StringTokenizer(pattern, "*", true);
while (stok.hasMoreTokens()) {
String tok = stok.nextToken();
if (tok.equals("*"))
sb.append("[^.]*");
else
sb.append(Pattern.quote(tok));
}
return className.matches(sb.toString());
}
private void parseProperties(Properties props) {
this.accessMap = new HashMap<String, Access>();
for (Map.Entry<Object, Object> entry : props.entrySet()) {
String identity = (String) entry.getKey();
String accessString = (String) entry.getValue();
Access access = Parser.parseAccess(identity, accessString);
accessMap.put(identity, access);
}
}
private void checkValues(Properties props) {
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 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 Properties props;
private Map<String, Access> accessMap;
private Properties originalProps;
private String accessFileName;
}
......@@ -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 {
......
/*
* 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;
......
......@@ -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;
}
});
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");
boolean copiedFontData = false;
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);
}
/**
......
......@@ -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.
......
......@@ -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]
......
......@@ -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]
......
......@@ -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]
......
......@@ -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();
}
......
......@@ -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
......
......@@ -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)
......
......@@ -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>
......
......@@ -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>
......
......@@ -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.
......
......@@ -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>).
*
......
......@@ -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
......
......@@ -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
......
......@@ -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)
......
......@@ -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
......
......@@ -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
......
......@@ -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;
}
}
}
......
/*
* 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;
}
}
......@@ -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() {}
}
......@@ -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;
}
......
......@@ -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);
}
......@@ -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.
......
......@@ -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;
}
}
......@@ -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>
......
......@@ -599,7 +599,7 @@ public class CounterMonitor extends Monitor implements CounterMonitorMBean {
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return notifsInfo;
return notifsInfo.clone();
}
/*
......
......@@ -481,7 +481,7 @@ public class GaugeMonitor extends Monitor implements GaugeMonitorMBean {
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return notifsInfo;
return notifsInfo.clone();
}
/*
......
......@@ -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.
......@@ -173,14 +179,20 @@ public abstract class Monitor
new DaemonThreadFactory("Scheduler"));
/**
* Maximum Pool Size
* Map containing the thread pool executor per thread group.
*/
private static final int maximumPoolSize;
private static final Map<ThreadPoolExecutor, Void> executors =
new WeakHashMap<ThreadPoolExecutor, Void>();
/**
* Lock for executors map.
*/
private static final Object executorsLock = new Object();
/**
* Executor Service.
* Maximum Pool Size
*/
private static final ThreadPoolExecutor executor;
private static final int maximumPoolSize;
static {
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,
......
......@@ -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();
}
/*
......
......@@ -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);
}
......
......@@ -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) {
......
/*
* Copyright 1998 Sun Microsystems, Inc. All Rights Reserved.
* 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
......@@ -23,83 +23,32 @@
* 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"
package sun.font;
#include "java_util_zip_ZipEntry.h"
public class CreatedFontTracker {
#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;");
}
public static final int MAX_FILE_SIZE = 32 * 1024 * 1024;
public static final int MAX_TOTAL_BYTES = 10 * MAX_FILE_SIZE;
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);
static int numBytes;
static CreatedFontTracker tracker;
if (name == 0) {
name = (*env)->NewStringUTF(env, ze->name);
if (name == 0) {
return;
public static synchronized CreatedFontTracker getTracker() {
if (tracker == null) {
tracker = new CreatedFontTracker();
}
(*env)->SetObjectField(env, obj, nameID, name);
return tracker;
}
(*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);
public synchronized int getNumBytes() {
return numBytes;
}
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);
public synchronized void addBytes(int sz) {
numBytes += sz;
}
if (ze->comment != 0) {
jstring comment = (*env)->NewStringUTF(env, ze->comment);
if (comment == 0) {
return;
}
(*env)->SetObjectField(env, obj, commentID, comment);
public synchronized void subBytes(int sz) {
numBytes -= sz;
}
}
/*
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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
......
......@@ -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) {
......
......@@ -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);
}
......
......@@ -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 {
......
......@@ -52,6 +52,9 @@ class Request {
os = rawout;
do {
startLine = readLine();
if (startLine == null) {
return;
}
/* skip blank lines */
} while (startLine == null ? false : startLine.equals (""));
}
......
......@@ -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();
......
......@@ -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.
*/
protected abstract void implRelease(FileLockImpl fli) throws IOException;
/**
* Invoked by FileLockImpl to release the given file lock and remove it
* from the lock table.
*/
abstract void release(FileLockImpl fli) throws IOException;
final void release(FileLockImpl fli) throws IOException {
try {
begin();
implRelease(fli);
removeFromFileLockTable(fli);
} finally {
end();
}
}
}
......@@ -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;
}
if (result == FileDispatcher.INTERRUPTED || result == FileDispatcher.NO_LOCK) {
flt.remove(fli);
i = false;
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;
}
} 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;
}
}
......
......@@ -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;
}
}
}
......@@ -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
......
......@@ -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
......
......@@ -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);
}
}
}
}
......@@ -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();
}
}
}
......
......@@ -93,4 +93,7 @@ public class UDPClient {
return data;
}
public void close() {
dgSocket.close();
}
}
/*
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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
......
......@@ -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,
......
/*
* 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),
......
......@@ -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];
......
/*
* 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");
}
}
......
/*
* 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
......
/*
* 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 {
......
/*
* 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 {
......
/*
* 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
......
......@@ -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
/*
* 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;
......
......@@ -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;
......
/*
* 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;
......
/*
* 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"
......
......@@ -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':
......
/*
* 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) {
......
......@@ -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;
......
......@@ -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 {
......
......@@ -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;
......
......@@ -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,
......
......@@ -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);
......
......@@ -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;
/*
......
......@@ -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)
......
......@@ -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)
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册