From 5f97d461c819a42c52aa772499f0046db8fa1dda Mon Sep 17 00:00:00 2001 From: aclement Date: Wed, 7 May 2008 15:31:18 +0000 Subject: [PATCH] 230817: remap NPE - switch ordering in match to do exception handlers first and insert an extra NOP if required. --- .../aspectj/weaver/bcel/BcelClassWeaver.java | 77 +++++++++----- .../aspectj/weaver/bcel/LazyMethodGen.java | 100 ++++++++++-------- 2 files changed, 108 insertions(+), 69 deletions(-) diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java index 5ac6b975d..87c8b390a 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java @@ -62,6 +62,7 @@ import org.aspectj.apache.bcel.generic.PUTSTATIC; import org.aspectj.apache.bcel.generic.RET; import org.aspectj.apache.bcel.generic.ReturnInstruction; import org.aspectj.apache.bcel.generic.Select; +import org.aspectj.apache.bcel.generic.StoreInstruction; import org.aspectj.apache.bcel.generic.Tag; import org.aspectj.apache.bcel.generic.Type; import org.aspectj.apache.bcel.generic.annotation.AnnotationGen; @@ -2454,7 +2455,53 @@ class BcelClassWeaver implements IClassWeaver { BcelShadow enclosingShadow, List shadowAccumulator) { - Instruction i = ih.getInstruction(); + Instruction i = ih.getInstruction(); + + // Exception handlers (pr230817) + if (canMatch(Shadow.ExceptionHandler) && !Range.isRangeHandle(ih)) { + InstructionTargeter[] targeters = ih.getTargeters(); + if (targeters != null) { + for (int j = 0; j < targeters.length; j++) { + InstructionTargeter t = targeters[j]; + if (t instanceof ExceptionRange) { + // assert t.getHandler() == ih + ExceptionRange er = (ExceptionRange) t; + if (er.getCatchType() == null) continue; + if (isInitFailureHandler(ih)) return; + + if (!(ih.getInstruction() instanceof StoreInstruction) && ih.getInstruction().getOpcode()!=Constants.NOP) { + // If using cobertura, the catch block stats with INVOKESTATIC rather than ASTORE, in order that the ranges + // for the methodcall and exceptionhandler shadows that occur at this same + // line, we need to modify the instruction list to split them - adding a + // NOP before the invokestatic that gets all the targeters + // that were aimed at the INVOKESTATIC + mg.getBody().insert(ih,InstructionConstants.NOP); + InstructionHandle newNOP = ih.getPrev(); + // what about a try..catch that starts at the start of the exception handler? need to only include certain targeters really. + er.updateTarget(ih, newNOP,mg.getBody()); + for (int ii=0;ii= 0; i--) { - assertGoodTargeter(ts[i], ih, body, from); - } - } - } + if (true) return; // only to be enabled for debugging // should be switchonable via an option + StringBuffer assertionLog = new StringBuffer(); + assertionLog.append("Checking state of an instruction body, from="+from+"\n"); + try { + if (il == null) return; + Set body = new HashSet(); + Stack ranges = new Stack(); + for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) { + body.add(ih); + if (ih.getInstruction() instanceof BranchInstruction) { + body.add(ih.getInstruction()); + } + } + + for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) { + assertGoodHandle(ih, body, ranges, from, assertionLog); + InstructionTargeter[] ts = ih.getTargeters(); + if (ts != null) { + for (int i = ts.length - 1; i >= 0; i--) { + assertGoodTargeter(ts[i], ih, body, from, assertionLog); + } + } + } + } catch (RuntimeException re) { + System.err.println(assertionLog.toString()); + throw re; + } } - private static void assertGoodHandle(InstructionHandle ih, Set body, Stack ranges, String from) { + private static void assertGoodHandle(InstructionHandle ih, Set body, Stack ranges, String from, StringBuffer log) { Instruction inst = ih.getInstruction(); if ((inst instanceof BranchInstruction) ^ (ih instanceof BranchHandle)) { throw new BCException("bad instruction/handle pair in " + from); } if (Range.isRangeHandle(ih)) { - assertGoodRangeHandle(ih, body, ranges, from); + log.append("Checking range handle '"+ih+"'\n"); + assertGoodRangeHandle(ih, body, ranges, from,log); } else if (inst instanceof BranchInstruction) { - assertGoodBranchInstruction((BranchHandle) ih, (BranchInstruction) inst, body, ranges, from); + assertGoodBranchInstruction((BranchHandle) ih, (BranchInstruction) inst, body, ranges, from, log); } } @@ -1376,32 +1384,33 @@ public final class LazyMethodGen implements Traceable { BranchInstruction inst, Set body, Stack ranges, - String from) + String from, StringBuffer log) { if (ih.getTarget() != inst.getTarget()) { throw new BCException("bad branch instruction/handle pair in " + from); } InstructionHandle target = ih.getTarget(); - assertInBody(target, body, from); + assertInBody(target, body, from, log); assertTargetedBy(target, inst, from); if (inst instanceof Select) { Select sel = (Select) inst; InstructionHandle[] itargets = sel.getTargets(); for (int k = itargets.length - 1; k >= 0; k--) { - assertInBody(itargets[k], body, from); + assertInBody(itargets[k], body, from, log); + assertTargetedBy(itargets[k], inst, from); } } } /** ih is an InstructionHandle or a BranchInstruction */ - private static void assertInBody(Object ih, Set body, String from) { + private static void assertInBody(Object ih, Set body, String from,StringBuffer log) { if (! body.contains(ih)) throw new BCException("thing not in body in " + from); } - private static void assertGoodRangeHandle(InstructionHandle ih, Set body, Stack ranges, String from) { + private static void assertGoodRangeHandle(InstructionHandle ih, Set body, Stack ranges, String from, StringBuffer log) { Range r = getRangeAndAssertExactlyOne(ih, from); - assertGoodRange(r, body, from); + assertGoodRange(r, body, from, log); if (r.getStart() == ih) { ranges.push(r); } else if (r.getEnd() == ih) { @@ -1410,18 +1419,23 @@ public final class LazyMethodGen implements Traceable { } } - private static void assertGoodRange(Range r, Set body, String from) { - assertInBody(r.getStart(), body, from); + private static void assertGoodRange(Range r, Set body, String from, StringBuffer log) { + assertInBody(r.getStart(), body, from, log); assertRangeHandle(r.getStart(), from); assertTargetedBy(r.getStart(), r, from); - assertInBody(r.getEnd(), body, from); + assertInBody(r.getEnd(), body, from, log); assertRangeHandle(r.getEnd(), from); assertTargetedBy(r.getEnd(), r, from); if (r instanceof ExceptionRange) { ExceptionRange er = (ExceptionRange) r; - assertInBody(er.getHandler(), body, from); + log.append("Checking exception range \n"); + if (!body.contains(er.getHandler())) { + log.append("Exception handler not within body\n"); + throw new BCException("exception handler not in body"); + } +// assertInBody(er.getHandler(), body, from, log); assertTargetedBy(er.getHandler(), r, from); } } @@ -1485,13 +1499,13 @@ public final class LazyMethodGen implements Traceable { InstructionTargeter t, InstructionHandle ih, Set body, - String from) + String from, StringBuffer log) { assertTargets(t, ih, from); if (t instanceof Range) { - assertGoodRange((Range) t, body, from); + assertGoodRange((Range) t, body, from, log); } else if (t instanceof BranchInstruction) { - assertInBody(t, body, from); + assertInBody(t, body, from, log); } } -- 2.39.5