提交 e06c9d77 编写于 作者: E ewendeli

Merge

...@@ -66,7 +66,7 @@ int JLI_GetStdArgc(); ...@@ -66,7 +66,7 @@ int JLI_GetStdArgc();
#include <io.h> #include <io.h>
#define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2)) #define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2))
#define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3)) #define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3))
#define JLI_Snprintf _snprintf int JLI_Snprintf(char *buffer, size_t size, const char *format, ...);
void JLI_CmdToArgs(char *cmdline); void JLI_CmdToArgs(char *cmdline);
#define JLI_Lseek _lseeki64 #define JLI_Lseek _lseeki64
#else /* NIXES */ #else /* NIXES */
......
...@@ -569,9 +569,9 @@ JLI_ParseManifest(char *jarfile, manifest_info *info) ...@@ -569,9 +569,9 @@ JLI_ParseManifest(char *jarfile, manifest_info *info)
#ifdef O_BINARY #ifdef O_BINARY
| O_BINARY /* use binary mode on windows */ | O_BINARY /* use binary mode on windows */
#endif #endif
)) == -1) )) == -1) {
return (-1); return (-1);
}
info->manifest_version = NULL; info->manifest_version = NULL;
info->main_class = NULL; info->main_class = NULL;
info->jre_version = NULL; info->jre_version = NULL;
...@@ -618,15 +618,17 @@ JLI_JarUnpackFile(const char *jarfile, const char *filename, int *size) { ...@@ -618,15 +618,17 @@ JLI_JarUnpackFile(const char *jarfile, const char *filename, int *size) {
zentry entry; zentry entry;
void *data = NULL; void *data = NULL;
fd = open(jarfile, O_RDONLY if ((fd = open(jarfile, O_RDONLY
#ifdef O_LARGEFILE #ifdef O_LARGEFILE
| O_LARGEFILE /* large file mode */ | O_LARGEFILE /* large file mode */
#endif #endif
#ifdef O_BINARY #ifdef O_BINARY
| O_BINARY /* use binary mode on windows */ | O_BINARY /* use binary mode on windows */
#endif #endif
); )) == -1) {
if (fd != -1 && find_file(fd, &entry, filename) == 0) { return NULL;
}
if (find_file(fd, &entry, filename) == 0) {
data = inflate_file(fd, &entry, size); data = inflate_file(fd, &entry, size);
} }
close(fd); close(fd);
...@@ -671,8 +673,9 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data) ...@@ -671,8 +673,9 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data)
#ifdef O_BINARY #ifdef O_BINARY
| O_BINARY /* use binary mode on windows */ | O_BINARY /* use binary mode on windows */
#endif #endif
)) == -1) )) == -1) {
return (-1); return (-1);
}
if (rc = find_file(fd, &entry, manifest_name) != 0) { if (rc = find_file(fd, &entry, manifest_name) != 0) {
close(fd); close(fd);
......
...@@ -66,11 +66,14 @@ public final class MethodFinder extends AbstractFinder<Method> { ...@@ -66,11 +66,14 @@ public final class MethodFinder extends AbstractFinder<Method> {
Signature signature = new Signature(type, name, args); Signature signature = new Signature(type, name, args);
Method method = CACHE.get(signature); Method method = CACHE.get(signature);
if (method != null) { boolean cached = method != null;
if (cached && isPackageAccessible(method.getDeclaringClass())) {
return method; return method;
} }
method = findAccessibleMethod(new MethodFinder(name, args).find(type.getMethods())); method = findAccessibleMethod(new MethodFinder(name, args).find(type.getMethods()));
CACHE.put(signature, method); if (!cached) {
CACHE.put(signature, method);
}
return method; return method;
} }
......
...@@ -41,6 +41,8 @@ import javax.crypto.ShortBufferException; ...@@ -41,6 +41,8 @@ import javax.crypto.ShortBufferException;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.spec.*; import javax.crypto.spec.*;
import sun.security.util.KeyUtil;
/** /**
* This class implements the Diffie-Hellman key agreement protocol between * This class implements the Diffie-Hellman key agreement protocol between
* any number of parties. * any number of parties.
...@@ -200,6 +202,9 @@ extends KeyAgreementSpi { ...@@ -200,6 +202,9 @@ extends KeyAgreementSpi {
throw new InvalidKeyException("Incompatible parameters"); throw new InvalidKeyException("Incompatible parameters");
} }
// validate the Diffie-Hellman public key
KeyUtil.validate(dhPubKey);
// store the y value // store the y value
this.y = dhPubKey.getY(); this.y = dhPubKey.getY();
......
...@@ -1000,7 +1000,6 @@ class BandStructure { ...@@ -1000,7 +1000,6 @@ class BandStructure {
/** Write a constant pool reference. */ /** Write a constant pool reference. */
public void putRef(Entry e) { public void putRef(Entry e) {
assert(index != null);
addValue(encodeRefOrNull(e, index)); addValue(encodeRefOrNull(e, index));
} }
public void putRef(Entry e, Index index) { public void putRef(Entry e, Index index) {
...@@ -1052,6 +1051,8 @@ class BandStructure { ...@@ -1052,6 +1051,8 @@ class BandStructure {
int encodeRef(Entry e, Index ix) { int encodeRef(Entry e, Index ix) {
if (ix == null)
throw new RuntimeException("null index for " + e.stringValue());
int coding = ix.indexOf(e); int coding = ix.indexOf(e);
if (verbose > 2) if (verbose > 2)
Utils.log.fine("putRef "+coding+" => "+e); Utils.log.fine("putRef "+coding+" => "+e);
......
...@@ -1405,6 +1405,8 @@ class ConstantPool { ...@@ -1405,6 +1405,8 @@ class ConstantPool {
/** Index of all CP entries of a given tag and class. */ /** Index of all CP entries of a given tag and class. */
public Index getMemberIndex(byte tag, ClassEntry classRef) { public Index getMemberIndex(byte tag, ClassEntry classRef) {
if (classRef == null)
throw new RuntimeException("missing class reference for " + tagName(tag));
if (indexByTagAndClass == null) if (indexByTagAndClass == null)
indexByTagAndClass = new Index[CONSTANT_Limit][]; indexByTagAndClass = new Index[CONSTANT_Limit][];
Index allClasses = getIndexByTag(CONSTANT_Class); Index allClasses = getIndexByTag(CONSTANT_Class);
......
...@@ -109,6 +109,10 @@ class NativeUnpack { ...@@ -109,6 +109,10 @@ class NativeUnpack {
return (p200 == null)? null: p200._nunp; return (p200 == null)? null: p200._nunp;
} }
private synchronized long getUnpackerPtr() {
return unpackerPtr;
}
// Callback from the unpacker engine to get more data. // Callback from the unpacker engine to get more data.
private long readInputFn(ByteBuffer pbuf, long minlen) throws IOException { private long readInputFn(ByteBuffer pbuf, long minlen) throws IOException {
if (in == null) return 0; // nothing is readable if (in == null) return 0; // nothing is readable
......
...@@ -83,7 +83,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { ...@@ -83,7 +83,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
* @param out an OutputStream * @param out an OutputStream
* @exception IOException if an error is encountered. * @exception IOException if an error is encountered.
*/ */
public void pack(JarFile in, OutputStream out) throws IOException { public synchronized void pack(JarFile in, OutputStream out) throws IOException {
assert(Utils.currentInstance.get() == null); assert(Utils.currentInstance.get() == null);
TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
? null ? null
...@@ -118,7 +118,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer { ...@@ -118,7 +118,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
* @param out an OutputStream * @param out an OutputStream
* @exception IOException if an error is encountered. * @exception IOException if an error is encountered.
*/ */
public void pack(JarInputStream in, OutputStream out) throws IOException { public synchronized void pack(JarInputStream in, OutputStream out) throws IOException {
assert(Utils.currentInstance.get() == null); assert(Utils.currentInstance.get() == null);
TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
TimeZone.getDefault(); TimeZone.getDefault();
......
/* /*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -106,7 +106,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker { ...@@ -106,7 +106,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker {
* @param out a JarOutputStream. * @param out a JarOutputStream.
* @exception IOException if an error is encountered. * @exception IOException if an error is encountered.
*/ */
public void unpack(InputStream in, JarOutputStream out) throws IOException { public synchronized void unpack(InputStream in, JarOutputStream out) throws IOException {
if (in == null) { if (in == null) {
throw new NullPointerException("null input"); throw new NullPointerException("null input");
} }
...@@ -151,7 +151,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker { ...@@ -151,7 +151,7 @@ public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker {
* @param out a JarOutputStream. * @param out a JarOutputStream.
* @exception IOException if an error is encountered. * @exception IOException if an error is encountered.
*/ */
public void unpack(File in, JarOutputStream out) throws IOException { public synchronized void unpack(File in, JarOutputStream out) throws IOException {
if (in == null) { if (in == null) {
throw new NullPointerException("null input"); throw new NullPointerException("null input");
} }
......
...@@ -36,6 +36,7 @@ import java.util.logging.Level; ...@@ -36,6 +36,7 @@ import java.util.logging.Level;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.management.loading.PrivateClassLoader; import javax.management.loading.PrivateClassLoader;
import sun.reflect.misc.ReflectUtil;
/** /**
* This class keeps the list of Class Loaders registered in the MBean Server. * This class keeps the list of Class Loaders registered in the MBean Server.
...@@ -192,6 +193,7 @@ final class ClassLoaderRepositorySupport ...@@ -192,6 +193,7 @@ final class ClassLoaderRepositorySupport
final ClassLoader without, final ClassLoader without,
final ClassLoader stop) final ClassLoader stop)
throws ClassNotFoundException { throws ClassNotFoundException {
ReflectUtil.checkPackageAccess(className);
final int size = list.length; final int size = list.length;
for(int i=0; i<size; i++) { for(int i=0; i<size; i++) {
try { try {
......
...@@ -54,6 +54,8 @@ import java.lang.reflect.Array; ...@@ -54,6 +54,8 @@ import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import javax.management.AttributeNotFoundException; import javax.management.AttributeNotFoundException;
import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeData;
import sun.reflect.misc.MethodUtil;
import sun.reflect.misc.ReflectUtil;
/** /**
* This class contains the methods for performing all the tests needed to verify * This class contains the methods for performing all the tests needed to verify
...@@ -526,8 +528,10 @@ public class Introspector { ...@@ -526,8 +528,10 @@ public class Introspector {
// to locate method // to locate method
readMethod = SimpleIntrospector.getReadMethod(clazz, element); readMethod = SimpleIntrospector.getReadMethod(clazz, element);
} }
if (readMethod != null) if (readMethod != null) {
return readMethod.invoke(complex); ReflectUtil.checkPackageAccess(readMethod.getDeclaringClass());
return MethodUtil.invoke(readMethod, complex, new Class[0]);
}
throw new AttributeNotFoundException( throw new AttributeNotFoundException(
"Could not find the getter method for the property " + "Could not find the getter method for the property " +
......
...@@ -51,6 +51,7 @@ import javax.management.MBeanPermission; ...@@ -51,6 +51,7 @@ import javax.management.MBeanPermission;
import javax.management.MBeanRegistrationException; import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer; import javax.management.MBeanServer;
import javax.management.MBeanServerDelegate; import javax.management.MBeanServerDelegate;
import javax.management.MBeanServerPermission;
import javax.management.NotCompliantMBeanException; import javax.management.NotCompliantMBeanException;
import javax.management.NotificationFilter; import javax.management.NotificationFilter;
import javax.management.NotificationListener; import javax.management.NotificationListener;
...@@ -1409,6 +1410,8 @@ public final class JmxMBeanServer ...@@ -1409,6 +1410,8 @@ public final class JmxMBeanServer
// Default is true. // Default is true.
final boolean fairLock = DEFAULT_FAIR_LOCK_POLICY; final boolean fairLock = DEFAULT_FAIR_LOCK_POLICY;
checkNewMBeanServerPermission();
// This constructor happens to disregard the value of the interceptors // This constructor happens to disregard the value of the interceptors
// flag - that is, it always uses the default value - false. // flag - that is, it always uses the default value - false.
// This is admitedly a bug, but we chose not to fix it for now // This is admitedly a bug, but we chose not to fix it for now
...@@ -1494,4 +1497,11 @@ public final class JmxMBeanServer ...@@ -1494,4 +1497,11 @@ public final class JmxMBeanServer
} }
} }
private static void checkNewMBeanServerPermission() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
Permission perm = new MBeanServerPermission("newMBeanServer");
sm.checkPermission(perm);
}
}
} }
...@@ -32,11 +32,13 @@ import java.io.IOException; ...@@ -32,11 +32,13 @@ import java.io.IOException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.security.Permission;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import javax.management.InstanceNotFoundException; import javax.management.InstanceNotFoundException;
import javax.management.MBeanException; import javax.management.MBeanException;
import javax.management.MBeanPermission;
import javax.management.NotCompliantMBeanException; import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.management.OperationsException; import javax.management.OperationsException;
...@@ -44,7 +46,7 @@ import javax.management.ReflectionException; ...@@ -44,7 +46,7 @@ import javax.management.ReflectionException;
import javax.management.RuntimeErrorException; import javax.management.RuntimeErrorException;
import javax.management.RuntimeMBeanException; import javax.management.RuntimeMBeanException;
import javax.management.RuntimeOperationsException; import javax.management.RuntimeOperationsException;
import sun.reflect.misc.ConstructorUtil;
import sun.reflect.misc.ReflectUtil; import sun.reflect.misc.ReflectUtil;
/** /**
...@@ -56,7 +58,6 @@ import sun.reflect.misc.ReflectUtil; ...@@ -56,7 +58,6 @@ import sun.reflect.misc.ReflectUtil;
* @since 1.5 * @since 1.5
*/ */
public class MBeanInstantiator { public class MBeanInstantiator {
private final ModifiableClassLoaderRepository clr; private final ModifiableClassLoaderRepository clr;
// private MetaData meta = null; // private MetaData meta = null;
...@@ -88,6 +89,7 @@ public class MBeanInstantiator { ...@@ -88,6 +89,7 @@ public class MBeanInstantiator {
"Exception occurred during object instantiation"); "Exception occurred during object instantiation");
} }
ReflectUtil.checkPackageAccess(className);
try { try {
if (clr == null) throw new ClassNotFoundException(className); if (clr == null) throw new ClassNotFoundException(className);
theClass = clr.loadClass(className); theClass = clr.loadClass(className);
...@@ -162,6 +164,7 @@ public class MBeanInstantiator { ...@@ -162,6 +164,7 @@ public class MBeanInstantiator {
continue; continue;
} }
ReflectUtil.checkPackageAccess(signature[i]);
// Ok we do not have a primitive type ! We need to build // Ok we do not have a primitive type ! We need to build
// the signature of the method // the signature of the method
// //
...@@ -205,6 +208,9 @@ public class MBeanInstantiator { ...@@ -205,6 +208,9 @@ public class MBeanInstantiator {
*/ */
public Object instantiate(Class<?> theClass) public Object instantiate(Class<?> theClass)
throws ReflectionException, MBeanException { throws ReflectionException, MBeanException {
checkMBeanPermission(theClass, null, null, "instantiate");
Object moi; Object moi;
...@@ -260,6 +266,9 @@ public class MBeanInstantiator { ...@@ -260,6 +266,9 @@ public class MBeanInstantiator {
public Object instantiate(Class<?> theClass, Object params[], public Object instantiate(Class<?> theClass, Object params[],
String signature[], ClassLoader loader) String signature[], ClassLoader loader)
throws ReflectionException, MBeanException { throws ReflectionException, MBeanException {
checkMBeanPermission(theClass, null, null, "instantiate");
// Instantiate the new object // Instantiate the new object
// ------------------------------ // ------------------------------
...@@ -407,6 +416,8 @@ public class MBeanInstantiator { ...@@ -407,6 +416,8 @@ public class MBeanInstantiator {
throw new RuntimeOperationsException(new throw new RuntimeOperationsException(new
IllegalArgumentException(), "Null className passed in parameter"); IllegalArgumentException(), "Null className passed in parameter");
} }
ReflectUtil.checkPackageAccess(className);
Class<?> theClass; Class<?> theClass;
if (loaderName == null) { if (loaderName == null) {
// Load the class using the agent class loader // Load the class using the agent class loader
...@@ -619,13 +630,13 @@ public class MBeanInstantiator { ...@@ -619,13 +630,13 @@ public class MBeanInstantiator {
**/ **/
static Class<?> loadClass(String className, ClassLoader loader) static Class<?> loadClass(String className, ClassLoader loader)
throws ReflectionException { throws ReflectionException {
Class<?> theClass; Class<?> theClass;
if (className == null) { if (className == null) {
throw new RuntimeOperationsException(new throw new RuntimeOperationsException(new
IllegalArgumentException("The class name cannot be null"), IllegalArgumentException("The class name cannot be null"),
"Exception occurred during object instantiation"); "Exception occurred during object instantiation");
} }
ReflectUtil.checkPackageAccess(className);
try { try {
if (loader == null) if (loader == null)
loader = MBeanInstantiator.class.getClassLoader(); loader = MBeanInstantiator.class.getClassLoader();
...@@ -676,6 +687,7 @@ public class MBeanInstantiator { ...@@ -676,6 +687,7 @@ public class MBeanInstantiator {
// We need to load the class through the class // We need to load the class through the class
// loader of the target object. // loader of the target object.
// //
ReflectUtil.checkPackageAccess(signature[i]);
tab[i] = Class.forName(signature[i], false, aLoader); tab[i] = Class.forName(signature[i], false, aLoader);
} }
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
...@@ -701,7 +713,7 @@ public class MBeanInstantiator { ...@@ -701,7 +713,7 @@ public class MBeanInstantiator {
private Constructor<?> findConstructor(Class<?> c, Class<?>[] params) { private Constructor<?> findConstructor(Class<?> c, Class<?>[] params) {
try { try {
return c.getConstructor(params); return ConstructorUtil.getConstructor(c, params);
} catch (Exception e) { } catch (Exception e) {
return null; return null;
} }
...@@ -715,4 +727,18 @@ public class MBeanInstantiator { ...@@ -715,4 +727,18 @@ public class MBeanInstantiator {
char.class, boolean.class}) char.class, boolean.class})
primitiveClasses.put(c.getName(), c); primitiveClasses.put(c.getName(), c);
} }
private static void checkMBeanPermission(Class<?> clazz,
String member,
ObjectName objectName,
String actions) {
SecurityManager sm = System.getSecurityManager();
if (clazz != null && sm != null) {
Permission perm = new MBeanPermission(clazz.getName(),
member,
objectName,
actions);
sm.checkPermission(perm);
}
}
} }
...@@ -38,6 +38,7 @@ import javax.management.NotCompliantMBeanException; ...@@ -38,6 +38,7 @@ import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.management.ReflectionException; import javax.management.ReflectionException;
import com.sun.jmx.mbeanserver.MXBeanMappingFactory; import com.sun.jmx.mbeanserver.MXBeanMappingFactory;
import sun.reflect.misc.ReflectUtil;
/** /**
* Base class for MBeans. There is one instance of this class for * Base class for MBeans. There is one instance of this class for
...@@ -131,6 +132,7 @@ public abstract class MBeanSupport<M> ...@@ -131,6 +132,7 @@ public abstract class MBeanSupport<M>
" is not an instance of " + mbeanInterfaceType.getName(); " is not an instance of " + mbeanInterfaceType.getName();
throw new NotCompliantMBeanException(msg); throw new NotCompliantMBeanException(msg);
} }
ReflectUtil.checkPackageAccess(mbeanInterfaceType);
this.resource = resource; this.resource = resource;
MBeanIntrospector<M> introspector = getMBeanIntrospector(); MBeanIntrospector<M> introspector = getMBeanIntrospector();
this.perInterface = introspector.getPerInterface(mbeanInterfaceType); this.perInterface = introspector.getPerInterface(mbeanInterfaceType);
......
...@@ -39,6 +39,7 @@ import sun.awt.PeerEvent; ...@@ -39,6 +39,7 @@ import sun.awt.PeerEvent;
import sun.awt.util.IdentityArrayList; import sun.awt.util.IdentityArrayList;
import sun.awt.util.IdentityLinkedList; import sun.awt.util.IdentityLinkedList;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
import java.security.AccessControlException;
/** /**
* A Dialog is a top-level window with a title and a border * A Dialog is a top-level window with a title and a border
...@@ -128,6 +129,8 @@ public class Dialog extends Window { ...@@ -128,6 +129,8 @@ public class Dialog extends Window {
*/ */
boolean undecorated = false; boolean undecorated = false;
private transient boolean initialized = false;
/** /**
* Modal dialogs block all input to some top-level windows. * Modal dialogs block all input to some top-level windows.
* Whether a particular window is blocked depends on dialog's type * Whether a particular window is blocked depends on dialog's type
...@@ -671,6 +674,7 @@ public class Dialog extends Window { ...@@ -671,6 +674,7 @@ public class Dialog extends Window {
this.title = title; this.title = title;
setModalityType(modalityType); setModalityType(modalityType);
SunToolkit.checkAndSetPolicy(this); SunToolkit.checkAndSetPolicy(this);
initialized = true;
} }
/** /**
...@@ -722,6 +726,7 @@ public class Dialog extends Window { ...@@ -722,6 +726,7 @@ public class Dialog extends Window {
this.title = title; this.title = title;
setModalityType(modalityType); setModalityType(modalityType);
SunToolkit.checkAndSetPolicy(this); SunToolkit.checkAndSetPolicy(this);
initialized = true;
} }
/** /**
...@@ -851,12 +856,9 @@ public class Dialog extends Window { ...@@ -851,12 +856,9 @@ public class Dialog extends Window {
if (modalityType == type) { if (modalityType == type) {
return; return;
} }
if (type == ModalityType.TOOLKIT_MODAL) {
SecurityManager sm = System.getSecurityManager(); checkModalityPermission(type);
if (sm != null) {
sm.checkPermission(SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION);
}
}
modalityType = type; modalityType = type;
modal = (modalityType != ModalityType.MODELESS); modal = (modalityType != ModalityType.MODELESS);
} }
...@@ -1025,6 +1027,11 @@ public class Dialog extends Window { ...@@ -1025,6 +1027,11 @@ public class Dialog extends Window {
*/ */
@Deprecated @Deprecated
public void show() { public void show() {
if (!initialized) {
throw new IllegalStateException("The dialog component " +
"has not been initialized properly");
}
beforeFirstShow = false; beforeFirstShow = false;
if (!isModal()) { if (!isModal()) {
conditionalShow(null, null); conditionalShow(null, null);
...@@ -1600,18 +1607,51 @@ public class Dialog extends Window { ...@@ -1600,18 +1607,51 @@ public class Dialog extends Window {
} }
} }
private void checkModalityPermission(ModalityType mt) {
if (mt == ModalityType.TOOLKIT_MODAL) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION
);
}
}
}
private void readObject(ObjectInputStream s) private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException, HeadlessException throws ClassNotFoundException, IOException, HeadlessException
{ {
GraphicsEnvironment.checkHeadless(); GraphicsEnvironment.checkHeadless();
s.defaultReadObject();
java.io.ObjectInputStream.GetField fields =
s.readFields();
ModalityType localModalityType = (ModalityType)fields.get("modalityType", null);
try {
checkModalityPermission(localModalityType);
} catch (AccessControlException ace) {
localModalityType = DEFAULT_MODALITY_TYPE;
}
// in 1.5 or earlier modalityType was absent, so use "modal" instead // in 1.5 or earlier modalityType was absent, so use "modal" instead
if (modalityType == null) { if (localModalityType == null) {
this.modal = fields.get("modal", false);
setModal(modal); setModal(modal);
} else {
this.modalityType = localModalityType;
} }
this.resizable = fields.get("resizable", true);
this.undecorated = fields.get("undecorated", false);
this.title = (String)fields.get("title", "");
blockedWindows = new IdentityArrayList<>(); blockedWindows = new IdentityArrayList<>();
SunToolkit.checkAndSetPolicy(this);
initialized = true;
} }
/* /*
......
...@@ -194,7 +194,8 @@ public class EventQueue { ...@@ -194,7 +194,8 @@ public class EventQueue {
} }
public void removeSourceEvents(EventQueue eventQueue, public void removeSourceEvents(EventQueue eventQueue,
Object source, Object source,
boolean removeAllEvents) { boolean removeAllEvents)
{
eventQueue.removeSourceEvents(source, removeAllEvents); eventQueue.removeSourceEvents(source, removeAllEvents);
} }
public boolean noEvents(EventQueue eventQueue) { public boolean noEvents(EventQueue eventQueue) {
...@@ -203,6 +204,11 @@ public class EventQueue { ...@@ -203,6 +204,11 @@ public class EventQueue {
public void wakeup(EventQueue eventQueue, boolean isShutdown) { public void wakeup(EventQueue eventQueue, boolean isShutdown) {
eventQueue.wakeup(isShutdown); eventQueue.wakeup(isShutdown);
} }
public void invokeAndWait(Object source, Runnable r)
throws InterruptedException, InvocationTargetException
{
EventQueue.invokeAndWait(source, r);
}
}); });
} }
...@@ -1245,8 +1251,14 @@ public class EventQueue { ...@@ -1245,8 +1251,14 @@ public class EventQueue {
* @since 1.2 * @since 1.2
*/ */
public static void invokeAndWait(Runnable runnable) public static void invokeAndWait(Runnable runnable)
throws InterruptedException, InvocationTargetException { throws InterruptedException, InvocationTargetException
{
invokeAndWait(Toolkit.getDefaultToolkit(), runnable);
}
static void invokeAndWait(Object source, Runnable runnable)
throws InterruptedException, InvocationTargetException
{
if (EventQueue.isDispatchThread()) { if (EventQueue.isDispatchThread()) {
throw new Error("Cannot call invokeAndWait from the event dispatcher thread"); throw new Error("Cannot call invokeAndWait from the event dispatcher thread");
} }
...@@ -1255,8 +1267,7 @@ public class EventQueue { ...@@ -1255,8 +1267,7 @@ public class EventQueue {
Object lock = new AWTInvocationLock(); Object lock = new AWTInvocationLock();
InvocationEvent event = InvocationEvent event =
new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock, new InvocationEvent(source, runnable, lock, true);
true);
synchronized (lock) { synchronized (lock) {
Toolkit.getEventQueue().postEvent(event); Toolkit.getEventQueue().postEvent(event);
......
...@@ -109,12 +109,6 @@ public class TextComponent extends Component implements Accessible { ...@@ -109,12 +109,6 @@ public class TextComponent extends Component implements Accessible {
// the background color of non-editable TextComponents. // the background color of non-editable TextComponents.
boolean backgroundSetByClientCode = false; boolean backgroundSetByClientCode = false;
/**
* True if this <code>TextComponent</code> has access
* to the System clipboard.
*/
transient private boolean canAccessClipboard;
transient protected TextListener textListener; transient protected TextListener textListener;
/* /*
...@@ -139,7 +133,6 @@ public class TextComponent extends Component implements Accessible { ...@@ -139,7 +133,6 @@ public class TextComponent extends Component implements Accessible {
GraphicsEnvironment.checkHeadless(); GraphicsEnvironment.checkHeadless();
this.text = (text != null) ? text : ""; this.text = (text != null) ? text : "";
setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
checkSystemClipboardAccess();
} }
private void enableInputMethodsIfNecessary() { private void enableInputMethodsIfNecessary() {
...@@ -734,17 +727,14 @@ public class TextComponent extends Component implements Accessible { ...@@ -734,17 +727,14 @@ public class TextComponent extends Component implements Accessible {
/** /**
* Assigns a valid value to the canAccessClipboard instance variable. * Assigns a valid value to the canAccessClipboard instance variable.
*/ */
private void checkSystemClipboardAccess() { private boolean canAccessClipboard() {
canAccessClipboard = true;
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm == null) return true;
try { try {
sm.checkSystemClipboardAccess(); sm.checkSystemClipboardAccess();
} return true;
catch (SecurityException e) { } catch (SecurityException e) {}
canAccessClipboard = false; return false;
}
}
} }
/* /*
...@@ -827,7 +817,6 @@ public class TextComponent extends Component implements Accessible { ...@@ -827,7 +817,6 @@ public class TextComponent extends Component implements Accessible {
} }
} }
enableInputMethodsIfNecessary(); enableInputMethodsIfNecessary();
checkSystemClipboardAccess();
} }
......
...@@ -1206,7 +1206,7 @@ public class Window extends Container implements Accessible { ...@@ -1206,7 +1206,7 @@ public class Window extends Container implements Accessible {
} }
else { else {
try { try {
EventQueue.invokeAndWait(action); EventQueue.invokeAndWait(this, action);
} }
catch (InterruptedException e) { catch (InterruptedException e) {
System.err.println("Disposal was interrupted:"); System.err.println("Disposal was interrupted:");
......
...@@ -1752,6 +1752,12 @@ public class ObjectInputStream ...@@ -1752,6 +1752,12 @@ public class ObjectInputStream
ObjectStreamClass desc = readClassDesc(false); ObjectStreamClass desc = readClassDesc(false);
desc.checkDeserialize(); desc.checkDeserialize();
Class<?> cl = desc.forClass();
if (cl == String.class || cl == Class.class
|| cl == ObjectStreamClass.class) {
throw new InvalidClassException("invalid class descriptor");
}
Object obj; Object obj;
try { try {
obj = desc.isInstantiable() ? desc.newInstance() : null; obj = desc.isInstantiable() ? desc.newInstance() : null;
......
...@@ -63,7 +63,9 @@ import sun.reflect.generics.repository.ConstructorRepository; ...@@ -63,7 +63,9 @@ import sun.reflect.generics.repository.ConstructorRepository;
import sun.reflect.generics.scope.ClassScope; import sun.reflect.generics.scope.ClassScope;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.Proxy;
import sun.reflect.annotation.*; import sun.reflect.annotation.*;
import sun.reflect.misc.ReflectUtil;
/** /**
* Instances of the class {@code Class} represent classes and * Instances of the class {@code Class} represent classes and
...@@ -250,11 +252,11 @@ public final ...@@ -250,11 +252,11 @@ public final
ClassLoader loader) ClassLoader loader)
throws ClassNotFoundException throws ClassNotFoundException
{ {
if (loader == null) { if (sun.misc.VM.isSystemDomainLoader(loader)) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader(); ClassLoader ccl = ClassLoader.getCallerClassLoader();
if (ccl != null) { if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
sm.checkPermission( sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION); SecurityConstants.GET_CLASSLOADER_PERMISSION);
} }
...@@ -319,7 +321,7 @@ public final ...@@ -319,7 +321,7 @@ public final
throws InstantiationException, IllegalAccessException throws InstantiationException, IllegalAccessException
{ {
if (System.getSecurityManager() != null) { if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);
} }
return newInstance0(); return newInstance0();
} }
...@@ -1299,7 +1301,7 @@ public final ...@@ -1299,7 +1301,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);
// Privileged so this implementation can look at DECLARED classes, // Privileged so this implementation can look at DECLARED classes,
// something the caller might not have privilege to do. The code here // something the caller might not have privilege to do. The code here
...@@ -1374,7 +1376,7 @@ public final ...@@ -1374,7 +1376,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyFields(privateGetPublicFields(null)); return copyFields(privateGetPublicFields(null));
} }
...@@ -1425,7 +1427,7 @@ public final ...@@ -1425,7 +1427,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyMethods(privateGetPublicMethods()); return copyMethods(privateGetPublicMethods());
} }
...@@ -1474,7 +1476,7 @@ public final ...@@ -1474,7 +1476,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyConstructors(privateGetDeclaredConstructors(true)); return copyConstructors(privateGetDeclaredConstructors(true));
} }
...@@ -1533,7 +1535,7 @@ public final ...@@ -1533,7 +1535,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
Field field = getField0(name); Field field = getField0(name);
if (field == null) { if (field == null) {
throw new NoSuchFieldException(name); throw new NoSuchFieldException(name);
...@@ -1618,7 +1620,7 @@ public final ...@@ -1618,7 +1620,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
Method method = getMethod0(name, parameterTypes); Method method = getMethod0(name, parameterTypes);
if (method == null) { if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
...@@ -1672,7 +1674,7 @@ public final ...@@ -1672,7 +1674,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return getConstructor0(parameterTypes, Member.PUBLIC); return getConstructor0(parameterTypes, Member.PUBLIC);
} }
...@@ -1714,7 +1716,7 @@ public final ...@@ -1714,7 +1716,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), false);
return getDeclaredClasses0(); return getDeclaredClasses0();
} }
...@@ -1758,7 +1760,7 @@ public final ...@@ -1758,7 +1760,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyFields(privateGetDeclaredFields(false)); return copyFields(privateGetDeclaredFields(false));
} }
...@@ -1806,7 +1808,7 @@ public final ...@@ -1806,7 +1808,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyMethods(privateGetDeclaredMethods(false)); return copyMethods(privateGetDeclaredMethods(false));
} }
...@@ -1851,7 +1853,7 @@ public final ...@@ -1851,7 +1853,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyConstructors(privateGetDeclaredConstructors(false)); return copyConstructors(privateGetDeclaredConstructors(false));
} }
...@@ -1895,7 +1897,7 @@ public final ...@@ -1895,7 +1897,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
Field field = searchFields(privateGetDeclaredFields(false), name); Field field = searchFields(privateGetDeclaredFields(false), name);
if (field == null) { if (field == null) {
throw new NoSuchFieldException(name); throw new NoSuchFieldException(name);
...@@ -1950,7 +1952,7 @@ public final ...@@ -1950,7 +1952,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) { if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
...@@ -2000,7 +2002,7 @@ public final ...@@ -2000,7 +2002,7 @@ public final
// be very careful not to change the stack depth of this // be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons // checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess // see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return getConstructor0(parameterTypes, Member.DECLARED); return getConstructor0(parameterTypes, Member.DECLARED);
} }
...@@ -2170,18 +2172,26 @@ public final ...@@ -2170,18 +2172,26 @@ public final
* <p> Default policy: allow all clients access with normal Java access * <p> Default policy: allow all clients access with normal Java access
* control. * control.
*/ */
private void checkMemberAccess(int which, ClassLoader ccl) { private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) {
SecurityManager s = System.getSecurityManager(); SecurityManager s = System.getSecurityManager();
if (s != null) { if (s != null) {
s.checkMemberAccess(this, which); s.checkMemberAccess(this, which);
ClassLoader cl = getClassLoader0(); ClassLoader cl = getClassLoader0();
if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(ccl, cl)) { if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
String name = this.getName(); String name = this.getName();
int i = name.lastIndexOf('.'); int i = name.lastIndexOf('.');
if (i != -1) { if (i != -1) {
s.checkPackageAccess(name.substring(0, i)); // skip the package access check on a proxy class in default proxy package
String pkg = name.substring(0, i);
if (!Proxy.isProxyClass(this) || !pkg.equals(ReflectUtil.PROXY_PACKAGE)) {
s.checkPackageAccess(pkg);
}
} }
} }
// check package access on the proxy interfaces
if (checkProxyInterfaces && Proxy.isProxyClass(this)) {
ReflectUtil.checkProxyPackageAccess(ccl, this.getInterfaces());
}
} }
} }
......
...@@ -476,6 +476,8 @@ class MethodHandleNatives { ...@@ -476,6 +476,8 @@ class MethodHandleNatives {
case "getProxyClass": case "getProxyClass":
case "newProxyInstance": case "newProxyInstance":
return defc == java.lang.reflect.Proxy.class; return defc == java.lang.reflect.Proxy.class;
case "asInterfaceInstance":
return defc == java.lang.invoke.MethodHandleProxies.class;
case "getBundle": case "getBundle":
case "clearCache": case "clearCache":
return defc == java.util.ResourceBundle.class; return defc == java.util.ResourceBundle.class;
......
...@@ -26,8 +26,12 @@ ...@@ -26,8 +26,12 @@
package java.lang.invoke; package java.lang.invoke;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.invoke.WrapperInstance; import sun.invoke.WrapperInstance;
import java.util.ArrayList; import java.util.ArrayList;
import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
/** /**
* This class consists exclusively of static methods that help adapt * This class consists exclusively of static methods that help adapt
...@@ -137,6 +141,21 @@ public class MethodHandleProxies { ...@@ -137,6 +141,21 @@ public class MethodHandleProxies {
<T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) { <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers())) if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
throw new IllegalArgumentException("not a public interface: "+intfc.getName()); throw new IllegalArgumentException("not a public interface: "+intfc.getName());
final MethodHandle mh;
if (System.getSecurityManager() != null) {
final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller
final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
final ClassLoader ccl = caller != null ? caller.getClassLoader() : null;
ReflectUtil.checkProxyPackageAccess(ccl, intfc);
mh = ccl != null ? bindCaller(target, caller) : target;
} else {
mh = target;
}
ClassLoader proxyLoader = intfc.getClassLoader();
if (proxyLoader == null) {
ClassLoader cl = Thread.currentThread().getContextClassLoader(); // avoid use of BCP
proxyLoader = cl != null ? cl : ClassLoader.getSystemClassLoader();
}
final Method[] methods = getSingleNameMethods(intfc); final Method[] methods = getSingleNameMethods(intfc);
if (methods == null) if (methods == null)
throw new IllegalArgumentException("not a single-method interface: "+intfc.getName()); throw new IllegalArgumentException("not a single-method interface: "+intfc.getName());
...@@ -144,31 +163,58 @@ public class MethodHandleProxies { ...@@ -144,31 +163,58 @@ public class MethodHandleProxies {
for (int i = 0; i < methods.length; i++) { for (int i = 0; i < methods.length; i++) {
Method sm = methods[i]; Method sm = methods[i];
MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes()); MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
MethodHandle checkTarget = target.asType(smMT); // make throw WMT MethodHandle checkTarget = mh.asType(smMT); // make throw WMT
checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class)); checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount()); vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
} }
return intfc.cast(Proxy.newProxyInstance( final InvocationHandler ih = new InvocationHandler() {
intfc.getClassLoader(), private Object getArg(String name) {
new Class<?>[]{ intfc, WrapperInstance.class }, if ((Object)name == "getWrapperInstanceTarget") return target;
new InvocationHandler() { if ((Object)name == "getWrapperInstanceType") return intfc;
private Object getArg(String name) { throw new AssertionError();
if ((Object)name == "getWrapperInstanceTarget") return target; }
if ((Object)name == "getWrapperInstanceType") return intfc; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
throw new AssertionError(); for (int i = 0; i < methods.length; i++) {
if (method.equals(methods[i]))
return vaTargets[i].invokeExact(args);
} }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getDeclaringClass() == WrapperInstance.class)
for (int i = 0; i < methods.length; i++) { return getArg(method.getName());
if (method.equals(methods[i])) if (isObjectMethod(method))
return vaTargets[i].invokeExact(args); return callObjectMethod(proxy, method, args);
} throw new InternalError("bad proxy method: "+method);
if (method.getDeclaringClass() == WrapperInstance.class) }
return getArg(method.getName()); };
if (isObjectMethod(method))
return callObjectMethod(proxy, method, args); final Object proxy;
throw new InternalError("bad proxy method: "+method); if (System.getSecurityManager() != null) {
} // sun.invoke.WrapperInstance is a restricted interface not accessible
})); // by any non-null class loader.
final ClassLoader loader = proxyLoader;
proxy = AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
return Proxy.newProxyInstance(
loader,
new Class<?>[]{ intfc, WrapperInstance.class },
ih);
}
});
} else {
proxy = Proxy.newProxyInstance(proxyLoader,
new Class<?>[]{ intfc, WrapperInstance.class },
ih);
}
return intfc.cast(proxy);
}
private static MethodHandle bindCaller(MethodHandle target, Class<?> hostClass) {
MethodHandle cbmh = MethodHandleImpl.bindCaller(target, hostClass);
if (target.isVarargsCollector()) {
MethodType type = cbmh.type();
int arity = type.parameterCount();
return cbmh.asVarargsCollector(type.parameterType(arity-1));
}
return cbmh;
} }
/** /**
......
...@@ -802,20 +802,20 @@ public class ManagementFactory { ...@@ -802,20 +802,20 @@ public class ManagementFactory {
*/ */
private static void addMXBean(final MBeanServer mbs, final PlatformManagedObject pmo) { private static void addMXBean(final MBeanServer mbs, final PlatformManagedObject pmo) {
// Make DynamicMBean out of MXBean by wrapping it with a StandardMBean // Make DynamicMBean out of MXBean by wrapping it with a StandardMBean
final DynamicMBean dmbean;
if (pmo instanceof DynamicMBean) {
dmbean = DynamicMBean.class.cast(pmo);
} else if (pmo instanceof NotificationEmitter) {
dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo);
} else {
dmbean = new StandardMBean(pmo, null, true);
}
try { try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
public Void run() throws InstanceAlreadyExistsException, public Void run() throws InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanRegistrationException,
NotCompliantMBeanException { NotCompliantMBeanException {
final DynamicMBean dmbean;
if (pmo instanceof DynamicMBean) {
dmbean = DynamicMBean.class.cast(pmo);
} else if (pmo instanceof NotificationEmitter) {
dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo);
} else {
dmbean = new StandardMBean(pmo, null, true);
}
mbs.registerMBean(dmbean, pmo.getObjectName()); mbs.registerMBean(dmbean, pmo.getObjectName());
return null; return null;
} }
......
...@@ -27,6 +27,9 @@ package java.lang.reflect; ...@@ -27,6 +27,9 @@ package java.lang.reflect;
import java.lang.ref.Reference; import java.lang.ref.Reference;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
...@@ -36,6 +39,9 @@ import java.util.Set; ...@@ -36,6 +39,9 @@ import java.util.Set;
import java.util.List; import java.util.List;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import sun.misc.ProxyGenerator; import sun.misc.ProxyGenerator;
import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
import sun.security.util.SecurityConstants;
/** /**
* {@code Proxy} provides static methods for creating dynamic proxy * {@code Proxy} provides static methods for creating dynamic proxy
...@@ -265,9 +271,69 @@ public class Proxy implements java.io.Serializable { ...@@ -265,9 +271,69 @@ public class Proxy implements java.io.Serializable {
* @param h the invocation handler for this proxy instance * @param h the invocation handler for this proxy instance
*/ */
protected Proxy(InvocationHandler h) { protected Proxy(InvocationHandler h) {
doNewInstanceCheck();
this.h = h; this.h = h;
} }
private static class ProxyAccessHelper {
// The permission is implementation specific.
static final Permission PROXY_PERMISSION =
new ReflectPermission("proxyConstructorNewInstance");
// These system properties are defined to provide a short-term
// workaround if customers need to disable the new security checks.
static final boolean allowNewInstance;
static final boolean allowNullLoader;
static {
allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance");
allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader");
}
private static boolean getBooleanProperty(final String key) {
String s = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty(key);
}
});
return Boolean.valueOf(s);
}
static boolean needsNewInstanceCheck(Class<?> proxyClass) {
if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) {
return false;
}
if (proxyClass.getName().startsWith(ReflectUtil.PROXY_PACKAGE + ".")) {
// all proxy interfaces are public
return false;
}
for (Class<?> intf : proxyClass.getInterfaces()) {
if (!Modifier.isPublic(intf.getModifiers())) {
return true;
}
}
return false;
}
}
/*
* Access check on a proxy class that implements any non-public interface.
*
* @throws SecurityException if a security manager exists, and
* the caller does not have the permission.
*/
private void doNewInstanceCheck() {
SecurityManager sm = System.getSecurityManager();
Class<?> proxyClass = this.getClass();
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) {
try {
sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION);
} catch (SecurityException e) {
throw new SecurityException("Not allowed to construct a Proxy "
+ "instance that implements a non-public interface", e);
}
}
}
/** /**
* Returns the {@code java.lang.Class} object for a proxy class * Returns the {@code java.lang.Class} object for a proxy class
* given a class loader and an array of interfaces. The proxy class * given a class loader and an array of interfaces. The proxy class
...@@ -346,6 +412,51 @@ public class Proxy implements java.io.Serializable { ...@@ -346,6 +412,51 @@ public class Proxy implements java.io.Serializable {
Class<?>... interfaces) Class<?>... interfaces)
throws IllegalArgumentException throws IllegalArgumentException
{ {
return getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
}
private static void checkProxyLoader(ClassLoader ccl,
ClassLoader loader)
{
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
if (loader == null && ccl != null) {
if (!ProxyAccessHelper.allowNullLoader) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
}
}
/*
* Generate a proxy class (caller-sensitive).
*
* To define a proxy class, it performs the access checks as in
* Class.forName (VM will invoke ClassLoader.checkPackageAccess):
* 1. "getClassLoader" permission check if loader == null
* 2. checkPackageAccess on the interfaces it implements
*
* To get a constructor and new instance of a proxy class, it performs
* the package access check on the interfaces it implements
* as in Class.getConstructor.
*
* If an interface is non-public, the proxy class must be defined by
* the defining loader of the interface. If the caller's class loader
* is not the same as the defining loader of the interface, the VM
* will throw IllegalAccessError when the generated proxy class is
* being defined via the defineClass0 method.
*/
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller
final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
final ClassLoader ccl = caller.getClassLoader();
checkProxyLoader(ccl, loader);
ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
}
if (interfaces.length > 65535) { if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded"); throw new IllegalArgumentException("interface limit exceeded");
} }
...@@ -497,8 +608,9 @@ public class Proxy implements java.io.Serializable { ...@@ -497,8 +608,9 @@ public class Proxy implements java.io.Serializable {
} }
} }
if (proxyPkg == null) { // if no non-public proxy interfaces, if (proxyPkg == null) {
proxyPkg = ""; // use the unnamed package // if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
} }
{ {
...@@ -598,19 +710,43 @@ public class Proxy implements java.io.Serializable { ...@@ -598,19 +710,43 @@ public class Proxy implements java.io.Serializable {
/* /*
* Look up or generate the designated proxy class. * Look up or generate the designated proxy class.
*/ */
Class<?> cl = getProxyClass(loader, interfaces); Class<?> cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
/* /*
* Invoke its constructor with the designated invocation handler. * Invoke its constructor with the designated invocation handler.
*/ */
try { try {
Constructor<?> cons = cl.getConstructor(constructorParams); final Constructor<?> cons = cl.getConstructor(constructorParams);
return cons.newInstance(new Object[] { h }); final InvocationHandler ih = h;
} catch (NoSuchMethodException | SecurityManager sm = System.getSecurityManager();
IllegalAccessException | if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
InstantiationException | // create proxy instance with doPrivilege as the proxy class may
InvocationTargetException e) { // implement non-public interfaces that requires a special permission
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
return newInstance(cons, ih);
}
});
} else {
return newInstance(cons, ih);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
try {
return cons.newInstance(new Object[] {h} );
} catch (IllegalAccessException | InstantiationException e) {
throw new InternalError(e.toString(), e); throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} }
} }
......
/* /*
* Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -24,9 +24,12 @@ ...@@ -24,9 +24,12 @@
*/ */
package java.net; package java.net;
import java.io.ObjectInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InvalidObjectException; import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.ObjectStreamField;
/** /**
* *
...@@ -46,23 +49,105 @@ import java.io.InvalidObjectException; ...@@ -46,23 +49,105 @@ import java.io.InvalidObjectException;
* @see java.net.ServerSocket * @see java.net.ServerSocket
* @since 1.4 * @since 1.4
*/ */
public class InetSocketAddress extends SocketAddress { public class InetSocketAddress
/* The hostname of the Socket Address extends SocketAddress
* @serial {
*/ // Private implementation class pointed to by all public methods.
private String hostname = null; private static class InetSocketAddressHolder {
/* The IP address of the Socket Address // The hostname of the Socket Address
* @serial private String hostname;
*/ // The IP address of the Socket Address
private InetAddress addr = null; private InetAddress addr;
/* The port number of the Socket Address // The port number of the Socket Address
* @serial private int port;
*/
private int port; private InetSocketAddressHolder(String hostname, InetAddress addr, int port) {
this.hostname = hostname;
this.addr = addr;
this.port = port;
}
private int getPort() {
return port;
}
private InetAddress getAddress() {
return addr;
}
private String getHostName() {
if (hostname != null)
return hostname;
if (addr != null)
return addr.getHostName();
return null;
}
private String getHostString() {
if (hostname != null)
return hostname;
if (addr != null) {
if (addr.hostName != null)
return addr.hostName;
else
return addr.getHostAddress();
}
return null;
}
private boolean isUnresolved() {
return addr == null;
}
@Override
public String toString() {
if (isUnresolved()) {
return hostname + ":" + port;
} else {
return addr.toString() + ":" + port;
}
}
@Override
public final boolean equals(Object obj) {
if (obj == null || !(obj instanceof InetSocketAddressHolder))
return false;
InetSocketAddressHolder that = (InetSocketAddressHolder)obj;
boolean sameIP;
if (addr != null)
sameIP = addr.equals(that.addr);
else if (hostname != null)
sameIP = (that.addr == null) &&
hostname.equalsIgnoreCase(that.hostname);
else
sameIP = (that.addr == null) && (that.hostname == null);
return sameIP && (port == that.port);
}
@Override
public final int hashCode() {
if (addr != null)
return addr.hashCode() + port;
if (hostname != null)
return hostname.toLowerCase().hashCode() + port;
return port;
}
}
private final transient InetSocketAddressHolder holder;
private static final long serialVersionUID = 5076001401234631237L; private static final long serialVersionUID = 5076001401234631237L;
private InetSocketAddress() { private static int checkPort(int port) {
if (port < 0 || port > 0xFFFF)
throw new IllegalArgumentException("port out of range:" + port);
return port;
}
private static String checkHost(String hostname) {
if (hostname == null)
throw new IllegalArgumentException("hostname can't be null");
return hostname;
} }
/** /**
...@@ -97,14 +182,10 @@ public class InetSocketAddress extends SocketAddress { ...@@ -97,14 +182,10 @@ public class InetSocketAddress extends SocketAddress {
* range of valid port values. * range of valid port values.
*/ */
public InetSocketAddress(InetAddress addr, int port) { public InetSocketAddress(InetAddress addr, int port) {
if (port < 0 || port > 0xFFFF) { holder = new InetSocketAddressHolder(
throw new IllegalArgumentException("port out of range:" + port); null,
} addr == null ? InetAddress.anyLocalAddress() : addr,
this.port = port; checkPort(port));
if (addr == null)
this.addr = InetAddress.anyLocalAddress();
else
this.addr = addr;
} }
/** /**
...@@ -132,19 +213,20 @@ public class InetSocketAddress extends SocketAddress { ...@@ -132,19 +213,20 @@ public class InetSocketAddress extends SocketAddress {
* @see #isUnresolved() * @see #isUnresolved()
*/ */
public InetSocketAddress(String hostname, int port) { public InetSocketAddress(String hostname, int port) {
if (port < 0 || port > 0xFFFF) { checkHost(hostname);
throw new IllegalArgumentException("port out of range:" + port); InetAddress addr = null;
} String host = null;
if (hostname == null) {
throw new IllegalArgumentException("hostname can't be null");
}
try { try {
addr = InetAddress.getByName(hostname); addr = InetAddress.getByName(hostname);
} catch(UnknownHostException e) { } catch(UnknownHostException e) {
this.hostname = hostname; host = hostname;
addr = null;
} }
this.port = port; holder = new InetSocketAddressHolder(host, addr, checkPort(port));
}
// private constructor for creating unresolved instances
private InetSocketAddress(int port, String hostname) {
holder = new InetSocketAddressHolder(hostname, null, port);
} }
/** /**
...@@ -169,31 +251,67 @@ public class InetSocketAddress extends SocketAddress { ...@@ -169,31 +251,67 @@ public class InetSocketAddress extends SocketAddress {
* @since 1.5 * @since 1.5
*/ */
public static InetSocketAddress createUnresolved(String host, int port) { public static InetSocketAddress createUnresolved(String host, int port) {
if (port < 0 || port > 0xFFFF) { return new InetSocketAddress(checkPort(port), checkHost(host));
throw new IllegalArgumentException("port out of range:" + port);
}
if (host == null) {
throw new IllegalArgumentException("hostname can't be null");
}
InetSocketAddress s = new InetSocketAddress();
s.port = port;
s.hostname = host;
s.addr = null;
return s;
} }
private void readObject(ObjectInputStream s) /**
throws IOException, ClassNotFoundException { * @serialField hostname String
s.defaultReadObject(); * @serialField addr InetAddress
* @serialField port int
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("hostname", String.class),
new ObjectStreamField("addr", InetAddress.class),
new ObjectStreamField("port", int.class)};
private void writeObject(ObjectOutputStream out)
throws IOException
{
// Don't call defaultWriteObject()
ObjectOutputStream.PutField pfields = out.putFields();
pfields.put("hostname", holder.hostname);
pfields.put("addr", holder.addr);
pfields.put("port", holder.port);
out.writeFields();
}
// Check that our invariants are satisfied private void readObject(ObjectInputStream in)
if (port < 0 || port > 0xFFFF) { throws IOException, ClassNotFoundException
throw new InvalidObjectException("port out of range:" + port); {
} // Don't call defaultReadObject()
ObjectInputStream.GetField oisFields = in.readFields();
final String oisHostname = (String)oisFields.get("hostname", null);
final InetAddress oisAddr = (InetAddress)oisFields.get("addr", null);
final int oisPort = oisFields.get("port", -1);
if (hostname == null && addr == null) { // Check that our invariants are satisfied
checkPort(oisPort);
if (oisHostname == null && oisAddr == null)
throw new InvalidObjectException("hostname and addr " + throw new InvalidObjectException("hostname and addr " +
"can't both be null"); "can't both be null");
InetSocketAddressHolder h = new InetSocketAddressHolder(oisHostname,
oisAddr,
oisPort);
UNSAFE.putObject(this, FIELDS_OFFSET, h);
}
private void readObjectNoData()
throws ObjectStreamException
{
throw new InvalidObjectException("Stream data required");
}
private static final long FIELDS_OFFSET;
private static final sun.misc.Unsafe UNSAFE;
static {
try {
sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
FIELDS_OFFSET = unsafe.objectFieldOffset(
InetSocketAddress.class.getDeclaredField("holder"));
UNSAFE = unsafe;
} catch (ReflectiveOperationException e) {
throw new Error(e);
} }
} }
...@@ -203,7 +321,7 @@ public class InetSocketAddress extends SocketAddress { ...@@ -203,7 +321,7 @@ public class InetSocketAddress extends SocketAddress {
* @return the port number. * @return the port number.
*/ */
public final int getPort() { public final int getPort() {
return port; return holder.getPort();
} }
/** /**
...@@ -213,7 +331,7 @@ public class InetSocketAddress extends SocketAddress { ...@@ -213,7 +331,7 @@ public class InetSocketAddress extends SocketAddress {
* @return the InetAdress or <code>null</code> if it is unresolved. * @return the InetAdress or <code>null</code> if it is unresolved.
*/ */
public final InetAddress getAddress() { public final InetAddress getAddress() {
return addr; return holder.getAddress();
} }
/** /**
...@@ -224,31 +342,19 @@ public class InetSocketAddress extends SocketAddress { ...@@ -224,31 +342,19 @@ public class InetSocketAddress extends SocketAddress {
* @return the hostname part of the address. * @return the hostname part of the address.
*/ */
public final String getHostName() { public final String getHostName() {
if (hostname != null) return holder.getHostName();
return hostname;
if (addr != null)
return addr.getHostName();
return null;
} }
/** /**
* Returns the hostname, or the String form of the address if it * Returns the hostname, or the String form of the address if it
* doesn't have a hostname (it was created using a literal). * doesn't have a hostname (it was created using a literal).
* This has the benefit of <b>not</b> attemptimg a reverse lookup. * This has the benefit of <b>not</b> attempting a reverse lookup.
* *
* @return the hostname, or String representation of the address. * @return the hostname, or String representation of the address.
* @since 1.7 * @since 1.7
*/ */
public final String getHostString() { public final String getHostString() {
if (hostname != null) return holder.getHostString();
return hostname;
if (addr != null) {
if (addr.hostName != null)
return addr.hostName;
else
return addr.getHostAddress();
}
return null;
} }
/** /**
...@@ -258,7 +364,7 @@ public class InetSocketAddress extends SocketAddress { ...@@ -258,7 +364,7 @@ public class InetSocketAddress extends SocketAddress {
* an <code>InetAddress</code>. * an <code>InetAddress</code>.
*/ */
public final boolean isUnresolved() { public final boolean isUnresolved() {
return addr == null; return holder.isUnresolved();
} }
/** /**
...@@ -269,12 +375,9 @@ public class InetSocketAddress extends SocketAddress { ...@@ -269,12 +375,9 @@ public class InetSocketAddress extends SocketAddress {
* *
* @return a string representation of this object. * @return a string representation of this object.
*/ */
@Override
public String toString() { public String toString() {
if (isUnresolved()) { return holder.toString();
return hostname + ":" + port;
} else {
return addr.toString() + ":" + port;
}
} }
/** /**
...@@ -297,19 +400,11 @@ public class InetSocketAddress extends SocketAddress { ...@@ -297,19 +400,11 @@ public class InetSocketAddress extends SocketAddress {
* <code>false</code> otherwise. * <code>false</code> otherwise.
* @see java.net.InetAddress#equals(java.lang.Object) * @see java.net.InetAddress#equals(java.lang.Object)
*/ */
@Override
public final boolean equals(Object obj) { public final boolean equals(Object obj) {
if (obj == null || !(obj instanceof InetSocketAddress)) if (obj == null || !(obj instanceof InetSocketAddress))
return false; return false;
InetSocketAddress sockAddr = (InetSocketAddress) obj; return holder.equals(((InetSocketAddress) obj).holder);
boolean sameIP = false;
if (this.addr != null)
sameIP = this.addr.equals(sockAddr.addr);
else if (this.hostname != null)
sameIP = (sockAddr.addr == null) &&
this.hostname.equalsIgnoreCase(sockAddr.hostname);
else
sameIP = (sockAddr.addr == null) && (sockAddr.hostname == null);
return sameIP && (this.port == sockAddr.port);
} }
/** /**
...@@ -317,11 +412,8 @@ public class InetSocketAddress extends SocketAddress { ...@@ -317,11 +412,8 @@ public class InetSocketAddress extends SocketAddress {
* *
* @return a hash code value for this socket address. * @return a hash code value for this socket address.
*/ */
@Override
public final int hashCode() { public final int hashCode() {
if (addr != null) return holder.hashCode();
return addr.hashCode() + port;
if (hostname != null)
return hostname.toLowerCase().hashCode() + port;
return port;
} }
} }
...@@ -34,8 +34,10 @@ ...@@ -34,8 +34,10 @@
*/ */
package java.util.concurrent; package java.util.concurrent;
import java.util.concurrent.locks.*; import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.atomic.*; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.*; import java.util.*;
/** /**
...@@ -491,10 +493,15 @@ public class ThreadPoolExecutor extends AbstractExecutorService { ...@@ -491,10 +493,15 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* policy limiting the number of threads. Even though it is not * policy limiting the number of threads. Even though it is not
* treated as an error, failure to create threads may result in * treated as an error, failure to create threads may result in
* new tasks being rejected or existing ones remaining stuck in * new tasks being rejected or existing ones remaining stuck in
* the queue. On the other hand, no special precautions exist to * the queue.
* handle OutOfMemoryErrors that might be thrown while trying to *
* create threads, since there is generally no recourse from * We go further and preserve pool invariants even in the face of
* within this class. * errors such as OutOfMemoryError, that might be thrown while
* trying to create threads. Such errors are rather common due to
* the need to allocate a native stack in Thread#start, and users
* will want to perform clean pool shutdown to clean up. There
* will likely be enough memory available for the cleanup code to
* complete without encountering yet another OutOfMemoryError.
*/ */
private volatile ThreadFactory threadFactory; private volatile ThreadFactory threadFactory;
...@@ -568,9 +575,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService { ...@@ -568,9 +575,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* task execution. This protects against interrupts that are * task execution. This protects against interrupts that are
* intended to wake up a worker thread waiting for a task from * intended to wake up a worker thread waiting for a task from
* instead interrupting a task being run. We implement a simple * instead interrupting a task being run. We implement a simple
* non-reentrant mutual exclusion lock rather than use ReentrantLock * non-reentrant mutual exclusion lock rather than use
* because we do not want worker tasks to be able to reacquire the * ReentrantLock because we do not want worker tasks to be able to
* lock when they invoke pool control methods like setCorePoolSize. * reacquire the lock when they invoke pool control methods like
* setCorePoolSize. Additionally, to suppress interrupts until
* the thread actually starts running tasks, we initialize lock
* state to a negative value, and clear it upon start (in
* runWorker).
*/ */
private final class Worker private final class Worker
extends AbstractQueuedSynchronizer extends AbstractQueuedSynchronizer
...@@ -594,6 +605,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { ...@@ -594,6 +605,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* @param firstTask the first task (null if none) * @param firstTask the first task (null if none)
*/ */
Worker(Runnable firstTask) { Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask; this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this); this.thread = getThreadFactory().newThread(this);
} }
...@@ -609,7 +621,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService { ...@@ -609,7 +621,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
// The value 1 represents the locked state. // The value 1 represents the locked state.
protected boolean isHeldExclusively() { protected boolean isHeldExclusively() {
return getState() == 1; return getState() != 0;
} }
protected boolean tryAcquire(int unused) { protected boolean tryAcquire(int unused) {
...@@ -630,6 +642,16 @@ public class ThreadPoolExecutor extends AbstractExecutorService { ...@@ -630,6 +642,16 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
public boolean tryLock() { return tryAcquire(1); } public boolean tryLock() { return tryAcquire(1); }
public void unlock() { release(1); } public void unlock() { release(1); }
public boolean isLocked() { return isHeldExclusively(); } public boolean isLocked() { return isHeldExclusively(); }
void interruptIfStarted() {
Thread t;
if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
}
}
}
} }
/* /*
...@@ -728,12 +750,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService { ...@@ -728,12 +750,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
final ReentrantLock mainLock = this.mainLock; final ReentrantLock mainLock = this.mainLock;
mainLock.lock(); mainLock.lock();
try { try {
for (Worker w : workers) { for (Worker w : workers)
try { w.interruptIfStarted();
w.thread.interrupt();
} catch (SecurityException ignore) {
}
}
} finally { } finally {
mainLock.unlock(); mainLock.unlock();
} }
...@@ -790,19 +808,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService { ...@@ -790,19 +808,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
private static final boolean ONLY_ONE = true; private static final boolean ONLY_ONE = true;
/**
* Ensures that unless the pool is stopping, the current thread
* does not have its interrupt set. This requires a double-check
* of state in case the interrupt was cleared concurrently with a
* shutdownNow -- if so, the interrupt is re-enabled.
*/
private void clearInterruptsForTaskRun() {
if (runStateLessThan(ctl.get(), STOP) &&
Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))
Thread.currentThread().interrupt();
}
/* /*
* Misc utilities, most of which are also exported to * Misc utilities, most of which are also exported to
* ScheduledThreadPoolExecutor * ScheduledThreadPoolExecutor
...@@ -862,12 +867,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService { ...@@ -862,12 +867,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* Checks if a new worker can be added with respect to current * Checks if a new worker can be added with respect to current
* pool state and the given bound (either core or maximum). If so, * pool state and the given bound (either core or maximum). If so,
* the worker count is adjusted accordingly, and, if possible, a * the worker count is adjusted accordingly, and, if possible, a
* new worker is created and started running firstTask as its * new worker is created and started, running firstTask as its
* first task. This method returns false if the pool is stopped or * first task. This method returns false if the pool is stopped or
* eligible to shut down. It also returns false if the thread * eligible to shut down. It also returns false if the thread
* factory fails to create a thread when asked, which requires a * factory fails to create a thread when asked. If the thread
* backout of workerCount, and a recheck for termination, in case * creation fails, either due to the thread factory returning
* the existence of this worker was holding up termination. * null, or due to an exception (typically OutOfMemoryError in
* Thread#start), we roll back cleanly.
* *
* @param firstTask the task the new thread should run first (or * @param firstTask the task the new thread should run first (or
* null if none). Workers are created with an initial first task * null if none). Workers are created with an initial first task
...@@ -910,46 +916,65 @@ public class ThreadPoolExecutor extends AbstractExecutorService { ...@@ -910,46 +916,65 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
} }
} }
Worker w = new Worker(firstTask); boolean workerStarted = false;
Thread t = w.thread; boolean workerAdded = false;
Worker w = null;
try {
final ReentrantLock mainLock = this.mainLock;
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int c = ctl.get();
int rs = runStateOf(c);
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
/**
* Rolls back the worker thread creation.
* - removes worker from workers, if present
* - decrements worker count
* - rechecks for termination, in case the existence of this
* worker was holding up termination
*/
private void addWorkerFailed(Worker w) {
final ReentrantLock mainLock = this.mainLock; final ReentrantLock mainLock = this.mainLock;
mainLock.lock(); mainLock.lock();
try { try {
// Recheck while holding lock. if (w != null)
// Back out on ThreadFactory failure or if workers.remove(w);
// shut down before lock acquired. decrementWorkerCount();
int c = ctl.get(); tryTerminate();
int rs = runStateOf(c);
if (t == null ||
(rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null))) {
decrementWorkerCount();
tryTerminate();
return false;
}
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
} finally { } finally {
mainLock.unlock(); mainLock.unlock();
} }
t.start();
// It is possible (but unlikely) for a thread to have been
// added to workers, but not yet started, during transition to
// STOP, which could result in a rare missed interrupt,
// because Thread.interrupt is not guaranteed to have any effect
// on a non-yet-started Thread (see Thread#interrupt).
if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted())
t.interrupt();
return true;
} }
/** /**
...@@ -1096,15 +1121,25 @@ public class ThreadPoolExecutor extends AbstractExecutorService { ...@@ -1096,15 +1121,25 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* @param w the worker * @param w the worker
*/ */
final void runWorker(Worker w) { final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask; Runnable task = w.firstTask;
w.firstTask = null; w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true; boolean completedAbruptly = true;
try { try {
while (task != null || (task = getTask()) != null) { while (task != null || (task = getTask()) != null) {
w.lock(); w.lock();
clearInterruptsForTaskRun(); // If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try { try {
beforeExecute(w.thread, task); beforeExecute(wt, task);
Throwable thrown = null; Throwable thrown = null;
try { try {
task.run(); task.run();
...@@ -2064,3 +2099,4 @@ public class ThreadPoolExecutor extends AbstractExecutorService { ...@@ -2064,3 +2099,4 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
} }
} }
} }
...@@ -34,6 +34,7 @@ import java.security.CodeSigner; ...@@ -34,6 +34,7 @@ import java.security.CodeSigner;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.AccessController; import java.security.AccessController;
import java.security.CodeSource; import java.security.CodeSource;
import sun.misc.IOUtils;
import sun.security.action.GetPropertyAction; import sun.security.action.GetPropertyAction;
import sun.security.util.ManifestEntryVerifier; import sun.security.util.ManifestEntryVerifier;
import sun.misc.SharedSecrets; import sun.misc.SharedSecrets;
...@@ -334,6 +335,9 @@ class JarFile extends ZipFile { ...@@ -334,6 +335,9 @@ class JarFile extends ZipFile {
if (names != null) { if (names != null) {
for (int i = 0; i < names.length; i++) { for (int i = 0; i < names.length; i++) {
JarEntry e = getJarEntry(names[i]); JarEntry e = getJarEntry(names[i]);
if (e == null) {
throw new JarException("corrupted jar file");
}
if (!e.isDirectory()) { if (!e.isDirectory()) {
if (mev == null) { if (mev == null) {
mev = new ManifestEntryVerifier mev = new ManifestEntryVerifier
...@@ -353,6 +357,10 @@ class JarFile extends ZipFile { ...@@ -353,6 +357,10 @@ class JarFile extends ZipFile {
// treat the jar file as being unsigned // treat the jar file as being unsigned
jv = null; jv = null;
verify = false; verify = false;
if (JarVerifier.debug != null) {
JarVerifier.debug.println("jarfile parsing error!");
ex.printStackTrace();
}
} }
// if after initializing the verifier we have nothing // if after initializing the verifier we have nothing
...@@ -380,11 +388,9 @@ class JarFile extends ZipFile { ...@@ -380,11 +388,9 @@ class JarFile extends ZipFile {
* META-INF files. * META-INF files.
*/ */
private byte[] getBytes(ZipEntry ze) throws IOException { private byte[] getBytes(ZipEntry ze) throws IOException {
byte[] b = new byte[(int)ze.getSize()]; try (InputStream is = super.getInputStream(ze)) {
try (DataInputStream is = new DataInputStream(super.getInputStream(ze))) { return IOUtils.readFully(is, (int)ze.getSize(), true);
is.readFully(b, 0, b.length);
} }
return b;
} }
/** /**
...@@ -540,11 +546,7 @@ class JarFile extends ZipFile { ...@@ -540,11 +546,7 @@ class JarFile extends ZipFile {
if (!isKnownNotToHaveSpecialAttributes()) { if (!isKnownNotToHaveSpecialAttributes()) {
JarEntry manEntry = getManEntry(); JarEntry manEntry = getManEntry();
if (manEntry != null) { if (manEntry != null) {
byte[] b = new byte[(int)manEntry.getSize()]; byte[] b = getBytes(manEntry);
try (DataInputStream dis = new DataInputStream(
super.getInputStream(manEntry))) {
dis.readFully(b, 0, b.length);
}
if (match(CLASSPATH_CHARS, b, CLASSPATH_LASTOCC, CLASSPATH_OPTOSFT)) if (match(CLASSPATH_CHARS, b, CLASSPATH_LASTOCC, CLASSPATH_OPTOSFT))
hasClassPathAttribute = true; hasClassPathAttribute = true;
if (match(PROFILE_CHARS, b, PROFILE_LASTOCC, PROFILE_OPTOSFT)) if (match(PROFILE_CHARS, b, PROFILE_LASTOCC, PROFILE_OPTOSFT))
......
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
*/ */
package java.util.logging; package java.util.logging;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle; import java.util.ResourceBundle;
/** /**
...@@ -59,7 +63,6 @@ import java.util.ResourceBundle; ...@@ -59,7 +63,6 @@ import java.util.ResourceBundle;
*/ */
public class Level implements java.io.Serializable { public class Level implements java.io.Serializable {
private static java.util.ArrayList<Level> known = new java.util.ArrayList<>();
private static String defaultBundle = "sun.util.logging.resources.logging"; private static String defaultBundle = "sun.util.logging.resources.logging";
/** /**
...@@ -77,6 +80,9 @@ public class Level implements java.io.Serializable { ...@@ -77,6 +80,9 @@ public class Level implements java.io.Serializable {
*/ */
private final String resourceBundleName; private final String resourceBundleName;
// localized level name
private String localizedLevelName;
/** /**
* OFF is a special level that can be used to turn off logging. * OFF is a special level that can be used to turn off logging.
* This level is initialized to <CODE>Integer.MAX_VALUE</CODE>. * This level is initialized to <CODE>Integer.MAX_VALUE</CODE>.
...@@ -202,9 +208,8 @@ public class Level implements java.io.Serializable { ...@@ -202,9 +208,8 @@ public class Level implements java.io.Serializable {
this.name = name; this.name = name;
this.value = value; this.value = value;
this.resourceBundleName = resourceBundleName; this.resourceBundleName = resourceBundleName;
synchronized (Level.class) { this.localizedLevelName = resourceBundleName == null ? name : null;
known.add(this); KnownLevel.add(this);
}
} }
/** /**
...@@ -236,12 +241,76 @@ public class Level implements java.io.Serializable { ...@@ -236,12 +241,76 @@ public class Level implements java.io.Serializable {
* @return localized name * @return localized name
*/ */
public String getLocalizedName() { public String getLocalizedName() {
return getLocalizedLevelName();
}
// package-private getLevelName() is used by the implementation
// instead of getName() to avoid calling the subclass's version
final String getLevelName() {
return this.name;
}
final synchronized String getLocalizedLevelName() {
if (localizedLevelName != null) {
return localizedLevelName;
}
try { try {
ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName); ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName);
return rb.getString(name); localizedLevelName = rb.getString(name);
} catch (Exception ex) { } catch (Exception ex) {
return name; localizedLevelName = name;
}
return localizedLevelName;
}
// Returns a mirrored Level object that matches the given name as
// specified in the Level.parse method. Returns null if not found.
//
// It returns the same Level object as the one returned by Level.parse
// method if the given name is a non-localized name or integer.
//
// If the name is a localized name, findLevel and parse method may
// return a different level value if there is a custom Level subclass
// that overrides Level.getLocalizedName() to return a different string
// than what's returned by the default implementation.
//
static Level findLevel(String name) {
if (name == null) {
throw new NullPointerException();
}
KnownLevel level;
// Look for a known Level with the given non-localized name.
level = KnownLevel.findByName(name);
if (level != null) {
return level.mirroredLevel;
} }
// Now, check if the given name is an integer. If so,
// first look for a Level with the given value and then
// if necessary create one.
try {
int x = Integer.parseInt(name);
level = KnownLevel.findByValue(x);
if (level == null) {
// add new Level
Level levelObject = new Level(name, x);
level = KnownLevel.findByValue(x);
}
return level.mirroredLevel;
} catch (NumberFormatException ex) {
// Not an integer.
// Drop through.
}
level = KnownLevel.findByLocalizedLevelName(name);
if (level != null) {
return level.mirroredLevel;
}
return null;
} }
/** /**
...@@ -268,21 +337,15 @@ public class Level implements java.io.Serializable { ...@@ -268,21 +337,15 @@ public class Level implements java.io.Serializable {
// Serialization magic to prevent "doppelgangers". // Serialization magic to prevent "doppelgangers".
// This is a performance optimization. // This is a performance optimization.
private Object readResolve() { private Object readResolve() {
synchronized (Level.class) { KnownLevel o = KnownLevel.matches(this);
for (int i = 0; i < known.size(); i++) { if (o != null) {
Level other = known.get(i); return o.levelObject;
if (this.name.equals(other.name) && this.value == other.value
&& (this.resourceBundleName == other.resourceBundleName ||
(this.resourceBundleName != null &&
this.resourceBundleName.equals(other.resourceBundleName)))) {
return other;
}
}
// Woops. Whoever sent us this object knows
// about a new log level. Add it to our list.
known.add(this);
return this;
} }
// Woops. Whoever sent us this object knows
// about a new log level. Add it to our list.
Level level = new Level(this.name, this.value, this.resourceBundleName);
return level;
} }
/** /**
...@@ -296,6 +359,7 @@ public class Level implements java.io.Serializable { ...@@ -296,6 +359,7 @@ public class Level implements java.io.Serializable {
* <li> "SEVERE" * <li> "SEVERE"
* <li> "1000" * <li> "1000"
* </ul> * </ul>
*
* @param name string to be parsed * @param name string to be parsed
* @throws NullPointerException if the name is null * @throws NullPointerException if the name is null
* @throws IllegalArgumentException if the value is not valid. * @throws IllegalArgumentException if the value is not valid.
...@@ -315,12 +379,12 @@ public class Level implements java.io.Serializable { ...@@ -315,12 +379,12 @@ public class Level implements java.io.Serializable {
// Check that name is not null. // Check that name is not null.
name.length(); name.length();
KnownLevel level;
// Look for a known Level with the given non-localized name. // Look for a known Level with the given non-localized name.
for (int i = 0; i < known.size(); i++) { level = KnownLevel.findByName(name);
Level l = known.get(i); if (level != null) {
if (name.equals(l.name)) { return level.levelObject;
return l;
}
} }
// Now, check if the given name is an integer. If so, // Now, check if the given name is an integer. If so,
...@@ -328,14 +392,13 @@ public class Level implements java.io.Serializable { ...@@ -328,14 +392,13 @@ public class Level implements java.io.Serializable {
// if necessary create one. // if necessary create one.
try { try {
int x = Integer.parseInt(name); int x = Integer.parseInt(name);
for (int i = 0; i < known.size(); i++) { level = KnownLevel.findByValue(x);
Level l = known.get(i); if (level == null) {
if (l.value == x) { // add new Level
return l; Level levelObject = new Level(name, x);
} level = KnownLevel.findByValue(x);
} }
// Create a new Level. return level.levelObject;
return new Level(name, x);
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
// Not an integer. // Not an integer.
// Drop through. // Drop through.
...@@ -344,11 +407,9 @@ public class Level implements java.io.Serializable { ...@@ -344,11 +407,9 @@ public class Level implements java.io.Serializable {
// Finally, look for a known level with the given localized name, // Finally, look for a known level with the given localized name,
// in the current default locale. // in the current default locale.
// This is relatively expensive, but not excessively so. // This is relatively expensive, but not excessively so.
for (int i = 0; i < known.size(); i++) { level = KnownLevel.findByLocalizedName(name);
Level l = known.get(i); if (level != null) {
if (name.equals(l.getLocalizedName())) { return level.levelObject;
return l;
}
} }
// OK, we've tried everything and failed // OK, we've tried everything and failed
...@@ -375,4 +436,124 @@ public class Level implements java.io.Serializable { ...@@ -375,4 +436,124 @@ public class Level implements java.io.Serializable {
public int hashCode() { public int hashCode() {
return this.value; return this.value;
} }
// KnownLevel class maintains the global list of all known levels.
// The API allows multiple custom Level instances of the same name/value
// be created. This class provides convenient methods to find a level
// by a given name, by a given value, or by a given localized name.
//
// KnownLevel wraps the following Level objects:
// 1. levelObject: standard Level object or custom Level object
// 2. mirroredLevel: Level object representing the level specified in the
// logging configuration.
//
// Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods
// are non-final but the name and resource bundle name are parameters to
// the Level constructor. Use the mirroredLevel object instead of the
// levelObject to prevent the logging framework to execute foreign code
// implemented by untrusted Level subclass.
//
// Implementation Notes:
// If Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods
// were final, the following KnownLevel implementation can be removed.
// Future API change should take this into consideration.
static final class KnownLevel {
private static Map<String, List<KnownLevel>> nameToLevels = new HashMap<>();
private static Map<Integer, List<KnownLevel>> intToLevels = new HashMap<>();
final Level levelObject; // instance of Level class or Level subclass
final Level mirroredLevel; // instance of Level class
KnownLevel(Level l) {
this.levelObject = l;
if (l.getClass() == Level.class) {
this.mirroredLevel = l;
} else {
this.mirroredLevel = new Level(l.name, l.value, l.resourceBundleName);
}
}
static synchronized void add(Level l) {
// the mirroredLevel object is always added to the list
// before the custom Level instance
KnownLevel o = new KnownLevel(l);
List<KnownLevel> list = nameToLevels.get(l.name);
if (list == null) {
list = new ArrayList<>();
nameToLevels.put(l.name, list);
}
list.add(o);
list = intToLevels.get(l.value);
if (list == null) {
list = new ArrayList<>();
intToLevels.put(l.value, list);
}
list.add(o);
}
// Returns a KnownLevel with the given non-localized name.
static synchronized KnownLevel findByName(String name) {
List<KnownLevel> list = nameToLevels.get(name);
if (list != null) {
return list.get(0);
}
return null;
}
// Returns a KnownLevel with the given value.
static synchronized KnownLevel findByValue(int value) {
List<KnownLevel> list = intToLevels.get(value);
if (list != null) {
return list.get(0);
}
return null;
}
// Returns a KnownLevel with the given localized name matching
// by calling the Level.getLocalizedLevelName() method (i.e. found
// from the resourceBundle associated with the Level object).
// This method does not call Level.getLocalizedName() that may
// be overridden in a subclass implementation
static synchronized KnownLevel findByLocalizedLevelName(String name) {
for (List<KnownLevel> levels : nameToLevels.values()) {
for (KnownLevel l : levels) {
String lname = l.levelObject.getLocalizedLevelName();
if (name.equals(lname)) {
return l;
}
}
}
return null;
}
// Returns a KnownLevel with the given localized name matching
// by calling the Level.getLocalizedName() method
static synchronized KnownLevel findByLocalizedName(String name) {
for (List<KnownLevel> levels : nameToLevels.values()) {
for (KnownLevel l : levels) {
String lname = l.levelObject.getLocalizedName();
if (name.equals(lname)) {
return l;
}
}
}
return null;
}
static synchronized KnownLevel matches(Level l) {
List<KnownLevel> list = nameToLevels.get(l.name);
if (list != null) {
for (KnownLevel level : list) {
Level other = level.mirroredLevel;
if (l.value == other.value &&
(l.resourceBundleName == other.resourceBundleName ||
(l.resourceBundleName != null &&
l.resourceBundleName.equals(other.resourceBundleName)))) {
return level;
}
}
}
return null;
}
}
} }
...@@ -314,6 +314,40 @@ public class Logger { ...@@ -314,6 +314,40 @@ public class Logger {
} }
} }
// Until all JDK code converted to call sun.util.logging.PlatformLogger
// (see 7054233), we need to determine if Logger.getLogger is to add
// a system logger or user logger.
//
// As an interim solution, if the immediate caller whose caller loader is
// null, we assume it's a system logger and add it to the system context.
// These system loggers only set the resource bundle to the given
// resource bundle name (rather than the default system resource bundle).
private static class SystemLoggerHelper {
static boolean disableCallerCheck = getBooleanProperty("sun.util.logging.disableCallerCheck");
private static boolean getBooleanProperty(final String key) {
String s = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty(key);
}
});
return Boolean.valueOf(s);
}
}
private static Logger demandLogger(String name, String resourceBundleName) {
LogManager manager = LogManager.getLogManager();
SecurityManager sm = System.getSecurityManager();
if (sm != null && !SystemLoggerHelper.disableCallerCheck) {
// 0: Reflection 1: Logger.demandLogger 2: Logger.getLogger 3: caller
final int SKIP_FRAMES = 3;
Class<?> caller = sun.reflect.Reflection.getCallerClass(SKIP_FRAMES);
if (caller.getClassLoader() == null) {
return manager.demandSystemLogger(name, resourceBundleName);
}
}
return manager.demandLogger(name, resourceBundleName);
}
/** /**
* Find or create a logger for a named subsystem. If a logger has * Find or create a logger for a named subsystem. If a logger has
* already been created with the given name it is returned. Otherwise * already been created with the given name it is returned. Otherwise
...@@ -355,8 +389,7 @@ public class Logger { ...@@ -355,8 +389,7 @@ public class Logger {
// would throw an IllegalArgumentException in the second call // would throw an IllegalArgumentException in the second call
// because the wrapper would result in an attempt to replace // because the wrapper would result in an attempt to replace
// the existing "resourceBundleForFoo" with null. // the existing "resourceBundleForFoo" with null.
LogManager manager = LogManager.getLogManager(); return demandLogger(name, null);
return manager.demandLogger(name);
} }
/** /**
...@@ -403,8 +436,7 @@ public class Logger { ...@@ -403,8 +436,7 @@ public class Logger {
// Synchronization is not required here. All synchronization for // Synchronization is not required here. All synchronization for
// adding a new Logger object is handled by LogManager.addLogger(). // adding a new Logger object is handled by LogManager.addLogger().
public static Logger getLogger(String name, String resourceBundleName) { public static Logger getLogger(String name, String resourceBundleName) {
LogManager manager = LogManager.getLogManager(); Logger result = demandLogger(name, resourceBundleName);
Logger result = manager.demandLogger(name);
// MissingResourceException or IllegalArgumentException can be // MissingResourceException or IllegalArgumentException can be
// thrown by setupResourceInfo(). // thrown by setupResourceInfo().
...@@ -412,6 +444,17 @@ public class Logger { ...@@ -412,6 +444,17 @@ public class Logger {
return result; return result;
} }
// package-private
// Add a platform logger to the system context.
// i.e. caller of sun.util.logging.PlatformLogger.getLogger
static Logger getPlatformLogger(String name) {
LogManager manager = LogManager.getLogManager();
// all loggers in the system context will default to
// the system logger's resource bundle
Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME);
return result;
}
/** /**
* Create an anonymous Logger. The newly created Logger is not * Create an anonymous Logger. The newly created Logger is not
...@@ -564,7 +607,7 @@ public class Logger { ...@@ -564,7 +607,7 @@ public class Logger {
private void doLog(LogRecord lr) { private void doLog(LogRecord lr) {
lr.setLoggerName(name); lr.setLoggerName(name);
String ebname = getEffectiveResourceBundleName(); String ebname = getEffectiveResourceBundleName();
if (ebname != null) { if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) {
lr.setResourceBundleName(ebname); lr.setResourceBundleName(ebname);
lr.setResourceBundle(findResourceBundle(ebname)); lr.setResourceBundle(findResourceBundle(ebname));
} }
...@@ -1547,6 +1590,23 @@ public class Logger { ...@@ -1547,6 +1590,23 @@ public class Logger {
// May also return null if we can't find the resource bundle and // May also return null if we can't find the resource bundle and
// there is no suitable previous cached value. // there is no suitable previous cached value.
static final String SYSTEM_LOGGER_RB_NAME = "sun.util.logging.resources.logging";
private static ResourceBundle findSystemResourceBundle(final Locale locale) {
// the resource bundle is in a restricted package
return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {
public ResourceBundle run() {
try {
return ResourceBundle.getBundle(SYSTEM_LOGGER_RB_NAME,
locale,
ClassLoader.getSystemClassLoader());
} catch (MissingResourceException e) {
throw new InternalError(e.toString());
}
}
});
}
private synchronized ResourceBundle findResourceBundle(String name) { private synchronized ResourceBundle findResourceBundle(String name) {
// Return a null bundle for a null name. // Return a null bundle for a null name.
if (name == null) { if (name == null) {
...@@ -1561,6 +1621,13 @@ public class Logger { ...@@ -1561,6 +1621,13 @@ public class Logger {
return catalog; return catalog;
} }
if (name.equals(SYSTEM_LOGGER_RB_NAME)) {
catalog = findSystemResourceBundle(currentLocale);
catalogName = name;
catalogLocale = currentLocale;
return catalog;
}
// Use the thread's context ClassLoader. If there isn't one, // Use the thread's context ClassLoader. If there isn't one,
// use the SystemClassloader. // use the SystemClassloader.
ClassLoader cl = Thread.currentThread().getContextClassLoader(); ClassLoader cl = Thread.currentThread().getContextClassLoader();
...@@ -1577,7 +1644,6 @@ public class Logger { ...@@ -1577,7 +1644,6 @@ public class Logger {
// ClassLoader. Drop through. // ClassLoader. Drop through.
} }
// Fall back to searching up the call stack and trying each // Fall back to searching up the call stack and trying each
// calling ClassLoader. // calling ClassLoader.
for (int ix = 0; ; ix++) { for (int ix = 0; ; ix++) {
......
...@@ -34,7 +34,7 @@ import java.util.ArrayList; ...@@ -34,7 +34,7 @@ import java.util.ArrayList;
* *
* The <tt>LoggingMXBean</tt> interface provides a standard * The <tt>LoggingMXBean</tt> interface provides a standard
* method for management access to the individual * method for management access to the individual
* java.util.Logger objects available at runtime. * {@code Logger} objects available at runtime.
* *
* @author Ron Mann * @author Ron Mann
* @author Mandy Chung * @author Mandy Chung
...@@ -75,7 +75,7 @@ class Logging implements LoggingMXBean { ...@@ -75,7 +75,7 @@ class Logging implements LoggingMXBean {
if (level == null) { if (level == null) {
return EMPTY_STRING; return EMPTY_STRING;
} else { } else {
return level.getName(); return level.getLevelName();
} }
} }
...@@ -85,7 +85,6 @@ class Logging implements LoggingMXBean { ...@@ -85,7 +85,6 @@ class Logging implements LoggingMXBean {
} }
Logger logger = logManager.getLogger(loggerName); Logger logger = logManager.getLogger(loggerName);
if (logger == null) { if (logger == null) {
throw new IllegalArgumentException("Logger " + loggerName + throw new IllegalArgumentException("Logger " + loggerName +
"does not exist"); "does not exist");
...@@ -94,7 +93,10 @@ class Logging implements LoggingMXBean { ...@@ -94,7 +93,10 @@ class Logging implements LoggingMXBean {
Level level = null; Level level = null;
if (levelName != null) { if (levelName != null) {
// parse will throw IAE if logLevel is invalid // parse will throw IAE if logLevel is invalid
level = Level.parse(levelName); level = Level.findLevel(levelName);
if (level == null) {
throw new IllegalArgumentException("Unknown level \"" + levelName + "\"");
}
} }
logger.setLevel(level); logger.setLevel(level);
......
...@@ -37,7 +37,8 @@ class LoggingProxyImpl implements LoggingProxy { ...@@ -37,7 +37,8 @@ class LoggingProxyImpl implements LoggingProxy {
@Override @Override
public Object getLogger(String name) { public Object getLogger(String name) {
return Logger.getLogger(name); // always create a platform logger with the resource bundle name
return Logger.getPlatformLogger(name);
} }
@Override @Override
...@@ -92,12 +93,16 @@ class LoggingProxyImpl implements LoggingProxy { ...@@ -92,12 +93,16 @@ class LoggingProxyImpl implements LoggingProxy {
@Override @Override
public Object parseLevel(String levelName) { public Object parseLevel(String levelName) {
return Level.parse(levelName); Level level = Level.findLevel(levelName);
if (level == null) {
throw new IllegalArgumentException("Unknown level \"" + levelName + "\"");
}
return level;
} }
@Override @Override
public String getLevelName(Object level) { public String getLevelName(Object level) {
return ((Level) level).getName(); return ((Level) level).getLevelName();
} }
@Override @Override
......
...@@ -162,7 +162,7 @@ public class SimpleFormatter extends Formatter { ...@@ -162,7 +162,7 @@ public class SimpleFormatter extends Formatter {
dat, dat,
source, source,
record.getLoggerName(), record.getLoggerName(),
record.getLevel().getLocalizedName(), record.getLevel().getLocalizedLevelName(),
message, message,
throwable); throwable);
} }
......
/* /*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -39,11 +39,13 @@ import java.io.PrintStream; ...@@ -39,11 +39,13 @@ import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -78,6 +80,8 @@ import javax.management.RuntimeErrorException; ...@@ -78,6 +80,8 @@ import javax.management.RuntimeErrorException;
import javax.management.RuntimeOperationsException; import javax.management.RuntimeOperationsException;
import javax.management.ServiceNotFoundException; import javax.management.ServiceNotFoundException;
import javax.management.loading.ClassLoaderRepository; import javax.management.loading.ClassLoaderRepository;
import sun.misc.JavaSecurityAccess;
import sun.misc.SharedSecrets;
import sun.reflect.misc.MethodUtil; import sun.reflect.misc.MethodUtil;
import sun.reflect.misc.ReflectUtil; import sun.reflect.misc.ReflectUtil;
...@@ -138,6 +142,9 @@ public class RequiredModelMBean ...@@ -138,6 +142,9 @@ public class RequiredModelMBean
private boolean registered = false; private boolean registered = false;
private transient MBeanServer server = null; private transient MBeanServer server = null;
private final static JavaSecurityAccess javaSecurityAccess = SharedSecrets.getJavaSecurityAccess();
final private AccessControlContext acc = AccessController.getContext();
/*************************************/ /*************************************/
/* constructors */ /* constructors */
/*************************************/ /*************************************/
...@@ -1025,10 +1032,31 @@ public class RequiredModelMBean ...@@ -1025,10 +1032,31 @@ public class RequiredModelMBean
if (opClassName != null) { if (opClassName != null) {
try { try {
final ClassLoader targetClassLoader = AccessControlContext stack = AccessController.getContext();
targetObject.getClass().getClassLoader(); final Object obj = targetObject;
targetClass = Class.forName(opClassName, false, final String className = opClassName;
targetClassLoader); final ClassNotFoundException[] caughtException = new ClassNotFoundException[1];
targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
@Override
public Class<?> run() {
try {
ReflectUtil.checkPackageAccess(className);
final ClassLoader targetClassLoader =
obj.getClass().getClassLoader();
return Class.forName(className, false,
targetClassLoader);
} catch (ClassNotFoundException e) {
caughtException[0] = e;
}
return null;
}
}, stack, acc);
if (caughtException[0] != null) {
throw caughtException[0];
}
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
final String msg = final String msg =
"class for invoke " + opName + " not found"; "class for invoke " + opName + " not found";
...@@ -1061,9 +1089,9 @@ public class RequiredModelMBean ...@@ -1061,9 +1089,9 @@ public class RequiredModelMBean
return result; return result;
} }
private static Method resolveMethod(Class<?> targetClass, private Method resolveMethod(Class<?> targetClass,
String opMethodName, String opMethodName,
String[] sig) final String[] sig)
throws ReflectionException { throws ReflectionException {
final boolean tracing = MODELMBEAN_LOGGER.isLoggable(Level.FINER); final boolean tracing = MODELMBEAN_LOGGER.isLoggable(Level.FINER);
...@@ -1078,30 +1106,45 @@ public class RequiredModelMBean ...@@ -1078,30 +1106,45 @@ public class RequiredModelMBean
if (sig == null) if (sig == null)
argClasses = null; argClasses = null;
else { else {
final AccessControlContext stack = AccessController.getContext();
final ReflectionException[] caughtException = new ReflectionException[1];
final ClassLoader targetClassLoader = targetClass.getClassLoader(); final ClassLoader targetClassLoader = targetClass.getClassLoader();
argClasses = new Class<?>[sig.length]; argClasses = new Class<?>[sig.length];
for (int i = 0; i < sig.length; i++) {
if (tracing) { javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() {
MODELMBEAN_LOGGER.logp(Level.FINER,
RequiredModelMBean.class.getName(),"resolveMethod", @Override
"resolve type " + sig[i]); public Void run() {
} for (int i = 0; i < sig.length; i++) {
argClasses[i] = (Class<?>) primitiveClassMap.get(sig[i]);
if (argClasses[i] == null) {
try {
argClasses[i] =
Class.forName(sig[i], false, targetClassLoader);
} catch (ClassNotFoundException e) {
if (tracing) { if (tracing) {
MODELMBEAN_LOGGER.logp(Level.FINER, MODELMBEAN_LOGGER.logp(Level.FINER,
RequiredModelMBean.class.getName(), RequiredModelMBean.class.getName(),"resolveMethod",
"resolveMethod", "resolve type " + sig[i]);
"class not found"); }
argClasses[i] = (Class<?>) primitiveClassMap.get(sig[i]);
if (argClasses[i] == null) {
try {
ReflectUtil.checkPackageAccess(sig[i]);
argClasses[i] =
Class.forName(sig[i], false, targetClassLoader);
} catch (ClassNotFoundException e) {
if (tracing) {
MODELMBEAN_LOGGER.logp(Level.FINER,
RequiredModelMBean.class.getName(),
"resolveMethod",
"class not found");
}
final String msg = "Parameter class not found";
caughtException[0] = new ReflectionException(e, msg);
}
} }
final String msg = "Parameter class not found";
throw new ReflectionException(e, msg);
} }
return null;
} }
}, stack, acc);
if (caughtException[0] != null) {
throw caughtException[0];
} }
} }
...@@ -1133,7 +1176,7 @@ public class RequiredModelMBean ...@@ -1133,7 +1176,7 @@ public class RequiredModelMBean
/* Find a method in RequiredModelMBean as determined by the given /* Find a method in RequiredModelMBean as determined by the given
parameters. Return null if there is none, or if the parameters parameters. Return null if there is none, or if the parameters
exclude using it. Called from invoke. */ exclude using it. Called from invoke. */
private static Method findRMMBMethod(String opMethodName, private Method findRMMBMethod(String opMethodName,
Object targetObjectField, Object targetObjectField,
String opClassName, String opClassName,
String[] sig) { String[] sig) {
...@@ -1155,19 +1198,29 @@ public class RequiredModelMBean ...@@ -1155,19 +1198,29 @@ public class RequiredModelMBean
if (opClassName == null) if (opClassName == null)
targetClass = rmmbClass; targetClass = rmmbClass;
else { else {
try { AccessControlContext stack = AccessController.getContext();
final ClassLoader targetClassLoader = final String className = opClassName;
rmmbClass.getClassLoader(); targetClass = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
targetClass = Class.forName(opClassName, false,
targetClassLoader); @Override
if (!rmmbClass.isAssignableFrom(targetClass)) public Class<?> run() {
return null; try {
} catch (ClassNotFoundException e) { ReflectUtil.checkPackageAccess(className);
return null; final ClassLoader targetClassLoader =
} rmmbClass.getClassLoader();
Class clz = Class.forName(className, false,
targetClassLoader);
if (!rmmbClass.isAssignableFrom(clz))
return null;
return clz;
} catch (ClassNotFoundException e) {
return null;
}
}
}, stack, acc);
} }
try { try {
return resolveMethod(targetClass, opMethodName, sig); return targetClass != null ? resolveMethod(targetClass, opMethodName, sig) : null;
} catch (ReflectionException e) { } catch (ReflectionException e) {
return null; return null;
} }
...@@ -1177,12 +1230,35 @@ public class RequiredModelMBean ...@@ -1177,12 +1230,35 @@ public class RequiredModelMBean
* Invoke the given method, and throw the somewhat unpredictable * Invoke the given method, and throw the somewhat unpredictable
* appropriate exception if the method itself gets an exception. * appropriate exception if the method itself gets an exception.
*/ */
private Object invokeMethod(String opName, Method method, private Object invokeMethod(String opName, final Method method,
Object targetObject, Object[] opArgs) final Object targetObject, final Object[] opArgs)
throws MBeanException, ReflectionException { throws MBeanException, ReflectionException {
try { try {
ReflectUtil.checkPackageAccess(method.getDeclaringClass()); final Throwable[] caughtException = new Throwable[1];
return MethodUtil.invoke(method, targetObject, opArgs); AccessControlContext stack = AccessController.getContext();
Object rslt = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
ReflectUtil.checkPackageAccess(method.getDeclaringClass());
return MethodUtil.invoke(method, targetObject, opArgs);
} catch (InvocationTargetException e) {
caughtException[0] = e;
} catch (IllegalAccessException e) {
caughtException[0] = e;
}
return null;
}
}, stack, acc);
if (caughtException[0] != null) {
if (caughtException[0] instanceof Exception) {
throw (Exception)caughtException[0];
} else if(caughtException[0] instanceof Error) {
throw (Error)caughtException[0];
}
}
return rslt;
} catch (RuntimeErrorException ree) { } catch (RuntimeErrorException ree) {
throw new RuntimeOperationsException(ree, throw new RuntimeOperationsException(ree,
"RuntimeException occurred in RequiredModelMBean "+ "RuntimeException occurred in RequiredModelMBean "+
...@@ -1567,7 +1643,7 @@ public class RequiredModelMBean ...@@ -1567,7 +1643,7 @@ public class RequiredModelMBean
} }
// make sure response class matches type field // make sure response class matches type field
String respType = attrInfo.getType(); final String respType = attrInfo.getType();
if (response != null) { if (response != null) {
String responseClass = response.getClass().getName(); String responseClass = response.getClass().getName();
if (!respType.equals(responseClass)) { if (!respType.equals(responseClass)) {
...@@ -1590,9 +1666,31 @@ public class RequiredModelMBean ...@@ -1590,9 +1666,31 @@ public class RequiredModelMBean
// inequality may come from type subclassing // inequality may come from type subclassing
boolean subtype; boolean subtype;
try { try {
ClassLoader cl = final Class respClass = response.getClass();
response.getClass().getClassLoader(); final Exception[] caughException = new Exception[1];
Class<?> c = Class.forName(respType, true, cl);
AccessControlContext stack = AccessController.getContext();
Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
@Override
public Class<?> run() {
try {
ReflectUtil.checkPackageAccess(respType);
ClassLoader cl =
respClass.getClassLoader();
return Class.forName(respType, true, cl);
} catch (Exception e) {
caughException[0] = e;
}
return null;
}
}, stack, acc);
if (caughException[0] != null) {
throw caughException[0];
}
subtype = c.isInstance(response); subtype = c.isInstance(response);
} catch (Exception e) { } catch (Exception e) {
subtype = false; subtype = false;
...@@ -2745,16 +2843,37 @@ public class RequiredModelMBean ...@@ -2745,16 +2843,37 @@ public class RequiredModelMBean
return MBeanServerFactory.getClassLoaderRepository(server); return MBeanServerFactory.getClassLoaderRepository(server);
} }
private Class<?> loadClass(String className) private Class<?> loadClass(final String className)
throws ClassNotFoundException { throws ClassNotFoundException {
try { AccessControlContext stack = AccessController.getContext();
return Class.forName(className); final ClassNotFoundException[] caughtException = new ClassNotFoundException[1];
} catch (ClassNotFoundException e) {
final ClassLoaderRepository clr = Class c = javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Class<?>>() {
getClassLoaderRepository();
if (clr == null) throw new ClassNotFoundException(className); @Override
return clr.loadClass(className); public Class<?> run() {
try {
ReflectUtil.checkPackageAccess(className);
return Class.forName(className);
} catch (ClassNotFoundException e) {
final ClassLoaderRepository clr =
getClassLoaderRepository();
try {
if (clr == null) throw new ClassNotFoundException(className);
return clr.loadClass(className);
} catch (ClassNotFoundException ex) {
caughtException[0] = ex;
}
}
return null;
}
}, stack, acc);
if (caughtException[0] != null) {
throw caughtException[0];
} }
return c;
} }
......
...@@ -781,15 +781,11 @@ public class JTable extends JComponent implements TableModelListener, Scrollable ...@@ -781,15 +781,11 @@ public class JTable extends JComponent implements TableModelListener, Scrollable
scrollPane.getCorner(JScrollPane.UPPER_TRAILING_CORNER); scrollPane.getCorner(JScrollPane.UPPER_TRAILING_CORNER);
if (corner == null || corner instanceof UIResource){ if (corner == null || corner instanceof UIResource){
corner = null; corner = null;
Object componentClass = UIManager.get( try {
"Table.scrollPaneCornerComponent"); corner = (Component) UIManager.get(
if (componentClass instanceof Class){ "Table.scrollPaneCornerComponent");
try { } catch (Exception e) {
corner = (Component) // just ignore and don't set corner
((Class)componentClass).newInstance();
} catch (Exception e) {
// just ignore and don't set corner
}
} }
scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER, scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER,
corner); corner);
......
...@@ -27,11 +27,12 @@ package javax.swing; ...@@ -27,11 +27,12 @@ package javax.swing;
import java.awt.*; import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.image.VolatileImage; import java.awt.image.VolatileImage;
import java.security.AccessControlContext;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.applet.*; import java.applet.*;
import sun.awt.AWTAccessor; import sun.awt.AWTAccessor;
...@@ -39,6 +40,8 @@ import sun.awt.AppContext; ...@@ -39,6 +40,8 @@ import sun.awt.AppContext;
import sun.awt.DisplayChangedListener; import sun.awt.DisplayChangedListener;
import sun.awt.SunToolkit; import sun.awt.SunToolkit;
import sun.java2d.SunGraphicsEnvironment; import sun.java2d.SunGraphicsEnvironment;
import sun.misc.JavaSecurityAccess;
import sun.misc.SharedSecrets;
import sun.security.action.GetPropertyAction; import sun.security.action.GetPropertyAction;
import com.sun.java.swing.SwingUtilities3; import com.sun.java.swing.SwingUtilities3;
...@@ -176,6 +179,9 @@ public class RepaintManager ...@@ -176,6 +179,9 @@ public class RepaintManager
*/ */
private final ProcessingRunnable processingRunnable; private final ProcessingRunnable processingRunnable;
private final static JavaSecurityAccess javaSecurityAccess =
SharedSecrets.getJavaSecurityAccess();
static { static {
volatileImageBufferEnabled = "true".equals(AccessController. volatileImageBufferEnabled = "true".equals(AccessController.
...@@ -548,13 +554,26 @@ public class RepaintManager ...@@ -548,13 +554,26 @@ public class RepaintManager
// This is called from the toolkit thread when awt needs to run a // This is called from the toolkit thread when awt needs to run a
// Runnable before we paint. // Runnable before we paint.
// //
void nativeQueueSurfaceDataRunnable(AppContext appContext, Component c, void nativeQueueSurfaceDataRunnable(AppContext appContext,
Runnable r) { final Component c, final Runnable r)
{
synchronized(this) { synchronized(this) {
if (runnableList == null) { if (runnableList == null) {
runnableList = new LinkedList<Runnable>(); runnableList = new LinkedList<Runnable>();
} }
runnableList.add(r); runnableList.add(new Runnable() {
public void run() {
AccessControlContext stack = AccessController.getContext();
AccessControlContext acc =
AWTAccessor.getComponentAccessor().getAccessControlContext(c);
javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() {
public Void run() {
r.run();
return null;
}
}, stack, acc);
}
});
} }
scheduleProcessingRunnable(appContext); scheduleProcessingRunnable(appContext);
} }
...@@ -652,9 +671,9 @@ public class RepaintManager ...@@ -652,9 +671,9 @@ public class RepaintManager
* @see #addInvalidComponent * @see #addInvalidComponent
*/ */
public void validateInvalidComponents() { public void validateInvalidComponents() {
java.util.List<Component> ic; final java.util.List<Component> ic;
synchronized(this) { synchronized(this) {
if(invalidComponents == null) { if (invalidComponents == null) {
return; return;
} }
ic = invalidComponents; ic = invalidComponents;
...@@ -662,7 +681,17 @@ public class RepaintManager ...@@ -662,7 +681,17 @@ public class RepaintManager
} }
int n = ic.size(); int n = ic.size();
for(int i = 0; i < n; i++) { for(int i = 0; i < n; i++) {
ic.get(i).validate(); final Component c = ic.get(i);
AccessControlContext stack = AccessController.getContext();
AccessControlContext acc =
AWTAccessor.getComponentAccessor().getAccessControlContext(c);
javaSecurityAccess.doIntersectionPrivilege(
new PrivilegedAction<Void>() {
public Void run() {
c.validate();
return null;
}
}, stack, acc);
} }
} }
...@@ -740,78 +769,78 @@ public class RepaintManager ...@@ -740,78 +769,78 @@ public class RepaintManager
paintDirtyRegions(tmpDirtyComponents); paintDirtyRegions(tmpDirtyComponents);
} }
private void paintDirtyRegions(Map<Component,Rectangle> private void paintDirtyRegions(
tmpDirtyComponents){ final Map<Component,Rectangle> tmpDirtyComponents)
int i, count; {
java.util.List<Component> roots; if (tmpDirtyComponents.isEmpty()) {
Component dirtyComponent;
count = tmpDirtyComponents.size();
if (count == 0) {
return; return;
} }
Rectangle rect; final java.util.List<Component> roots =
int localBoundsX = 0; new ArrayList<Component>(tmpDirtyComponents.size());
int localBoundsY = 0;
int localBoundsH;
int localBoundsW;
roots = new ArrayList<Component>(count);
for (Component dirty : tmpDirtyComponents.keySet()) { for (Component dirty : tmpDirtyComponents.keySet()) {
collectDirtyComponents(tmpDirtyComponents, dirty, roots); collectDirtyComponents(tmpDirtyComponents, dirty, roots);
} }
count = roots.size(); final AtomicInteger count = new AtomicInteger(roots.size());
painting = true; painting = true;
try { try {
for(i=0 ; i < count ; i++) { for (int j=0 ; j < count.get(); j++) {
dirtyComponent = roots.get(i); final int i = j;
rect = tmpDirtyComponents.get(dirtyComponent); final Component dirtyComponent = roots.get(j);
// Sometimes when RepaintManager is changed during the painting AccessControlContext stack = AccessController.getContext();
// we may get null here, see #6995769 for details AccessControlContext acc =
if (rect == null) { AWTAccessor.getComponentAccessor().getAccessControlContext(dirtyComponent);
continue; javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() {
} public Void run() {
localBoundsH = dirtyComponent.getHeight(); Rectangle rect = tmpDirtyComponents.get(dirtyComponent);
localBoundsW = dirtyComponent.getWidth(); // Sometimes when RepaintManager is changed during the painting
// we may get null here, see #6995769 for details
SwingUtilities.computeIntersection(localBoundsX, if (rect == null) {
localBoundsY, return null;
localBoundsW, }
localBoundsH,
rect); int localBoundsH = dirtyComponent.getHeight();
if (dirtyComponent instanceof JComponent) { int localBoundsW = dirtyComponent.getWidth();
((JComponent)dirtyComponent).paintImmediately( SwingUtilities.computeIntersection(0,
rect.x,rect.y,rect.width, rect.height); 0,
} localBoundsW,
else if (dirtyComponent.isShowing()) { localBoundsH,
Graphics g = JComponent.safelyGetGraphics( rect);
dirtyComponent, dirtyComponent); if (dirtyComponent instanceof JComponent) {
// If the Graphics goes away, it means someone disposed of ((JComponent)dirtyComponent).paintImmediately(
// the window, don't do anything. rect.x,rect.y,rect.width, rect.height);
if (g != null) { }
g.setClip(rect.x, rect.y, rect.width, rect.height); else if (dirtyComponent.isShowing()) {
try { Graphics g = JComponent.safelyGetGraphics(
dirtyComponent.paint(g); dirtyComponent, dirtyComponent);
} finally { // If the Graphics goes away, it means someone disposed of
g.dispose(); // the window, don't do anything.
if (g != null) {
g.setClip(rect.x, rect.y, rect.width, rect.height);
try {
dirtyComponent.paint(g);
} finally {
g.dispose();
}
}
} }
// If the repaintRoot has been set, service it now and
// remove any components that are children of repaintRoot.
if (repaintRoot != null) {
adjustRoots(repaintRoot, roots, i + 1);
count.set(roots.size());
paintManager.isRepaintingRoot = true;
repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(),
repaintRoot.getHeight());
paintManager.isRepaintingRoot = false;
// Only service repaintRoot once.
repaintRoot = null;
}
return null;
} }
} }, stack, acc);
// If the repaintRoot has been set, service it now and
// remove any components that are children of repaintRoot.
if (repaintRoot != null) {
adjustRoots(repaintRoot, roots, i + 1);
count = roots.size();
paintManager.isRepaintingRoot = true;
repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(),
repaintRoot.getHeight());
paintManager.isRepaintingRoot = false;
// Only service repaintRoot once.
repaintRoot = null;
}
} }
} finally { } finally {
painting = false; painting = false;
......
...@@ -677,6 +677,8 @@ public class UIDefaults extends Hashtable<Object,Object> ...@@ -677,6 +677,8 @@ public class UIDefaults extends Hashtable<Object,Object>
try { try {
String className = (String)get(uiClassID); String className = (String)get(uiClassID);
if (className != null) { if (className != null) {
ReflectUtil.checkPackageAccess(className);
Class cls = (Class)get(className); Class cls = (Class)get(className);
if (cls == null) { if (cls == null) {
if (uiClassLoader == null) { if (uiClassLoader == null) {
......
...@@ -159,7 +159,12 @@ public class NimbusLookAndFeel extends SynthLookAndFeel { ...@@ -159,7 +159,12 @@ public class NimbusLookAndFeel extends SynthLookAndFeel {
// Store Table ScrollPane Corner Component // Store Table ScrollPane Corner Component
uiDefaults.put("Table.scrollPaneCornerComponent", uiDefaults.put("Table.scrollPaneCornerComponent",
TableScrollPaneCorner.class); new UIDefaults.ActiveValue() {
@Override
public Object createValue(UIDefaults table) {
return new TableScrollPaneCorner();
}
});
// Setup the settings for ToolBarSeparator which is custom // Setup the settings for ToolBarSeparator which is custom
// installed for Nimbus // installed for Nimbus
......
...@@ -45,6 +45,7 @@ import java.util.*; ...@@ -45,6 +45,7 @@ import java.util.*;
import java.util.Collections; import java.util.Collections;
import java.util.Locale; import java.util.Locale;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import sun.awt.AWTAccessor;
import sun.awt.AppContext; import sun.awt.AppContext;
import sun.awt.EmbeddedFrame; import sun.awt.EmbeddedFrame;
import sun.awt.SunToolkit; import sun.awt.SunToolkit;
...@@ -448,12 +449,12 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { ...@@ -448,12 +449,12 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable {
// to avoid deadlock. // to avoid deadlock.
try { try {
final AppletPanel p = this; final AppletPanel p = this;
Runnable r = new Runnable() {
EventQueue.invokeAndWait(new Runnable() { public void run() {
public void run() { p.validate();
p.validate(); }
} };
}); AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
} }
catch(InterruptedException ie) { catch(InterruptedException ie) {
} }
...@@ -478,18 +479,19 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { ...@@ -478,18 +479,19 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable {
try { try {
final AppletPanel p = this; final AppletPanel p = this;
final Applet a = applet; final Applet a = applet;
Runnable r = new Runnable() {
EventQueue.invokeAndWait(new Runnable() { public void run() {
public void run() { p.validate();
p.validate(); a.setVisible(true);
a.setVisible(true);
// Fix for BugTraq ID 4041703.
// Fix for BugTraq ID 4041703. // Set the default focus for an applet.
// Set the default focus for an applet. if (hasInitialFocus()) {
if (hasInitialFocus()) setDefaultFocus();
setDefaultFocus();
} }
}); }
};
AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
} }
catch(InterruptedException ie) { catch(InterruptedException ie) {
} }
...@@ -512,13 +514,12 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { ...@@ -512,13 +514,12 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable {
// to avoid deadlock. // to avoid deadlock.
try { try {
final Applet a = applet; final Applet a = applet;
Runnable r = new Runnable() {
EventQueue.invokeAndWait(new Runnable() { public void run() {
public void run() a.setVisible(false);
{ }
a.setVisible(false); };
} AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
});
} }
catch(InterruptedException ie) { catch(InterruptedException ie) {
} }
...@@ -570,17 +571,14 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable { ...@@ -570,17 +571,14 @@ abstract class AppletPanel extends Panel implements AppletStub, Runnable {
} }
status = APPLET_DISPOSE; status = APPLET_DISPOSE;
try try {
{
final Applet a = applet; final Applet a = applet;
Runnable r = new Runnable() {
EventQueue.invokeAndWait(new Runnable() public void run() {
{
public void run()
{
remove(a); remove(a);
} }
}); };
AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
} }
catch(InterruptedException ie) catch(InterruptedException ie)
{ {
......
...@@ -34,6 +34,8 @@ import java.awt.event.InputEvent; ...@@ -34,6 +34,8 @@ import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.peer.ComponentPeer; import java.awt.peer.ComponentPeer;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessControlContext; import java.security.AccessControlContext;
import java.io.File; import java.io.File;
...@@ -476,6 +478,12 @@ public final class AWTAccessor { ...@@ -476,6 +478,12 @@ public final class AWTAccessor {
* appeared. * appeared.
*/ */
void wakeup(EventQueue eventQueue, boolean isShutdown); void wakeup(EventQueue eventQueue, boolean isShutdown);
/**
* Static in EventQueue
*/
void invokeAndWait(Object source, Runnable r)
throws InterruptedException, InvocationTargetException;
} }
/* /*
......
...@@ -327,21 +327,27 @@ public final class AppContext { ...@@ -327,21 +327,27 @@ public final class AppContext {
// Before we return the main "system" AppContext, check to // Before we return the main "system" AppContext, check to
// see if there's an AWTSecurityManager installed. If so, // see if there's an AWTSecurityManager installed. If so,
// allow it to choose the AppContext to return. // allow it to choose the AppContext to return.
SecurityManager securityManager = System.getSecurityManager(); AppContext secAppContext = getExecutionAppContext();
if ((securityManager != null) && if (secAppContext != null) {
(securityManager instanceof AWTSecurityManager)) appContext = secAppContext; // Return what we're told
{
AWTSecurityManager awtSecMgr = (AWTSecurityManager)securityManager;
AppContext secAppContext = awtSecMgr.getAppContext();
if (secAppContext != null) {
appContext = secAppContext; // Return what we're told
}
} }
} }
return appContext; return appContext;
} }
private final static AppContext getExecutionAppContext() {
SecurityManager securityManager = System.getSecurityManager();
if ((securityManager != null) &&
(securityManager instanceof AWTSecurityManager))
{
AWTSecurityManager awtSecMgr = (AWTSecurityManager) securityManager;
AppContext secAppContext = awtSecMgr.getAppContext();
return secAppContext; // Return what we're told
}
return null;
}
/** /**
* Returns the main ("system") AppContext. * Returns the main ("system") AppContext.
* *
...@@ -806,6 +812,21 @@ public final class AppContext { ...@@ -806,6 +812,21 @@ public final class AppContext {
public boolean isMainAppContext() { public boolean isMainAppContext() {
return (numAppContexts.get() == 1); return (numAppContexts.get() == 1);
} }
public Object getContext() {
return getAppContext();
}
public Object getExecutionContext() {
return getExecutionAppContext();
}
public Object get(Object context, Object key) {
return ((AppContext)context).get(key);
}
public void put(Object context, Object key, Object value) {
((AppContext)context).put(key, value);
}
public void remove(Object context, Object key) {
((AppContext)context).remove(key);
}
}); });
} }
} }
......
...@@ -198,7 +198,7 @@ public class ByteComponentRaster extends SunWritableRaster { ...@@ -198,7 +198,7 @@ public class ByteComponentRaster extends SunWritableRaster {
} }
this.bandOffset = this.dataOffsets[0]; this.bandOffset = this.dataOffsets[0];
verify(false); verify();
} }
/** /**
...@@ -857,38 +857,68 @@ public class ByteComponentRaster extends SunWritableRaster { ...@@ -857,38 +857,68 @@ public class ByteComponentRaster extends SunWritableRaster {
} }
/** /**
* Verify that the layout parameters are consistent with * Verify that the layout parameters are consistent with the data.
* the data. If strictCheck *
* is false, this method will check for ArrayIndexOutOfBounds conditions. If * The method verifies whether scanline stride and pixel stride do not
* strictCheck is true, this method will check for additional error * cause an integer overflow during calculation of a position of the pixel
* conditions such as line wraparound (width of a line greater than * in data buffer. It also verifies whether the data buffer has enough data
* the scanline stride). * to correspond the raster layout attributes.
* @return String Error string, if the layout is incompatible with *
* the data. Otherwise returns null. * @throws RasterFormatException if an integer overflow is detected,
* or if data buffer has not enough capacity.
*/ */
private void verify (boolean strictCheck) { protected final void verify() {
// Make sure data for Raster is in a legal range for (int i = 0; i < dataOffsets.length; i++) {
for (int i=0; i < dataOffsets.length; i++) {
if (dataOffsets[i] < 0) { if (dataOffsets[i] < 0) {
throw new RasterFormatException("Data offsets for band "+i+ throw new RasterFormatException("Data offsets for band " + i
"("+dataOffsets[i]+ + "(" + dataOffsets[i]
") must be >= 0"); + ") must be >= 0");
} }
} }
int maxSize = 0; int maxSize = 0;
int size; int size;
for (int i=0; i < numDataElements; i++) { // we can be sure that width and height are greater than 0
size = (height-1)*scanlineStride + (width-1)*pixelStride + if (scanlineStride < 0 ||
dataOffsets[i]; scanlineStride > (Integer.MAX_VALUE / height))
{
// integer overflow
throw new RasterFormatException("Incorrect scanline stride: "
+ scanlineStride);
}
int lastScanOffset = (height - 1) * scanlineStride;
if (pixelStride < 0 ||
pixelStride > (Integer.MAX_VALUE / width))
{
// integer overflow
throw new RasterFormatException("Incorrect pixel stride: "
+ pixelStride);
}
int lastPixelOffset = (width - 1) * pixelStride;
if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) {
// integer overflow
throw new RasterFormatException("Incorrect raster attributes");
}
lastPixelOffset += lastScanOffset;
for (int i = 0; i < numDataElements; i++) {
size = lastPixelOffset + dataOffsets[i];
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
throw new RasterFormatException("Incorrect band offset: "
+ dataOffsets[i]);
}
if (size > maxSize) { if (size > maxSize) {
maxSize = size; maxSize = size;
} }
} }
if (data.length < maxSize) { if (data.length < maxSize) {
throw new RasterFormatException("Data array too small (should be "+ throw new RasterFormatException("Data array too small (should be "
maxSize+" )"); + maxSize + " )");
} }
} }
......
...@@ -250,7 +250,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster { ...@@ -250,7 +250,7 @@ public class ByteInterleavedRaster extends ByteComponentRaster {
} }
} }
verify(false); verify();
} }
/** /**
...@@ -1292,33 +1292,6 @@ public class ByteInterleavedRaster extends ByteComponentRaster { ...@@ -1292,33 +1292,6 @@ public class ByteInterleavedRaster extends ByteComponentRaster {
return createCompatibleWritableRaster(width,height); return createCompatibleWritableRaster(width,height);
} }
/**
* Verify that the layout parameters are consistent with
* the data. If strictCheck
* is false, this method will check for ArrayIndexOutOfBounds conditions. If
* strictCheck is true, this method will check for additional error
* conditions such as line wraparound (width of a line greater than
* the scanline stride).
* @return String Error string, if the layout is incompatible with
* the data. Otherwise returns null.
*/
private void verify (boolean strictCheck) {
int maxSize = 0;
int size;
for (int i=0; i < numDataElements; i++) {
size = (height-1)*scanlineStride + (width-1)*pixelStride +
dataOffsets[i];
if (size > maxSize) {
maxSize = size;
}
}
if (data.length < maxSize) {
throw new RasterFormatException("Data array too small (should be "+
maxSize+" )");
}
}
public String toString() { public String toString() {
return new String ("ByteInterleavedRaster: width = "+width+" height = " return new String ("ByteInterleavedRaster: width = "+width+" height = "
+ height + height
......
...@@ -198,7 +198,7 @@ public class ShortComponentRaster extends SunWritableRaster { ...@@ -198,7 +198,7 @@ public class ShortComponentRaster extends SunWritableRaster {
} }
this.bandOffset = this.dataOffsets[0]; this.bandOffset = this.dataOffsets[0];
verify(false); verify();
} }
/** /**
...@@ -791,38 +791,67 @@ public class ShortComponentRaster extends SunWritableRaster { ...@@ -791,38 +791,67 @@ public class ShortComponentRaster extends SunWritableRaster {
} }
/** /**
* Verify that the layout parameters are consistent with * Verify that the layout parameters are consistent with the data.
* the data. If strictCheck *
* is false, this method will check for ArrayIndexOutOfBounds conditions. If * The method verifies whether scanline stride and pixel stride do not
* strictCheck is true, this method will check for additional error * cause an integer overflow during calculation of a position of the pixel
* conditions such as line wraparound (width of a line greater than * in data buffer. It also verifies whether the data buffer has enough data
* the scanline stride). * to correspond the raster layout attributes.
* @return String Error string, if the layout is incompatible with *
* the data. Otherwise returns null. * @throws RasterFormatException if an integer overflow is detected,
* or if data buffer has not enough capacity.
*/ */
private void verify (boolean strictCheck) { protected final void verify() {
// Make sure data for Raster is in a legal range for (int i = 0; i < dataOffsets.length; i++) {
for (int i=0; i < dataOffsets.length; i++) {
if (dataOffsets[i] < 0) { if (dataOffsets[i] < 0) {
throw new RasterFormatException("Data offsets for band "+i+ throw new RasterFormatException("Data offsets for band " + i
"("+dataOffsets[i]+ + "(" + dataOffsets[i]
") must be >= 0"); + ") must be >= 0");
} }
} }
int maxSize = 0; int maxSize = 0;
int size; int size;
for (int i=0; i < numDataElements; i++) { // we can be sure that width and height are greater than 0
size = (height-1)*scanlineStride + (width-1)*pixelStride + if (scanlineStride < 0 ||
dataOffsets[i]; scanlineStride > (Integer.MAX_VALUE / height))
{
// integer overflow
throw new RasterFormatException("Incorrect scanline stride: "
+ scanlineStride);
}
int lastScanOffset = (height - 1) * scanlineStride;
if (pixelStride < 0 ||
pixelStride > (Integer.MAX_VALUE / width))
{
// integer overflow
throw new RasterFormatException("Incorrect pixel stride: "
+ pixelStride);
}
int lastPixelOffset = (width - 1) * pixelStride;
if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) {
// integer overflow
throw new RasterFormatException("Incorrect raster attributes");
}
lastPixelOffset += lastScanOffset;
for (int i = 0; i < numDataElements; i++) {
size = lastPixelOffset + dataOffsets[i];
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
throw new RasterFormatException("Incorrect band offset: "
+ dataOffsets[i]);
}
if (size > maxSize) { if (size > maxSize) {
maxSize = size; maxSize = size;
} }
} }
if (data.length < maxSize) { if (data.length < maxSize) {
throw new RasterFormatException("Data array too small (should be "+ throw new RasterFormatException("Data array too small (should be "
maxSize+" )"); + maxSize + " )");
} }
} }
......
...@@ -171,7 +171,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster { ...@@ -171,7 +171,7 @@ public class ShortInterleavedRaster extends ShortComponentRaster {
sampleModel); sampleModel);
} }
this.bandOffset = this.dataOffsets[0]; this.bandOffset = this.dataOffsets[0];
verify(false); verify();
} }
/** /**
...@@ -762,33 +762,6 @@ public class ShortInterleavedRaster extends ShortComponentRaster { ...@@ -762,33 +762,6 @@ public class ShortInterleavedRaster extends ShortComponentRaster {
return createCompatibleWritableRaster(width,height); return createCompatibleWritableRaster(width,height);
} }
/**
* Verify that the layout parameters are consistent with
* the data. If strictCheck
* is false, this method will check for ArrayIndexOutOfBounds conditions. If
* strictCheck is true, this method will check for additional error
* conditions such as line wraparound (width of a line greater than
* the scanline stride).
* @return String Error string, if the layout is incompatible with
* the data. Otherwise returns null.
*/
private void verify (boolean strictCheck) {
int maxSize = 0;
int size;
for (int i=0; i < numDataElements; i++) {
size = (height-1)*scanlineStride + (width-1)*pixelStride +
dataOffsets[i];
if (size > maxSize) {
maxSize = size;
}
}
if (data.length < maxSize) {
throw new RasterFormatException("Data array too small (should be "+
maxSize+" )");
}
}
public String toString() { public String toString() {
return new String ("ShortInterleavedRaster: width = "+width return new String ("ShortInterleavedRaster: width = "+width
+" height = " + height +" height = " + height
......
...@@ -26,6 +26,14 @@ ...@@ -26,6 +26,14 @@
package sun.misc; package sun.misc;
public interface JavaAWTAccess { public interface JavaAWTAccess {
public Object getContext();
public Object getExecutionContext();
public Object get(Object context, Object key);
public void put(Object context, Object key, Object value);
public void remove(Object context, Object key);
// convenience methods whose context is the object returned by getContext()
public Object get(Object key); public Object get(Object key);
public void put(Object key, Object value); public void put(Object key, Object value);
public void remove(Object key); public void remove(Object key);
......
...@@ -41,8 +41,12 @@ class ChunkedInputStream extends LeftOverInputStream { ...@@ -41,8 +41,12 @@ class ChunkedInputStream extends LeftOverInputStream {
private boolean needToReadHeader = true; private boolean needToReadHeader = true;
static char CR = '\r'; final static char CR = '\r';
static char LF = '\n'; final static char LF = '\n';
/*
* Maximum chunk header size of 2KB + 2 bytes for CRLF
*/
private final static int MAX_CHUNK_HEADER_SIZE = 2050;
private int numeric (char[] arr, int nchars) throws IOException { private int numeric (char[] arr, int nchars) throws IOException {
assert arr.length >= nchars; assert arr.length >= nchars;
...@@ -73,10 +77,14 @@ class ChunkedInputStream extends LeftOverInputStream { ...@@ -73,10 +77,14 @@ class ChunkedInputStream extends LeftOverInputStream {
char[] len_arr = new char [16]; char[] len_arr = new char [16];
int len_size = 0; int len_size = 0;
boolean end_of_len = false; boolean end_of_len = false;
int read = 0;
while ((c=in.read())!= -1) { while ((c=in.read())!= -1) {
char ch = (char) c; char ch = (char) c;
if (len_size == len_arr.length -1) { read++;
if ((len_size == len_arr.length -1) ||
(read > MAX_CHUNK_HEADER_SIZE))
{
throw new IOException ("invalid chunk header"); throw new IOException ("invalid chunk header");
} }
if (gotCR) { if (gotCR) {
......
...@@ -125,6 +125,11 @@ class ChunkedInputStream extends InputStream implements Hurryable { ...@@ -125,6 +125,11 @@ class ChunkedInputStream extends InputStream implements Hurryable {
*/ */
private boolean closed; private boolean closed;
/*
* Maximum chunk header size of 2KB + 2 bytes for CRLF
*/
private final static int MAX_CHUNK_HEADER_SIZE = 2050;
/** /**
* State to indicate that next field should be :- * State to indicate that next field should be :-
* chunk-size [ chunk-extension ] CRLF * chunk-size [ chunk-extension ] CRLF
...@@ -290,6 +295,10 @@ class ChunkedInputStream extends InputStream implements Hurryable { ...@@ -290,6 +295,10 @@ class ChunkedInputStream extends InputStream implements Hurryable {
break; break;
} }
pos++; pos++;
if ((pos - rawPos) >= MAX_CHUNK_HEADER_SIZE) {
error = true;
throw new IOException("Chunk header too long");
}
} }
if (pos >= rawCount) { if (pos >= rawCount) {
return; return;
......
...@@ -421,7 +421,7 @@ class DatagramChannelImpl ...@@ -421,7 +421,7 @@ class DatagramChannelImpl
synchronized (writeLock) { synchronized (writeLock) {
ensureOpen(); ensureOpen();
InetSocketAddress isa = (InetSocketAddress)target; InetSocketAddress isa = Net.checkAddress(target);
InetAddress ia = isa.getAddress(); InetAddress ia = isa.getAddress();
if (ia == null) if (ia == null)
throw new IOException("Target address not resolved"); throw new IOException("Target address not resolved");
...@@ -432,9 +432,9 @@ class DatagramChannelImpl ...@@ -432,9 +432,9 @@ class DatagramChannelImpl
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
if (ia.isMulticastAddress()) { if (ia.isMulticastAddress()) {
sm.checkMulticast(isa.getAddress()); sm.checkMulticast(ia);
} else { } else {
sm.checkConnect(isa.getAddress().getHostAddress(), sm.checkConnect(ia.getHostAddress(),
isa.getPort()); isa.getPort());
} }
} }
...@@ -454,7 +454,7 @@ class DatagramChannelImpl ...@@ -454,7 +454,7 @@ class DatagramChannelImpl
return 0; return 0;
writerThread = NativeThread.current(); writerThread = NativeThread.current();
do { do {
n = send(fd, src, target); n = send(fd, src, isa);
} while ((n == IOStatus.INTERRUPTED) && isOpen()); } while ((n == IOStatus.INTERRUPTED) && isOpen());
synchronized (stateLock) { synchronized (stateLock) {
...@@ -471,7 +471,7 @@ class DatagramChannelImpl ...@@ -471,7 +471,7 @@ class DatagramChannelImpl
} }
} }
private int send(FileDescriptor fd, ByteBuffer src, SocketAddress target) private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target)
throws IOException throws IOException
{ {
if (src instanceof DirectBuffer) if (src instanceof DirectBuffer)
...@@ -502,7 +502,7 @@ class DatagramChannelImpl ...@@ -502,7 +502,7 @@ class DatagramChannelImpl
} }
private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
SocketAddress target) InetSocketAddress target)
throws IOException throws IOException
{ {
int pos = bb.position(); int pos = bb.position();
...@@ -514,7 +514,7 @@ class DatagramChannelImpl ...@@ -514,7 +514,7 @@ class DatagramChannelImpl
int written; int written;
try { try {
written = send0(preferIPv6, fd, ((DirectBuffer)bb).address() + pos, written = send0(preferIPv6, fd, ((DirectBuffer)bb).address() + pos,
rem, target); rem, target.getAddress(), target.getPort());
} catch (PortUnreachableException pue) { } catch (PortUnreachableException pue) {
if (isConnected()) if (isConnected())
throw pue; throw pue;
...@@ -1116,8 +1116,8 @@ class DatagramChannelImpl ...@@ -1116,8 +1116,8 @@ class DatagramChannelImpl
boolean connected) boolean connected)
throws IOException; throws IOException;
private native int send0(boolean preferIPv6, FileDescriptor fd, long address, int len, private native int send0(boolean preferIPv6, FileDescriptor fd, long address,
SocketAddress sa) int len, InetAddress addr, int port)
throws IOException; throws IOException;
static { static {
......
...@@ -178,4 +178,31 @@ public final class ReflectUtil { ...@@ -178,4 +178,31 @@ public final class ReflectUtil {
return !isAncestor(from, to); return !isAncestor(from, to);
} }
/**
* Access check on the interfaces that a proxy class implements and throw
* {@code SecurityException} if it accesses a restricted package.
*
* @param ccl the caller's class loader
* @param interfaces the list of interfaces that a proxy class implements
*
* @see Proxy#checkProxyAccess
*/
public static void checkProxyPackageAccess(ClassLoader ccl,
Class<?>... interfaces)
{
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
for (Class<?> intf : interfaces) {
ClassLoader cl = intf.getClassLoader();
if (needsPackageAccessCheck(ccl, cl)) {
checkPackageAccess(intf);
}
}
}
}
// Note that bytecode instrumentation tools may exclude 'sun.*'
// classes but not generated proxy classes and so keep it in com.sun.*
public static final String PROXY_PACKAGE = "com.sun.proxy";
} }
...@@ -153,7 +153,7 @@ public final class CGIHandler { ...@@ -153,7 +153,7 @@ public final class CGIHandler {
returnServerError(e.getMessage()); returnServerError(e.getMessage());
} }
else else
returnClientError("invalid command: " + command); returnClientError("invalid command.");
} catch (Exception e) { } catch (Exception e) {
returnServerError("internal error: " + e.getMessage()); returnServerError("internal error: " + e.getMessage());
} }
...@@ -225,7 +225,7 @@ final class CGIForwardCommand implements CGICommandHandler { ...@@ -225,7 +225,7 @@ final class CGIForwardCommand implements CGICommandHandler {
try { try {
port = Integer.parseInt(param); port = Integer.parseInt(param);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new CGIClientException("invalid port number: " + param); throw new CGIClientException("invalid port number.");
} }
if (port <= 0 || port > 0xFFFF) if (port <= 0 || port > 0xFFFF)
throw new CGIClientException("invalid port: " + port); throw new CGIClientException("invalid port: " + port);
...@@ -293,11 +293,14 @@ final class CGIForwardCommand implements CGICommandHandler { ...@@ -293,11 +293,14 @@ final class CGIForwardCommand implements CGICommandHandler {
"unexpected EOF reading server response"); "unexpected EOF reading server response");
if (line.toLowerCase().startsWith(key)) { if (line.toLowerCase().startsWith(key)) {
// if contentLengthFound is true if (contentLengthFound) {
// we should probably do something here throw new CGIServerException(
responseContentLength = "Multiple Content-length entries found.");
Integer.parseInt(line.substring(key.length()).trim()); } else {
contentLengthFound = true; responseContentLength =
Integer.parseInt(line.substring(key.length()).trim());
contentLengthFound = true;
}
} }
} while ((line.length() != 0) && } while ((line.length() != 0) &&
(line.charAt(0) != '\r') && (line.charAt(0) != '\n')); (line.charAt(0) != '\r') && (line.charAt(0) != '\n'));
......
...@@ -70,11 +70,14 @@ class HttpInputStream extends FilterInputStream { ...@@ -70,11 +70,14 @@ class HttpInputStream extends FilterInputStream {
throw new EOFException(); throw new EOFException();
if (line.toLowerCase().startsWith(key)) { if (line.toLowerCase().startsWith(key)) {
// if contentLengthFound is true if (contentLengthFound) {
// we should probably do something here throw new IOException(
bytesLeft = "Multiple Content-length entries found.");
Integer.parseInt(line.substring(key.length()).trim()); } else {
contentLengthFound = true; bytesLeft =
Integer.parseInt(line.substring(key.length()).trim());
contentLengthFound = true;
}
} }
// The idea here is to go past the first blank line. // The idea here is to go past the first blank line.
......
...@@ -37,6 +37,7 @@ import javax.crypto.spec.*; ...@@ -37,6 +37,7 @@ import javax.crypto.spec.*;
import static sun.security.pkcs11.TemplateManager.*; import static sun.security.pkcs11.TemplateManager.*;
import sun.security.pkcs11.wrapper.*; import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import sun.security.util.KeyUtil;
/** /**
* KeyAgreement implementation class. This class currently supports * KeyAgreement implementation class. This class currently supports
...@@ -134,6 +135,10 @@ final class P11KeyAgreement extends KeyAgreementSpi { ...@@ -134,6 +135,10 @@ final class P11KeyAgreement extends KeyAgreementSpi {
BigInteger p, g, y; BigInteger p, g, y;
if (key instanceof DHPublicKey) { if (key instanceof DHPublicKey) {
DHPublicKey dhKey = (DHPublicKey)key; DHPublicKey dhKey = (DHPublicKey)key;
// validate the Diffie-Hellman public key
KeyUtil.validate(dhKey);
y = dhKey.getY(); y = dhKey.getY();
DHParameterSpec params = dhKey.getParams(); DHParameterSpec params = dhKey.getParams();
p = params.getP(); p = params.getP();
...@@ -145,6 +150,10 @@ final class P11KeyAgreement extends KeyAgreementSpi { ...@@ -145,6 +150,10 @@ final class P11KeyAgreement extends KeyAgreementSpi {
try { try {
DHPublicKeySpec spec = kf.engineGetKeySpec( DHPublicKeySpec spec = kf.engineGetKeySpec(
key, DHPublicKeySpec.class); key, DHPublicKeySpec.class);
// validate the Diffie-Hellman public key
KeyUtil.validate(spec);
y = spec.getY(); y = spec.getY();
p = spec.getP(); p = spec.getP();
g = spec.getG(); g = spec.getG();
......
/* /*
* Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -392,7 +392,8 @@ final class CipherBox { ...@@ -392,7 +392,8 @@ final class CipherBox {
* uniformly use the bad_record_mac alert to hide the specific type of * uniformly use the bad_record_mac alert to hide the specific type of
* the error. * the error.
*/ */
int decrypt(byte[] buf, int offset, int len) throws BadPaddingException { int decrypt(byte[] buf, int offset, int len,
int tagLen) throws BadPaddingException {
if (cipher == null) { if (cipher == null) {
return len; return len;
} }
...@@ -416,9 +417,10 @@ final class CipherBox { ...@@ -416,9 +417,10 @@ final class CipherBox {
System.out); System.out);
} catch (IOException e) { } } catch (IOException e) { }
} }
if (blockSize != 0) { if (blockSize != 0) {
newLen = removePadding(buf, offset, newLen, newLen = removePadding(
blockSize, protocolVersion); buf, offset, newLen, tagLen, blockSize, protocolVersion);
if (protocolVersion.v >= ProtocolVersion.TLS11.v) { if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
if (newLen < blockSize) { if (newLen < blockSize) {
...@@ -448,7 +450,7 @@ final class CipherBox { ...@@ -448,7 +450,7 @@ final class CipherBox {
* *
* @see decrypt(byte[], int, int) * @see decrypt(byte[], int, int)
*/ */
int decrypt(ByteBuffer bb) throws BadPaddingException { int decrypt(ByteBuffer bb, int tagLen) throws BadPaddingException {
int len = bb.remaining(); int len = bb.remaining();
...@@ -471,7 +473,6 @@ final class CipherBox { ...@@ -471,7 +473,6 @@ final class CipherBox {
} }
if (debug != null && Debug.isOn("plaintext")) { if (debug != null && Debug.isOn("plaintext")) {
bb.position(pos);
try { try {
HexDumpEncoder hd = new HexDumpEncoder(); HexDumpEncoder hd = new HexDumpEncoder();
...@@ -479,7 +480,8 @@ final class CipherBox { ...@@ -479,7 +480,8 @@ final class CipherBox {
"Padded plaintext after DECRYPTION: len = " "Padded plaintext after DECRYPTION: len = "
+ newLen); + newLen);
hd.encodeBuffer(bb, System.out); hd.encodeBuffer(
(ByteBuffer)bb.duplicate().position(pos), System.out);
} catch (IOException e) { } } catch (IOException e) { }
} }
...@@ -488,7 +490,8 @@ final class CipherBox { ...@@ -488,7 +490,8 @@ final class CipherBox {
*/ */
if (blockSize != 0) { if (blockSize != 0) {
bb.position(pos); bb.position(pos);
newLen = removePadding(bb, blockSize, protocolVersion); newLen = removePadding(
bb, tagLen, blockSize, protocolVersion);
if (protocolVersion.v >= ProtocolVersion.TLS11.v) { if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
if (newLen < blockSize) { if (newLen < blockSize) {
...@@ -590,6 +593,65 @@ final class CipherBox { ...@@ -590,6 +593,65 @@ final class CipherBox {
return newlen; return newlen;
} }
/*
* A constant-time check of the padding.
*
* NOTE that we are checking both the padding and the padLen bytes here.
*
* The caller MUST ensure that the len parameter is a positive number.
*/
private static int[] checkPadding(
byte[] buf, int offset, int len, byte pad) {
if (len <= 0) {
throw new RuntimeException("padding len must be positive");
}
// An array of hits is used to prevent Hotspot optimization for
// the purpose of a constant-time check.
int[] results = {0, 0}; // {missed #, matched #}
for (int i = 0; i <= 256;) {
for (int j = 0; j < len && i <= 256; j++, i++) { // j <= i
if (buf[offset + j] != pad) {
results[0]++; // mismatched padding data
} else {
results[1]++; // matched padding data
}
}
}
return results;
}
/*
* A constant-time check of the padding.
*
* NOTE that we are checking both the padding and the padLen bytes here.
*
* The caller MUST ensure that the bb parameter has remaining.
*/
private static int[] checkPadding(ByteBuffer bb, byte pad) {
if (!bb.hasRemaining()) {
throw new RuntimeException("hasRemaining() must be positive");
}
// An array of hits is used to prevent Hotspot optimization for
// the purpose of a constant-time check.
int[] results = {0, 0}; // {missed #, matched #}
bb.mark();
for (int i = 0; i <= 256; bb.reset()) {
for (; bb.hasRemaining() && i <= 256; i++) {
if (bb.get() != pad) {
results[0]++; // mismatched padding data
} else {
results[1]++; // matched padding data
}
}
}
return results;
}
/* /*
* Typical TLS padding format for a 64 bit block cipher is as follows: * Typical TLS padding format for a 64 bit block cipher is as follows:
...@@ -602,86 +664,95 @@ final class CipherBox { ...@@ -602,86 +664,95 @@ final class CipherBox {
* as it makes the data a multiple of the block size * as it makes the data a multiple of the block size
*/ */
private static int removePadding(byte[] buf, int offset, int len, private static int removePadding(byte[] buf, int offset, int len,
int blockSize, ProtocolVersion protocolVersion) int tagLen, int blockSize,
throws BadPaddingException { ProtocolVersion protocolVersion) throws BadPaddingException {
// last byte is length byte (i.e. actual padding length - 1) // last byte is length byte (i.e. actual padding length - 1)
int padOffset = offset + len - 1; int padOffset = offset + len - 1;
int pad = buf[padOffset] & 0x0ff; int padLen = buf[padOffset] & 0xFF;
int newlen = len - (pad + 1); int newLen = len - (padLen + 1);
if (newlen < 0) { if ((newLen - tagLen) < 0) {
throw new BadPaddingException("Padding length invalid: " + pad); // If the buffer is not long enough to contain the padding plus
// a MAC tag, do a dummy constant-time padding check.
//
// Note that it is a dummy check, so we won't care about what is
// the actual padding data.
checkPadding(buf, offset, len, (byte)(padLen & 0xFF));
throw new BadPaddingException("Invalid Padding length: " + padLen);
} }
// The padding data should be filled with the padding length value.
int[] results = checkPadding(buf, offset + newLen,
padLen + 1, (byte)(padLen & 0xFF));
if (protocolVersion.v >= ProtocolVersion.TLS10.v) { if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
for (int i = 1; i <= pad; i++) { if (results[0] != 0) { // padding data has invalid bytes
int val = buf[padOffset - i] & 0xff; throw new BadPaddingException("Invalid TLS padding data");
if (val != pad) {
throw new BadPaddingException
("Invalid TLS padding: " + val);
}
} }
} else { // SSLv3 } else { // SSLv3
// SSLv3 requires 0 <= length byte < block size // SSLv3 requires 0 <= length byte < block size
// some implementations do 1 <= length byte <= block size, // some implementations do 1 <= length byte <= block size,
// so accept that as well // so accept that as well
// v3 does not require any particular value for the other bytes // v3 does not require any particular value for the other bytes
if (pad > blockSize) { if (padLen > blockSize) {
throw new BadPaddingException("Invalid SSLv3 padding: " + pad); throw new BadPaddingException("Invalid SSLv3 padding");
} }
} }
return newlen; return newLen;
} }
/* /*
* Position/limit is equal the removed padding. * Position/limit is equal the removed padding.
*/ */
private static int removePadding(ByteBuffer bb, private static int removePadding(ByteBuffer bb,
int blockSize, ProtocolVersion protocolVersion) int tagLen, int blockSize,
throws BadPaddingException { ProtocolVersion protocolVersion) throws BadPaddingException {
int len = bb.remaining(); int len = bb.remaining();
int offset = bb.position(); int offset = bb.position();
// last byte is length byte (i.e. actual padding length - 1) // last byte is length byte (i.e. actual padding length - 1)
int padOffset = offset + len - 1; int padOffset = offset + len - 1;
int pad = bb.get(padOffset) & 0x0ff; int padLen = bb.get(padOffset) & 0xFF;
int newlen = len - (pad + 1); int newLen = len - (padLen + 1);
if (newlen < 0) { if ((newLen - tagLen) < 0) {
throw new BadPaddingException("Padding length invalid: " + pad); // If the buffer is not long enough to contain the padding plus
// a MAC tag, do a dummy constant-time padding check.
//
// Note that it is a dummy check, so we won't care about what is
// the actual padding data.
checkPadding(bb.duplicate(), (byte)(padLen & 0xFF));
throw new BadPaddingException("Invalid Padding length: " + padLen);
} }
/* // The padding data should be filled with the padding length value.
* We could zero the padding area, but not much useful int[] results = checkPadding(
* information there. (ByteBuffer)bb.duplicate().position(offset + newLen),
*/ (byte)(padLen & 0xFF));
if (protocolVersion.v >= ProtocolVersion.TLS10.v) { if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
bb.put(padOffset, (byte)0); // zero the padding. if (results[0] != 0) { // padding data has invalid bytes
for (int i = 1; i <= pad; i++) { throw new BadPaddingException("Invalid TLS padding data");
int val = bb.get(padOffset - i) & 0xff;
if (val != pad) {
throw new BadPaddingException
("Invalid TLS padding: " + val);
}
} }
} else { // SSLv3 } else { // SSLv3
// SSLv3 requires 0 <= length byte < block size // SSLv3 requires 0 <= length byte < block size
// some implementations do 1 <= length byte <= block size, // some implementations do 1 <= length byte <= block size,
// so accept that as well // so accept that as well
// v3 does not require any particular value for the other bytes // v3 does not require any particular value for the other bytes
if (pad > blockSize) { if (padLen > blockSize) {
throw new BadPaddingException("Invalid SSLv3 padding: " + pad); throw new BadPaddingException("Invalid SSLv3 padding");
} }
} }
/* /*
* Reset buffer limit to remove padding. * Reset buffer limit to remove padding.
*/ */
bb.position(offset + newlen); bb.position(offset + newLen);
bb.limit(offset + newlen); bb.limit(offset + newLen);
return newlen; return newLen;
} }
/* /*
...@@ -708,4 +779,45 @@ final class CipherBox { ...@@ -708,4 +779,45 @@ final class CipherBox {
boolean isCBCMode() { boolean isCBCMode() {
return isCBCMode; return isCBCMode;
} }
/**
* Is the cipher null?
*
* @return true if the cipher is null, false otherwise.
*/
boolean isNullCipher() {
return cipher == null;
}
/**
* Sanity check the length of a fragment before decryption.
*
* In CBC mode, check that the fragment length is one or multiple times
* of the block size of the cipher suite, and is at least one (one is the
* smallest size of padding in CBC mode) bigger than the tag size of the
* MAC algorithm except the explicit IV size for TLS 1.1 or later.
*
* In non-CBC mode, check that the fragment length is not less than the
* tag size of the MAC algorithm.
*
* @return true if the length of a fragment matches above requirements
*/
boolean sanityCheck(int tagLen, int fragmentLen) {
if (!isCBCMode) {
return fragmentLen >= tagLen;
}
if ((fragmentLen % blockSize) == 0) {
int minimal = tagLen + 1;
minimal = (minimal >= blockSize) ? minimal : blockSize;
if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
minimal += blockSize; // plus the size of the explicit IV
}
return (fragmentLen >= minimal);
}
return false;
}
} }
/* /*
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -549,9 +549,18 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -549,9 +549,18 @@ final class CipherSuite implements Comparable<CipherSuite> {
// size of the MAC value (and MAC key) in bytes // size of the MAC value (and MAC key) in bytes
final int size; final int size;
MacAlg(String name, int size) { // block size of the underlying hash algorithm
final int hashBlockSize;
// minimal padding size of the underlying hash algorithm
final int minimalPaddingSize;
MacAlg(String name, int size,
int hashBlockSize, int minimalPaddingSize) {
this.name = name; this.name = name;
this.size = size; this.size = size;
this.hashBlockSize = hashBlockSize;
this.minimalPaddingSize = minimalPaddingSize;
} }
/** /**
...@@ -596,11 +605,11 @@ final class CipherSuite implements Comparable<CipherSuite> { ...@@ -596,11 +605,11 @@ final class CipherSuite implements Comparable<CipherSuite> {
new BulkCipher(CIPHER_AES, 32, 16, true); new BulkCipher(CIPHER_AES, 32, 16, true);
// MACs // MACs
final static MacAlg M_NULL = new MacAlg("NULL", 0); final static MacAlg M_NULL = new MacAlg("NULL", 0, 0, 0);
final static MacAlg M_MD5 = new MacAlg("MD5", 16); final static MacAlg M_MD5 = new MacAlg("MD5", 16, 64, 9);
final static MacAlg M_SHA = new MacAlg("SHA", 20); final static MacAlg M_SHA = new MacAlg("SHA", 20, 64, 9);
final static MacAlg M_SHA256 = new MacAlg("SHA256", 32); final static MacAlg M_SHA256 = new MacAlg("SHA256", 32, 64, 9);
final static MacAlg M_SHA384 = new MacAlg("SHA384", 48); final static MacAlg M_SHA384 = new MacAlg("SHA384", 48, 128, 17);
/** /**
* PRFs (PseudoRandom Function) from TLS specifications. * PRFs (PseudoRandom Function) from TLS specifications.
......
...@@ -129,9 +129,8 @@ final class ClientHandshaker extends Handshaker { ...@@ -129,9 +129,8 @@ final class ClientHandshaker extends Handshaker {
*/ */
@Override @Override
void processMessage(byte type, int messageLen) throws IOException { void processMessage(byte type, int messageLen) throws IOException {
if (state > type if (state >= type
&& (type != HandshakeMessage.ht_hello_request && (type != HandshakeMessage.ht_hello_request)) {
&& state != HandshakeMessage.ht_client_hello)) {
throw new SSLProtocolException( throw new SSLProtocolException(
"Handshake message sequence violation, " + type); "Handshake message sequence violation, " + type);
} }
...@@ -194,8 +193,12 @@ final class ClientHandshaker extends Handshaker { ...@@ -194,8 +193,12 @@ final class ClientHandshaker extends Handshaker {
} }
break; break;
case K_DH_ANON: case K_DH_ANON:
this.serverKeyExchange(new DH_ServerKeyExchange( try {
this.serverKeyExchange(new DH_ServerKeyExchange(
input, protocolVersion)); input, protocolVersion));
} catch (GeneralSecurityException e) {
throwSSLException("Server key", e);
}
break; break;
case K_DHE_DSS: case K_DHE_DSS:
case K_DHE_RSA: case K_DHE_RSA:
...@@ -921,7 +924,7 @@ final class ClientHandshaker extends Handshaker { ...@@ -921,7 +924,7 @@ final class ClientHandshaker extends Handshaker {
case K_DHE_RSA: case K_DHE_RSA:
case K_DHE_DSS: case K_DHE_DSS:
case K_DH_ANON: case K_DH_ANON:
preMasterSecret = dh.getAgreedSecret(serverDH); preMasterSecret = dh.getAgreedSecret(serverDH, true);
break; break;
case K_ECDHE_RSA: case K_ECDHE_RSA:
case K_ECDHE_ECDSA: case K_ECDHE_ECDSA:
......
/* /*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,7 +29,7 @@ package sun.security.ssl; ...@@ -29,7 +29,7 @@ package sun.security.ssl;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.math.BigInteger; import java.math.BigInteger;
import javax.net.ssl.SSLHandshakeException;
/* /*
* Message used by clients to send their Diffie-Hellman public * Message used by clients to send their Diffie-Hellman public
...@@ -51,7 +51,7 @@ final class DHClientKeyExchange extends HandshakeMessage { ...@@ -51,7 +51,7 @@ final class DHClientKeyExchange extends HandshakeMessage {
private byte dh_Yc[]; // 1 to 2^16 -1 bytes private byte dh_Yc[]; // 1 to 2^16 -1 bytes
BigInteger getClientPublicKey() { BigInteger getClientPublicKey() {
return new BigInteger(1, dh_Yc); return dh_Yc == null ? null : new BigInteger(1, dh_Yc);
} }
/* /*
...@@ -73,7 +73,14 @@ final class DHClientKeyExchange extends HandshakeMessage { ...@@ -73,7 +73,14 @@ final class DHClientKeyExchange extends HandshakeMessage {
* but that's what the protocol spec requires.) * but that's what the protocol spec requires.)
*/ */
DHClientKeyExchange(HandshakeInStream input) throws IOException { DHClientKeyExchange(HandshakeInStream input) throws IOException {
dh_Yc = input.getBytes16(); if (input.available() >= 2) {
dh_Yc = input.getBytes16();
} else {
// currently, we don't support cipher suites that requires
// implicit public key of client.
throw new SSLHandshakeException(
"Unsupported implicit client DiffieHellman public key");
}
} }
@Override @Override
...@@ -87,7 +94,9 @@ final class DHClientKeyExchange extends HandshakeMessage { ...@@ -87,7 +94,9 @@ final class DHClientKeyExchange extends HandshakeMessage {
@Override @Override
void send(HandshakeOutStream s) throws IOException { void send(HandshakeOutStream s) throws IOException {
s.putBytes16(dh_Yc); if (dh_Yc != null && dh_Yc.length != 0) {
s.putBytes16(dh_Yc);
}
} }
@Override @Override
......
/* /*
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -28,12 +28,15 @@ package sun.security.ssl; ...@@ -28,12 +28,15 @@ package sun.security.ssl;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.*; import java.security.*;
import java.io.IOException;
import javax.net.ssl.SSLHandshakeException;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.KeyAgreement; import javax.crypto.KeyAgreement;
import javax.crypto.interfaces.DHPublicKey; import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.*; import javax.crypto.spec.*;
import sun.security.util.KeyUtil;
/** /**
* This class implements the Diffie-Hellman key exchange algorithm. * This class implements the Diffie-Hellman key exchange algorithm.
* D-H means combining your private key with your partners public key to * D-H means combining your private key with your partners public key to
...@@ -54,7 +57,8 @@ import javax.crypto.spec.*; ...@@ -54,7 +57,8 @@ import javax.crypto.spec.*;
* . if we are server, call DHCrypt(keyLength,random). This generates * . if we are server, call DHCrypt(keyLength,random). This generates
* an ephemeral keypair of the request length. * an ephemeral keypair of the request length.
* . if we are client, call DHCrypt(modulus, base, random). This * . if we are client, call DHCrypt(modulus, base, random). This
* generates an ephemeral keypair using the parameters specified by the server. * generates an ephemeral keypair using the parameters specified by
* the server.
* . send parameters and public value to remote peer * . send parameters and public value to remote peer
* . receive peers ephemeral public key * . receive peers ephemeral public key
* . call getAgreedSecret() to calculate the shared secret * . call getAgreedSecret() to calculate the shared secret
...@@ -83,6 +87,9 @@ final class DHCrypt { ...@@ -83,6 +87,9 @@ final class DHCrypt {
// public component of our key, X = (g ^ x) mod p // public component of our key, X = (g ^ x) mod p
private BigInteger publicValue; // X (aka y) private BigInteger publicValue; // X (aka y)
// the times to recove from failure if public key validation
private static int MAX_FAILOVER_TIMES = 2;
/** /**
* Generate a Diffie-Hellman keypair of the specified size. * Generate a Diffie-Hellman keypair of the specified size.
*/ */
...@@ -90,9 +97,12 @@ final class DHCrypt { ...@@ -90,9 +97,12 @@ final class DHCrypt {
try { try {
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman"); KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
kpg.initialize(keyLength, random); kpg.initialize(keyLength, random);
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate(); DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); if (spec == null) {
throw new RuntimeException("Could not generate DH keypair");
}
publicValue = spec.getY(); publicValue = spec.getY();
modulus = spec.getP(); modulus = spec.getP();
base = spec.getG(); base = spec.getG();
...@@ -115,20 +125,25 @@ final class DHCrypt { ...@@ -115,20 +125,25 @@ final class DHCrypt {
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman"); KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
DHParameterSpec params = new DHParameterSpec(modulus, base); DHParameterSpec params = new DHParameterSpec(modulus, base);
kpg.initialize(params, random); kpg.initialize(params, random);
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate(); DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); if (spec == null) {
throw new RuntimeException("Could not generate DH keypair");
}
publicValue = spec.getY(); publicValue = spec.getY();
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new RuntimeException("Could not generate DH keypair", e); throw new RuntimeException("Could not generate DH keypair", e);
} }
} }
static DHPublicKeySpec getDHPublicKeySpec(PublicKey key) { static DHPublicKeySpec getDHPublicKeySpec(PublicKey key) {
if (key instanceof DHPublicKey) { if (key instanceof DHPublicKey) {
DHPublicKey dhKey = (DHPublicKey)key; DHPublicKey dhKey = (DHPublicKey)key;
DHParameterSpec params = dhKey.getParams(); DHParameterSpec params = dhKey.getParams();
return new DHPublicKeySpec(dhKey.getY(), params.getP(), params.getG()); return new DHPublicKeySpec(dhKey.getY(),
params.getP(), params.getG());
} }
try { try {
KeyFactory factory = JsseJce.getKeyFactory("DH"); KeyFactory factory = JsseJce.getKeyFactory("DH");
...@@ -166,17 +181,32 @@ final class DHCrypt { ...@@ -166,17 +181,32 @@ final class DHCrypt {
* <P>It is illegal to call this member function if the private key * <P>It is illegal to call this member function if the private key
* has not been set (or generated). * has not been set (or generated).
* *
* @param peerPublicKey the peer's public key. * @param peerPublicKey the peer's public key.
* @returns the secret, which is an unsigned big-endian integer * @param keyIsValidated whether the {@code peerPublicKey} has beed
* the same size as the Diffie-Hellman modulus. * validated
* @return the secret, which is an unsigned big-endian integer
* the same size as the Diffie-Hellman modulus.
*/ */
SecretKey getAgreedSecret(BigInteger peerPublicValue) { SecretKey getAgreedSecret(BigInteger peerPublicValue,
boolean keyIsValidated) throws IOException {
try { try {
KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman"); KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
DHPublicKeySpec spec = DHPublicKeySpec spec =
new DHPublicKeySpec(peerPublicValue, modulus, base); new DHPublicKeySpec(peerPublicValue, modulus, base);
PublicKey publicKey = kf.generatePublic(spec); PublicKey publicKey = kf.generatePublic(spec);
KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman"); KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
// validate the Diffie-Hellman public key
if (!keyIsValidated &&
!KeyUtil.isOracleJCEProvider(ka.getProvider().getName())) {
try {
KeyUtil.validate(spec);
} catch (InvalidKeyException ike) {
// prefer handshake_failure alert to internal_error alert
throw new SSLHandshakeException(ike.getMessage());
}
}
ka.init(privateKey); ka.init(privateKey);
ka.doPhase(publicKey, true); ka.doPhase(publicKey, true);
return ka.generateSecret("TlsPremasterSecret"); return ka.generateSecret("TlsPremasterSecret");
...@@ -185,4 +215,33 @@ final class DHCrypt { ...@@ -185,4 +215,33 @@ final class DHCrypt {
} }
} }
// Generate and validate DHPublicKeySpec
private DHPublicKeySpec generateDHPublicKeySpec(KeyPairGenerator kpg)
throws GeneralSecurityException {
boolean doExtraValiadtion =
(!KeyUtil.isOracleJCEProvider(kpg.getProvider().getName()));
for (int i = 0; i <= MAX_FAILOVER_TIMES; i++) {
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate();
DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
// validate the Diffie-Hellman public key
if (doExtraValiadtion) {
try {
KeyUtil.validate(spec);
} catch (InvalidKeyException ivke) {
if (i == MAX_FAILOVER_TIMES) {
throw ivke;
}
// otherwise, ignore the exception and try the next one
continue;
}
}
return spec;
}
return null;
}
} }
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -118,7 +118,7 @@ final class EngineOutputRecord extends OutputRecord { ...@@ -118,7 +118,7 @@ final class EngineOutputRecord extends OutputRecord {
throws IOException { throws IOException {
if (signer.MAClen() != 0) { if (signer.MAClen() != 0) {
byte[] hash = signer.compute(contentType(), bb); byte[] hash = signer.compute(contentType(), bb, false);
/* /*
* position was advanced to limit in compute above. * position was advanced to limit in compute above.
......
...@@ -41,12 +41,14 @@ import javax.security.auth.x500.X500Principal; ...@@ -41,12 +41,14 @@ import javax.security.auth.x500.X500Principal;
import javax.crypto.KeyGenerator; import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.spec.DHPublicKeySpec;
import javax.net.ssl.*; import javax.net.ssl.*;
import sun.security.internal.spec.TlsPrfParameterSpec; import sun.security.internal.spec.TlsPrfParameterSpec;
import sun.security.ssl.CipherSuite.*; import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.PRF.*; import static sun.security.ssl.CipherSuite.PRF.*;
import sun.security.util.KeyUtil;
/** /**
* Many data structures are involved in the handshake messages. These * Many data structures are involved in the handshake messages. These
...@@ -712,6 +714,7 @@ class DH_ServerKeyExchange extends ServerKeyExchange ...@@ -712,6 +714,7 @@ class DH_ServerKeyExchange extends ServerKeyExchange
this.protocolVersion = protocolVersion; this.protocolVersion = protocolVersion;
this.preferableSignatureAlgorithm = null; this.preferableSignatureAlgorithm = null;
// The DH key has been validated in the constructor of DHCrypt.
setValues(obj); setValues(obj);
signature = null; signature = null;
} }
...@@ -728,6 +731,7 @@ class DH_ServerKeyExchange extends ServerKeyExchange ...@@ -728,6 +731,7 @@ class DH_ServerKeyExchange extends ServerKeyExchange
this.protocolVersion = protocolVersion; this.protocolVersion = protocolVersion;
// The DH key has been validated in the constructor of DHCrypt.
setValues(obj); setValues(obj);
Signature sig; Signature sig;
...@@ -754,7 +758,8 @@ class DH_ServerKeyExchange extends ServerKeyExchange ...@@ -754,7 +758,8 @@ class DH_ServerKeyExchange extends ServerKeyExchange
* DH_anon key exchange * DH_anon key exchange
*/ */
DH_ServerKeyExchange(HandshakeInStream input, DH_ServerKeyExchange(HandshakeInStream input,
ProtocolVersion protocolVersion) throws IOException { ProtocolVersion protocolVersion)
throws IOException, GeneralSecurityException {
this.protocolVersion = protocolVersion; this.protocolVersion = protocolVersion;
this.preferableSignatureAlgorithm = null; this.preferableSignatureAlgorithm = null;
...@@ -762,6 +767,10 @@ class DH_ServerKeyExchange extends ServerKeyExchange ...@@ -762,6 +767,10 @@ class DH_ServerKeyExchange extends ServerKeyExchange
dh_p = input.getBytes16(); dh_p = input.getBytes16();
dh_g = input.getBytes16(); dh_g = input.getBytes16();
dh_Ys = input.getBytes16(); dh_Ys = input.getBytes16();
KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
new BigInteger(1, dh_p),
new BigInteger(1, dh_g)));
signature = null; signature = null;
} }
...@@ -782,6 +791,9 @@ class DH_ServerKeyExchange extends ServerKeyExchange ...@@ -782,6 +791,9 @@ class DH_ServerKeyExchange extends ServerKeyExchange
dh_p = input.getBytes16(); dh_p = input.getBytes16();
dh_g = input.getBytes16(); dh_g = input.getBytes16();
dh_Ys = input.getBytes16(); dh_Ys = input.getBytes16();
KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
new BigInteger(1, dh_p),
new BigInteger(1, dh_g)));
// read the signature and hash algorithm // read the signature and hash algorithm
if (protocolVersion.v >= ProtocolVersion.TLS12.v) { if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
......
/* /*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -205,7 +205,7 @@ class OutputRecord extends ByteArrayOutputStream implements Record { ...@@ -205,7 +205,7 @@ class OutputRecord extends ByteArrayOutputStream implements Record {
} }
if (signer.MAClen() != 0) { if (signer.MAClen() != 0) {
byte[] hash = signer.compute(contentType, buf, byte[] hash = signer.compute(contentType, buf,
headerSize, count - headerSize); headerSize, count - headerSize, false);
write(hash); write(hash);
} }
} }
......
...@@ -34,7 +34,7 @@ import javax.crypto.*; ...@@ -34,7 +34,7 @@ import javax.crypto.*;
import javax.net.ssl.*; import javax.net.ssl.*;
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
import sun.security.util.KeyLength; import sun.security.util.KeyUtil;
/** /**
* This is the client key exchange message (CLIENT --> SERVER) used with * This is the client key exchange message (CLIENT --> SERVER) used with
...@@ -191,7 +191,7 @@ final class RSAClientKeyExchange extends HandshakeMessage { ...@@ -191,7 +191,7 @@ final class RSAClientKeyExchange extends HandshakeMessage {
"unable to get the plaintext of the premaster secret"); "unable to get the plaintext of the premaster secret");
} }
int keySize = KeyLength.getKeySize(secretKey); int keySize = KeyUtil.getKeySize(secretKey);
if (keySize > 0 && keySize != 384) { // 384 = 48 * 8 if (keySize > 0 && keySize != 384) { // 384 = 48 * 8
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
System.out.println( System.out.println(
......
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -958,35 +958,15 @@ final public class SSLEngineImpl extends SSLEngine { ...@@ -958,35 +958,15 @@ final public class SSLEngineImpl extends SSLEngine {
* throw a fatal alert if the integrity check fails. * throw a fatal alert if the integrity check fails.
*/ */
try { try {
decryptedBB = inputRecord.decrypt(readCipher, readBB); decryptedBB = inputRecord.decrypt(readMAC, readCipher, readBB);
} catch (BadPaddingException e) { } catch (BadPaddingException e) {
// RFC 2246 states that decryption_failed should be used
// for this purpose. However, that allows certain attacks,
// so we just send bad record MAC. We also need to make
// sure to always check the MAC to avoid a timing attack
// for the same issue. See paper by Vaudenay et al.
//
// rewind the BB if necessary.
readBB.rewind();
inputRecord.checkMAC(readMAC, readBB);
// use the same alert types as for MAC failure below
byte alertType = (inputRecord.contentType() == byte alertType = (inputRecord.contentType() ==
Record.ct_handshake) ? Record.ct_handshake) ?
Alerts.alert_handshake_failure : Alerts.alert_handshake_failure :
Alerts.alert_bad_record_mac; Alerts.alert_bad_record_mac;
fatal(alertType, "Invalid padding", e); fatal(alertType, e.getMessage(), e);
} }
if (!inputRecord.checkMAC(readMAC, decryptedBB)) {
if (inputRecord.contentType() == Record.ct_handshake) {
fatal(Alerts.alert_handshake_failure,
"bad handshake record MAC");
} else {
fatal(Alerts.alert_bad_record_mac, "bad record MAC");
}
}
// if (!inputRecord.decompress(c)) // if (!inputRecord.decompress(c))
// fatal(Alerts.alert_decompression_failure, // fatal(Alerts.alert_decompression_failure,
......
...@@ -38,7 +38,7 @@ import java.util.Collection; ...@@ -38,7 +38,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.ArrayList; import java.util.ArrayList;
import sun.security.util.KeyLength; import sun.security.util.KeyUtil;
/** /**
* Signature and hash algorithm. * Signature and hash algorithm.
...@@ -274,7 +274,7 @@ final class SignatureAndHashAlgorithm { ...@@ -274,7 +274,7 @@ final class SignatureAndHashAlgorithm {
* If key size is less than 512, the digest length should be * If key size is less than 512, the digest length should be
* less than or equal to 20 bytes. * less than or equal to 20 bytes.
*/ */
int keySize = KeyLength.getKeySize(signingKey); int keySize = KeyUtil.getKeySize(signingKey);
if (keySize >= 768) { if (keySize >= 768) {
maxDigestLength = HashAlgorithm.SHA512.length; maxDigestLength = HashAlgorithm.SHA512.length;
} else if ((keySize >= 512) && (keySize < 768)) { } else if ((keySize >= 512) && (keySize < 768)) {
......
...@@ -325,6 +325,10 @@ class DerIndefLenConverter { ...@@ -325,6 +325,10 @@ class DerIndefLenConverter {
} }
} }
if (unresolved != 0) {
throw new IOException("not all indef len BER resolved");
}
newData = new byte[dataSize + numOfTotalLenBytes + unused]; newData = new byte[dataSize + numOfTotalLenBytes + unused];
dataPos=0; newDataPos=0; index=0; dataPos=0; newDataPos=0; index=0;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册