From 2cccf8adcedd2b28175a8ae0c9cc5ad012de60f9 Mon Sep 17 00:00:00 2001 From: David Pichardie Date: Wed, 12 Feb 2020 06:36:59 -0800 Subject: [PATCH] Invokedynamic removing by class file rewriting Summary: Since Javalib 3.2, a new feature allows to rewrite methods that contain (some specific form of) closures. Infer now uses it. When loading each class we rewrite them and new classes generated by Javalib to implements closures (i.e. Java interfaces)< Reviewed By: ngorogiannis Differential Revision: D19389227 fbshipit-source-id: 245dd4404 --- infer/src/java/jClasspath.ml | 12 ++++++++++-- infer/tests/build_systems/ant/issues.exp | 2 +- infer/tests/codetoanalyze/java/infer/issues.exp | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/infer/src/java/jClasspath.ml b/infer/src/java/jClasspath.ml index c0906ffea..a31271595 100644 --- a/infer/src/java/jClasspath.ml +++ b/infer/src/java/jClasspath.ml @@ -256,8 +256,16 @@ let get_classpath_channel program = program.classpath.channel let get_models program = program.models let add_class cn jclass program = - program.classmap <- JBasics.ClassMap.add cn jclass program.classmap - + (* [prefix] must be a fresh class name *) + let prefix = JBasics.cn_name cn ^ "$Lambda$" in + (* we rewrite each class to replace invokedynamic (closure construction) + with equivalent old-style Java code that implements a suitable Java interface *) + let rewritten_jclass, new_classes = Javalib.remove_invokedynamics jclass ~prefix in + program.classmap <- JBasics.ClassMap.add cn rewritten_jclass program.classmap ; + (* the rewrite will generate new classes and we add them to the program *) + JBasics.ClassMap.iter + (fun cn jcl -> program.classmap <- JBasics.ClassMap.add cn jcl program.classmap) + new_classes let set_callee_translated program pname = Procname.Hash.replace program.callees pname Translated diff --git a/infer/tests/build_systems/ant/issues.exp b/infer/tests/build_systems/ant/issues.exp index 8662bf14d..8d89d1977 100644 --- a/infer/tests/build_systems/ant/issues.exp +++ b/infer/tests/build_systems/ant/issues.exp @@ -97,7 +97,7 @@ codetoanalyze/java/infer/HashMapExample.java, codetoanalyze.java.infer.HashMapEx codetoanalyze/java/infer/HashMapExample.java, codetoanalyze.java.infer.HashMapExample.getOneIntegerWithoutCheck():int, 5, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure getOneIntegerWithoutCheck()] codetoanalyze/java/infer/HashMapExample.java, codetoanalyze.java.infer.HashMapExample.getTwoIntegersWithOneCheck(java.lang.Integer,java.lang.Integer):void, 7, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure getTwoIntegersWithOneCheck(...),Taking true branch,Taking true branch] codetoanalyze/java/infer/IntegerExample.java, codetoanalyze.java.infer.IntegerExample.testIntegerEqualsBad():void, 5, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure testIntegerEqualsBad(),Taking true branch] -codetoanalyze/java/infer/InvokeDynamic.java, codetoanalyze.java.infer.InvokeDynamic.invokeDynamicThenNpeBad(java.util.List):void, 6, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure invokeDynamicThenNpeBad(...),Skipping sort(...): unknown method] +codetoanalyze/java/infer/InvokeDynamic.java, codetoanalyze.java.infer.InvokeDynamic.invokeDynamicThenNpeBad(java.util.List):void, 6, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure invokeDynamicThenNpeBad(...),start of procedure callsite_codetoanalyze.java.infer.InvokeDynamic$Lambda$_3_3(),return from a call to Comparator InvokeDynamic.callsite_codetoanalyze.java.infer.InvokeDynamic$Lambda$_3_3(),Skipping sort(...): unknown method] codetoanalyze/java/infer/InvokeDynamic.java, codetoanalyze.java.infer.InvokeDynamic.lambda$npeInLambdaBad$1(java.lang.String,java.lang.String):int, 1, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure lambda$npeInLambdaBad$1(...)] codetoanalyze/java/infer/Lists.java, codetoanalyze.java.infer.Lists.clearCausesEmptinessNPE(java.util.List,int):void, 4, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure clearCausesEmptinessNPE(...),Taking true branch,Taking true branch] codetoanalyze/java/infer/Lists.java, codetoanalyze.java.infer.Lists.getElementNPE(java.util.List):void, 3, NULL_DEREFERENCE, no_bucket, ERROR, [start of procedure getElementNPE(...),Taking false branch,start of procedure getElement(...),Taking true branch,return from a call to Object Lists.getElement(List)] diff --git a/infer/tests/codetoanalyze/java/infer/issues.exp b/infer/tests/codetoanalyze/java/infer/issues.exp index c0467b125..5e118a6e8 100644 --- a/infer/tests/codetoanalyze/java/infer/issues.exp +++ b/infer/tests/codetoanalyze/java/infer/issues.exp @@ -98,7 +98,7 @@ codetoanalyze/java/infer/HashMapExample.java, codetoanalyze.java.infer.HashMapEx codetoanalyze/java/infer/HashMapExample.java, codetoanalyze.java.infer.HashMapExample.getOneIntegerWithoutCheck():int, 5, NULL_DEREFERENCE, B1, ERROR, [start of procedure getOneIntegerWithoutCheck()] codetoanalyze/java/infer/HashMapExample.java, codetoanalyze.java.infer.HashMapExample.getTwoIntegersWithOneCheck(java.lang.Integer,java.lang.Integer):void, 7, NULL_DEREFERENCE, B2, ERROR, [start of procedure getTwoIntegersWithOneCheck(...),Taking true branch,Taking true branch] codetoanalyze/java/infer/IntegerExample.java, codetoanalyze.java.infer.IntegerExample.testIntegerEqualsBad():void, 5, NULL_DEREFERENCE, B1, ERROR, [start of procedure testIntegerEqualsBad(),Taking true branch] -codetoanalyze/java/infer/InvokeDynamic.java, codetoanalyze.java.infer.InvokeDynamic.invokeDynamicThenNpeBad(java.util.List):void, 6, NULL_DEREFERENCE, B1, ERROR, [start of procedure invokeDynamicThenNpeBad(...),Skipping sort(...): unknown method] +codetoanalyze/java/infer/InvokeDynamic.java, codetoanalyze.java.infer.InvokeDynamic.invokeDynamicThenNpeBad(java.util.List):void, 6, NULL_DEREFERENCE, B1, ERROR, [start of procedure invokeDynamicThenNpeBad(...),start of procedure callsite_codetoanalyze.java.infer.InvokeDynamic$Lambda$_3_3(),return from a call to Comparator InvokeDynamic.callsite_codetoanalyze.java.infer.InvokeDynamic$Lambda$_3_3(),Skipping sort(...): unknown method] codetoanalyze/java/infer/InvokeDynamic.java, codetoanalyze.java.infer.InvokeDynamic.lambda$npeInLambdaBad$1(java.lang.String,java.lang.String):int, 1, NULL_DEREFERENCE, B1, ERROR, [start of procedure lambda$npeInLambdaBad$1(...)] codetoanalyze/java/infer/JunitAssertion.java, codetoanalyze.java.infer.JunitAssertion.consistentAssertion(codetoanalyze.java.infer.JunitAssertion$A):void, 0, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure consistentAssertion(...),Taking false branch] codetoanalyze/java/infer/JunitAssertion.java, codetoanalyze.java.infer.JunitAssertion.inconsistentAssertion(codetoanalyze.java.infer.JunitAssertion$A):void, 1, NULL_DEREFERENCE, B5, ERROR, [start of procedure inconsistentAssertion(...),Taking false branch]