--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Tue Oct 04 17:15:49 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Wed Oct 05 11:30:16 2016 -0700
@@ -40,6 +40,7 @@
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;
import jdk.internal.misc.Unsafe;
@@ -411,7 +412,17 @@
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -433,6 +444,15 @@
}
/**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(class1.getPackageName(), class2.getPackageName());
+ }
+
+ /**
* Checks that target argument is instance of cclass. On
* failure, throws cause.
*/
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Tue Oct 04 17:15:49 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Wed Oct 05 11:30:16 2016 -0700
@@ -40,6 +40,7 @@
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.LongBinaryOperator;
import java.util.function.LongUnaryOperator;
import jdk.internal.misc.Unsafe;
@@ -409,7 +410,17 @@
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -540,7 +551,17 @@
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.offset = U.objectFieldOffset(field);
}
@@ -621,4 +642,13 @@
} while (acl != null);
return false;
}
+
+ /**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(class1.getPackageName(), class2.getPackageName());
+ }
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Tue Oct 04 17:15:49 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Wed Oct 05 11:30:16 2016 -0700
@@ -40,6 +40,7 @@
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
import java.util.function.BinaryOperator;
import java.util.function.UnaryOperator;
import jdk.internal.misc.Unsafe;
@@ -351,7 +352,17 @@
if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type");
- this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+ // Access to protected field members is restricted to receivers only
+ // of the accessing class, or one of its subclasses, and the
+ // accessing class must in turn be a subclass (or package sibling)
+ // of the protected member's defining class.
+ // If the updater refers to a protected field of a declaring class
+ // outside the current package, the receiver argument will be
+ // narrowed to the type of the accessing class.
+ this.cclass = (Modifier.isProtected(modifiers) &&
+ tclass.isAssignableFrom(caller) &&
+ !isSamePackage(tclass, caller))
+ ? caller : tclass;
this.tclass = tclass;
this.vclass = vclass;
this.offset = U.objectFieldOffset(field);
@@ -374,6 +385,15 @@
}
/**
+ * Returns true if the two classes have the same class loader and
+ * package qualifier
+ */
+ private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+ return class1.getClassLoader() == class2.getClassLoader()
+ && Objects.equals(class1.getPackageName(), class2.getPackageName());
+ }
+
+ /**
* Checks that target argument is instance of cclass. On
* failure, throws cause.
*/