Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to apply jb to some method. #1975

Open
evilpan opened this issue Jun 12, 2023 · 1 comment
Open

Failed to apply jb to some method. #1975

evilpan opened this issue Jun 12, 2023 · 1 comment

Comments

@evilpan
Copy link

evilpan commented Jun 12, 2023

Please examine each of the following points so that we can help you as soon and best as possible.

Describe the bug
While calling retrieveActiveBody on some method, soot will throws RuntimeException: Failed to apply jb to <org.springframework.http.client.Netty4ClientHttpRequest: org.springframework.util.concurrent.ListenableFuture executeInternal(org.springframework.http.HttpHeaders)>

Input file
Spring-Web 5.2.2.jar

To reproduce

Soot cofig option:

    Options.v().set_app(false)
    Options.v().set_debug(false)
    Options.v().set_verbose(false)
    Options.v().set_validate(false)
    Options.v().set_whole_program(true) // false got less phantom class
    Options.v().set_wrong_staticness(Options.wrong_staticness_ignore)
    // keep debugging info
    Options.v().set_keep_line_number(true)
    Options.v().set_keep_offset(true)
    // ignore library code
    Options.v().set_no_bodies_for_excluded(true)
    Options.v().set_allow_phantom_refs(true)
    // keep variable names
    Options.v().setPhaseOption("jb", "use-original-names:true")
    Options.v().setPhaseOption("jb.sils", "enabled:false")

    // Options.v().set_no_writeout_body_releasing(true);
    Options.v().set_drop_bodies_after_load(false);

Processing code:

    val total = Scene.v.getApplicationClasses.size()
    println(s"Start parsing $total classes")
    for ((c, i) <- Scene.v.getApplicationClasses().zipWithIndex) {
      for (m <- c.getMethods()) {
        if (!Modifier.isAbstract(m.getModifiers()) && !Modifier.isNative(m.getModifiers())) {
          try {
            val body = m.retrieveActiveBody()
          } catch {
            case ex: Exception => ex.printStackTrace()
          }
        }
      }
    }

Expected behavior
A clear and concise description of what you expected to happen.

Stacktrace

java.lang.RuntimeException: Failed to apply jb to <org.springframework.http.client.Netty4ClientHttpRequest: org.springframework.util.concurrent.ListenableFuture executeInternal(org.springframework.http.HttpHeaders)>
	at soot.asm.AsmMethodSource.getBody(AsmMethodSource.java:2281)
	at soot.SootMethod.retrieveActiveBody(SootMethod.java:447)
        ...

Caused by: java.lang.RuntimeException: This operation requires resolving level HIERARCHY but io.netty.channel.ChannelFutureListener is at resolving level DANGLING
If you are extending Soot, try to add the following call before calling soot.Main.main(..):
Scene.v().addBasicClass(io.netty.channel.ChannelFutureListener,HIERARCHY);
Otherwise, try whole-program mode (-w).
	at soot.SootClass.checkLevelIgnoreResolving(SootClass.java:210)
	at soot.SootClass.checkLevel(SootClass.java:192)
	at soot.FastHierarchy.canStoreClass(FastHierarchy.java:384)
	at soot.FastHierarchy.canStoreType(FastHierarchy.java:293)
	at soot.jimple.toolkits.typing.fast.BytecodeHierarchy.ancestor_(BytecodeHierarchy.java:230)
	at soot.jimple.toolkits.typing.fast.BytecodeHierarchy.ancestor(BytecodeHierarchy.java:288)
	at soot.jimple.toolkits.typing.fast.TypeResolver$CastInsertionUseVisitor.visit(TypeResolver.java:224)
	at soot.jimple.toolkits.typing.fast.IUseVisitor.visit(IUseVisitor.java:38)
	at soot.jimple.toolkits.typing.fast.UseChecker.handleInvokeExpr(UseChecker.java:153)
	at soot.jimple.toolkits.typing.fast.UseChecker.caseAssignStmt(UseChecker.java:416)
	at soot.jimple.internal.JAssignStmt.apply(JAssignStmt.java:217)
	at soot.jimple.toolkits.typing.fast.UseChecker.check(UseChecker.java:140)
	at soot.jimple.toolkits.typing.fast.TypeResolver.insertCasts(TypeResolver.java:369)
	at soot.jimple.toolkits.typing.fast.TypeResolver.minCasts(TypeResolver.java:392)
	at soot.jimple.toolkits.typing.fast.TypeResolver.inferTypes(TypeResolver.java:159)
	at soot.jimple.toolkits.typing.TypeAssigner.internalTransform(TypeAssigner.java:129)
	at soot.BodyTransformer.transform(BodyTransformer.java:47)
	at soot.Transform.apply(Transform.java:126)
	at soot.JimpleBodyPack.applyPhaseOptions(JimpleBodyPack.java:79)
	at soot.JimpleBodyPack.internalApply(JimpleBodyPack.java:112)
	at soot.Pack.apply(Pack.java:126)
	at soot.asm.AsmMethodSource.getBody(AsmMethodSource.java:2279)
	... 39 more

Additional context
I've also tried whole-program mode (-w) and got the same result.

Just for your information, the source code of the method which throws exception is:

https://github.com/spring-projects/spring-framework/blob/5.2.x/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpRequest.java#L113

In the method a lambda experession is assigned to functional interface io.netty.channel.ChannelFutureListener, which is not in classpath so the resolving level is DANGLING. Is there any workaround to still get Jimple body of that method anyway?

BTW, the bytecode of ChannelFutureListener connectionListener = future -> {} is:

invokedynamic java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; : operationComplete(Lorg/springframework/http/client/Netty4ClientHttpRequest;Lorg/springframework/util/concurrent/SettableListenableFuture;Lorg/springframework/http/HttpHeaders;)Lio/netty/channel/ChannelFutureListener; (Lio/netty/util/concurrent/Future;)V org/springframework/http/client/Netty4ClientHttpRequest.lambda$executeInternal$0(Lorg/springframework/util/concurrent/SettableListenableFuture;Lorg/springframework/http/HttpHeaders;Lio/netty/channel/ChannelFuture;)V (7) (Lio/netty/channel/ChannelFuture;)V
@jsantibout-pjr
Copy link

jsantibout-pjr commented Jun 22, 2023

In the messages it states

If you are extending Soot, try to add the following call before calling soot.Main.main(..):
Scene.v().addBasicClass(io.netty.channel.ChannelFutureListener,HIERARCHY);
Otherwise, try whole-program mode (-w).

Adding Scene.v().addBasicClass(io.netty.channel.ChannelFutureListener,HIERARCHY); before you load classes should work.

In a case we've dealt with we added it before Scene.v().loadNecessaryClasses();
The lambda expression does not exist in the input so you cannot get the method body of the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants