From 66de068c66836735fe3d1e138b8927361333a410 Mon Sep 17 00:00:00 2001 From: Jeff Disher Date: Wed, 30 Jan 2019 13:13:18 -0500 Subject: [PATCH] Re #335: NoSuchMethodError shouldn't be fatal to the AVM -this renders safe the DApp-level failure mode associated with default methods (although this could have been done more directly, through nefarious means) --- .../aion/avm/core/persistence/LoadedDApp.java | 5 +++- .../DefaultMethodIntegrationTest.java | 30 +++++-------------- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/org.aion.avm.core/src/org/aion/avm/core/persistence/LoadedDApp.java b/org.aion.avm.core/src/org/aion/avm/core/persistence/LoadedDApp.java index bffd2a732..b4af86135 100644 --- a/org.aion.avm.core/src/org/aion/avm/core/persistence/LoadedDApp.java +++ b/org.aion.avm.core/src/org/aion/avm/core/persistence/LoadedDApp.java @@ -278,6 +278,9 @@ public void forceInitializeAllClasses() throws Throwable { } catch (ExceptionInInitializerError e) { // handle the real exception handleUncaughtException(e.getException()); + } catch (Throwable t) { + // Some other exceptions can float out from the user clinit, not always wrapped in ExceptionInInitializerError. + handleUncaughtException(t); } } } @@ -292,7 +295,7 @@ private void handleUncaughtException(Throwable cause) throws Throwable { throw cause; // thrown by runtime, but is never handled - } else if (cause instanceof RuntimeException) { + } else if ((cause instanceof RuntimeException) || (cause instanceof Error)) { throw new UncaughtException(cause); // thrown by users diff --git a/org.aion.avm.core/test/org/aion/avm/core/shadowing/DefaultMethodIntegrationTest.java b/org.aion.avm.core/test/org/aion/avm/core/shadowing/DefaultMethodIntegrationTest.java index 3ac8e0446..8f1e8d5fe 100644 --- a/org.aion.avm.core/test/org/aion/avm/core/shadowing/DefaultMethodIntegrationTest.java +++ b/org.aion.avm.core/test/org/aion/avm/core/shadowing/DefaultMethodIntegrationTest.java @@ -39,11 +39,7 @@ public void setup() { @After public void tearDown() { - try { - this.avm.shutdown(); - } catch (AssertionError e) { - // Note that this is just an echo of the issue pointed out below (it stays in the AVM instance). - } + this.avm.shutdown(); } @Test @@ -57,15 +53,9 @@ public void testMissingDefaultInClinit() throws Exception { long energyPrice = 1l; Transaction create = Transaction.create(deployer, kernel.getNonce(deployer), BigInteger.ZERO, txData, energyLimit, energyPrice); - // Getting the result code will trigger the internal exception to be thrown back to us - we are expecting AssertionError. - boolean didCatchAssertionError = false; - try { - // This should show up as an uncaught exception (we can't statically prove that the method isn't there, on create). - avm.run(new TransactionContext[] {new TransactionContextImpl(create, block)})[0].get(); - } catch (AssertionError e) { - didCatchAssertionError = true; - } - Assert.assertTrue(didCatchAssertionError); + // The NoSuchMethodError triggers a "FAILED_EXCEPTION" state. + AvmTransactionResult result = (AvmTransactionResult) avm.run(new TransactionContext[] {new TransactionContextImpl(create, block)})[0].get(); + Assert.assertEquals(AvmTransactionResult.Code.FAILED_EXCEPTION, result.getResultCode()); } @Test @@ -86,14 +76,8 @@ public void testMissingDefaultInMain() throws Exception { byte[] argData = new byte[0]; Transaction call = Transaction.call(deployer, AvmAddress.wrap(contractAddr.unwrap()), kernel.getNonce(deployer), BigInteger.ZERO, argData, energyLimit, 1l); - // Getting the result code will trigger the internal exception to be thrown back to us - we are expecting AssertionError. - boolean didCatchAssertionError = false; - try { - // This should show up as an uncaught exception (we can't statically prove that the method isn't there, on create). - avm.run(new TransactionContext[] {new TransactionContextImpl(call, block)})[0].get(); - } catch (AssertionError e) { - didCatchAssertionError = true; - } - Assert.assertTrue(didCatchAssertionError); + // The NoSuchMethodError triggers a "FAILED_EXCEPTION" state. + AvmTransactionResult result = (AvmTransactionResult) avm.run(new TransactionContext[] {new TransactionContextImpl(call, block)})[0].get(); + Assert.assertEquals(AvmTransactionResult.Code.FAILED_EXCEPTION, result.getResultCode()); } }