Mercurial > hg > release > icedtea6-1.10
view patches/security/20120214/7082299.patch @ 2555:4e7a700d4ecc
Add 2012/02/14 security patches.
2012-02-08 Omair Majid <omajid@redhat.com>
* NEWS: Update with security fixes.
* Makefile.am
(SECURITY_PATCHES): Add security patches.
(SPECIAL_SECURITY_PATCH): Add new variable.
(ICEDTEA_PATCHES): Add security patch that epends on backport.
* patches/security/20120214/7082299.patch,
* patches/security/20120214/7088367.patch,
* patches/security/20120214/7110683.patch,
* patches/security/20120214/7110687.patch,
* patches/security/20120214/7110700.patch,
* patches/security/20120214/7110704.patch,
* patches/security/20120214/7112642.patch,
* patches/security/20120214/7118283.patch,
* patches/security/20120214/7126960.patch: New security fixes.
author | Andrew John Hughes <ahughes@redhat.com> |
---|---|
date | Thu, 09 Feb 2012 17:05:26 +0000 |
parents | |
children |
line wrap: on
line source
# HG changeset patch # User robm # Date 1322691030 0 # Node ID ee0f12b18cb8d20c3fb61e96817bde6318a29221 # Parent dd8956e41b892ed7102e1d5668781f2c68ea9ac5 7082299: AtomicReferenceArray should ensure that array is Object[] Summary: java.util.concurrent.AtomicReferenceArray needs to ensure that internal array is always Object[]. Reviewed-by: chegar, coffeys diff --git a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java --- openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java +++ openjdk/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -34,8 +34,9 @@ */ package java.util.concurrent.atomic; +import java.lang.reflect.Array; +import java.util.Arrays; import sun.misc.Unsafe; -import java.util.*; /** * An array of object references in which elements may be updated @@ -49,15 +50,37 @@ public class AtomicReferenceArray<E> imp public class AtomicReferenceArray<E> implements java.io.Serializable { private static final long serialVersionUID = -6209656149925076980L; - private static final Unsafe unsafe = Unsafe.getUnsafe(); - private static final int base = unsafe.arrayBaseOffset(Object[].class); - private static final int scale = unsafe.arrayIndexScale(Object[].class); - private final Object[] array; + private static final Unsafe unsafe; + private static final int base; + private static final int shift; + private static final long arrayFieldOffset; + private final Object[] array; // must have exact type Object[] - private long rawIndex(int i) { + static { + int scale; + try { + unsafe = Unsafe.getUnsafe(); + arrayFieldOffset = unsafe.objectFieldOffset + (AtomicReferenceArray.class.getDeclaredField("array")); + base = unsafe.arrayBaseOffset(Object[].class); + scale = unsafe.arrayIndexScale(Object[].class); + } catch (Exception e) { + throw new Error(e); + } + if ((scale & (scale - 1)) != 0) + throw new Error("data type scale not a power of two"); + shift = 31 - Integer.numberOfLeadingZeros(scale); + } + + private long checkedByteOffset(int i) { if (i < 0 || i >= array.length) throw new IndexOutOfBoundsException("index " + i); - return base + (long) i * scale; + + return byteOffset(i); + } + + private static long byteOffset(int i) { + return ((long) i << shift) + base; } /** @@ -66,9 +89,6 @@ public class AtomicReferenceArray<E> imp */ public AtomicReferenceArray(int length) { array = new Object[length]; - // must perform at least one volatile write to conform to JMM - if (length > 0) - unsafe.putObjectVolatile(array, rawIndex(0), null); } /** @@ -79,18 +99,8 @@ public class AtomicReferenceArray<E> imp * @throws NullPointerException if array is null */ public AtomicReferenceArray(E[] array) { - if (array == null) - throw new NullPointerException(); - int length = array.length; - this.array = new Object[length]; - if (length > 0) { - int last = length-1; - for (int i = 0; i < last; ++i) - this.array[i] = array[i]; - // Do the last write as volatile - E e = array[last]; - unsafe.putObjectVolatile(this.array, rawIndex(last), e); - } + // Visibility guaranteed by final field guarantees + this.array = Arrays.copyOf(array, array.length, Object[].class); } /** @@ -109,7 +119,11 @@ public class AtomicReferenceArray<E> imp * @return the current value */ public final E get(int i) { - return (E) unsafe.getObjectVolatile(array, rawIndex(i)); + return getRaw(checkedByteOffset(i)); + } + + private E getRaw(long offset) { + return (E) unsafe.getObjectVolatile(array, offset); } /** @@ -119,7 +133,7 @@ public class AtomicReferenceArray<E> imp * @param newValue the new value */ public final void set(int i, E newValue) { - unsafe.putObjectVolatile(array, rawIndex(i), newValue); + unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue); } /** @@ -130,7 +144,7 @@ public class AtomicReferenceArray<E> imp * @since 1.6 */ public final void lazySet(int i, E newValue) { - unsafe.putOrderedObject(array, rawIndex(i), newValue); + unsafe.putOrderedObject(array, checkedByteOffset(i), newValue); } @@ -143,9 +157,10 @@ public class AtomicReferenceArray<E> imp * @return the previous value */ public final E getAndSet(int i, E newValue) { + long offset = checkedByteOffset(i); while (true) { - E current = get(i); - if (compareAndSet(i, current, newValue)) + E current = getRaw(offset); + if (compareAndSetRaw(offset, current, newValue)) return current; } } @@ -153,6 +168,7 @@ public class AtomicReferenceArray<E> imp /** * Atomically sets the element at position {@code i} to the given * updated value if the current value {@code ==} the expected value. + * * @param i the index * @param expect the expected value * @param update the new value @@ -160,8 +176,11 @@ public class AtomicReferenceArray<E> imp * the actual value was not equal to the expected value. */ public final boolean compareAndSet(int i, E expect, E update) { - return unsafe.compareAndSwapObject(array, rawIndex(i), - expect, update); + return compareAndSetRaw(checkedByteOffset(i), expect, update); + } + + private boolean compareAndSetRaw(long offset, E expect, E update) { + return unsafe.compareAndSwapObject(array, offset, expect, update); } /** @@ -186,9 +205,33 @@ public class AtomicReferenceArray<E> imp * @return the String representation of the current values of array. */ public String toString() { - if (array.length > 0) // force volatile read - get(0); - return Arrays.toString(array); + int iMax = array.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; ; i++) { + b.append(getRaw(byteOffset(i))); + if (i == iMax) + return b.append(']').toString(); + b.append(',').append(' '); + } + } + + /** + * Reconstitutes the instance from a stream (that is, deserializes it). + * @param s the stream + */ + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException { + // Note: This must be changed if any additional fields are defined + Object a = s.readFields().get("array", null); + if (a == null || !a.getClass().isArray()) + throw new java.io.InvalidObjectException("Not array type"); + if (a.getClass() != Object[].class) + a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); + unsafe.putObjectVolatile(this, arrayFieldOffset, a); } }