Skip to content

Commit

Permalink
Re #335: NoSuchMethodError shouldn't be fatal to the AVM
Browse files Browse the repository at this point in the history
-this renders safe the DApp-level failure mode associated with default methods (although this could have been done more directly, through nefarious means)
  • Loading branch information
jeff-aion committed Jan 30, 2019
1 parent 14be99e commit 66de068
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 24 deletions.
Expand Up @@ -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);
}
}
}
Expand All @@ -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
Expand Down
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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());
}
}

0 comments on commit 66de068

Please sign in to comment.