#!/bin/bash # # 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. # Stop if something fails. set -e # Write out the source file. mkdir src cat >src/Main.java <<EOF /* * 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. */ EOF for i in {0..8192}; do echo "class Level1Class$i { }" >>src/Main.java; done for i in {0..1024}; do echo "class Level2Class$i extends Level1Class0 { }" >>src/Main.java; done cat >>src/Main.java <<EOF class Level3Class0 extends Level2Class0 { } class Level4Class0 extends Level3Class0 { } class Level5Class0 extends Level4Class0 { } class Level6Class0 extends Level5Class0 { } class Level7Class0 extends Level6Class0 { } class Level8Class0 extends Level7Class0 { } class Level9Class0 extends Level8Class0 { } public class Main { public static void main(String[] args) throws Exception { // 8193 classes at level 1 make sure we shall have an overflow if there are 13 or // less bits for the level 1 character. 1025 classes at level 2 similarly guarantees // an overflow if the number of bits for level 2 character is 10 or less. To test // type checks also for the depth overflow, we provide a hierarchy 9 levels deep. // Make sure the bitstrings are initialized. for (int i = 0; i <= 8192; ++i) { Class.forName("Level1Class" + i).newInstance(); } for (int i = 0; i <= 1024; ++i) { Class.forName("Level2Class" + i).newInstance(); } // Note: Using a different class for tests so that verification of Main.main() does // not try to resolve classes used by the tests. This guarantees uninitialized type // check bitstrings when we enter Main.main() and start initializing them above. Helper.testInstanceOf(); Helper.testCheckCast(); } } class Helper { public static void testInstanceOf() throws Exception { for (int i = 1; i <= 9; ++i) { Object o = createInstance("Level" + i + "Class0"); assertTrue(o instanceof Level1Class0); if (o instanceof Level2Class0) { assertFalse(i < 2); } else { assertTrue(i < 2); } if (o instanceof Level3Class0) { assertFalse(i < 3); } else { assertTrue(i < 3); } if (o instanceof Level4Class0) { assertFalse(i < 4); } else { assertTrue(i < 4); } if (o instanceof Level5Class0) { assertFalse(i < 5); } else { assertTrue(i < 5); } if (o instanceof Level6Class0) { assertFalse(i < 6); } else { assertTrue(i < 6); } if (o instanceof Level7Class0) { assertFalse(i < 7); } else { assertTrue(i < 7); } if (o instanceof Level8Class0) { assertFalse(i < 8); } else { assertTrue(i < 8); } if (o instanceof Level9Class0) { assertFalse(i < 9); } else { assertTrue(i < 9); } } assertTrue(createInstance("Level1Class8192") instanceof Level1Class8192); assertFalse(createInstance("Level1Class8192") instanceof Level1Class0); assertTrue(createInstance("Level2Class1024") instanceof Level2Class1024); assertTrue(createInstance("Level2Class1024") instanceof Level1Class0); assertFalse(createInstance("Level2Class1024") instanceof Level2Class0); } public static void testCheckCast() throws Exception { for (int i = 1; i <= 9; ++i) { Object o = createInstance("Level" + i + "Class0"); Level1Class0 l1c0 = (Level1Class0) o; try { Level2Class0 l2c0 = (Level2Class0) o; assertFalse(i < 2); } catch (ClassCastException cce) { assertTrue(i < 2); } try { Level3Class0 l3c0 = (Level3Class0) o; assertFalse(i < 3); } catch (ClassCastException cce) { assertTrue(i < 3); } try { Level4Class0 l4c0 = (Level4Class0) o; assertFalse(i < 4); } catch (ClassCastException cce) { assertTrue(i < 4); } try { Level5Class0 l5c0 = (Level5Class0) o; assertFalse(i < 5); } catch (ClassCastException cce) { assertTrue(i < 5); } try { Level6Class0 l6c0 = (Level6Class0) o; assertFalse(i < 6); } catch (ClassCastException cce) { assertTrue(i < 6); } try { Level7Class0 l7c0 = (Level7Class0) o; assertFalse(i < 7); } catch (ClassCastException cce) { assertTrue(i < 7); } try { Level8Class0 l8c0 = (Level8Class0) o; assertFalse(i < 8); } catch (ClassCastException cce) { assertTrue(i < 8); } try { Level9Class0 l9c0 = (Level9Class0) o; assertFalse(i < 9); } catch (ClassCastException cce) { assertTrue(i < 9); } } Level1Class8192 l1c8192 = (Level1Class8192) createInstance("Level1Class8192"); try { Level1Class0 l1c0 = (Level1Class0) createInstance("Level1Class8192"); throw new AssertionError("Unexpected"); } catch (ClassCastException expected) {} Level2Class1024 l2c1024 = (Level2Class1024) createInstance("Level2Class1024"); Level1Class0 l1c0 = (Level1Class0) createInstance("Level2Class1024"); try { Level2Class0 l2c0 = (Level2Class0) createInstance("Level2Class1024"); throw new AssertionError("Unexpected"); } catch (ClassCastException expected) {} } public static Object createInstance(String className) throws Exception { return Class.forName(className).newInstance(); } public static void assertTrue(boolean value) throws Exception { if (!value) { throw new AssertionError(); } } public static void assertFalse(boolean value) throws Exception { if (value) { throw new AssertionError(); } } } EOF ./default-build "$@"