--- a/jdk/src/share/bin/jli_util.h Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/bin/jli_util.h Sun Feb 03 23:25:38 2013 +0100
@@ -66,7 +66,7 @@
#include <io.h>
#define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2))
#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);
#define JLI_Lseek _lseeki64
#else /* NIXES */
--- a/jdk/src/share/bin/parse_manifest.c Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/bin/parse_manifest.c Sun Feb 03 23:25:38 2013 +0100
@@ -568,9 +568,9 @@
#ifdef O_BINARY
| O_BINARY /* use binary mode on windows */
#endif
- )) == -1)
+ )) == -1) {
return (-1);
-
+ }
info->manifest_version = NULL;
info->main_class = NULL;
info->jre_version = NULL;
@@ -617,12 +617,14 @@
zentry entry;
void *data = NULL;
- fd = open(jarfile, O_RDONLY
+ if ((fd = open(jarfile, O_RDONLY
#ifdef O_BINARY
| O_BINARY /* use binary mode on windows */
#endif
- );
- if (fd != -1 && find_file(fd, &entry, filename) == 0) {
+ )) == -1) {
+ return NULL;
+ }
+ if (find_file(fd, &entry, filename) == 0) {
data = inflate_file(fd, &entry, size);
}
close(fd);
@@ -664,8 +666,9 @@
#ifdef O_BINARY
| O_BINARY /* use binary mode on windows */
#endif
- )) == -1)
+ )) == -1) {
return (-1);
+ }
if (rc = find_file(fd, &entry, manifest_name) != 0) {
close(fd);
--- a/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/com/sun/beans/finder/MethodFinder.java Sun Feb 03 23:25:38 2013 +0100
@@ -66,11 +66,14 @@
Signature signature = new Signature(type, name, args);
Method method = CACHE.get(signature);
- if (method != null) {
+ boolean cached = method != null;
+ if (cached && isPackageAccessible(method.getDeclaringClass())) {
return method;
}
method = findAccessibleMethod(new MethodFinder(name, args).find(type.getMethods()));
- CACHE.put(signature, method);
+ if (!cached) {
+ CACHE.put(signature, method);
+ }
return method;
}
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java Sun Feb 03 23:25:38 2013 +0100
@@ -41,6 +41,8 @@
import javax.crypto.SecretKey;
import javax.crypto.spec.*;
+import sun.security.util.KeyUtil;
+
/**
* This class implements the Diffie-Hellman key agreement protocol between
* any number of parties.
@@ -200,6 +202,9 @@
throw new InvalidKeyException("Incompatible parameters");
}
+ // validate the Diffie-Hellman public key
+ KeyUtil.validate(dhPubKey);
+
// store the y value
this.y = dhPubKey.getY();
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Sun Feb 03 23:25:38 2013 +0100
@@ -1000,7 +1000,6 @@
/** Write a constant pool reference. */
public void putRef(Entry e) {
- assert(index != null);
addValue(encodeRefOrNull(e, index));
}
public void putRef(Entry e, Index index) {
@@ -1052,6 +1051,8 @@
int encodeRef(Entry e, Index ix) {
+ if (ix == null)
+ throw new RuntimeException("null index for " + e.stringValue());
int coding = ix.indexOf(e);
if (verbose > 2)
Utils.log.fine("putRef "+coding+" => "+e);
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java Sun Feb 03 23:25:38 2013 +0100
@@ -1381,6 +1381,8 @@
/** Index of all CP entries of a given tag and class. */
public Index getMemberIndex(byte tag, ClassEntry classRef) {
+ if (classRef == null)
+ throw new RuntimeException("missing class reference for " + tagName(tag));
if (indexByTagAndClass == null)
indexByTagAndClass = new Index[CONSTANT_Limit][];
Index allClasses = getIndexByTag(CONSTANT_Class);
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/NativeUnpack.java Sun Feb 03 23:25:38 2013 +0100
@@ -109,6 +109,10 @@
return (p200 == null)? null: p200._nunp;
}
+ private synchronized long getUnpackerPtr() {
+ return unpackerPtr;
+ }
+
// Callback from the unpacker engine to get more data.
private long readInputFn(ByteBuffer pbuf, long minlen) throws IOException {
if (in == null) return 0; // nothing is readable
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackerImpl.java Sun Feb 03 23:25:38 2013 +0100
@@ -83,7 +83,7 @@
* @param out an OutputStream
* @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);
TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
? null
@@ -118,7 +118,7 @@
* @param out an OutputStream
* @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);
TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
TimeZone.getDefault();
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/UnpackerImpl.java Sun Feb 03 23:25:38 2013 +0100
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -106,7 +106,7 @@
* @param out a JarOutputStream.
* @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) {
throw new NullPointerException("null input");
}
@@ -151,7 +151,7 @@
* @param out a JarOutputStream.
* @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) {
throw new NullPointerException("null input");
}
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Sun Feb 03 23:25:38 2013 +0100
@@ -56,6 +56,8 @@
import java.lang.reflect.InvocationTargetException;
import javax.management.AttributeNotFoundException;
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
@@ -528,8 +530,10 @@
// to locate method
readMethod = SimpleIntrospector.getReadMethod(clazz, element);
}
- if (readMethod != null)
- return readMethod.invoke(complex);
+ if (readMethod != null) {
+ ReflectUtil.checkPackageAccess(readMethod.getDeclaringClass());
+ return MethodUtil.invoke(readMethod, complex, new Class[0]);
+ }
throw new AttributeNotFoundException(
"Could not find the getter method for the property " +
--- a/jdk/src/share/classes/java/awt/Dialog.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/awt/Dialog.java Sun Feb 03 23:25:38 2013 +0100
@@ -39,6 +39,7 @@
import sun.awt.util.IdentityArrayList;
import sun.awt.util.IdentityLinkedList;
import sun.security.util.SecurityConstants;
+import java.security.AccessControlException;
/**
* A Dialog is a top-level window with a title and a border
@@ -128,6 +129,8 @@
*/
boolean undecorated = false;
+ private transient boolean initialized = false;
+
/**
* Modal dialogs block all input to some top-level windows.
* Whether a particular window is blocked depends on dialog's type
@@ -671,6 +674,7 @@
this.title = title;
setModalityType(modalityType);
SunToolkit.checkAndSetPolicy(this);
+ initialized = true;
}
/**
@@ -722,6 +726,7 @@
this.title = title;
setModalityType(modalityType);
SunToolkit.checkAndSetPolicy(this);
+ initialized = true;
}
/**
@@ -851,12 +856,9 @@
if (modalityType == type) {
return;
}
- if (type == ModalityType.TOOLKIT_MODAL) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkPermission(SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION);
- }
- }
+
+ checkModalityPermission(type);
+
modalityType = type;
modal = (modalityType != ModalityType.MODELESS);
}
@@ -1025,6 +1027,11 @@
*/
@Deprecated
public void show() {
+ if (!initialized) {
+ throw new IllegalStateException("The dialog component " +
+ "has not been initialized properly");
+ }
+
beforeFirstShow = false;
if (!isModal()) {
conditionalShow(null, null);
@@ -1600,18 +1607,50 @@
}
}
+ 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)
throws ClassNotFoundException, IOException, HeadlessException
{
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
- if (modalityType == null) {
+ if (localModalityType == null) {
+ this.modal = fields.get("modal", false);
setModal(modal);
}
+ this.resizable = fields.get("resizable", true);
+ this.undecorated = fields.get("undecorated", false);
+ this.title = (String)fields.get("title", "");
+ this.modalityType = localModalityType;
+
blockedWindows = new IdentityArrayList<>();
+
+ SunToolkit.checkAndSetPolicy(this);
+
+ initialized = true;
+
}
/*
--- a/jdk/src/share/classes/java/awt/EventQueue.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/awt/EventQueue.java Sun Feb 03 23:25:38 2013 +0100
@@ -194,7 +194,8 @@
}
public void removeSourceEvents(EventQueue eventQueue,
Object source,
- boolean removeAllEvents) {
+ boolean removeAllEvents)
+ {
eventQueue.removeSourceEvents(source, removeAllEvents);
}
public boolean noEvents(EventQueue eventQueue) {
@@ -203,6 +204,11 @@
public void wakeup(EventQueue eventQueue, boolean isShutdown) {
eventQueue.wakeup(isShutdown);
}
+ public void invokeAndWait(Object source, Runnable r)
+ throws InterruptedException, InvocationTargetException
+ {
+ EventQueue.invokeAndWait(source, r);
+ }
});
}
@@ -1245,8 +1251,14 @@
* @since 1.2
*/
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()) {
throw new Error("Cannot call invokeAndWait from the event dispatcher thread");
}
@@ -1255,8 +1267,7 @@
Object lock = new AWTInvocationLock();
InvocationEvent event =
- new InvocationEvent(Toolkit.getDefaultToolkit(), runnable, lock,
- true);
+ new InvocationEvent(source, runnable, lock, true);
synchronized (lock) {
Toolkit.getEventQueue().postEvent(event);
--- a/jdk/src/share/classes/java/awt/TextComponent.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/awt/TextComponent.java Sun Feb 03 23:25:38 2013 +0100
@@ -109,12 +109,6 @@
// the background color of non-editable TextComponents.
boolean backgroundSetByClientCode = false;
- /**
- * True if this <code>TextComponent</code> has access
- * to the System clipboard.
- */
- transient private boolean canAccessClipboard;
-
transient protected TextListener textListener;
/*
@@ -139,7 +133,6 @@
GraphicsEnvironment.checkHeadless();
this.text = (text != null) ? text : "";
setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
- checkSystemClipboardAccess();
}
private void enableInputMethodsIfNecessary() {
@@ -734,17 +727,14 @@
/**
* Assigns a valid value to the canAccessClipboard instance variable.
*/
- private void checkSystemClipboardAccess() {
- canAccessClipboard = true;
+ private boolean canAccessClipboard() {
SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- try {
- sm.checkSystemClipboardAccess();
- }
- catch (SecurityException e) {
- canAccessClipboard = false;
- }
- }
+ if (sm == null) return true;
+ try {
+ sm.checkSystemClipboardAccess();
+ return true;
+ } catch (SecurityException e) {}
+ return false;
}
/*
@@ -827,7 +817,6 @@
}
}
enableInputMethodsIfNecessary();
- checkSystemClipboardAccess();
}
--- a/jdk/src/share/classes/java/awt/Window.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/awt/Window.java Sun Feb 03 23:25:38 2013 +0100
@@ -1206,7 +1206,7 @@
}
else {
try {
- EventQueue.invokeAndWait(action);
+ EventQueue.invokeAndWait(this, action);
}
catch (InterruptedException e) {
System.err.println("Disposal was interrupted:");
--- a/jdk/src/share/classes/java/io/ObjectInputStream.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/io/ObjectInputStream.java Sun Feb 03 23:25:38 2013 +0100
@@ -1752,6 +1752,12 @@
ObjectStreamClass desc = readClassDesc(false);
desc.checkDeserialize();
+ Class<?> cl = desc.forClass();
+ if (cl == String.class || cl == Class.class
+ || cl == ObjectStreamClass.class) {
+ throw new InvalidClassException("invalid class descriptor");
+ }
+
Object obj;
try {
obj = desc.isInstantiable() ? desc.newInstance() : null;
--- a/jdk/src/share/classes/java/lang/Class.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/lang/Class.java Sun Feb 03 23:25:38 2013 +0100
@@ -61,7 +61,9 @@
import sun.reflect.generics.scope.ClassScope;
import sun.security.util.SecurityConstants;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Proxy;
import sun.reflect.annotation.*;
+import sun.reflect.misc.ReflectUtil;
/**
* Instances of the class {@code Class} represent classes and
@@ -248,11 +250,11 @@
ClassLoader loader)
throws ClassNotFoundException
{
- if (loader == null) {
+ if (sun.misc.VM.isSystemDomainLoader(loader)) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader();
- if (ccl != null) {
+ if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
@@ -317,7 +319,7 @@
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);
}
return newInstance0();
}
@@ -1297,7 +1299,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// 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,
// something the caller might not have privilege to do. The code here
@@ -1372,7 +1374,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyFields(privateGetPublicFields(null));
}
@@ -1423,7 +1425,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyMethods(privateGetPublicMethods());
}
@@ -1472,7 +1474,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyConstructors(privateGetDeclaredConstructors(true));
}
@@ -1531,7 +1533,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
Field field = getField0(name);
if (field == null) {
throw new NoSuchFieldException(name);
@@ -1616,7 +1618,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
Method method = getMethod0(name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
@@ -1670,7 +1672,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return getConstructor0(parameterTypes, Member.PUBLIC);
}
@@ -1712,7 +1714,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), false);
return getDeclaredClasses0();
}
@@ -1756,7 +1758,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyFields(privateGetDeclaredFields(false));
}
@@ -1804,7 +1806,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyMethods(privateGetDeclaredMethods(false));
}
@@ -1849,7 +1851,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyConstructors(privateGetDeclaredConstructors(false));
}
@@ -1893,7 +1895,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
Field field = searchFields(privateGetDeclaredFields(false), name);
if (field == null) {
throw new NoSuchFieldException(name);
@@ -1948,7 +1950,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
@@ -1998,7 +2000,7 @@
// be very careful not to change the stack depth of this
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
- checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader());
+ checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return getConstructor0(parameterTypes, Member.DECLARED);
}
@@ -2168,18 +2170,26 @@
* <p> Default policy: allow all clients access with normal Java access
* control.
*/
- private void checkMemberAccess(int which, ClassLoader ccl) {
+ private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) {
SecurityManager s = System.getSecurityManager();
if (s != null) {
s.checkMemberAccess(this, which);
ClassLoader cl = getClassLoader0();
- if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
+ if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
String name = this.getName();
int i = name.lastIndexOf('.');
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());
+ }
}
}
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java Sun Feb 03 23:25:38 2013 +0100
@@ -26,8 +26,12 @@
package java.lang.invoke;
import java.lang.reflect.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import sun.invoke.WrapperInstance;
import java.util.ArrayList;
+import sun.reflect.Reflection;
+import sun.reflect.misc.ReflectUtil;
/**
* This class consists exclusively of static methods that help adapt
@@ -137,6 +141,18 @@
<T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
throw new IllegalArgumentException("not a public interface: "+intfc.getName());
+ SecurityManager smgr = System.getSecurityManager();
+ if (smgr != null) {
+ final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller
+ final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
+ final ClassLoader ccl = caller.getClassLoader();
+ ReflectUtil.checkProxyPackageAccess(ccl, intfc);
+ }
+ 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);
if (methods == null)
throw new IllegalArgumentException("not a single-method interface: "+intfc.getName());
@@ -148,27 +164,44 @@
checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
}
- return intfc.cast(Proxy.newProxyInstance(
- intfc.getClassLoader(),
- new Class<?>[]{ intfc, WrapperInstance.class },
- new InvocationHandler() {
- private Object getArg(String name) {
- if ((Object)name == "getWrapperInstanceTarget") return target;
- if ((Object)name == "getWrapperInstanceType") return intfc;
- throw new AssertionError();
+ final InvocationHandler ih = new InvocationHandler() {
+ private Object getArg(String name) {
+ if ((Object)name == "getWrapperInstanceTarget") return target;
+ if ((Object)name == "getWrapperInstanceType") return intfc;
+ throw new AssertionError();
+ }
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ 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 {
- for (int i = 0; i < methods.length; i++) {
- if (method.equals(methods[i]))
- return vaTargets[i].invokeExact(args);
- }
- if (method.getDeclaringClass() == WrapperInstance.class)
- return getArg(method.getName());
- if (isObjectMethod(method))
- 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);
+ throw new InternalError("bad proxy method: "+method);
+ }
+ };
+
+ Object proxy;
+ if (smgr != 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);
}
/**
--- a/jdk/src/share/classes/java/lang/reflect/Proxy.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java Sun Feb 03 23:25:38 2013 +0100
@@ -27,6 +27,9 @@
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -36,6 +39,9 @@
import java.util.List;
import java.util.WeakHashMap;
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
@@ -265,9 +271,69 @@
* @param h the invocation handler for this proxy instance
*/
protected Proxy(InvocationHandler h) {
+ doNewInstanceCheck();
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
* given a class loader and an array of interfaces. The proxy class
@@ -346,6 +412,51 @@
Class<?>... interfaces)
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) {
throw new IllegalArgumentException("interface limit exceeded");
}
@@ -497,8 +608,9 @@
}
}
- if (proxyPkg == null) { // if no non-public proxy interfaces,
- proxyPkg = ""; // use the unnamed package
+ if (proxyPkg == null) {
+ // if no non-public proxy interfaces, use sun.proxy package
+ proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
{
@@ -598,22 +710,46 @@
/*
* 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.
*/
try {
- Constructor<?> cons = cl.getConstructor(constructorParams);
- return cons.newInstance(new Object[] { h });
- } catch (NoSuchMethodException |
- IllegalAccessException |
- InstantiationException |
- InvocationTargetException e) {
+ final Constructor<?> cons = cl.getConstructor(constructorParams);
+ final InvocationHandler ih = h;
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
+ // create proxy instance with doPrivilege as the proxy class may
+ // 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);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getCause();
+ if (t instanceof RuntimeException) {
+ throw (RuntimeException) t;
+ } else {
+ throw new InternalError(t.toString(), t);
+ }
+ }
+ }
+
/**
* Returns true if and only if the specified class was dynamically
* generated to be a proxy class using the {@code getProxyClass}
--- a/jdk/src/share/classes/java/net/InetSocketAddress.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/net/InetSocketAddress.java Sun Feb 03 23:25:38 2013 +0100
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,9 +24,12 @@
*/
package java.net;
-import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.io.ObjectStreamField;
/**
*
@@ -46,23 +49,105 @@
* @see java.net.ServerSocket
* @since 1.4
*/
-public class InetSocketAddress extends SocketAddress {
- /* The hostname of the Socket Address
- * @serial
- */
- private String hostname = null;
- /* The IP address of the Socket Address
- * @serial
- */
- private InetAddress addr = null;
- /* The port number of the Socket Address
- * @serial
- */
- private int port;
+public class InetSocketAddress
+ extends SocketAddress
+{
+ // Private implementation class pointed to by all public methods.
+ private static class InetSocketAddressHolder {
+ // The hostname of the Socket Address
+ private String hostname;
+ // The IP address of the Socket Address
+ private InetAddress addr;
+ // The port number of the Socket Address
+ 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 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 @@
* range of valid port values.
*/
public InetSocketAddress(InetAddress addr, int port) {
- if (port < 0 || port > 0xFFFF) {
- throw new IllegalArgumentException("port out of range:" + port);
- }
- this.port = port;
- if (addr == null)
- this.addr = InetAddress.anyLocalAddress();
- else
- this.addr = addr;
+ holder = new InetSocketAddressHolder(
+ null,
+ addr == null ? InetAddress.anyLocalAddress() : addr,
+ checkPort(port));
}
/**
@@ -132,19 +213,20 @@
* @see #isUnresolved()
*/
public InetSocketAddress(String hostname, int port) {
- if (port < 0 || port > 0xFFFF) {
- throw new IllegalArgumentException("port out of range:" + port);
- }
- if (hostname == null) {
- throw new IllegalArgumentException("hostname can't be null");
- }
+ checkHost(hostname);
+ InetAddress addr = null;
+ String host = null;
try {
addr = InetAddress.getByName(hostname);
} catch(UnknownHostException e) {
- this.hostname = hostname;
- addr = null;
+ host = hostname;
}
- 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 @@
* @since 1.5
*/
public static InetSocketAddress createUnresolved(String host, int port) {
- if (port < 0 || port > 0xFFFF) {
- 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;
+ return new InetSocketAddress(checkPort(port), checkHost(host));
}
- private void readObject(ObjectInputStream s)
- throws IOException, ClassNotFoundException {
- s.defaultReadObject();
+ /**
+ * @serialField hostname String
+ * @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();
+ }
+
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException
+ {
+ // 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);
// Check that our invariants are satisfied
- if (port < 0 || port > 0xFFFF) {
- throw new InvalidObjectException("port out of range:" + port);
- }
-
- if (hostname == null && addr == null) {
+ checkPort(oisPort);
+ if (oisHostname == null && oisAddr == null)
throw new InvalidObjectException("hostname and addr " +
"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 @@
* @return the port number.
*/
public final int getPort() {
- return port;
+ return holder.getPort();
}
/**
@@ -213,7 +331,7 @@
* @return the InetAdress or <code>null</code> if it is unresolved.
*/
public final InetAddress getAddress() {
- return addr;
+ return holder.getAddress();
}
/**
@@ -224,31 +342,19 @@
* @return the hostname part of the address.
*/
public final String getHostName() {
- if (hostname != null)
- return hostname;
- if (addr != null)
- return addr.getHostName();
- return null;
+ return holder.getHostName();
}
/**
* Returns the hostname, or the String form of the address if it
* 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.
* @since 1.7
*/
public final String getHostString() {
- if (hostname != null)
- return hostname;
- if (addr != null) {
- if (addr.hostName != null)
- return addr.hostName;
- else
- return addr.getHostAddress();
- }
- return null;
+ return holder.getHostString();
}
/**
@@ -258,7 +364,7 @@
* an <code>InetAddress</code>.
*/
public final boolean isUnresolved() {
- return addr == null;
+ return holder.isUnresolved();
}
/**
@@ -269,12 +375,9 @@
*
* @return a string representation of this object.
*/
+ @Override
public String toString() {
- if (isUnresolved()) {
- return hostname + ":" + port;
- } else {
- return addr.toString() + ":" + port;
- }
+ return holder.toString();
}
/**
@@ -297,19 +400,11 @@
* <code>false</code> otherwise.
* @see java.net.InetAddress#equals(java.lang.Object)
*/
+ @Override
public final boolean equals(Object obj) {
if (obj == null || !(obj instanceof InetSocketAddress))
return false;
- InetSocketAddress sockAddr = (InetSocketAddress) obj;
- 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);
+ return holder.equals(((InetSocketAddress) obj).holder);
}
/**
@@ -317,11 +412,8 @@
*
* @return a hash code value for this socket address.
*/
+ @Override
public final int hashCode() {
- if (addr != null)
- return addr.hashCode() + port;
- if (hostname != null)
- return hostname.toLowerCase().hashCode() + port;
- return port;
+ return holder.hashCode();
}
}
--- a/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Sun Feb 03 23:25:38 2013 +0100
@@ -34,8 +34,10 @@
*/
package java.util.concurrent;
-import java.util.concurrent.locks.*;
-import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.*;
/**
@@ -491,10 +493,15 @@
* policy limiting the number of threads. Even though it is not
* treated as an error, failure to create threads may result in
* new tasks being rejected or existing ones remaining stuck in
- * the queue. On the other hand, no special precautions exist to
- * handle OutOfMemoryErrors that might be thrown while trying to
- * create threads, since there is generally no recourse from
- * within this class.
+ * the queue.
+ *
+ * We go further and preserve pool invariants even in the face of
+ * 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;
@@ -568,9 +575,13 @@
* task execution. This protects against interrupts that are
* intended to wake up a worker thread waiting for a task from
* instead interrupting a task being run. We implement a simple
- * non-reentrant mutual exclusion lock rather than use ReentrantLock
- * because we do not want worker tasks to be able to reacquire the
- * lock when they invoke pool control methods like setCorePoolSize.
+ * non-reentrant mutual exclusion lock rather than use
+ * ReentrantLock because we do not want worker tasks to be able to
+ * 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
extends AbstractQueuedSynchronizer
@@ -594,6 +605,7 @@
* @param firstTask the first task (null if none)
*/
Worker(Runnable firstTask) {
+ setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
@@ -609,7 +621,7 @@
// The value 1 represents the locked state.
protected boolean isHeldExclusively() {
- return getState() == 1;
+ return getState() != 0;
}
protected boolean tryAcquire(int unused) {
@@ -630,6 +642,16 @@
public boolean tryLock() { return tryAcquire(1); }
public void unlock() { release(1); }
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 @@
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
- for (Worker w : workers) {
- try {
- w.thread.interrupt();
- } catch (SecurityException ignore) {
- }
- }
+ for (Worker w : workers)
+ w.interruptIfStarted();
} finally {
mainLock.unlock();
}
@@ -790,19 +808,6 @@
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
* ScheduledThreadPoolExecutor
@@ -862,12 +867,13 @@
* Checks if a new worker can be added with respect to current
* pool state and the given bound (either core or maximum). If so,
* 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
* eligible to shut down. It also returns false if the thread
- * factory fails to create a thread when asked, which requires a
- * backout of workerCount, and a recheck for termination, in case
- * the existence of this worker was holding up termination.
+ * factory fails to create a thread when asked. If the thread
+ * creation fails, either due to the thread factory returning
+ * 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
* null if none). Workers are created with an initial first task
@@ -910,46 +916,65 @@
}
}
- Worker w = new Worker(firstTask);
- Thread t = w.thread;
+ boolean workerStarted = false;
+ 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;
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 (t == null ||
- (rs >= SHUTDOWN &&
- ! (rs == SHUTDOWN &&
- firstTask == null))) {
- decrementWorkerCount();
- tryTerminate();
- return false;
- }
-
- workers.add(w);
-
- int s = workers.size();
- if (s > largestPoolSize)
- largestPoolSize = s;
+ if (w != null)
+ workers.remove(w);
+ decrementWorkerCount();
+ tryTerminate();
} finally {
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 @@
* @param w the worker
*/
final void runWorker(Worker w) {
+ Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
+ w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
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 {
- beforeExecute(w.thread, task);
+ beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
@@ -2064,3 +2099,4 @@
}
}
}
+
--- a/jdk/src/share/classes/java/util/jar/JarFile.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/util/jar/JarFile.java Sun Feb 03 23:25:38 2013 +0100
@@ -34,6 +34,7 @@
import java.security.cert.Certificate;
import java.security.AccessController;
import java.security.CodeSource;
+import sun.misc.IOUtils;
import sun.security.action.GetPropertyAction;
import sun.security.util.ManifestEntryVerifier;
import sun.misc.SharedSecrets;
@@ -329,6 +330,9 @@
if (names != null) {
for (int i = 0; i < names.length; i++) {
JarEntry e = getJarEntry(names[i]);
+ if (e == null) {
+ throw new JarException("corrupted jar file");
+ }
if (!e.isDirectory()) {
if (mev == null) {
mev = new ManifestEntryVerifier
@@ -348,6 +352,10 @@
// treat the jar file as being unsigned
jv = null;
verify = false;
+ if (JarVerifier.debug != null) {
+ JarVerifier.debug.println("jarfile parsing error!");
+ ex.printStackTrace();
+ }
}
// if after initializing the verifier we have nothing
@@ -375,11 +383,9 @@
* META-INF files.
*/
private byte[] getBytes(ZipEntry ze) throws IOException {
- byte[] b = new byte[(int)ze.getSize()];
- try (DataInputStream is = new DataInputStream(super.getInputStream(ze))) {
- is.readFully(b, 0, b.length);
+ try (InputStream is = super.getInputStream(ze)) {
+ return IOUtils.readFully(is, (int)ze.getSize(), true);
}
- return b;
}
/**
@@ -479,12 +485,7 @@
if (!isKnownToNotHaveClassPathAttribute()) {
JarEntry manEntry = getManEntry();
if (manEntry != null) {
- byte[] b = new byte[(int)manEntry.getSize()];
- try (DataInputStream dis = new DataInputStream(
- super.getInputStream(manEntry))) {
- dis.readFully(b, 0, b.length);
- }
-
+ byte[] b = getBytes(manEntry);
int last = b.length - src.length;
int i = 0;
next:
--- a/jdk/src/share/classes/java/util/logging/Level.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/util/logging/Level.java Sun Feb 03 23:25:38 2013 +0100
@@ -24,6 +24,10 @@
*/
package java.util.logging;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.ResourceBundle;
/**
@@ -59,7 +63,6 @@
*/
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";
/**
@@ -77,6 +80,9 @@
*/
private final String resourceBundleName;
+ // localized level name
+ private String localizedLevelName;
+
/**
* OFF is a special level that can be used to turn off logging.
* This level is initialized to <CODE>Integer.MAX_VALUE</CODE>.
@@ -202,9 +208,8 @@
this.name = name;
this.value = value;
this.resourceBundleName = resourceBundleName;
- synchronized (Level.class) {
- known.add(this);
- }
+ this.localizedLevelName = resourceBundleName == null ? name : null;
+ KnownLevel.add(this);
}
/**
@@ -236,12 +241,76 @@
* @return localized name
*/
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 {
ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName);
- return rb.getString(name);
+ localizedLevelName = rb.getString(name);
} 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 @@
// Serialization magic to prevent "doppelgangers".
// This is a performance optimization.
private Object readResolve() {
- synchronized (Level.class) {
- for (int i = 0; i < known.size(); i++) {
- Level other = known.get(i);
- 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;
+ KnownLevel o = KnownLevel.matches(this);
+ if (o != null) {
+ return o.levelObject;
}
+
+ // 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 @@
* <li> "SEVERE"
* <li> "1000"
* </ul>
+ *
* @param name string to be parsed
* @throws NullPointerException if the name is null
* @throws IllegalArgumentException if the value is not valid.
@@ -315,12 +379,12 @@
// Check that name is not null.
name.length();
+ KnownLevel level;
+
// Look for a known Level with the given non-localized name.
- for (int i = 0; i < known.size(); i++) {
- Level l = known.get(i);
- if (name.equals(l.name)) {
- return l;
- }
+ level = KnownLevel.findByName(name);
+ if (level != null) {
+ return level.levelObject;
}
// Now, check if the given name is an integer. If so,
@@ -328,14 +392,13 @@
// if necessary create one.
try {
int x = Integer.parseInt(name);
- for (int i = 0; i < known.size(); i++) {
- Level l = known.get(i);
- if (l.value == x) {
- return l;
- }
+ level = KnownLevel.findByValue(x);
+ if (level == null) {
+ // add new Level
+ Level levelObject = new Level(name, x);
+ level = KnownLevel.findByValue(x);
}
- // Create a new Level.
- return new Level(name, x);
+ return level.levelObject;
} catch (NumberFormatException ex) {
// Not an integer.
// Drop through.
@@ -344,11 +407,9 @@
// Finally, look for a known level with the given localized name,
// in the current default locale.
// This is relatively expensive, but not excessively so.
- for (int i = 0; i < known.size(); i++) {
- Level l = known.get(i);
- if (name.equals(l.getLocalizedName())) {
- return l;
- }
+ level = KnownLevel.findByLocalizedName(name);
+ if (level != null) {
+ return level.levelObject;
}
// OK, we've tried everything and failed
@@ -375,4 +436,124 @@
public int hashCode() {
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;
+ }
+ }
+
}
--- a/jdk/src/share/classes/java/util/logging/LogManager.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java Sun Feb 03 23:25:38 2013 +0100
@@ -35,6 +35,10 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.beans.PropertyChangeListener;
+import java.net.URL;
+import sun.misc.JavaAWTAccess;
+import sun.misc.SharedSecrets;
+import sun.security.action.GetPropertyAction;
/**
* There is a single global LogManager object that is used to
@@ -152,10 +156,9 @@
// count to allow for cases where the same listener is registered many times.
private final Map<Object,Integer> listenerMap = new HashMap<>();
- // Table of named Loggers that maps names to Loggers.
- private Hashtable<String,LoggerWeakRef> namedLoggers = new Hashtable<>();
- // Tree of named Loggers
- private LogNode root = new LogNode(null);
+ // LoggerContext for system loggers and user loggers
+ private final LoggerContext systemContext = new SystemLoggerContext();
+ private final LoggerContext userContext = new UserLoggerContext();
private Logger rootLogger;
// Have we done the primordial reading of the configuration file?
@@ -193,12 +196,13 @@
// Create and retain Logger for the root of the namespace.
manager.rootLogger = manager.new RootLogger();
- manager.addLogger(manager.rootLogger);
+ manager.systemContext.addLogger(manager.rootLogger);
+ manager.userContext.addLogger(manager.rootLogger);
// Adding the global Logger. Doing so in the Logger.<clinit>
// would deadlock with the LogManager.<clinit>.
Logger.getGlobal().setLogManager(manager);
- manager.addLogger(Logger.getGlobal());
+ manager.systemContext.addLogger(Logger.getGlobal());
// We don't call readConfiguration() here, as we may be running
// very early in the JVM startup sequence. Instead readConfiguration
@@ -276,14 +280,14 @@
return;
}
readPrimordialConfiguration = true;
+
try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+ public Void run() throws Exception {
readConfiguration();
// Platform loggers begin to delegate to java.util.logging.Logger
sun.util.logging.PlatformLogger.redirectPlatformLoggers();
-
return null;
}
});
@@ -367,62 +371,290 @@
}
}
- // Package-level method.
- // Find or create a specified logger instance. If a logger has
- // already been created with the given name it is returned.
- // Otherwise a new logger instance is created and registered
- // in the LogManager global namespace.
+ // Returns the LoggerContext for the user code (i.e. application or AppContext).
+ // Loggers are isolated from each AppContext.
+ LoggerContext getUserContext() {
+ LoggerContext context = null;
- // This method will always return a non-null Logger object.
- // Synchronization is not required here. All synchronization for
- // adding a new Logger object is handled by addLogger().
- Logger demandLogger(String name) {
- Logger result = getLogger(name);
- if (result == null) {
- // only allocate the new logger once
- Logger newLogger = new Logger(name, null);
- do {
- if (addLogger(newLogger)) {
- // We successfully added the new Logger that we
- // created above so return it without refetching.
- return newLogger;
+ SecurityManager sm = System.getSecurityManager();
+ JavaAWTAccess javaAwtAccess = SharedSecrets.getJavaAWTAccess();
+ if (sm != null && javaAwtAccess != null) {
+ synchronized (javaAwtAccess) {
+ // AppContext.getAppContext() returns the system AppContext if called
+ // from a system thread but Logger.getLogger might be called from
+ // an applet code. Instead, find the AppContext of the applet code
+ // from the execution stack.
+ Object ecx = javaAwtAccess.getExecutionContext();
+ if (ecx == null) {
+ // fall back to AppContext.getAppContext()
+ ecx = javaAwtAccess.getContext();
}
+ context = (LoggerContext)javaAwtAccess.get(ecx, LoggerContext.class);
+ if (context == null) {
+ if (javaAwtAccess.isMainAppContext()) {
+ context = userContext;
+ } else {
+ context = new UserLoggerContext();
+ context.addLogger(manager.rootLogger);
+ }
+ javaAwtAccess.put(ecx, LoggerContext.class, context);
+ }
+ }
+ } else {
+ context = userContext;
+ }
+ return context;
+ }
- // We didn't add the new Logger that we created above
- // because another thread added a Logger with the same
- // name after our null check above and before our call
- // to addLogger(). We have to refetch the Logger because
- // addLogger() returns a boolean instead of the Logger
- // reference itself. However, if the thread that created
- // the other Logger is not holding a strong reference to
- // the other Logger, then it is possible for the other
- // Logger to be GC'ed after we saw it in addLogger() and
- // before we can refetch it. If it has been GC'ed then
- // we'll just loop around and try again.
- result = getLogger(name);
- } while (result == null);
- }
- return result;
+ LoggerContext getSystemContext() {
+ return systemContext;
+ }
+
+ private List<LoggerContext> contexts() {
+ List<LoggerContext> cxs = new ArrayList<>();
+ cxs.add(systemContext);
+ cxs.add(getUserContext());
+ return cxs;
}
- // If logger.getUseParentHandlers() returns 'true' and any of the logger's
- // parents have levels or handlers defined, make sure they are instantiated.
- private void processParentHandlers(Logger logger, String name) {
- int ix = 1;
- for (;;) {
- int ix2 = name.indexOf(".", ix);
- if (ix2 < 0) {
- break;
+ static class LoggerContext {
+ // Table of named Loggers that maps names to Loggers.
+ private final Hashtable<String,LoggerWeakRef> namedLoggers = new Hashtable<>();
+ // Tree of named Loggers
+ private final LogNode root;
+
+ private LoggerContext() {
+ this.root = new LogNode(null, this);
+ }
+
+ synchronized Logger findLogger(String name) {
+ LoggerWeakRef ref = namedLoggers.get(name);
+ if (ref == null) {
+ return null;
+ }
+ Logger logger = ref.get();
+ if (logger == null) {
+ // Hashtable holds stale weak reference
+ // to a logger which has been GC-ed.
+ removeLogger(name);
+ }
+ return logger;
+ }
+
+ synchronized boolean addLogger(Logger logger) {
+ final String name = logger.getName();
+ if (name == null) {
+ throw new NullPointerException();
+ }
+
+ // cleanup some Loggers that have been GC'ed
+ manager.drainLoggerRefQueueBounded();
+
+ LoggerWeakRef ref = namedLoggers.get(name);
+ if (ref != null) {
+ if (ref.get() == null) {
+ // It's possible that the Logger was GC'ed after the
+ // drainLoggerRefQueueBounded() call above so allow
+ // a new one to be registered.
+ removeLogger(name);
+ } else {
+ // We already have a registered logger with the given name.
+ return false;
+ }
+ }
+
+ // We're adding a new logger.
+ // Note that we are creating a weak reference here.
+ ref = manager.new LoggerWeakRef(logger);
+ namedLoggers.put(name, ref);
+
+ // Apply any initial level defined for the new logger.
+ Level level = manager.getLevelProperty(name + ".level", null);
+ if (level != null) {
+ doSetLevel(logger, level);
+ }
+
+ // Do we have a per logger handler too?
+ // Note: this will add a 200ms penalty
+ manager.loadLoggerHandlers(logger, name, name + ".handlers");
+ processParentHandlers(logger, name);
+
+ // Find the new node and its parent.
+ LogNode node = getNode(name);
+ node.loggerRef = ref;
+ Logger parent = null;
+ LogNode nodep = node.parent;
+ while (nodep != null) {
+ LoggerWeakRef nodeRef = nodep.loggerRef;
+ if (nodeRef != null) {
+ parent = nodeRef.get();
+ if (parent != null) {
+ break;
+ }
+ }
+ nodep = nodep.parent;
+ }
+
+ if (parent != null) {
+ doSetParent(logger, parent);
}
- String pname = name.substring(0,ix2);
+ // Walk over the children and tell them we are their new parent.
+ node.walkAndSetParent(logger);
+ // new LogNode is ready so tell the LoggerWeakRef about it
+ ref.setNode(node);
+ return true;
+ }
+
+ void removeLogger(String name) {
+ namedLoggers.remove(name);
+ }
+
+ synchronized Enumeration<String> getLoggerNames() {
+ return namedLoggers.keys();
+ }
+
+ Logger demandLogger(String name) {
+ return demandLogger(name, null);
+ }
+
+ // Find or create a specified logger instance. If a logger has
+ // already been created with the given name it is returned.
+ // Otherwise a new logger instance is created and registered
+ // in the LogManager global namespace.
+
+ // This method will always return a non-null Logger object.
+ // Synchronization is not required here. All synchronization for
+ // adding a new Logger object is handled by addLogger().
+ Logger demandLogger(String name, String resourceBundleName) {
+ Logger result = findLogger(name);
+ if (result == null) {
+ // only allocate the new logger once
+ Logger newLogger = new Logger(name, resourceBundleName);
+ do {
+ if (addLogger(newLogger)) {
+ // We successfully added the new Logger that we
+ // created above so return it without refetching.
+ return newLogger;
+ }
+
+ // We didn't add the new Logger that we created above
+ // because another thread added a Logger with the same
+ // name after our null check above and before our call
+ // to addLogger(). We have to refetch the Logger because
+ // addLogger() returns a boolean instead of the Logger
+ // reference itself. However, if the thread that created
+ // the other Logger is not holding a strong reference to
+ // the other Logger, then it is possible for the other
+ // Logger to be GC'ed after we saw it in addLogger() and
+ // before we can refetch it. If it has been GC'ed then
+ // we'll just loop around and try again.
+ result = findLogger(name);
+ } while (result == null);
+ }
+ return result;
+ }
+
+ // If logger.getUseParentHandlers() returns 'true' and any of the logger's
+ // parents have levels or handlers defined, make sure they are instantiated.
+ private void processParentHandlers(Logger logger, String name) {
+ int ix = 1;
+ for (;;) {
+ int ix2 = name.indexOf(".", ix);
+ if (ix2 < 0) {
+ break;
+ }
+ String pname = name.substring(0, ix2);
+
+ if (manager.getProperty(pname + ".level") != null ||
+ manager.getProperty(pname + ".handlers") != null) {
+ // This pname has a level/handlers definition.
+ // Make sure it exists.
+ demandLogger(pname);
+ }
+ ix = ix2+1;
+ }
+ }
- if (getProperty(pname+".level") != null ||
- getProperty(pname+".handlers") != null) {
- // This pname has a level/handlers definition.
- // Make sure it exists.
- demandLogger(pname);
+ // Gets a node in our tree of logger nodes.
+ // If necessary, create it.
+ LogNode getNode(String name) {
+ if (name == null || name.equals("")) {
+ return root;
+ }
+ LogNode node = root;
+ while (name.length() > 0) {
+ int ix = name.indexOf(".");
+ String head;
+ if (ix > 0) {
+ head = name.substring(0, ix);
+ name = name.substring(ix + 1);
+ } else {
+ head = name;
+ name = "";
+ }
+ if (node.children == null) {
+ node.children = new HashMap<>();
+ }
+ LogNode child = node.children.get(head);
+ if (child == null) {
+ child = new LogNode(node, this);
+ node.children.put(head, child);
+ }
+ node = child;
}
- ix = ix2+1;
+ return node;
+ }
+ }
+
+ static class SystemLoggerContext extends LoggerContext {
+ // Default resource bundle for all system loggers
+ Logger demandLogger(String name) {
+ // default to use the system logger's resource bundle
+ return super.demandLogger(name, Logger.SYSTEM_LOGGER_RB_NAME);
+ }
+ }
+
+ static class UserLoggerContext extends LoggerContext {
+ /**
+ * Returns a Logger of the given name if there is one registered
+ * in this context. Otherwise, it will return the one registered
+ * in the system context if there is one. The returned Logger
+ * instance may be initialized with a different resourceBundleName.
+ * If no such logger exists, a new Logger instance will be created
+ * and registered in this context.
+ */
+ Logger demandLogger(String name, String resourceBundleName) {
+ Logger result = findLogger(name);
+ if (result == null) {
+ // use the system logger if exists; or allocate a new logger.
+ // The system logger is added to the app logger context so that
+ // any child logger created in the app logger context can have
+ // a system logger as its parent if already exist.
+ Logger logger = manager.systemContext.findLogger(name);
+ Logger newLogger =
+ logger != null ? logger : new Logger(name, resourceBundleName);
+ do {
+ if (addLogger(newLogger)) {
+ // We successfully added the new Logger that we
+ // created above so return it without refetching.
+ return newLogger;
+ }
+
+ // We didn't add the new Logger that we created above
+ // because another thread added a Logger with the same
+ // name after our null check above and before our call
+ // to addLogger(). We have to refetch the Logger because
+ // addLogger() returns a boolean instead of the Logger
+ // reference itself. However, if the thread that created
+ // the other Logger is not holding a strong reference to
+ // the other Logger, then it is possible for the other
+ // Logger to be GC'ed after we saw it in addLogger() and
+ // before we can refetch it. If it has been GC'ed then
+ // we'll just loop around and try again.
+ result = findLogger(name);
+ } while (result == null);
+ }
+ return result;
}
}
@@ -447,16 +679,17 @@
try {
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(word);
Handler hdl = (Handler) clz.newInstance();
- try {
- // Check if there is a property defining the
- // this handler's level.
- String levs = getProperty(word + ".level");
- if (levs != null) {
- hdl.setLevel(Level.parse(levs));
+ // Check if there is a property defining the
+ // this handler's level.
+ String levs = getProperty(word + ".level");
+ if (levs != null) {
+ Level l = Level.findLevel(levs);
+ if (l != null) {
+ hdl.setLevel(l);
+ } else {
+ // Probably a bad level. Drop through.
+ System.err.println("Can't set level for " + word);
}
- } catch (Exception ex) {
- System.err.println("Can't set level for " + word);
- // Probably a bad level. Drop through.
}
// Add this Handler to the logger
logger.addHandler(hdl);
@@ -512,7 +745,7 @@
if (node != null) {
// if we have a LogNode, then we were a named Logger
// so clear namedLoggers weak ref to us
- manager.namedLoggers.remove(name);
+ node.context.removeLogger(name);
name = null; // clear our ref to the Logger's name
node.loggerRef = null; // clear LogNode's weak ref to us
@@ -601,70 +834,15 @@
* false if a logger of that name already exists.
* @exception NullPointerException if the logger name is null.
*/
- public synchronized boolean addLogger(Logger logger) {
+ public boolean addLogger(Logger logger) {
final String name = logger.getName();
if (name == null) {
throw new NullPointerException();
}
-
- // cleanup some Loggers that have been GC'ed
- drainLoggerRefQueueBounded();
-
- LoggerWeakRef ref = namedLoggers.get(name);
- if (ref != null) {
- if (ref.get() == null) {
- // It's possible that the Logger was GC'ed after the
- // drainLoggerRefQueueBounded() call above so allow
- // a new one to be registered.
- namedLoggers.remove(name);
- } else {
- // We already have a registered logger with the given name.
- return false;
- }
- }
-
- // We're adding a new logger.
- // Note that we are creating a weak reference here.
- ref = new LoggerWeakRef(logger);
- namedLoggers.put(name, ref);
-
- // Apply any initial level defined for the new logger.
- Level level = getLevelProperty(name+".level", null);
- if (level != null) {
- doSetLevel(logger, level);
+ if (systemContext.findLogger(name) != null) {
+ return false;
}
-
- // Do we have a per logger handler too?
- // Note: this will add a 200ms penalty
- loadLoggerHandlers(logger, name, name+".handlers");
- processParentHandlers(logger, name);
-
- // Find the new node and its parent.
- LogNode node = findNode(name);
- node.loggerRef = ref;
- Logger parent = null;
- LogNode nodep = node.parent;
- while (nodep != null) {
- LoggerWeakRef nodeRef = nodep.loggerRef;
- if (nodeRef != null) {
- parent = nodeRef.get();
- if (parent != null) {
- break;
- }
- }
- nodep = nodep.parent;
- }
-
- if (parent != null) {
- doSetParent(logger, parent);
- }
- // Walk over the children and tell them we are their new parent.
- node.walkAndSetParent(logger);
-
- // new LogNode is ready so tell the LoggerWeakRef about it
- ref.setNode(node);
-
- return true;
+ return getUserContext().addLogger(logger);
}
@@ -706,36 +884,6 @@
}});
}
- // Find a node in our tree of logger nodes.
- // If necessary, create it.
- private LogNode findNode(String name) {
- if (name == null || name.equals("")) {
- return root;
- }
- LogNode node = root;
- while (name.length() > 0) {
- int ix = name.indexOf(".");
- String head;
- if (ix > 0) {
- head = name.substring(0,ix);
- name = name.substring(ix+1);
- } else {
- head = name;
- name = "";
- }
- if (node.children == null) {
- node.children = new HashMap<>();
- }
- LogNode child = node.children.get(head);
- if (child == null) {
- child = new LogNode(node);
- node.children.put(head, child);
- }
- node = child;
- }
- return node;
- }
-
/**
* Method to find a named logger.
* <p>
@@ -751,18 +899,16 @@
* @param name name of the logger
* @return matching logger or null if none is found
*/
- public synchronized Logger getLogger(String name) {
- LoggerWeakRef ref = namedLoggers.get(name);
- if (ref == null) {
- return null;
- }
- Logger logger = ref.get();
- if (logger == null) {
- // Hashtable holds stale weak reference
- // to a logger which has been GC-ed.
- namedLoggers.remove(name);
- }
- return logger;
+ public Logger getLogger(String name) {
+ // return the first logger added
+ //
+ // once a system logger is added in the system context, no one can
+ // adds a logger with the same name in the global context
+ // (see LogManager.addLogger). So if there is a logger in the global
+ // context with the same name as one in the system context, it must be
+ // added before the system logger was created.
+ Logger logger = getUserContext().findLogger(name);
+ return logger != null ? logger : systemContext.findLogger(name);
}
/**
@@ -781,8 +927,11 @@
* <p>
* @return enumeration of logger name strings
*/
- public synchronized Enumeration<String> getLoggerNames() {
- return namedLoggers.keys();
+ public Enumeration<String> getLoggerNames() {
+ // only return unique names
+ Set<String> names = new HashSet<>(Collections.list(systemContext.getLoggerNames()));
+ names.addAll(Collections.list(getUserContext().getLoggerNames()));
+ return Collections.enumeration(names);
}
/**
@@ -867,20 +1016,20 @@
// the global handlers, if they haven't been initialized yet.
initializedGlobalHandlers = true;
}
- Enumeration<String> enum_ = getLoggerNames();
- while (enum_.hasMoreElements()) {
- String name = enum_.nextElement();
- resetLogger(name);
+ for (LoggerContext cx : contexts()) {
+ Enumeration<String> enum_ = cx.getLoggerNames();
+ while (enum_.hasMoreElements()) {
+ String name = enum_.nextElement();
+ Logger logger = cx.findLogger(name);
+ if (logger != null) {
+ resetLogger(logger);
+ }
+ }
}
}
-
// Private method to reset an individual target logger.
- private void resetLogger(String name) {
- Logger logger = getLogger(name);
- if (logger == null) {
- return;
- }
+ private void resetLogger(Logger logger) {
// Close all the Logger's handlers.
Handler[] targets = logger.getHandlers();
for (int i = 0; i < targets.length; i++) {
@@ -892,6 +1041,7 @@
// Problems closing a handler? Keep going...
}
}
+ String name = logger.getName();
if (name != null && name.equals("")) {
// This is the root logger.
logger.setLevel(defaultLevel);
@@ -1057,11 +1207,8 @@
if (val == null) {
return defaultValue;
}
- try {
- return Level.parse(val.trim());
- } catch (Exception ex) {
- return defaultValue;
- }
+ Level l = Level.findLevel(val.trim());
+ return l != null ? l : defaultValue;
}
// Package private method to get a filter property.
@@ -1151,9 +1298,11 @@
HashMap<String,LogNode> children;
LoggerWeakRef loggerRef;
LogNode parent;
+ final LoggerContext context;
- LogNode(LogNode parent) {
+ LogNode(LogNode parent, LoggerContext context) {
this.parent = parent;
+ this.context = context;
}
// Recursive method to walk the tree below a node and set
@@ -1226,11 +1375,13 @@
System.err.println("Bad level value for property: " + key);
continue;
}
- Logger l = getLogger(name);
- if (l == null) {
- continue;
+ for (LoggerContext cx : contexts()) {
+ Logger l = cx.findLogger(name);
+ if (l == null) {
+ continue;
+ }
+ l.setLevel(level);
}
- l.setLevel(level);
}
}
--- a/jdk/src/share/classes/java/util/logging/Logger.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/util/logging/Logger.java Sun Feb 03 23:25:38 2013 +0100
@@ -31,6 +31,7 @@
import java.security.*;
import java.lang.ref.WeakReference;
import java.util.function.Supplier;
+import java.util.logging.LogManager.LoggerContext;
/**
* A Logger object is used to log messages for a specific
@@ -314,6 +315,26 @@
}
}
+ // 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.
+ private static LoggerContext getLoggerContext() {
+ LogManager manager = LogManager.getLogManager();
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ // 0: Reflection 1: Logger.getLoggerContext 2: Logger.getLogger 3: caller
+ final int SKIP_FRAMES = 3;
+ Class<?> caller = sun.reflect.Reflection.getCallerClass(SKIP_FRAMES);
+ if (caller.getClassLoader() == null) {
+ return manager.getSystemContext();
+ }
+ }
+ return manager.getUserContext();
+ }
+
/**
* Find or create a logger for a named subsystem. If a logger has
* already been created with the given name it is returned. Otherwise
@@ -355,8 +376,8 @@
// would throw an IllegalArgumentException in the second call
// because the wrapper would result in an attempt to replace
// the existing "resourceBundleForFoo" with null.
- LogManager manager = LogManager.getLogManager();
- return manager.demandLogger(name);
+ LoggerContext context = getLoggerContext();
+ return context.demandLogger(name);
}
/**
@@ -403,8 +424,8 @@
// Synchronization is not required here. All synchronization for
// adding a new Logger object is handled by LogManager.addLogger().
public static Logger getLogger(String name, String resourceBundleName) {
- LogManager manager = LogManager.getLogManager();
- Logger result = manager.demandLogger(name);
+ LoggerContext context = getLoggerContext();
+ Logger result = context.demandLogger(name, resourceBundleName);
// MissingResourceException or IllegalArgumentException can be
// thrown by setupResourceInfo().
@@ -412,6 +433,18 @@
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();
+ LoggerContext context = manager.getSystemContext();
+
+ // all loggers in the system context will default to
+ // the system logger's resource bundle
+ Logger result = context.demandLogger(name);
+ return result;
+ }
/**
* Create an anonymous Logger. The newly created Logger is not
@@ -564,7 +597,7 @@
private void doLog(LogRecord lr) {
lr.setLoggerName(name);
String ebname = getEffectiveResourceBundleName();
- if (ebname != null) {
+ if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) {
lr.setResourceBundleName(ebname);
lr.setResourceBundle(findResourceBundle(ebname));
}
@@ -1547,6 +1580,22 @@
// May also return null if we can't find the resource bundle and
// 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);
+ } catch (MissingResourceException e) {
+ throw new InternalError(e.toString());
+ }
+ }
+ });
+ }
+
private synchronized ResourceBundle findResourceBundle(String name) {
// Return a null bundle for a null name.
if (name == null) {
@@ -1561,6 +1610,13 @@
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 SystemClassloader.
ClassLoader cl = Thread.currentThread().getContextClassLoader();
@@ -1577,7 +1633,6 @@
// ClassLoader. Drop through.
}
-
// Fall back to searching up the call stack and trying each
// calling ClassLoader.
for (int ix = 0; ; ix++) {
--- a/jdk/src/share/classes/java/util/logging/Logging.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/util/logging/Logging.java Sun Feb 03 23:25:38 2013 +0100
@@ -34,7 +34,7 @@
*
* The <tt>LoggingMXBean</tt> interface provides a standard
* method for management access to the individual
- * java.util.Logger objects available at runtime.
+ * {@code Logger} objects available at runtime.
*
* @author Ron Mann
* @author Mandy Chung
@@ -75,7 +75,7 @@
if (level == null) {
return EMPTY_STRING;
} else {
- return level.getName();
+ return level.getLevelName();
}
}
@@ -85,7 +85,6 @@
}
Logger logger = logManager.getLogger(loggerName);
-
if (logger == null) {
throw new IllegalArgumentException("Logger " + loggerName +
"does not exist");
@@ -94,7 +93,10 @@
Level level = null;
if (levelName != null) {
// 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);
--- a/jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java Sun Feb 03 23:25:38 2013 +0100
@@ -37,7 +37,8 @@
@Override
public Object getLogger(String name) {
- return Logger.getLogger(name);
+ // always create a platform logger with the resource bundle name
+ return Logger.getPlatformLogger(name);
}
@Override
@@ -92,12 +93,16 @@
@Override
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
public String getLevelName(Object level) {
- return ((Level) level).getName();
+ return ((Level) level).getLevelName();
}
@Override
--- a/jdk/src/share/classes/java/util/logging/SimpleFormatter.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/java/util/logging/SimpleFormatter.java Sun Feb 03 23:25:38 2013 +0100
@@ -162,7 +162,7 @@
dat,
source,
record.getLoggerName(),
- record.getLevel().getLocalizedName(),
+ record.getLevel().getLocalizedLevelName(),
message,
throwable);
}
--- a/jdk/src/share/classes/javax/swing/JTable.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/javax/swing/JTable.java Sun Feb 03 23:25:38 2013 +0100
@@ -781,15 +781,11 @@
scrollPane.getCorner(JScrollPane.UPPER_TRAILING_CORNER);
if (corner == null || corner instanceof UIResource){
corner = null;
- Object componentClass = UIManager.get(
- "Table.scrollPaneCornerComponent");
- if (componentClass instanceof Class){
- try {
- corner = (Component)
- ((Class)componentClass).newInstance();
- } catch (Exception e) {
- // just ignore and don't set corner
- }
+ try {
+ corner = (Component) UIManager.get(
+ "Table.scrollPaneCornerComponent");
+ } catch (Exception e) {
+ // just ignore and don't set corner
}
scrollPane.setCorner(JScrollPane.UPPER_TRAILING_CORNER,
corner);
--- a/jdk/src/share/classes/javax/swing/RepaintManager.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/javax/swing/RepaintManager.java Sun Feb 03 23:25:38 2013 +0100
@@ -27,11 +27,12 @@
import java.awt.*;
import java.awt.event.*;
-import java.awt.peer.ComponentPeer;
-import java.awt.peer.ContainerPeer;
import java.awt.image.VolatileImage;
+import java.security.AccessControlContext;
import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
import java.applet.*;
import sun.awt.AWTAccessor;
@@ -39,6 +40,8 @@
import sun.awt.DisplayChangedListener;
import sun.awt.SunToolkit;
import sun.java2d.SunGraphicsEnvironment;
+import sun.misc.JavaSecurityAccess;
+import sun.misc.SharedSecrets;
import sun.security.action.GetPropertyAction;
import com.sun.java.swing.SwingUtilities3;
@@ -176,6 +179,9 @@
*/
private final ProcessingRunnable processingRunnable;
+ private final static JavaSecurityAccess javaSecurityAccess =
+ SharedSecrets.getJavaSecurityAccess();
+
static {
volatileImageBufferEnabled = "true".equals(AccessController.
@@ -548,13 +554,26 @@
// This is called from the toolkit thread when awt needs to run a
// Runnable before we paint.
//
- void nativeQueueSurfaceDataRunnable(AppContext appContext, Component c,
- Runnable r) {
+ void nativeQueueSurfaceDataRunnable(AppContext appContext,
+ final Component c, final Runnable r)
+ {
synchronized(this) {
if (runnableList == null) {
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);
}
@@ -652,9 +671,9 @@
* @see #addInvalidComponent
*/
public void validateInvalidComponents() {
- java.util.List<Component> ic;
+ final java.util.List<Component> ic;
synchronized(this) {
- if(invalidComponents == null) {
+ if (invalidComponents == null) {
return;
}
ic = invalidComponents;
@@ -662,7 +681,17 @@
}
int n = ic.size();
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 @@
paintDirtyRegions(tmpDirtyComponents);
}
- private void paintDirtyRegions(Map<Component,Rectangle>
- tmpDirtyComponents){
- int i, count;
- java.util.List<Component> roots;
- Component dirtyComponent;
-
- count = tmpDirtyComponents.size();
- if (count == 0) {
+ private void paintDirtyRegions(
+ final Map<Component,Rectangle> tmpDirtyComponents)
+ {
+ if (tmpDirtyComponents.isEmpty()) {
return;
}
- Rectangle rect;
- int localBoundsX = 0;
- int localBoundsY = 0;
- int localBoundsH;
- int localBoundsW;
-
- roots = new ArrayList<Component>(count);
-
+ final java.util.List<Component> roots =
+ new ArrayList<Component>(tmpDirtyComponents.size());
for (Component dirty : tmpDirtyComponents.keySet()) {
collectDirtyComponents(tmpDirtyComponents, dirty, roots);
}
- count = roots.size();
+ final AtomicInteger count = new AtomicInteger(roots.size());
painting = true;
try {
- for(i=0 ; i < count ; i++) {
- dirtyComponent = roots.get(i);
- rect = tmpDirtyComponents.get(dirtyComponent);
- // Sometimes when RepaintManager is changed during the painting
- // we may get null here, see #6995769 for details
- if (rect == null) {
- continue;
- }
- localBoundsH = dirtyComponent.getHeight();
- localBoundsW = dirtyComponent.getWidth();
+ for (int j=0 ; j < count.get(); j++) {
+ final int i = j;
+ final Component dirtyComponent = roots.get(j);
+ AccessControlContext stack = AccessController.getContext();
+ AccessControlContext acc =
+ AWTAccessor.getComponentAccessor().getAccessControlContext(dirtyComponent);
+ javaSecurityAccess.doIntersectionPrivilege(new PrivilegedAction<Void>() {
+ public Void run() {
+ Rectangle rect = tmpDirtyComponents.get(dirtyComponent);
+ // Sometimes when RepaintManager is changed during the painting
+ // we may get null here, see #6995769 for details
+ if (rect == null) {
+ return null;
+ }
- SwingUtilities.computeIntersection(localBoundsX,
- localBoundsY,
- localBoundsW,
- localBoundsH,
- rect);
- if (dirtyComponent instanceof JComponent) {
- ((JComponent)dirtyComponent).paintImmediately(
- rect.x,rect.y,rect.width, rect.height);
- }
- else if (dirtyComponent.isShowing()) {
- Graphics g = JComponent.safelyGetGraphics(
- dirtyComponent, dirtyComponent);
- // If the Graphics goes away, it means someone disposed of
- // 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();
+ int localBoundsH = dirtyComponent.getHeight();
+ int localBoundsW = dirtyComponent.getWidth();
+ SwingUtilities.computeIntersection(0,
+ 0,
+ localBoundsW,
+ localBoundsH,
+ rect);
+ if (dirtyComponent instanceof JComponent) {
+ ((JComponent)dirtyComponent).paintImmediately(
+ rect.x,rect.y,rect.width, rect.height);
}
+ else if (dirtyComponent.isShowing()) {
+ Graphics g = JComponent.safelyGetGraphics(
+ dirtyComponent, dirtyComponent);
+ // If the Graphics goes away, it means someone disposed of
+ // 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;
}
- }
- // 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;
- }
+ }, stack, acc);
}
} finally {
painting = false;
--- a/jdk/src/share/classes/javax/swing/UIDefaults.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/javax/swing/UIDefaults.java Sun Feb 03 23:25:38 2013 +0100
@@ -677,6 +677,8 @@
try {
String className = (String)get(uiClassID);
if (className != null) {
+ ReflectUtil.checkPackageAccess(className);
+
Class cls = (Class)get(className);
if (cls == null) {
if (uiClassLoader == null) {
--- a/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusLookAndFeel.java Sun Feb 03 23:25:38 2013 +0100
@@ -159,7 +159,12 @@
// Store Table ScrollPane Corner Component
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
// installed for Nimbus
--- a/jdk/src/share/classes/sun/applet/AppletPanel.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/applet/AppletPanel.java Sun Feb 03 23:25:38 2013 +0100
@@ -45,6 +45,7 @@
import java.util.Collections;
import java.util.Locale;
import java.util.WeakHashMap;
+import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.EmbeddedFrame;
import sun.awt.SunToolkit;
@@ -448,12 +449,12 @@
// to avoid deadlock.
try {
final AppletPanel p = this;
-
- EventQueue.invokeAndWait(new Runnable() {
- public void run() {
- p.validate();
- }
- });
+ Runnable r = new Runnable() {
+ public void run() {
+ p.validate();
+ }
+ };
+ AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
}
catch(InterruptedException ie) {
}
@@ -478,18 +479,19 @@
try {
final AppletPanel p = this;
final Applet a = applet;
-
- EventQueue.invokeAndWait(new Runnable() {
- public void run() {
- p.validate();
- a.setVisible(true);
+ Runnable r = new Runnable() {
+ public void run() {
+ p.validate();
+ a.setVisible(true);
- // Fix for BugTraq ID 4041703.
- // Set the default focus for an applet.
- if (hasInitialFocus())
- setDefaultFocus();
+ // Fix for BugTraq ID 4041703.
+ // Set the default focus for an applet.
+ if (hasInitialFocus()) {
+ setDefaultFocus();
}
- });
+ }
+ };
+ AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
}
catch(InterruptedException ie) {
}
@@ -512,13 +514,12 @@
// to avoid deadlock.
try {
final Applet a = applet;
-
- EventQueue.invokeAndWait(new Runnable() {
- public void run()
- {
- a.setVisible(false);
- }
- });
+ Runnable r = new Runnable() {
+ public void run() {
+ a.setVisible(false);
+ }
+ };
+ AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
}
catch(InterruptedException ie) {
}
@@ -570,17 +571,14 @@
}
status = APPLET_DISPOSE;
- try
- {
+ try {
final Applet a = applet;
-
- EventQueue.invokeAndWait(new Runnable()
- {
- public void run()
- {
+ Runnable r = new Runnable() {
+ public void run() {
remove(a);
}
- });
+ };
+ AWTAccessor.getEventQueueAccessor().invokeAndWait(applet, r);
}
catch(InterruptedException ie)
{
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java Sun Feb 03 23:25:38 2013 +0100
@@ -34,6 +34,8 @@
import java.awt.event.KeyEvent;
import java.awt.geom.Point2D;
import java.awt.peer.ComponentPeer;
+
+import java.lang.reflect.InvocationTargetException;
import java.security.AccessControlContext;
import java.io.File;
@@ -476,6 +478,12 @@
* appeared.
*/
void wakeup(EventQueue eventQueue, boolean isShutdown);
+
+ /**
+ * Static in EventQueue
+ */
+ void invokeAndWait(Object source, Runnable r)
+ throws InterruptedException, InvocationTargetException;
}
/*
--- a/jdk/src/share/classes/sun/awt/AppContext.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/awt/AppContext.java Sun Feb 03 23:25:38 2013 +0100
@@ -327,21 +327,27 @@
// Before we return the main "system" AppContext, check to
// see if there's an AWTSecurityManager installed. If so,
// allow it to choose the AppContext to return.
- SecurityManager securityManager = System.getSecurityManager();
- if ((securityManager != null) &&
- (securityManager instanceof AWTSecurityManager))
- {
- AWTSecurityManager awtSecMgr = (AWTSecurityManager)securityManager;
- AppContext secAppContext = awtSecMgr.getAppContext();
- if (secAppContext != null) {
- appContext = secAppContext; // Return what we're told
- }
+ AppContext secAppContext = getExecutionAppContext();
+ if (secAppContext != null) {
+ appContext = secAppContext; // Return what we're told
}
}
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.
*
@@ -806,6 +812,21 @@
public boolean isMainAppContext() {
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);
+ }
});
}
}
--- a/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java Sun Feb 03 23:25:38 2013 +0100
@@ -198,7 +198,7 @@
}
this.bandOffset = this.dataOffsets[0];
- verify(false);
+ verify();
}
/**
@@ -857,38 +857,68 @@
}
/**
- * 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.
+ * Verify that the layout parameters are consistent with the data.
+ *
+ * The method verifies whether scanline stride and pixel stride do not
+ * cause an integer overflow during calculation of a position of the pixel
+ * in data buffer. It also verifies whether the data buffer has enough data
+ * to correspond the raster layout attributes.
+ *
+ * @throws RasterFormatException if an integer overflow is detected,
+ * or if data buffer has not enough capacity.
*/
- private void verify (boolean strictCheck) {
- // Make sure data for Raster is in a legal range
- for (int i=0; i < dataOffsets.length; i++) {
+ protected final void verify() {
+ for (int i = 0; i < dataOffsets.length; i++) {
if (dataOffsets[i] < 0) {
- throw new RasterFormatException("Data offsets for band "+i+
- "("+dataOffsets[i]+
- ") must be >= 0");
+ throw new RasterFormatException("Data offsets for band " + i
+ + "(" + dataOffsets[i]
+ + ") must be >= 0");
}
}
int maxSize = 0;
int size;
- for (int i=0; i < numDataElements; i++) {
- size = (height-1)*scanlineStride + (width-1)*pixelStride +
- dataOffsets[i];
+ // we can be sure that width and height are greater than 0
+ if (scanlineStride < 0 ||
+ 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) {
maxSize = size;
}
}
if (data.length < maxSize) {
- throw new RasterFormatException("Data array too small (should be "+
- maxSize+" )");
+ throw new RasterFormatException("Data array too small (should be "
+ + maxSize + " )");
}
}
--- a/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/awt/image/ByteInterleavedRaster.java Sun Feb 03 23:25:38 2013 +0100
@@ -250,7 +250,7 @@
}
}
- verify(false);
+ verify();
}
/**
@@ -1292,33 +1292,6 @@
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() {
return new String ("ByteInterleavedRaster: width = "+width+" height = "
+ height
--- a/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/awt/image/ShortComponentRaster.java Sun Feb 03 23:25:38 2013 +0100
@@ -198,7 +198,7 @@
}
this.bandOffset = this.dataOffsets[0];
- verify(false);
+ verify();
}
/**
@@ -791,38 +791,67 @@
}
/**
- * 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.
+ * Verify that the layout parameters are consistent with the data.
+ *
+ * The method verifies whether scanline stride and pixel stride do not
+ * cause an integer overflow during calculation of a position of the pixel
+ * in data buffer. It also verifies whether the data buffer has enough data
+ * to correspond the raster layout attributes.
+ *
+ * @throws RasterFormatException if an integer overflow is detected,
+ * or if data buffer has not enough capacity.
*/
- private void verify (boolean strictCheck) {
- // Make sure data for Raster is in a legal range
- for (int i=0; i < dataOffsets.length; i++) {
+ protected final void verify() {
+ for (int i = 0; i < dataOffsets.length; i++) {
if (dataOffsets[i] < 0) {
- throw new RasterFormatException("Data offsets for band "+i+
- "("+dataOffsets[i]+
- ") must be >= 0");
+ throw new RasterFormatException("Data offsets for band " + i
+ + "(" + dataOffsets[i]
+ + ") must be >= 0");
}
}
int maxSize = 0;
int size;
- for (int i=0; i < numDataElements; i++) {
- size = (height-1)*scanlineStride + (width-1)*pixelStride +
- dataOffsets[i];
+ // we can be sure that width and height are greater than 0
+ if (scanlineStride < 0 ||
+ 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) {
maxSize = size;
}
}
if (data.length < maxSize) {
- throw new RasterFormatException("Data array too small (should be "+
- maxSize+" )");
+ throw new RasterFormatException("Data array too small (should be "
+ + maxSize + " )");
}
}
--- a/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/awt/image/ShortInterleavedRaster.java Sun Feb 03 23:25:38 2013 +0100
@@ -171,7 +171,7 @@
sampleModel);
}
this.bandOffset = this.dataOffsets[0];
- verify(false);
+ verify();
}
/**
@@ -762,33 +762,6 @@
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() {
return new String ("ShortInterleavedRaster: width = "+width
+" height = " + height
--- a/jdk/src/share/classes/sun/misc/JavaAWTAccess.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/misc/JavaAWTAccess.java Sun Feb 03 23:25:38 2013 +0100
@@ -26,6 +26,14 @@
package sun.misc;
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 void put(Object key, Object value);
public void remove(Object key);
--- a/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java Sun Feb 03 23:25:38 2013 +0100
@@ -41,8 +41,12 @@
private boolean needToReadHeader = true;
- static char CR = '\r';
- static char LF = '\n';
+ final static char CR = '\r';
+ 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 {
assert arr.length >= nchars;
@@ -73,10 +77,14 @@
char[] len_arr = new char [16];
int len_size = 0;
boolean end_of_len = false;
+ int read = 0;
while ((c=in.read())!= -1) {
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");
}
if (gotCR) {
--- a/jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/net/www/http/ChunkedInputStream.java Sun Feb 03 23:25:38 2013 +0100
@@ -125,6 +125,11 @@
*/
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 :-
* chunk-size [ chunk-extension ] CRLF
@@ -290,6 +295,10 @@
break;
}
pos++;
+ if ((pos - rawPos) >= MAX_CHUNK_HEADER_SIZE) {
+ error = true;
+ throw new IOException("Chunk header too long");
+ }
}
if (pos >= rawCount) {
return;
--- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Sun Feb 03 23:25:38 2013 +0100
@@ -421,7 +421,7 @@
synchronized (writeLock) {
ensureOpen();
- InetSocketAddress isa = (InetSocketAddress)target;
+ InetSocketAddress isa = Net.checkAddress(target);
InetAddress ia = isa.getAddress();
if (ia == null)
throw new IOException("Target address not resolved");
@@ -432,9 +432,9 @@
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
if (ia.isMulticastAddress()) {
- sm.checkMulticast(isa.getAddress());
+ sm.checkMulticast(ia);
} else {
- sm.checkConnect(isa.getAddress().getHostAddress(),
+ sm.checkConnect(ia.getHostAddress(),
isa.getPort());
}
}
@@ -454,7 +454,7 @@
return 0;
writerThread = NativeThread.current();
do {
- n = send(fd, src, target);
+ n = send(fd, src, isa);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
synchronized (stateLock) {
@@ -471,7 +471,7 @@
}
}
- private int send(FileDescriptor fd, ByteBuffer src, SocketAddress target)
+ private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target)
throws IOException
{
if (src instanceof DirectBuffer)
@@ -502,7 +502,7 @@
}
private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
- SocketAddress target)
+ InetSocketAddress target)
throws IOException
{
int pos = bb.position();
@@ -514,7 +514,7 @@
int written;
try {
written = send0(preferIPv6, fd, ((DirectBuffer)bb).address() + pos,
- rem, target);
+ rem, target.getAddress(), target.getPort());
} catch (PortUnreachableException pue) {
if (isConnected())
throw pue;
@@ -1116,8 +1116,8 @@
boolean connected)
throws IOException;
- private native int send0(boolean preferIPv6, FileDescriptor fd, long address, int len,
- SocketAddress sa)
+ private native int send0(boolean preferIPv6, FileDescriptor fd, long address,
+ int len, InetAddress addr, int port)
throws IOException;
static {
--- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java Sun Feb 03 23:25:38 2013 +0100
@@ -178,4 +178,29 @@
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);
+ }
+ }
+ }
+ }
+
+ public static final String PROXY_PACKAGE = "sun.proxy";
}
--- a/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java Sun Feb 03 23:25:38 2013 +0100
@@ -153,7 +153,7 @@
returnServerError(e.getMessage());
}
else
- returnClientError("invalid command: " + command);
+ returnClientError("invalid command.");
} catch (Exception e) {
returnServerError("internal error: " + e.getMessage());
}
@@ -225,7 +225,7 @@
try {
port = Integer.parseInt(param);
} catch (NumberFormatException e) {
- throw new CGIClientException("invalid port number: " + param);
+ throw new CGIClientException("invalid port number.");
}
if (port <= 0 || port > 0xFFFF)
throw new CGIClientException("invalid port: " + port);
@@ -293,11 +293,14 @@
"unexpected EOF reading server response");
if (line.toLowerCase().startsWith(key)) {
- // if contentLengthFound is true
- // we should probably do something here
- responseContentLength =
- Integer.parseInt(line.substring(key.length()).trim());
- contentLengthFound = true;
+ if (contentLengthFound) {
+ throw new CGIServerException(
+ "Multiple Content-length entries found.");
+ } else {
+ responseContentLength =
+ Integer.parseInt(line.substring(key.length()).trim());
+ contentLengthFound = true;
+ }
}
} while ((line.length() != 0) &&
(line.charAt(0) != '\r') && (line.charAt(0) != '\n'));
--- a/jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/rmi/transport/proxy/HttpInputStream.java Sun Feb 03 23:25:38 2013 +0100
@@ -70,11 +70,14 @@
throw new EOFException();
if (line.toLowerCase().startsWith(key)) {
- // if contentLengthFound is true
- // we should probably do something here
- bytesLeft =
- Integer.parseInt(line.substring(key.length()).trim());
- contentLengthFound = true;
+ if (contentLengthFound) {
+ throw new IOException(
+ "Multiple Content-length entries found.");
+ } else {
+ bytesLeft =
+ Integer.parseInt(line.substring(key.length()).trim());
+ contentLengthFound = true;
+ }
}
// The idea here is to go past the first blank line.
--- a/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java Sun Feb 03 23:25:38 2013 +0100
@@ -37,6 +37,7 @@
import static sun.security.pkcs11.TemplateManager.*;
import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+import sun.security.util.KeyUtil;
/**
* KeyAgreement implementation class. This class currently supports
@@ -134,6 +135,10 @@
BigInteger p, g, y;
if (key instanceof DHPublicKey) {
DHPublicKey dhKey = (DHPublicKey)key;
+
+ // validate the Diffie-Hellman public key
+ KeyUtil.validate(dhKey);
+
y = dhKey.getY();
DHParameterSpec params = dhKey.getParams();
p = params.getP();
@@ -145,6 +150,10 @@
try {
DHPublicKeySpec spec = kf.engineGetKeySpec(
key, DHPublicKeySpec.class);
+
+ // validate the Diffie-Hellman public key
+ KeyUtil.validate(spec);
+
y = spec.getY();
p = spec.getP();
g = spec.getG();
--- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Sun Feb 03 23:25:38 2013 +0100
@@ -129,9 +129,8 @@
*/
@Override
void processMessage(byte type, int messageLen) throws IOException {
- if (state > type
- && (type != HandshakeMessage.ht_hello_request
- && state != HandshakeMessage.ht_client_hello)) {
+ if (state >= type
+ && (type != HandshakeMessage.ht_hello_request)) {
throw new SSLProtocolException(
"Handshake message sequence violation, " + type);
}
@@ -194,8 +193,12 @@
}
break;
case K_DH_ANON:
- this.serverKeyExchange(new DH_ServerKeyExchange(
+ try {
+ this.serverKeyExchange(new DH_ServerKeyExchange(
input, protocolVersion));
+ } catch (GeneralSecurityException e) {
+ throwSSLException("Server key", e);
+ }
break;
case K_DHE_DSS:
case K_DHE_RSA:
@@ -921,7 +924,7 @@
case K_DHE_RSA:
case K_DHE_DSS:
case K_DH_ANON:
- preMasterSecret = dh.getAgreedSecret(serverDH);
+ preMasterSecret = dh.getAgreedSecret(serverDH, true);
break;
case K_ECDHE_RSA:
case K_ECDHE_ECDSA:
--- a/jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java Sun Feb 03 23:25:38 2013 +0100
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
import java.io.IOException;
import java.io.PrintStream;
import java.math.BigInteger;
-
+import javax.net.ssl.SSLHandshakeException;
/*
* Message used by clients to send their Diffie-Hellman public
@@ -51,7 +51,7 @@
private byte dh_Yc[]; // 1 to 2^16 -1 bytes
BigInteger getClientPublicKey() {
- return new BigInteger(1, dh_Yc);
+ return dh_Yc == null ? null : new BigInteger(1, dh_Yc);
}
/*
@@ -73,7 +73,14 @@
* but that's what the protocol spec requires.)
*/
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
@@ -87,7 +94,9 @@
@Override
void send(HandshakeOutStream s) throws IOException {
- s.putBytes16(dh_Yc);
+ if (dh_Yc != null && dh_Yc.length != 0) {
+ s.putBytes16(dh_Yc);
+ }
}
@Override
--- a/jdk/src/share/classes/sun/security/ssl/DHCrypt.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/DHCrypt.java Sun Feb 03 23:25:38 2013 +0100
@@ -1,5 +1,5 @@
/*
- * 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,12 +28,15 @@
import java.math.BigInteger;
import java.security.*;
-
+import java.io.IOException;
+import javax.net.ssl.SSLHandshakeException;
import javax.crypto.SecretKey;
import javax.crypto.KeyAgreement;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.*;
+import sun.security.util.KeyUtil;
+
/**
* This class implements the Diffie-Hellman key exchange algorithm.
* D-H means combining your private key with your partners public key to
@@ -54,7 +57,8 @@
* . if we are server, call DHCrypt(keyLength,random). This generates
* an ephemeral keypair of the request length.
* . 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
* . receive peers ephemeral public key
* . call getAgreedSecret() to calculate the shared secret
@@ -83,6 +87,9 @@
// public component of our key, X = (g ^ x) mod p
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.
*/
@@ -90,9 +97,12 @@
try {
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
kpg.initialize(keyLength, random);
- KeyPair kp = kpg.generateKeyPair();
- privateKey = kp.getPrivate();
- DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
+
+ DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
+ if (spec == null) {
+ throw new RuntimeException("Could not generate DH keypair");
+ }
+
publicValue = spec.getY();
modulus = spec.getP();
base = spec.getG();
@@ -115,20 +125,25 @@
KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
DHParameterSpec params = new DHParameterSpec(modulus, base);
kpg.initialize(params, random);
- KeyPair kp = kpg.generateKeyPair();
- privateKey = kp.getPrivate();
- DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
+
+ DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
+ if (spec == null) {
+ throw new RuntimeException("Could not generate DH keypair");
+ }
+
publicValue = spec.getY();
} catch (GeneralSecurityException e) {
throw new RuntimeException("Could not generate DH keypair", e);
}
}
+
static DHPublicKeySpec getDHPublicKeySpec(PublicKey key) {
if (key instanceof DHPublicKey) {
DHPublicKey dhKey = (DHPublicKey)key;
DHParameterSpec params = dhKey.getParams();
- return new DHPublicKeySpec(dhKey.getY(), params.getP(), params.getG());
+ return new DHPublicKeySpec(dhKey.getY(),
+ params.getP(), params.getG());
}
try {
KeyFactory factory = JsseJce.getKeyFactory("DH");
@@ -166,17 +181,32 @@
* <P>It is illegal to call this member function if the private key
* has not been set (or generated).
*
- * @param peerPublicKey the peer's public key.
- * @returns the secret, which is an unsigned big-endian integer
- * the same size as the Diffie-Hellman modulus.
+ * @param peerPublicKey the peer's public key.
+ * @param keyIsValidated whether the {@code peerPublicKey} has beed
+ * 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 {
KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
DHPublicKeySpec spec =
new DHPublicKeySpec(peerPublicValue, modulus, base);
PublicKey publicKey = kf.generatePublic(spec);
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.doPhase(publicKey, true);
return ka.generateSecret("TlsPremasterSecret");
@@ -185,4 +215,33 @@
}
}
+ // 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;
+ }
}
--- a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java Sun Feb 03 23:25:38 2013 +0100
@@ -41,12 +41,14 @@
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
+import javax.crypto.spec.DHPublicKeySpec;
import javax.net.ssl.*;
import sun.security.internal.spec.TlsPrfParameterSpec;
import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.PRF.*;
+import sun.security.util.KeyUtil;
/**
* Many data structures are involved in the handshake messages. These
@@ -712,6 +714,7 @@
this.protocolVersion = protocolVersion;
this.preferableSignatureAlgorithm = null;
+ // The DH key has been validated in the constructor of DHCrypt.
setValues(obj);
signature = null;
}
@@ -728,6 +731,7 @@
this.protocolVersion = protocolVersion;
+ // The DH key has been validated in the constructor of DHCrypt.
setValues(obj);
Signature sig;
@@ -754,7 +758,8 @@
* DH_anon key exchange
*/
DH_ServerKeyExchange(HandshakeInStream input,
- ProtocolVersion protocolVersion) throws IOException {
+ ProtocolVersion protocolVersion)
+ throws IOException, GeneralSecurityException {
this.protocolVersion = protocolVersion;
this.preferableSignatureAlgorithm = null;
@@ -762,6 +767,10 @@
dh_p = input.getBytes16();
dh_g = 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;
}
@@ -782,6 +791,9 @@
dh_p = input.getBytes16();
dh_g = 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
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
--- a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Sun Feb 03 23:25:38 2013 +0100
@@ -34,7 +34,7 @@
import javax.net.ssl.*;
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
@@ -191,7 +191,7 @@
"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 (debug != null && Debug.isOn("handshake")) {
System.out.println(
--- a/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java Sun Feb 03 23:25:38 2013 +0100
@@ -150,7 +150,7 @@
// In SSLv3 and TLS, messages follow strictly increasing
// numerical order _except_ for one annoying special case.
//
- if ((state > type)
+ if ((state >= type)
&& (state != HandshakeMessage.ht_client_key_exchange
&& type != HandshakeMessage.ht_certificate_verify)) {
throw new SSLProtocolException(
@@ -250,13 +250,15 @@
}
//
- // Move the state machine forward except for that annoying
- // special case. This means that clients could send extra
- // cert verify messages; not a problem so long as all of
- // them actually check out.
+ // Move state machine forward if the message handling
+ // code didn't already do so
//
- if (state < type && type != HandshakeMessage.ht_certificate_verify) {
- state = type;
+ if (state < type) {
+ if(type == HandshakeMessage.ht_certificate_verify) {
+ state = type + 2; // an annoying special case
+ } else {
+ state = type;
+ }
}
}
@@ -1406,7 +1408,7 @@
if (debug != null && Debug.isOn("handshake")) {
mesg.print(System.out);
}
- return dh.getAgreedSecret(mesg.getClientPublicKey());
+ return dh.getAgreedSecret(mesg.getClientPublicKey(), false);
}
private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg)
--- a/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java Sun Feb 03 23:25:38 2013 +0100
@@ -38,7 +38,7 @@
import java.util.Collections;
import java.util.ArrayList;
-import sun.security.util.KeyLength;
+import sun.security.util.KeyUtil;
/**
* Signature and hash algorithm.
@@ -274,7 +274,7 @@
* If key size is less than 512, the digest length should be
* less than or equal to 20 bytes.
*/
- int keySize = KeyLength.getKeySize(signingKey);
+ int keySize = KeyUtil.getKeySize(signingKey);
if (keySize >= 768) {
maxDigestLength = HashAlgorithm.SHA512.length;
} else if ((keySize >= 512) && (keySize < 768)) {
--- a/jdk/src/share/classes/sun/security/util/DerIndefLenConverter.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/security/util/DerIndefLenConverter.java Sun Feb 03 23:25:38 2013 +0100
@@ -325,6 +325,10 @@
}
}
+ if (unresolved != 0) {
+ throw new IOException("not all indef len BER resolved");
+ }
+
newData = new byte[dataSize + numOfTotalLenBytes + unused];
dataPos=0; newDataPos=0; index=0;
--- a/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Sun Feb 03 23:25:38 2013 +0100
@@ -440,7 +440,7 @@
// Does this key constraint disable the specified key?
public boolean disables(Key key) {
- int size = KeyLength.getKeySize(key);
+ int size = KeyUtil.getKeySize(key);
if (size == 0) {
return true; // we don't allow any key of size 0.
--- a/jdk/src/share/classes/sun/security/util/KeyLength.java Thu Jan 31 17:04:47 2013 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.util;
-
-import java.security.Key;
-import java.security.PrivilegedAction;
-import java.security.AccessController;
-import java.security.interfaces.ECKey;
-import java.security.interfaces.RSAKey;
-import java.security.interfaces.DSAKey;
-import javax.crypto.SecretKey;
-import javax.crypto.interfaces.DHKey;
-
-/**
- * A utility class to get key length
- */
-public final class KeyLength {
-
- /**
- * Returns the key size of the given key object in bits.
- *
- * @param key the key object, cannot be null
- * @return the key size of the given key object in bits, or -1 if the
- * key size is not accessible
- */
- final public static int getKeySize(Key key) {
- int size = -1;
-
- if (key instanceof Length) {
- try {
- Length ruler = (Length)key;
- size = ruler.length();
- } catch (UnsupportedOperationException usoe) {
- // ignore the exception
- }
-
- if (size >= 0) {
- return size;
- }
- }
-
- // try to parse the length from key specification
- if (key instanceof SecretKey) {
- SecretKey sk = (SecretKey)key;
- String format = sk.getFormat();
- if ("RAW".equals(format) && sk.getEncoded() != null) {
- size = (sk.getEncoded().length * 8);
- } // Otherwise, it may be a unextractable key of PKCS#11, or
- // a key we are not able to handle.
- } else if (key instanceof RSAKey) {
- RSAKey pubk = (RSAKey)key;
- size = pubk.getModulus().bitLength();
- } else if (key instanceof ECKey) {
- ECKey pubk = (ECKey)key;
- size = pubk.getParams().getOrder().bitLength();
- } else if (key instanceof DSAKey) {
- DSAKey pubk = (DSAKey)key;
- size = pubk.getParams().getP().bitLength();
- } else if (key instanceof DHKey) {
- DHKey pubk = (DHKey)key;
- size = pubk.getParams().getP().bitLength();
- } // Otherwise, it may be a unextractable key of PKCS#11, or
- // a key we are not able to handle.
-
- return size;
- }
-}
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/util/KeyUtil.java Sun Feb 03 23:25:38 2013 +0100
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.util;
+
+import java.security.Key;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.InvalidKeyException;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.DSAKey;
+import java.security.spec.KeySpec;
+import javax.crypto.SecretKey;
+import javax.crypto.interfaces.DHKey;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.DHPublicKeySpec;
+import java.math.BigInteger;
+
+/**
+ * A utility class to get key length, valiate keys, etc.
+ */
+public final class KeyUtil {
+
+ /**
+ * Returns the key size of the given key object in bits.
+ *
+ * @param key the key object, cannot be null
+ * @return the key size of the given key object in bits, or -1 if the
+ * key size is not accessible
+ */
+ public static final int getKeySize(Key key) {
+ int size = -1;
+
+ if (key instanceof Length) {
+ try {
+ Length ruler = (Length)key;
+ size = ruler.length();
+ } catch (UnsupportedOperationException usoe) {
+ // ignore the exception
+ }
+
+ if (size >= 0) {
+ return size;
+ }
+ }
+
+ // try to parse the length from key specification
+ if (key instanceof SecretKey) {
+ SecretKey sk = (SecretKey)key;
+ String format = sk.getFormat();
+ if ("RAW".equals(format) && sk.getEncoded() != null) {
+ size = (sk.getEncoded().length * 8);
+ } // Otherwise, it may be a unextractable key of PKCS#11, or
+ // a key we are not able to handle.
+ } else if (key instanceof RSAKey) {
+ RSAKey pubk = (RSAKey)key;
+ size = pubk.getModulus().bitLength();
+ } else if (key instanceof ECKey) {
+ ECKey pubk = (ECKey)key;
+ size = pubk.getParams().getOrder().bitLength();
+ } else if (key instanceof DSAKey) {
+ DSAKey pubk = (DSAKey)key;
+ size = pubk.getParams().getP().bitLength();
+ } else if (key instanceof DHKey) {
+ DHKey pubk = (DHKey)key;
+ size = pubk.getParams().getP().bitLength();
+ } // Otherwise, it may be a unextractable key of PKCS#11, or
+ // a key we are not able to handle.
+
+ return size;
+ }
+
+ /**
+ * Returns whether the key is valid or not.
+ * <P>
+ * Note that this method is only apply to DHPublicKey at present.
+ *
+ * @param publicKey
+ * the key object, cannot be null
+ *
+ * @throws NullPointerException if {@code publicKey} is null
+ * @throws InvalidKeyException if {@code publicKey} is invalid
+ */
+ public static final void validate(Key key)
+ throws InvalidKeyException {
+ if (key == null) {
+ throw new NullPointerException(
+ "The key to be validated cannot be null");
+ }
+
+ if (key instanceof DHPublicKey) {
+ validateDHPublicKey((DHPublicKey)key);
+ }
+ }
+
+
+ /**
+ * Returns whether the key spec is valid or not.
+ * <P>
+ * Note that this method is only apply to DHPublicKeySpec at present.
+ *
+ * @param keySpec
+ * the key spec object, cannot be null
+ *
+ * @throws NullPointerException if {@code keySpec} is null
+ * @throws InvalidKeyException if {@code keySpec} is invalid
+ */
+ public static final void validate(KeySpec keySpec)
+ throws InvalidKeyException {
+ if (keySpec == null) {
+ throw new NullPointerException(
+ "The key spec to be validated cannot be null");
+ }
+
+ if (keySpec instanceof DHPublicKeySpec) {
+ validateDHPublicKey((DHPublicKeySpec)keySpec);
+ }
+ }
+
+ /**
+ * Returns whether the specified provider is Oracle provider or not.
+ * <P>
+ * Note that this method is only apply to SunJCE and SunPKCS11 at present.
+ *
+ * @param providerName
+ * the provider name
+ * @return true if, and only if, the provider of the specified
+ * {@code providerName} is Oracle provider
+ */
+ public static final boolean isOracleJCEProvider(String providerName) {
+ return providerName != null && (providerName.equals("SunJCE") ||
+ providerName.startsWith("SunPKCS11"));
+ }
+
+ /**
+ * Returns whether the Diffie-Hellman public key is valid or not.
+ *
+ * Per RFC 2631 and NIST SP800-56A, the following algorithm is used to
+ * validate Diffie-Hellman public keys:
+ * 1. Verify that y lies within the interval [2,p-1]. If it does not,
+ * the key is invalid.
+ * 2. Compute y^q mod p. If the result == 1, the key is valid.
+ * Otherwise the key is invalid.
+ */
+ private static void validateDHPublicKey(DHPublicKey publicKey)
+ throws InvalidKeyException {
+ DHParameterSpec paramSpec = publicKey.getParams();
+
+ BigInteger p = paramSpec.getP();
+ BigInteger g = paramSpec.getG();
+ BigInteger y = publicKey.getY();
+
+ validateDHPublicKey(p, g, y);
+ }
+
+ private static void validateDHPublicKey(DHPublicKeySpec publicKeySpec)
+ throws InvalidKeyException {
+ validateDHPublicKey(publicKeySpec.getP(),
+ publicKeySpec.getG(), publicKeySpec.getY());
+ }
+
+ private static void validateDHPublicKey(BigInteger p,
+ BigInteger g, BigInteger y) throws InvalidKeyException {
+
+ // For better interoperability, the interval is limited to [2, p-2].
+ BigInteger leftOpen = BigInteger.ONE;
+ BigInteger rightOpen = p.subtract(BigInteger.ONE);
+ if (y.compareTo(leftOpen) <= 0) {
+ throw new InvalidKeyException(
+ "Diffie-Hellman public key is too small");
+ }
+ if (y.compareTo(rightOpen) >= 0) {
+ throw new InvalidKeyException(
+ "Diffie-Hellman public key is too large");
+ }
+
+ // Don't bother to check against the y^q mod p if safe primes are used.
+ }
+}
+
--- a/jdk/src/share/lib/security/java.security-macosx Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/lib/security/java.security-macosx Sun Feb 03 23:25:38 2013 +0100
@@ -146,7 +146,14 @@
# passed to checkPackageAccess unless the
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
-package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
+package.access=sun.,\
+ com.sun.xml.internal.,\
+ com.sun.imageio.,\
+ com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.xalan.internal.utils.,\
+ com.sun.org.glassfish.external.,\
+ com.sun.org.glassfish.gmbal.,\
+ apple.
#
# List of comma-separated packages that start with or equal this string
@@ -158,7 +165,14 @@
# by default, none of the class loaders supplied with the JDK call
# checkPackageDefinition.
#
-package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,apple.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
+package.definition=sun.,\
+ com.sun.xml.internal.,\
+ com.sun.imageio.,\
+ com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.xalan.internal.utils.,\
+ com.sun.org.glassfish.external.,\
+ com.sun.org.glassfish.gmbal.,\
+ apple.
#
# Determines whether this properties file can be appended to
--- a/jdk/src/share/lib/security/java.security-solaris Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/lib/security/java.security-solaris Sun Feb 03 23:25:38 2013 +0100
@@ -147,7 +147,13 @@
# passed to checkPackageAccess unless the
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
-package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
+package.access=sun.,\
+ com.sun.xml.internal.,\
+ com.sun.imageio.,\
+ com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.xalan.internal.utils.,\
+ com.sun.org.glassfish.external.,\
+ com.sun.org.glassfish.gmbal.
#
# List of comma-separated packages that start with or equal this string
@@ -159,7 +165,13 @@
# by default, none of the class loaders supplied with the JDK call
# checkPackageDefinition.
#
-package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
+package.definition=sun.,\
+ com.sun.xml.internal.,\
+ com.sun.imageio.,\
+ com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.xalan.internal.utils.,\
+ com.sun.org.glassfish.external.,\
+ com.sun.org.glassfish.gmbal.
#
# Determines whether this properties file can be appended to
--- a/jdk/src/share/lib/security/java.security-windows Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/lib/security/java.security-windows Sun Feb 03 23:25:38 2013 +0100
@@ -146,7 +146,13 @@
# passed to checkPackageAccess unless the
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
-package.access=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
+package.access=sun.,\
+ com.sun.xml.internal.,\
+ com.sun.imageio.,\
+ com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.xalan.internal.utils.,\
+ com.sun.org.glassfish.external.,\
+ com.sun.org.glassfish.gmbal.
#
# List of comma-separated packages that start with or equal this string
@@ -158,7 +164,13 @@
# by default, none of the class loaders supplied with the JDK call
# checkPackageDefinition.
#
-package.definition=sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.org.apache.xerces.internal.utils.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.glassfish.external.,com.sun.org.glassfish.gmbal.,jdk.internal.
+package.definition=sun.,\
+ com.sun.xml.internal.,\
+ com.sun.imageio.,\
+ com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.xalan.internal.utils.,\
+ com.sun.org.glassfish.external.,\
+ com.sun.org.glassfish.gmbal.
#
# Determines whether this properties file can be appended to
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.cpp Sun Feb 03 23:25:38 2013 +0100
@@ -187,6 +187,10 @@
entry* band::getRefCommon(cpindex* ix_, bool nullOKwithCaller) {
CHECK_0;
+ if (ix_ == NULL) {
+ abort("no index");
+ return NULL;
+ }
assert(ix_->ixTag == ixTag
|| ((ixTag == CONSTANT_All ||
ixTag == CONSTANT_LoadableValue ||
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/bands.h Sun Feb 03 23:25:38 2013 +0100
@@ -99,8 +99,8 @@
int getByte() { assert(ix == null); return vs[0].getByte(); }
int getInt() { assert(ix == null); return vs[0].getInt(); }
- entry* getRefN() { assert(ix != null); return getRefCommon(ix, true); }
- entry* getRef() { assert(ix != null); return getRefCommon(ix, false); }
+ entry* getRefN() { return getRefCommon(ix, true); }
+ entry* getRef() { return getRefCommon(ix, false); }
entry* getRefUsing(cpindex* ix2)
{ assert(ix == null); return getRefCommon(ix2, true); }
entry* getRefCommon(cpindex* ix, bool nullOK);
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/jni.cpp Sun Feb 03 23:25:38 2013 +0100
@@ -50,6 +50,7 @@
static jmethodID currentInstMID;
static jmethodID readInputMID;
static jclass NIclazz;
+static jmethodID getUnpackerPtrMID;
static char* dbg = null;
@@ -60,8 +61,8 @@
static unpacker* get_unpacker(JNIEnv *env, jobject pObj, bool noCreate=false) {
unpacker* uPtr;
- uPtr = (unpacker*)jlong2ptr(env->GetLongField(pObj, unpackerPtrFID));
- //fprintf(stderr, "get_unpacker(%p) uPtr=%p\n", pObj, uPtr);
+ jlong p = env->CallLongMethod(pObj, getUnpackerPtrMID);
+ uPtr = (unpacker*)jlong2ptr(p);
if (uPtr == null) {
if (noCreate) return null;
uPtr = new unpacker();
@@ -94,11 +95,15 @@
if (env == null)
return null;
jobject pObj = env->CallStaticObjectMethod(NIclazz, currentInstMID);
- //fprintf(stderr, "get_unpacker() pObj=%p\n", pObj);
- if (pObj == null)
- return null;
- // Got pObj and env; now do it the easy way.
- return get_unpacker(env, pObj);
+ //fprintf(stderr, "get_unpacker0() pObj=%p\n", pObj);
+ if (pObj != null) {
+ // Got pObj and env; now do it the easy way.
+ return get_unpacker(env, pObj);
+ }
+ // this should really not happen, if it does something is seriously
+ // wrong throw an exception
+ THROW_IOE(ERROR_INTERNAL);
+ return null;
}
static void free_unpacker(JNIEnv *env, jobject pObj, unpacker* uPtr) {
@@ -127,18 +132,23 @@
JNIEXPORT void JNICALL
Java_com_sun_java_util_jar_pack_NativeUnpack_initIDs(JNIEnv *env, jclass clazz) {
+#ifndef PRODUCT
dbg = getenv("DEBUG_ATTACH");
while( dbg != null) { sleep(10); }
+#endif
NIclazz = (jclass) env->NewGlobalRef(clazz);
unpackerPtrFID = env->GetFieldID(clazz, "unpackerPtr", "J");
currentInstMID = env->GetStaticMethodID(clazz, "currentInstance",
"()Ljava/lang/Object;");
readInputMID = env->GetMethodID(clazz, "readInputFn",
"(Ljava/nio/ByteBuffer;J)J");
+ getUnpackerPtrMID = env->GetMethodID(clazz, "getUnpackerPtr", "()J");
+
if (unpackerPtrFID == null ||
currentInstMID == null ||
readInputMID == null ||
- NIclazz == null) {
+ NIclazz == null ||
+ getUnpackerPtrMID == null) {
THROW_IOE("cannot init class members");
}
}
@@ -146,8 +156,13 @@
JNIEXPORT jlong JNICALL
Java_com_sun_java_util_jar_pack_NativeUnpack_start(JNIEnv *env, jobject pObj,
jobject pBuf, jlong offset) {
- unpacker* uPtr = get_unpacker(env, pObj);
-
+ // try to get the unpacker pointer the hard way first, we do this to ensure
+ // valid object pointers and env is intact, if not now is good time to bail.
+ unpacker* uPtr = get_unpacker();
+ //fprintf(stderr, "start(%p) uPtr=%p initializing\n", pObj, uPtr);
+ if (uPtr == null) {
+ return -1;
+ }
// redirect our io to the default log file or whatever.
uPtr->redirect_stdio();
@@ -163,7 +178,12 @@
else
{ buf = (char*)buf + (size_t)offset; buflen -= (size_t)offset; }
}
-
+ // before we start off we make sure there is no other error by the time we
+ // get here
+ if (uPtr->aborting()) {
+ THROW_IOE(uPtr->get_abort_message());
+ return 0;
+ }
uPtr->start(buf, buflen);
if (uPtr->aborting()) {
THROW_IOE(uPtr->get_abort_message());
@@ -230,11 +250,14 @@
// We have fetched all the files.
// Now swallow up any remaining input.
- if (uPtr->input_remaining() == 0)
+ if (uPtr->input_remaining() == 0) {
return null;
- else
- return env->NewDirectByteBuffer(uPtr->input_scan(),
- uPtr->input_remaining());
+ } else {
+ bytes remaining_bytes;
+ remaining_bytes.malloc(uPtr->input_remaining());
+ remaining_bytes.copyFrom(uPtr->input_scan(), uPtr->input_remaining());
+ return env->NewDirectByteBuffer(remaining_bytes.ptr, remaining_bytes.len);
+ }
}
JNIEXPORT jlong JNICALL
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp Sun Feb 03 23:25:38 2013 +0100
@@ -281,11 +281,13 @@
}
inline cpindex* cpool::getFieldIndex(entry* classRef) {
+ if (classRef == NULL) { abort("missing class reference"); return NULL; }
assert(classRef->tagMatches(CONSTANT_Class));
assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]);
return &member_indexes[classRef->inord*2+0];
}
inline cpindex* cpool::getMethodIndex(entry* classRef) {
+ if (classRef == NULL) { abort("missing class reference"); return NULL; }
assert(classRef->tagMatches(CONSTANT_Class));
assert((uint)classRef->inord < (uint)tag_count[CONSTANT_Class]);
return &member_indexes[classRef->inord*2+1];
@@ -1291,6 +1293,7 @@
entry& e = cpMap[i];
e.refs = U_NEW(entry*, e.nrefs = 2);
e.refs[0] = cp_band1.getRef();
+ CHECK;
e.refs[1] = cp_band2.getRef();
CHECK;
}
@@ -1371,6 +1374,7 @@
entry& e = cpMap[i];
e.refs = U_NEW(entry*, e.nrefs = 1);
e.refs[0] = cp_MethodType.getRef();
+ CHECK;
}
}
@@ -2106,6 +2110,7 @@
int attrc = ADH_BYTE_CONTEXT(header);
int idx = ADH_BYTE_INDEX(header);
entry* name = attr_definition_name.getRef();
+ CHECK;
entry* layout = attr_definition_layout.getRef();
CHECK;
attr_defs[attrc].defineLayout(idx, name, layout->value.b.strval());
@@ -2210,7 +2215,9 @@
if (ics[i].name == NO_ENTRY_YET) {
// Long form.
ics[i].outer = ic_outer_class.getRefN();
+ CHECK;
ics[i].name = ic_name.getRefN();
+ CHECK;
} else {
// Fill in outer and name based on inner.
bytes& n = ics[i].inner->value.b;
@@ -2733,6 +2740,7 @@
e = b.getRefUsing(cp.getKQIndex());
else
e = b.getRefN();
+ CHECK;
switch (b.le_len) {
case 0: break;
case 1: putu1ref(e); break;
@@ -3118,7 +3126,7 @@
void unpacker::read_bands() {
byte* rp0 = rp;
-
+ CHECK;
read_file_header();
CHECK;
@@ -3880,10 +3888,12 @@
// packed file and len is the length of the buffer.
// If null, the callback is used to fill an internal buffer.
void unpacker::start(void* packptr, size_t len) {
+ CHECK;
NOT_PRODUCT(debug_u = this);
if (packptr != null && len != 0) {
inbytes.set((byte*) packptr, len);
}
+ CHECK;
read_bands();
}
@@ -4015,6 +4025,7 @@
NOT_PRODUCT(bc_superfield.setIndex(null));
NOT_PRODUCT(bc_supermethod.setIndex(null));
}
+ CHECK;
for (int curIP = 0; ; curIP++) {
int curPC = (int)(wpoffset() - codeBase);
@@ -4128,7 +4139,8 @@
int coding = bc_initref.getInt();
// Find the nth overloading of <init> in classRef.
entry* ref = null;
- cpindex* ix = (classRef == null)? null: cp.getMethodIndex(classRef);
+ cpindex* ix = cp.getMethodIndex(classRef);
+ CHECK;
for (int j = 0, which_init = 0; ; j++) {
ref = (ix == null)? null: ix->get(j);
if (ref == null) break; // oops, bad input
@@ -4405,6 +4417,7 @@
case ADH_BYTE(ATTR_CONTEXT_CLASS, CLASS_ATTR_EnclosingMethod):
aname = cp.sym[cpool::s_EnclosingMethod];
putref(class_EnclosingMethod_RC.getRefN());
+ CHECK_0;
putref(class_EnclosingMethod_RDN.getRefN());
break;
@@ -4423,6 +4436,7 @@
putu2(count = method_Exceptions_N.getInt());
for (j = 0; j < count; j++) {
putref(method_Exceptions_RC.getRefN());
+ CHECK_0;
}
break;
@@ -4455,16 +4469,18 @@
// (253) [(1)(2)(2)]
// (254) [(1)(2)(2)(2)]
putu2(code_StackMapTable_offset.getInt());
+ CHECK_0;
for (int k = (tag - 251); k > 0; k--) {
put_stackmap_type();
+ CHECK_0;
}
} else {
// (255) [(1)NH[(2)]NH[(2)]]
putu2(code_StackMapTable_offset.getInt());
putu2(j2 = code_StackMapTable_local_N.getInt());
- while (j2-- > 0) put_stackmap_type();
+ while (j2-- > 0) {put_stackmap_type(); CHECK_0;}
putu2(j2 = code_StackMapTable_stack_N.getInt());
- while (j2-- > 0) put_stackmap_type();
+ while (j2-- > 0) {put_stackmap_type(); CHECK_0;}
}
}
break;
@@ -4488,7 +4504,9 @@
bii += code_LocalVariableTable_span_O.getInt();
putu2(to_bci(bii) - bci);
putref(code_LocalVariableTable_name_RU.getRefN());
+ CHECK_0;
putref(code_LocalVariableTable_type_RS.getRefN());
+ CHECK_0;
putu2(code_LocalVariableTable_slot.getInt());
}
break;
@@ -4503,7 +4521,9 @@
bii += code_LocalVariableTypeTable_span_O.getInt();
putu2(to_bci(bii) - bci);
putref(code_LocalVariableTypeTable_name_RU.getRefN());
+ CHECK_0;
putref(code_LocalVariableTypeTable_type_RS.getRefN());
+ CHECK_0;
putu2(code_LocalVariableTypeTable_slot.getInt());
}
break;
@@ -4531,7 +4551,7 @@
break;
}
}
-
+ CHECK_0;
if (aname == null) {
// Unparse a compressor-defined attribute.
layout_definition* lo = ad.getLayout(idx);
@@ -4687,7 +4707,9 @@
flags &= ~ACC_IC_LONG_FORM; // clear high bit if set to get clean zero
extra_ic.flags = flags;
extra_ic.outer = class_InnerClasses_outer_RCN.getRefN();
+ CHECK_0;
extra_ic.name = class_InnerClasses_name_RUN.getRefN();
+ CHECK_0;
// Detect if this is an exact copy of the global tuple.
if (global_ic != null) {
if (global_ic->flags != extra_ic.flags ||
@@ -4796,6 +4818,7 @@
julong indexMask = ad.flagIndexMask();
cur_class = class_this.getRef();
+ CHECK;
cur_super = class_super.getRef();
CHECK;
@@ -4809,6 +4832,7 @@
putu2(num = class_interface_count.getInt());
for (i = 0; i < num; i++) {
putref(class_interface.getRef());
+ CHECK;
}
write_members(class_field_count.getInt(), ATTR_CONTEXT_FIELD);
--- a/jdk/src/share/native/sun/awt/image/awt_parseImage.c Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.c Sun Feb 03 23:25:38 2013 +0100
@@ -114,6 +114,62 @@
return status;
}
+/* Verifies whether the channel offsets are sane and correspond to the type of
+ * the raster.
+ *
+ * Return value:
+ * 0: Failure: channel offsets are invalid
+ * 1: Success
+ */
+static int checkChannelOffsets(RasterS_t *rasterP, int dataArrayLength) {
+ int i, lastPixelOffset, lastScanOffset;
+ switch (rasterP->rasterType) {
+ case COMPONENT_RASTER_TYPE:
+ if (!SAFE_TO_MULT(rasterP->height, rasterP->scanlineStride)) {
+ return 0;
+ }
+ if (!SAFE_TO_MULT(rasterP->width, rasterP->pixelStride)) {
+ return 0;
+ }
+
+ lastScanOffset = (rasterP->height - 1) * rasterP->scanlineStride;
+ lastPixelOffset = (rasterP->width - 1) * rasterP->pixelStride;
+
+
+ if (!SAFE_TO_ADD(lastPixelOffset, lastScanOffset)) {
+ return 0;
+ }
+
+ lastPixelOffset += lastScanOffset;
+
+ for (i = 0; i < rasterP->numDataElements; i++) {
+ int off = rasterP->chanOffsets[i];
+ int size = lastPixelOffset + off;
+
+ if (off < 0 || !SAFE_TO_ADD(lastPixelOffset, off)) {
+ return 0;
+ }
+
+ if (size < lastPixelOffset || size >= dataArrayLength) {
+ // an overflow, or insufficient buffer capacity
+ return 0;
+ }
+ }
+ return 1;
+ case BANDED_RASTER_TYPE:
+ // NB:caller does not support the banded rasters yet,
+ // so this branch of the code must be re-defined in
+ // order to provide valid criteria for the data offsets
+ // verification, when/if banded rasters will be supported.
+ // At the moment, we prohibit banded rasters as well.
+ return 0;
+ default:
+ // PACKED_RASTER_TYPE: does not support channel offsets
+ // UNKNOWN_RASTER_TYPE: should not be used, likely indicates an error
+ return 0;
+ }
+}
+
/* Parse the raster. All of the raster information is returned in the
* rasterP structure.
*
@@ -125,7 +181,6 @@
int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) {
jobject joffs = NULL;
/* int status;*/
- int isDiscrete = TRUE;
if (JNU_IsNull(env, jraster)) {
JNU_ThrowNullPointerException(env, "null Raster object");
@@ -155,6 +210,9 @@
return -1;
}
+ // make sure that the raster type is initialized
+ rasterP->rasterType = UNKNOWN_RASTER_TYPE;
+
if (rasterP->numBands <= 0 ||
rasterP->numBands > MAX_NUMBANDS)
{
@@ -165,9 +223,14 @@
return 0;
}
+ rasterP->sppsm.isUsed = 0;
+
if ((*env)->IsInstanceOf(env, rasterP->jsampleModel,
(*env)->FindClass(env,"java/awt/image/SinglePixelPackedSampleModel"))) {
jobject jmask, joffs, jnbits;
+
+ rasterP->sppsm.isUsed = 1;
+
rasterP->sppsm.maxBitSize = (*env)->GetIntField(env,
rasterP->jsampleModel,
g_SPPSMmaxBitID);
@@ -254,7 +317,6 @@
}
rasterP->chanOffsets[0] = (*env)->GetIntField(env, jraster, g_BPRdataBitOffsetID);
rasterP->dataType = BYTE_DATA_TYPE;
- isDiscrete = FALSE;
}
else {
rasterP->type = sun_awt_image_IntegerComponentRaster_TYPE_CUSTOM;
@@ -265,7 +327,19 @@
return 0;
}
- if (isDiscrete) {
+ // do basic validation of the raster structure
+ if (rasterP->width <= 0 || rasterP->height <= 0 ||
+ rasterP->pixelStride <= 0 || rasterP->scanlineStride <= 0)
+ {
+ // invalid raster
+ return -1;
+ }
+
+ // channel (data) offsets
+ switch (rasterP->rasterType) {
+ case COMPONENT_RASTER_TYPE:
+ case BANDED_RASTER_TYPE: // note that this routine does not support banded rasters at the moment
+ // get channel (data) offsets
rasterP->chanOffsets = NULL;
if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) {
rasterP->chanOffsets =
@@ -278,10 +352,21 @@
}
(*env)->GetIntArrayRegion(env, joffs, 0, rasterP->numDataElements,
rasterP->chanOffsets);
+ if (rasterP->jdata == NULL) {
+ // unable to verify the raster
+ return -1;
+ }
+ // verify whether channel offsets look sane
+ if (!checkChannelOffsets(rasterP, (*env)->GetArrayLength(env, rasterP->jdata))) {
+ return -1;
+ }
+ break;
+ default:
+ ; // PACKED_RASTER_TYPE does not use the channel offsets.
}
- /* additioanl check for sppsm fields validity: make sure that
- * size of raster samples doesn't exceed the data type cpacity.
+ /* additional check for sppsm fields validity: make sure that
+ * size of raster samples doesn't exceed the data type capacity.
*/
if (rasterP->dataType > UNKNOWN_DATA_TYPE && /* data type has been recognized */
rasterP->sppsm.maxBitSize > 0 && /* raster has SPP sample model */
@@ -631,6 +716,21 @@
}
else if (cmodelP->cmType == DIRECT_CM_TYPE || cmodelP->cmType == PACKED_CM_TYPE) {
int i;
+
+ /* do some sanity check first: make sure that
+ * - sample model is SinglePixelPackedSampleModel
+ * - number of bands in the raster corresponds to the number
+ * of color components in the color model
+ */
+ if (!rasterP->sppsm.isUsed ||
+ rasterP->numBands != cmodelP->numComponents)
+ {
+ /* given raster is not compatible with the color model,
+ * so the operation has to be aborted.
+ */
+ return -1;
+ }
+
if (cmodelP->maxNbits > 8) {
hintP->needToExpand = TRUE;
hintP->expandToNbits = cmodelP->maxNbits;
--- a/jdk/src/share/native/sun/awt/image/awt_parseImage.h Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.h Sun Feb 03 23:25:38 2013 +0100
@@ -95,6 +95,7 @@
jint offsets[MAX_NUMBANDS];
jint nBits[MAX_NUMBANDS];
jint maxBitSize;
+ jint isUsed; // flag to indicate whether the raster sample model is SPPSM
} SPPSampleModelS_t;
/* Struct that holds information for the Raster object */
--- a/jdk/src/share/native/sun/awt/medialib/safe_alloc.h Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/native/sun/awt/medialib/safe_alloc.h Sun Feb 03 23:25:38 2013 +0100
@@ -41,5 +41,10 @@
(((w) > 0) && ((h) > 0) && ((sz) > 0) && \
(((0xffffffffu / ((juint)(w))) / ((juint)(h))) > ((juint)(sz))))
+#define SAFE_TO_MULT(a, b) \
+ (((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b)))
+
+#define SAFE_TO_ADD(a, b) \
+ (((a) >= 0) && ((b) >= 0) && ((0x7fffffff - (a)) > (b)))
#endif // __SAFE_ALLOC_H__
--- a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c Sun Feb 03 23:25:38 2013 +0100
@@ -133,6 +133,10 @@
ImageFormat srcFormat;
jpeg_read_header(cinfo, TRUE);
+
+ // SplashScreen jpeg converter expects data in RGB format only
+ cinfo->out_color_space = JCS_RGB;
+
jpeg_start_decompress(cinfo);
SplashCleanup(splash);
--- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java Sun Feb 03 23:25:38 2013 +0100
@@ -1026,13 +1026,21 @@
boolean unordered,
int ppid)
throws IOException {
+ InetAddress addr = null; // no preferred address
+ int port = 0;
+ if (target != null) {
+ InetSocketAddress isa = Net.checkAddress(target);
+ addr = isa.getAddress();
+ port = isa.getPort();
+ }
+
int pos = bb.position();
int lim = bb.limit();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
- int written = send0(fd, ((DirectBuffer)bb).address() + pos,
- rem, target, -1 /*121*/, streamNumber, unordered, ppid);
+ int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr,
+ port, -1 /*121*/, streamNumber, unordered, ppid);
if (written > 0)
bb.position(pos + written);
return written;
@@ -1091,7 +1099,7 @@
long address, int length, boolean peek) throws IOException;
static native int send0(int fd, long address, int length,
- SocketAddress target, int assocId, int streamNumber,
+ InetAddress addr, int port, int assocId, int streamNumber,
boolean unordered, int ppid) throws IOException;
private static native int checkConnect(FileDescriptor fd, boolean block,
--- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java Sun Feb 03 23:25:38 2013 +0100
@@ -889,13 +889,20 @@
boolean unordered,
int ppid)
throws IOException {
+ InetAddress addr = null; // no preferred address
+ int port = 0;
+ if (target != null) {
+ InetSocketAddress isa = Net.checkAddress(target);
+ addr = isa.getAddress();
+ port = isa.getPort();
+ }
int pos = bb.position();
int lim = bb.limit();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
- int written = send0(fd, ((DirectBuffer)bb).address() + pos,
- rem, target, assocId, streamNumber, unordered, ppid);
+ int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr,
+ port, assocId, streamNumber, unordered, ppid);
if (written > 0)
bb.position(pos + written);
return written;
@@ -976,13 +983,14 @@
private static int send0(int fd,
long address,
int length,
- SocketAddress target,
+ InetAddress addr,
+ int port,
int assocId,
int streamNumber,
boolean unordered,
int ppid)
throws IOException {
- return SctpChannelImpl.send0(fd, address, length, target, assocId,
+ return SctpChannelImpl.send0(fd, address, length, addr, port, assocId,
streamNumber, unordered, ppid);
}
--- a/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c Sun Feb 03 23:25:38 2013 +0100
@@ -46,8 +46,6 @@
#include "sun_nio_ch_DatagramChannelImpl.h"
-static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */
-static jfieldID isa_portID; /* port in java.net.InetSocketAddress */
static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */
static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */
static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */
@@ -61,9 +59,6 @@
isa_class = (*env)->NewGlobalRef(env, clazz);
isa_ctorID = (*env)->GetMethodID(env, clazz, "<init>",
"(Ljava/net/InetAddress;I)V");
- isa_addrID = (*env)->GetFieldID(env, clazz, "addr",
- "Ljava/net/InetAddress;");
- isa_portID = (*env)->GetFieldID(env, clazz, "port", "I");
clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl");
dci_senderID = (*env)->GetFieldID(env, clazz, "sender",
@@ -212,15 +207,13 @@
JNIEXPORT jint JNICALL
Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
jboolean preferIPv6, jobject fdo, jlong address,
- jint len, jobject dest)
+ jint len, jobject destAddress, jint destPort)
{
jint fd = fdval(env, fdo);
void *buf = (void *)jlong_to_ptr(address);
SOCKADDR sa;
int sa_len = SOCKADDR_LEN;
jint n = 0;
- jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID);
- jint destPort = (*env)->GetIntField(env, dest, isa_portID);
if (len > MAX_PACKET_LEN) {
len = MAX_PACKET_LEN;
--- a/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/solaris/native/sun/nio/ch/sctp/SctpChannelImpl.c Sun Feb 03 23:25:38 2013 +0100
@@ -67,8 +67,6 @@
static jmethodID spc_ctrID; /* sun.nio.ch.sctp.PeerAddressChanged.<init> */
static jclass ss_class; /* sun.nio.ch.sctp.Shutdown */
static jmethodID ss_ctrID; /* sun.nio.ch.sctp.Shutdown.<init> */
-static jfieldID isa_addrID; /* java.net.InetSocketAddress.addr */
-static jfieldID isa_portID; /* java.net.InetSocketAddress.port */
/* defined in SctpNet.c */
jobject SockAddrToInetSocketAddress(JNIEnv* env, struct sockaddr* addr);
@@ -138,13 +136,6 @@
CHECK_NULL(ss_class);
ss_ctrID = (*env)->GetMethodID(env, cls, "<init>", "(I)V");
CHECK_NULL(ss_ctrID);
-
- /* InetSocketAddress */
- cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
- CHECK_NULL(cls);
- isa_addrID = (*env)->GetFieldID(env, cls, "addr", "Ljava/net/InetAddress;");
- CHECK_NULL(isa_addrID);
- isa_portID = (*env)->GetFieldID(env, cls, "port", "I");
}
void getControlData
@@ -509,12 +500,12 @@
/*
* Class: sun_nio_ch_sctp_SctpChannelImpl
* Method: send0
- * Signature: (IJILjava/net/SocketAddress;IIZI)I
+ * Signature: (IJILjava/net/InetAddress;IIIZI)I
*/
JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_send0
(JNIEnv *env, jclass klass, jint fd, jlong address, jint length,
- jobject saTarget, jint assocId, jint streamNumber, jboolean unordered,
- jint ppid) {
+ jobject targetAddress, jint targetPort, jint assocId, jint streamNumber,
+ jboolean unordered, jint ppid) {
SOCKADDR sa;
int sa_len = sizeof(sa);
ssize_t rv = 0;
@@ -526,17 +517,13 @@
struct controlData cdata[1];
/* SctpChannel:
- * saTarget may contain the preferred address or NULL to use primary,
+ * targetAddress may contain the preferred address or NULL to use primary,
* assocId will always be -1
* SctpMultiChannell:
- * Setup new association, saTarget will contain address, assocId = -1
- * Association already existing, assocId != -1, saTarget = preferred addr
+ * Setup new association, targetAddress will contain address, assocId = -1
+ * Association already existing, assocId != -1, targetAddress = preferred addr
*/
- if (saTarget != NULL /*&& assocId <= 0*/) {
-
- jobject targetAddress = (*env)->GetObjectField(env, saTarget, isa_addrID);
- jint targetPort = (*env)->GetIntField(env, saTarget, isa_portID);
-
+ if (targetAddress != NULL /*&& assocId <= 0*/) {
if (NET_InetAddressToSockaddr(env, targetAddress, targetPort,
(struct sockaddr *)&sa,
&sa_len, JNI_TRUE) != 0) {
--- a/jdk/src/windows/bin/java_md.c Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/windows/bin/java_md.c Sun Feb 03 23:25:38 2013 +0100
@@ -101,7 +101,6 @@
/* funtion in awt.dll (src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp) */
#define D3D_PRELOAD_FUNC "preloadD3D"
-
/* Extracts value of a parameter with the specified name
* from command line argument (returns pointer in the argument).
* Returns NULL if the argument does not contains the parameter.
@@ -276,7 +275,8 @@
#endif
#ifdef CRT_DLL
if (GetJREPath(crtpath, MAXPATHLEN)) {
- if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") + JLI_StrLen(CRT_DLL) >= MAXPATHLEN) {
+ if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") +
+ JLI_StrLen(CRT_DLL) >= MAXPATHLEN) {
JLI_ReportErrorMessage(JRE_ERROR11);
return JNI_FALSE;
}
@@ -347,7 +347,8 @@
if (JLI_StrChr(jvmtype, '/') || JLI_StrChr(jvmtype, '\\')) {
JLI_Snprintf(jvmpath, jvmpathsize, "%s\\" JVM_DLL, jvmtype);
} else {
- JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype);
+ JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL,
+ jrepath, jvmtype);
}
if (stat(jvmpath, &s) == 0) {
return JNI_TRUE;
@@ -525,6 +526,37 @@
}
return (counts * 1000 * 1000)/counterFrequency.QuadPart;
}
+/*
+ * windows snprintf does not guarantee a null terminator in the buffer,
+ * if the computed size is equal to or greater than the buffer size,
+ * as well as error conditions. This function guarantees a null terminator
+ * under all these conditions. An unreasonable buffer or size will return
+ * an error value. Under all other conditions this function will return the
+ * size of the bytes actually written minus the null terminator, similar
+ * to ansi snprintf api. Thus when calling this function the caller must
+ * ensure storage for the null terminator.
+ */
+int
+JLI_Snprintf(char* buffer, size_t size, const char* format, ...) {
+ int rc;
+ va_list vl;
+ if (size == 0 || buffer == NULL)
+ return -1;
+ buffer[0] = '\0';
+ va_start(vl, format);
+ rc = vsnprintf(buffer, size, format, vl);
+ va_end(vl);
+ /* force a null terminator, if something is amiss */
+ if (rc < 0) {
+ /* apply ansi semantics */
+ buffer[size - 1] = '\0';
+ return size;
+ } else if (rc == size) {
+ /* force a null terminator */
+ buffer[size - 1] = '\0';
+ }
+ return rc;
+}
void
JLI_ReportErrorMessage(const char* fmt, ...) {
@@ -880,7 +912,7 @@
*/
void
ExecJRE(char *jre, char **argv) {
- int len;
+ jint len;
char path[MAXPATHLEN + 1];
const char *progname = GetProgramName();
@@ -1417,7 +1449,10 @@
// we add the indicator
tlen = 1 + JLI_StrLen(strv[i]) + 1;
nargv[i] = (char *) JLI_MemAlloc(tlen);
- JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F', strv[i]);
+ if (JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F',
+ strv[i]) < 0) {
+ return NULL;
+ }
JLI_TraceLauncher("%s\n", nargv[i]);
}
--- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java Sun Feb 03 23:25:38 2013 +0100
@@ -488,14 +488,15 @@
try {
replaceSurfaceData();
} catch (InvalidPipeException e) {
- // REMIND : what do we do if our surface creation failed?
+ // REMIND : what do we do if our surface creation failed?
}
}
}
};
+ Component c = (Component)target;
// Fix 6255371.
- if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing((Component)target, r)) {
- postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), r));
+ if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing(c, r)) {
+ postEvent(new InvocationEvent(c, r));
}
}
@@ -618,7 +619,7 @@
}
public void disposeLater() {
- postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), new Runnable() {
+ postEvent(new InvocationEvent(target, new Runnable() {
public void run() {
dispose();
}
--- a/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java Sun Feb 03 23:25:38 2013 +0100
@@ -27,6 +27,7 @@
import sun.awt.*;
import java.awt.*;
+import java.awt.event.InvocationEvent;
import java.awt.peer.ComponentPeer;
import java.awt.image.*;
import sun.awt.image.ByteInterleavedRaster;
@@ -232,11 +233,13 @@
} else {
// To avoid focus concurrence b/w IE and EmbeddedFrame
// activation is postponed by means of posting it to EDT.
- EventQueue.invokeLater(new Runnable() {
- public void run() {
- ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true);
- }
- });
+ Runnable r = new Runnable() {
+ public void run() {
+ ((WEmbeddedFramePeer)getPeer()).synthesizeWmActivate(true);
+ }
+ };
+ WToolkit.postEvent(WToolkit.targetToAppContext(this),
+ new InvocationEvent(this, r));
}
}
--- a/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/windows/native/sun/nio/ch/DatagramChannelImpl.c Sun Feb 03 23:25:38 2013 +0100
@@ -34,8 +34,6 @@
#include "net_util.h"
#include <winsock2.h>
-static jfieldID isa_addrID; /* address in java.net.InetSocketAddress */
-static jfieldID isa_portID; /* port in java.net.InetSocketAddress */
static jfieldID dci_senderID; /* sender in sun.nio.ch.DatagramChannelImpl */
static jfieldID dci_senderAddrID; /* sender InetAddress in sun.nio.ch.DatagramChannelImpl */
static jfieldID dci_senderPortID; /* sender port in sun.nio.ch.DatagramChannelImpl */
@@ -50,9 +48,6 @@
isa_class = (*env)->NewGlobalRef(env, clazz);
isa_ctorID = (*env)->GetMethodID(env, clazz, "<init>",
"(Ljava/net/InetAddress;I)V");
- isa_addrID = (*env)->GetFieldID(env, clazz, "addr",
- "Ljava/net/InetAddress;");
- isa_portID = (*env)->GetFieldID(env, clazz, "port", "I");
clazz = (*env)->FindClass(env, "sun/nio/ch/DatagramChannelImpl");
dci_senderID = (*env)->GetFieldID(env, clazz, "sender",
@@ -214,15 +209,14 @@
JNIEXPORT jint JNICALL
Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jobject this,
jboolean preferIPv6, jobject fdo,
- jlong address, jint len, jobject dest)
+ jlong address, jint len,
+ jobject destAddress, jint destPort)
{
jint fd = fdval(env, fdo);
void *buf = (void *)jlong_to_ptr(address);
SOCKETADDRESS sa;
int sa_len;
jint rv = 0;
- jobject destAddress = (*env)->GetObjectField(env, dest, isa_addrID);
- jint destPort = (*env)->GetIntField(env, dest, isa_portID);
if (NET_InetAddressToSockaddr(env, destAddress, destPort,
(struct sockaddr *)&sa,
--- a/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/windows/native/sun/windows/awt_TextComponent.cpp Sun Feb 03 23:25:38 2013 +0100
@@ -53,14 +53,12 @@
* AwtTextComponent fields
*/
-/* java.awt.TextComponent fields */
-jfieldID AwtTextComponent::canAccessClipboardID;
-
-
/************************************************************************
* AwtTextComponent methods
*/
+jmethodID AwtTextComponent::canAccessClipboardMID;
+
AwtTextComponent::AwtTextComponent() {
m_synthetic = FALSE;
m_lStartPos = -1;
@@ -367,8 +365,7 @@
}
jobject target = GetTarget(env);
jboolean canAccessClipboard =
- env->GetBooleanField(target,
- AwtTextComponent::canAccessClipboardID);
+ env->CallBooleanMethod (target, AwtTextComponent::canAccessClipboardMID);
env->DeleteLocalRef(target);
return (canAccessClipboard) ? mrDoDefault : mrConsume;
}
@@ -854,12 +851,13 @@
{
TRY;
- cls = env->FindClass("java/awt/TextComponent");
- if (cls != NULL) {
- AwtTextComponent::canAccessClipboardID =
- env->GetFieldID(cls, "canAccessClipboard", "Z");
- DASSERT(AwtTextComponent::canAccessClipboardID != NULL);
- }
+ jclass textComponentClassID = env->FindClass("java/awt/TextComponent");
+ AwtTextComponent::canAccessClipboardMID =
+ env->GetMethodID(textComponentClassID,
+ "canAccessClipboard", "()Z");
+ env->DeleteLocalRef(textComponentClassID);
+
+ DASSERT(AwtTextComponent::canAccessClipboardMID != NULL);
CATCH_BAD_ALLOC;
}
--- a/jdk/src/windows/native/sun/windows/awt_TextComponent.h Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/src/windows/native/sun/windows/awt_TextComponent.h Sun Feb 03 23:25:38 2013 +0100
@@ -42,8 +42,7 @@
class AwtTextComponent : public AwtComponent {
public:
- /* java.awt.TextComponent canAccessClipboard field ID */
- static jfieldID canAccessClipboardID;
+ static jmethodID canAccessClipboardMID;
AwtTextComponent();
--- a/jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/test/java/nio/channels/DatagramChannel/SendToUnresolved.java Sun Feb 03 23:25:38 2013 +0100
@@ -42,7 +42,7 @@
try {
dc.send(bb, sa);
throw new RuntimeException("Expected exception not thrown");
- } catch (IOException e) {
+ } catch (IOException | UnresolvedAddressException e) {
// Correct result
}
dc.close();
--- a/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy Sun Feb 03 23:25:38 2013 +0100
@@ -13,6 +13,7 @@
permission java.io.FilePermission ".${/}-", "read,write,delete";
permission java.lang.RuntimePermission "createClassLoader";
+ permission java.lang.RuntimePermission "getClassLoader";
permission java.lang.RuntimePermission "setContextClassLoader";
// used by TestLibrary to determine test environment
--- a/jdk/test/java/rmi/testlibrary/JavaVM.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/test/java/rmi/testlibrary/JavaVM.java Sun Feb 03 23:25:38 2013 +0100
@@ -110,6 +110,14 @@
return TestLibrary.getExtraProperty("jcov.options","");
}
+ public void start(Runnable runnable) throws IOException {
+ if (runnable == null) {
+ throw new NullPointerException("Runnable cannot be null.");
+ }
+
+ start();
+ new JavaVMCallbackHandler(runnable).start();
+ }
/**
* Exec the VM as specified in this object's constructor.
@@ -183,4 +191,35 @@
start();
return waitFor();
}
+
+ /**
+ * Handles calling the callback.
+ */
+ private class JavaVMCallbackHandler extends Thread {
+ Runnable runnable;
+
+ JavaVMCallbackHandler(Runnable runnable) {
+ this.runnable = runnable;
+ }
+
+
+ /**
+ * Wait for the Process to terminate and notify the callback.
+ */
+ @Override
+ public void run() {
+ if (vm != null) {
+ try {
+ vm.waitFor();
+ } catch(InterruptedException ie) {
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ if (runnable != null) {
+ runnable.run();
+ }
+ }
+ }
}
--- a/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/test/sun/security/mscapi/ShortRSAKeyWithinTLS.java Sun Feb 03 23:25:38 2013 +0100
@@ -29,7 +29,7 @@
import javax.net.ssl.*;
import java.lang.reflect.*;
-import sun.security.util.KeyLength;
+import sun.security.util.KeyUtil;
public class ShortRSAKeyWithinTLS {
@@ -175,13 +175,13 @@
privateKey = (PrivateKey)ks.getKey(keyAlias, null);
publicKey = (PublicKey)ks.getCertificate(keyAlias).getPublicKey();
- int privateKeySize = KeyLength.getKeySize(privateKey);
+ int privateKeySize = KeyUtil.getKeySize(privateKey);
if (privateKeySize != keySize) {
throw new Exception("Expected key size is " + keySize +
", but the private key size is " + privateKeySize);
}
- int publicKeySize = KeyLength.getKeySize(publicKey);
+ int publicKeySize = KeyUtil.getKeySize(publicKey);
if (publicKeySize != keySize) {
throw new Exception("Expected key size is " + keySize +
", but the public key size is " + publicKeySize);
--- a/jdk/test/tools/launcher/ToolsOpts.java Thu Jan 31 17:04:47 2013 -0800
+++ b/jdk/test/tools/launcher/ToolsOpts.java Sun Feb 03 23:25:38 2013 +0100
@@ -23,6 +23,7 @@
/*
* @test
+ * @bug 8002091
* @summary Test options patterns for javac,javah,javap and javadoc using
* javac as a test launcher. Create a dummy javac and intercept options to check
* reception of options as passed through the launcher without having to launch