/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.lang.invoke.WrongMethodTypeException; import java.nio.ByteBuffer; import java.nio.ByteOrder; public class VarHandleBadCoordinateTests { public static class FieldCoordinateTypeTest extends VarHandleUnitTest { private static final VarHandle vh; public static class A { public byte field; } public static class B extends A { private byte other_field; } public static class C {} static { try { vh = MethodHandles.lookup().findVarHandle(A.class, "field", byte.class); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { vh.compareAndSet(new A(), (byte) 0, (byte) 3); vh.compareAndSet(new B(), (byte) 0, (byte) 3); try { vh.compareAndSet(new C(), (byte) 0, (byte) 3); failUnreachable(); } catch (ClassCastException ex) { } try { vh.compareAndSet(0xbad0bad0, (byte) 0, (byte) 3); failUnreachable(); } catch (WrongMethodTypeException ex) { } try { vh.compareAndSet(0xbad0bad0, (byte) 0, Integer.MAX_VALUE); failUnreachable(); } catch (WrongMethodTypeException ex) { } try { vh.compareAndSet(0xbad0bad0, (byte) 0); failUnreachable(); } catch (WrongMethodTypeException ex) { } try { vh.compareAndSet(new A(), (byte) 0, Integer.MAX_VALUE); failUnreachable(); } catch (WrongMethodTypeException ex) { } try { vh.compareAndSet((A) null, (byte) 0, (byte) 3); failUnreachable(); } catch (NullPointerException ex) { } try { byte unused = (byte) vh.get(); failUnreachable(); } catch (WrongMethodTypeException ex) { } } public static void main(String[] args) { new FieldCoordinateTypeTest().run(); } } public static class ArrayElementOutOfBoundsIndexTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.arrayElementVarHandle(long[].class); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { long[] values = new long[33]; try { vh.get(values, -1); failUnreachable(); } catch (ArrayIndexOutOfBoundsException ex) { } try { vh.get(values, values.length); failUnreachable(); } catch (ArrayIndexOutOfBoundsException ex) { } try { vh.get(values, Integer.MAX_VALUE - 1); failUnreachable(); } catch (ArrayIndexOutOfBoundsException ex) { } } public static void main(String[] args) { new ArrayElementOutOfBoundsIndexTest().run(); } } public static class ArrayElementBadIndexTypeTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.arrayElementVarHandle(long[].class); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { long[] values = new long[33]; vh.set(values, Integer.valueOf(3), Long.MIN_VALUE); vh.set(values, Byte.valueOf((byte) 0), Long.MIN_VALUE); try { vh.set(values, 3.3f, Long.MAX_VALUE); failUnreachable(); } catch (WrongMethodTypeException ex) { } } public static void main(String[] args) { new ArrayElementBadIndexTypeTest().run(); } } public static class ArrayElementNullArrayTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.arrayElementVarHandle(long[].class); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { long[] values = null; try { vh.get(values); failUnreachable(); } catch (WrongMethodTypeException ex) { } } public static void main(String[] args) { new ArrayElementNullArrayTest().run(); } } public static class ArrayElementWrongArrayTypeTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.arrayElementVarHandle(long[].class); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { try { vh.get(new char[10], 0); failUnreachable(); } catch (ClassCastException ex) { } } public static void main(String[] args) { new ArrayElementWrongArrayTypeTest().run(); } } public static class ArrayElementMissingIndexTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.arrayElementVarHandle(long[].class); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { long[] values = new long[33]; try { vh.get(values); failUnreachable(); } catch (WrongMethodTypeException ex) { } } public static void main(String[] args) { new ArrayElementMissingIndexTest().run(); } } public static class ByteArrayViewOutOfBoundsIndexTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { byte[] bytes = new byte[16]; try { vh.get(bytes, -1); failUnreachable(); } catch (IndexOutOfBoundsException ex) { } try { vh.get(bytes, bytes.length); failUnreachable(); } catch (IndexOutOfBoundsException ex) { } try { vh.get(bytes, Integer.MAX_VALUE - 1); failUnreachable(); } catch (IndexOutOfBoundsException ex) { } try { vh.get(bytes, bytes.length - Integer.SIZE / 8 + 1); failUnreachable(); } catch (IndexOutOfBoundsException ex) { } vh.get(bytes, bytes.length - Integer.SIZE / 8); } public static void main(String[] args) { new ByteArrayViewOutOfBoundsIndexTest().run(); } } public static class ByteArrayViewUnalignedAccessesIndexTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { byte[] bytes = new byte[33]; int alignedIndex = VarHandleUnitTestHelpers.alignedOffset_int(bytes, 0); for (int i = alignedIndex; i < Integer.SIZE / 8; ++i) { // No exceptions are expected for GET and SET // accessors irrespective of the access alignment. vh.set(bytes, i, 380); vh.get(bytes, i); // Other accessors raise an IllegalStateException if // the access is unaligned. try { vh.compareAndExchange(bytes, i, 777, 320); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.compareAndExchangeAcquire(bytes, i, 320, 767); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.compareAndExchangeRelease(bytes, i, 767, 321); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.compareAndSet(bytes, i, 767, 321); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAcquire(bytes, i); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndAdd(bytes, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndAddAcquire(bytes, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndAddRelease(bytes, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseAnd(bytes, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseAndAcquire(bytes, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseAndRelease(bytes, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseOr(bytes, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseOrAcquire(bytes, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseOrRelease(bytes, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseXor(bytes, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseXorAcquire(bytes, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseXorRelease(bytes, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndSet(bytes, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndSetAcquire(bytes, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndSetRelease(bytes, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getOpaque(bytes, i); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getVolatile(bytes, i); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.setOpaque(bytes, i, 777); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.setRelease(bytes, i, 319); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.setVolatile(bytes, i, 787); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.weakCompareAndSet(bytes, i, 787, 340); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.weakCompareAndSetAcquire(bytes, i, 787, 340); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.weakCompareAndSetPlain(bytes, i, 787, 340); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.weakCompareAndSetRelease(bytes, i, 787, 340); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } } } public static void main(String[] args) { new ByteArrayViewUnalignedAccessesIndexTest().run(); } } public static class ByteArrayViewBadIndexTypeTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { byte[] bytes = new byte[16]; // Boxed index goes through argument conversion so no exception expected. vh.get(bytes, Integer.valueOf(3)); vh.get(bytes, Short.valueOf((short) 3)); try { vh.get(bytes, System.out); failUnreachable(); } catch (WrongMethodTypeException ex) { } } public static void main(String[] args) { new ByteArrayViewBadIndexTypeTest().run(); } } public static class ByteArrayViewMissingIndexTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { byte[] bytes = new byte[16]; try { vh.get(bytes); failUnreachable(); } catch (WrongMethodTypeException ex) { } } public static void main(String[] args) { new ByteArrayViewMissingIndexTest().run(); } } public static class ByteArrayViewBadByteArrayTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { byte[] bytes = null; try { vh.get(bytes, Integer.valueOf(3)); failUnreachable(); } catch (NullPointerException ex) { } try { vh.get(System.err, Integer.valueOf(3)); failUnreachable(); } catch (ClassCastException ex) { } } public static void main(String[] args) { new ByteArrayViewBadByteArrayTest().run(); } } public static class ByteBufferViewOutOfBoundsIndexTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.byteBufferViewVarHandle(float[].class, ByteOrder.LITTLE_ENDIAN); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { ByteBuffer[] buffers = new ByteBuffer[] { ByteBuffer.allocateDirect(16), ByteBuffer.allocate(37), ByteBuffer.wrap(new byte[27], 3, 27 - 3) }; for (ByteBuffer buffer : buffers) { try { vh.get(buffer, -1); failUnreachable(); } catch (IndexOutOfBoundsException ex) { } try { vh.get(buffer, buffer.limit()); failUnreachable(); } catch (IndexOutOfBoundsException ex) { } try { vh.get(buffer, Integer.MAX_VALUE - 1); failUnreachable(); } catch (IndexOutOfBoundsException ex) { } try { vh.get(buffer, buffer.limit() - Integer.SIZE / 8 + 1); failUnreachable(); } catch (IndexOutOfBoundsException ex) { } vh.get(buffer, buffer.limit() - Integer.SIZE / 8); } } public static void main(String[] args) { new ByteBufferViewOutOfBoundsIndexTest().run(); } } public static class ByteBufferViewUnalignedAccessesIndexTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { ByteBuffer[] buffers = new ByteBuffer[] { ByteBuffer.allocateDirect(16), ByteBuffer.allocate(37), ByteBuffer.wrap(new byte[27], 3, 27 - 3) }; for (ByteBuffer buffer : buffers) { int alignedIndex = VarHandleUnitTestHelpers.alignedOffset_int(buffer, 0); for (int i = alignedIndex; i < Integer.SIZE / 8; ++i) { // No exceptions are expected for GET and SET // accessors irrespective of the access alignment. vh.set(buffer, i, 380); vh.get(buffer, i); // Other accessors raise an IllegalStateException if // the access is unaligned. try { vh.compareAndExchange(buffer, i, 777, 320); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.compareAndExchangeAcquire(buffer, i, 320, 767); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.compareAndExchangeRelease(buffer, i, 767, 321); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.compareAndSet(buffer, i, 767, 321); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAcquire(buffer, i); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndAdd(buffer, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndAddAcquire(buffer, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndAddRelease(buffer, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseAnd(buffer, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseAndAcquire(buffer, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseAndRelease(buffer, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseOr(buffer, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseOrAcquire(buffer, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseOrRelease(buffer, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseXor(buffer, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseXorAcquire(buffer, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndBitwiseXorRelease(buffer, i, 118); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndSet(buffer, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndSetAcquire(buffer, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getAndSetRelease(buffer, i, 117); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getOpaque(buffer, i); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.getVolatile(buffer, i); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.setOpaque(buffer, i, 777); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.setRelease(buffer, i, 319); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.setVolatile(buffer, i, 787); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.weakCompareAndSet(buffer, i, 787, 340); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.weakCompareAndSetAcquire(buffer, i, 787, 340); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.weakCompareAndSetPlain(buffer, i, 787, 340); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } try { vh.weakCompareAndSetRelease(buffer, i, 787, 340); assertTrue(i == alignedIndex); } catch (IllegalStateException ex) { assertFalse(i == alignedIndex); } } } } public static void main(String[] args) { new ByteBufferViewUnalignedAccessesIndexTest().run(); } } public static class ByteBufferViewBadIndexTypeTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { ByteBuffer[] buffers = new ByteBuffer[] { ByteBuffer.allocateDirect(16), ByteBuffer.allocate(16), ByteBuffer.wrap(new byte[32], 4, 32 - 4) }; for (ByteBuffer buffer : buffers) { // Boxed index goes through argument conversion so no exception expected. vh.get(buffer, Integer.valueOf(3)); vh.get(buffer, Short.valueOf((short) 3)); vh.get(buffer, Byte.valueOf((byte) 7)); try { vh.get(buffer, System.out); failUnreachable(); } catch (WrongMethodTypeException ex) { } } } public static void main(String[] args) { new ByteBufferViewBadIndexTypeTest().run(); } } public static class ByteBufferViewMissingIndexTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { ByteBuffer[] buffers = new ByteBuffer[] { ByteBuffer.allocateDirect(16), ByteBuffer.allocate(16), ByteBuffer.wrap(new byte[32], 4, 32 - 4) }; for (ByteBuffer buffer : buffers) { try { vh.get(buffer); failUnreachable(); } catch (WrongMethodTypeException ex) { } } } public static void main(String[] args) { new ByteBufferViewMissingIndexTest().run(); } } public static class ByteBufferViewBadByteBufferTest extends VarHandleUnitTest { private static final VarHandle vh; static { try { vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); } catch (Exception e) { throw new RuntimeException(e); } } @Override protected void doTest() { if (VarHandleUnitTestHelpers.isRunningOnAndroid()) { ByteBuffer buffer = null; // The RI does not like this test try { vh.get(buffer, 3); failUnreachable(); } catch (NullPointerException ex) { } } try { vh.get(System.err, 3); failUnreachable(); } catch (ClassCastException ex) { } } public static void main(String[] args) { new ByteBufferViewBadByteBufferTest().run(); } } public static void main(String[] args) { FieldCoordinateTypeTest.main(args); ArrayElementOutOfBoundsIndexTest.main(args); ArrayElementBadIndexTypeTest.main(args); ArrayElementNullArrayTest.main(args); ArrayElementWrongArrayTypeTest.main(args); ArrayElementMissingIndexTest.main(args); ByteArrayViewOutOfBoundsIndexTest.main(args); ByteArrayViewUnalignedAccessesIndexTest.main(args); ByteArrayViewBadIndexTypeTest.main(args); ByteArrayViewMissingIndexTest.main(args); ByteArrayViewBadByteArrayTest.main(args); ByteBufferViewOutOfBoundsIndexTest.main(args); ByteBufferViewUnalignedAccessesIndexTest.main(args); ByteBufferViewBadIndexTypeTest.main(args); ByteBufferViewMissingIndexTest.main(args); ByteBufferViewBadByteBufferTest.main(args); } }