Skip to content

Commit

Permalink
Added stack monitor for advice code to avoid that stack underflows ge…
Browse files Browse the repository at this point in the history
…nerate verifier errors for irregular advice code.
  • Loading branch information
raphw committed Jul 15, 2016
1 parent 175d1ba commit 4073031
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -25,7 +25,7 @@ matrix:
- jdk: oraclejdk7
env: TARGET=-Pjava7

script: mvn verify $TARGET -Pintegration -Dnet.bytebuddy.travis=true
script: mvn verify $TARGET -Pintegration -Dnet.bytebuddy.test.travis=true

after_success:
- mvn clean cobertura:cobertura coveralls:report -Pintegration
14 changes: 13 additions & 1 deletion byte-buddy-dep/src/main/java/net/bytebuddy/asm/Advice.java
Expand Up @@ -5784,7 +5784,9 @@ protected ExceptionTableSubstitutor(MethodVisitor methodVisitor) {
public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
substitutions.put(start, labels.get(index++));
substitutions.put(end, labels.get(index++));
substitutions.put(handler, labels.get(index++));
Label actualHandler = labels.get(index++);
substitutions.put(handler, actualHandler);
((CodeTranslationVisitor) mv).propagateHandler(actualHandler);
}

@Override
Expand Down Expand Up @@ -6328,6 +6330,16 @@ protected CodeTranslationVisitor(MethodVisitor methodVisitor,
endOfMethod = new Label();
}

/**
* Propagates a label for an exception handler that is typically suppressed by the overlaying
* {@link Resolved.AdviceMethodInliner.ExceptionTableSubstitutor}.
*
* @param label The label to register as a target for an exception handler.
*/
protected void propagateHandler(Label label) {
((StackAwareMethodVisitor) mv).register(label, Collections.singletonList(StackSize.SINGLE));
}

@Override
public void visitParameter(String name, int modifiers) {
/* do nothing */
Expand Down
Expand Up @@ -146,6 +146,16 @@ private void doDrain(List<StackSize> stackSizes) {
}
}

/**
* Explicitly registers a label to define a given stack state.
*
* @param label The label to register a stack state for.
* @param stackSizes The stack sizes to assume when reaching the supplied label.
*/
public void register(Label label, List<StackSize> stackSizes) {
sizes.put(label, stackSizes);
}

@Override
public void visitInsn(int opcode) {
switch (opcode) {
Expand Down
Expand Up @@ -64,7 +64,7 @@ public class AgentBuilderDefaultApplicationTest {
@Parameterized.Parameters
public static Collection<Object[]> data() {
// Travis runs out of memory if all of these tests are run. This property serves as a protection (on some profiles).
if (Boolean.getBoolean("net.bytebuddy.travis")) {
if (Boolean.getBoolean("net.bytebuddy.test.travis")) {
Logger.getLogger("net.bytebuddy").info("Only running agent application with a single type locator on Travis CI server");
return Arrays.asList(new Object[][]{{AgentBuilder.TypeLocator.Default.FAST}});
}
Expand Down
Expand Up @@ -10,7 +10,7 @@

public class IntegrationRule implements MethodRule {

private static final String PROPERTY_KEY = "net.bytebuddy.property.integration";
private static final String PROPERTY_KEY = "net.bytebuddy.test.integration";

private final boolean integration;

Expand Down
Expand Up @@ -9,9 +9,12 @@
import org.junit.rules.TestRule;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import java.util.Arrays;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.mockito.Mockito.*;
Expand Down Expand Up @@ -125,6 +128,20 @@ public void testDrainFreeList() throws Exception {
verifyNoMoreInteractions(this.methodVisitor);
}

@Test
public void testManualRegistration() throws Exception {
StackAwareMethodVisitor methodVisitor = new StackAwareMethodVisitor(this.methodVisitor, methodDescription);
Label label = new Label();
methodVisitor.register(label, Arrays.asList(StackSize.DOUBLE, StackSize.SINGLE));
methodVisitor.visitLabel(label);
methodVisitor.drainStack();
InOrder inOrder = inOrder(this.methodVisitor);
inOrder.verify(this.methodVisitor).visitLabel(label);
inOrder.verify(this.methodVisitor).visitInsn(Opcodes.POP);
inOrder.verify(this.methodVisitor).visitInsn(Opcodes.POP2);
verifyNoMoreInteractions(this.methodVisitor);
}

@Test
public void testStackCanUnderflow() throws Exception {
StackAwareMethodVisitor methodVisitor = new StackAwareMethodVisitor(this.methodVisitor, methodDescription);
Expand Down

0 comments on commit 4073031

Please sign in to comment.