[frontend] support Java 8

Summary:
Our patch to Javalib has been accepted, so we can parse programs with invokedynamic!
invokedynamic still crashes Sawja, but I have worked around this by replacing all invokedynamic's with invokestatic's before passing them to Sawja.
This means we can handle everything about invokedynamic except calling the correct function (I call a dummy function with the correct signature for now).
We can try to actually call the right method in the future.

Reviewed By: jvillard

Differential Revision: D4160384

fbshipit-source-id: a8ef4e1
master
Sam Blackshear 8 years ago committed by Facebook Github Bot
parent b792d04fbd
commit 75d6fb30e4

@ -1,3 +1,7 @@
[project] [project]
ignore = .git, .ml, .mli ignore = .git, .ml, .mli
[java]
source_level = 8
target_level = 8

@ -199,8 +199,8 @@ if test "x$enable_java_analyzers" = "xyes"; then
AC_CHECK_TOOL([JAVAC], [javac], [no]) AC_CHECK_TOOL([JAVAC], [javac], [no])
AC_ASSERT_PROG([javac], [$JAVAC]) AC_ASSERT_PROG([javac], [$JAVAC])
AC_ASSERT_PROG([java], [$JAVA]) AC_ASSERT_PROG([java], [$JAVA])
AC_ASSERT_OCAML_PKG([javalib], [], [2.3.1]) AC_ASSERT_OCAML_PKG([javalib], [], [2.3.3])
AC_ASSERT_OCAML_PKG([sawja], [], [1.5.1]) AC_ASSERT_OCAML_PKG([sawja], [], [1.5.2])
AC_ASSERT_OCAML_PKG([ptrees]) AC_ASSERT_OCAML_PKG([ptrees])
AC_MSG_CHECKING([for JAVA_HOME]) AC_MSG_CHECKING([for JAVA_HOME])

@ -14,7 +14,7 @@ ANNOT_SOURCES = $(shell find com/facebook/infer/annotation -name "*.java")
PROCESSOR_SOURCES = $(shell find com/facebook/infer/annotprocess -name "*.java") PROCESSOR_SOURCES = $(shell find com/facebook/infer/annotprocess -name "*.java")
ANNOT_CLASSES = 'annot_classes' ANNOT_CLASSES = 'annot_classes'
PROCESSOR_CLASSES = 'processor_classes' PROCESSOR_CLASSES = 'processor_classes'
TARGET_JDK_VERSION = '1.7' TARGET_JDK_VERSION = '1.8'
ANNOTATIONS_JAR = $(CWD)/annotations.jar ANNOTATIONS_JAR = $(CWD)/annotations.jar
PROCESSOR_JAR = $(JAVA_LIB_DIR)/processor.jar PROCESSOR_JAR = $(JAVA_LIB_DIR)/processor.jar

@ -217,7 +217,21 @@ let get_implementation cm =
let cn, ms = JBasics.cms_split cms in let cn, ms = JBasics.cms_split cms in
failwithf "native method %s found in %s@." (JBasics.ms_name ms) (JBasics.cn_name cn) failwithf "native method %s found in %s@." (JBasics.ms_name ms) (JBasics.cn_name cn)
| Javalib.Java t -> | Javalib.Java t ->
JBir.transform ~bcv: false ~ch_link: false ~formula: false ~formula_cmd:[] cm (Lazy.force t) (* Sawja doesn't handle invokedynamic, and it will crash with a Match_failure if we give it
bytecode with this instruction. hack around this problem by converting all invokedynamic's
to invokestatic's that call a method with the same signature as the lambda on
java.lang.Object. this isn't great, but it's a lot better than crashing *)
let code = Lazy.force t in
let c_code =
Array.map
(function
| (JCode.OpInvoke (`Dynamic _, ms)) ->
JCode.OpInvoke (`Static JBasics.java_lang_object, ms)
| opcode ->
opcode)
code.JCode.c_code in
let code' = { code with JCode.c_code; } in
JBir.transform ~bcv: false ~ch_link: false ~formula: false ~formula_cmd:[] cm code'
let update_constr_loc cn ms loc_start = let update_constr_loc cn ms loc_start =
if (JBasics.ms_name ms) = JConfig.constructor_name then if (JBasics.ms_name ms) = JConfig.constructor_name then

@ -7,10 +7,8 @@
<target name="compile"> <target name="compile">
<mkdir dir="ant_out"/> <mkdir dir="ant_out"/>
<javac srcdir="src/infer" destdir="ant_out" includeantruntime="false"> <javac srcdir="src/infer" destdir="ant_out" includeantruntime="false">
<bootclasspath>
<pathelement location="../../../lib/java/android/android-19.jar"/>
</bootclasspath>
<classpath> <classpath>
<pathelement location="../../../lib/java/android/android-19.jar"/>
<pathelement location="../../../../dependencies/java/jackson/jackson-2.2.3.jar"/> <pathelement location="../../../../dependencies/java/jackson/jackson-2.2.3.jar"/>
<pathelement location="../../../lib/java/models.jar"/> <pathelement location="../../../lib/java/models.jar"/>
<pathelement location="../../../annotations//annotations.jar"/> <pathelement location="../../../annotations//annotations.jar"/>

@ -64,6 +64,8 @@ src/infer/GuardedByExample.java, void GuardedByExample.writeFBad(), 1, UNSAFE_GU
src/infer/GuardedByExample.java, void GuardedByExample.writeFBadWrongLock(), 2, UNSAFE_GUARDED_BY_ACCESS src/infer/GuardedByExample.java, void GuardedByExample.writeFBadWrongLock(), 2, UNSAFE_GUARDED_BY_ACCESS
src/infer/HashMapExample.java, int HashMapExample.getOneIntegerWithoutCheck(), 6, NULL_DEREFERENCE src/infer/HashMapExample.java, int HashMapExample.getOneIntegerWithoutCheck(), 6, NULL_DEREFERENCE
src/infer/HashMapExample.java, void HashMapExample.getTwoIntegersWithOneCheck(Integer,Integer), 11, NULL_DEREFERENCE src/infer/HashMapExample.java, void HashMapExample.getTwoIntegersWithOneCheck(Integer,Integer), 11, NULL_DEREFERENCE
src/infer/InvokeDynamic.java, int InvokeDynamic.lambda$npeInLambdaBad$1(String,String), 1, NULL_DEREFERENCE
src/infer/InvokeDynamic.java, void InvokeDynamic.invokeDynamicThenNpeBad(List), 5, NULL_DEREFERENCE
src/infer/NullPointerExceptions.java, String NullPointerExceptions.hashmapNPE(HashMap,Object), 1, NULL_DEREFERENCE src/infer/NullPointerExceptions.java, String NullPointerExceptions.hashmapNPE(HashMap,Object), 1, NULL_DEREFERENCE
src/infer/NullPointerExceptions.java, String NullPointerExceptions.nullTryLock(FileChannel), 2, NULL_DEREFERENCE src/infer/NullPointerExceptions.java, String NullPointerExceptions.nullTryLock(FileChannel), 2, NULL_DEREFERENCE
src/infer/NullPointerExceptions.java, String NullPointerExceptions.testSystemGetPropertyArgument(), 1, NULL_DEREFERENCE src/infer/NullPointerExceptions.java, String NullPointerExceptions.testSystemGetPropertyArgument(), 1, NULL_DEREFERENCE

@ -474,6 +474,11 @@
"file": "infer/tests/codetoanalyze/java/infer/DynamicDispatch.java", "file": "infer/tests/codetoanalyze/java/infer/DynamicDispatch.java",
"procedure": "void DynamicDispatch.interfaceShouldNotCauseFalseNegativeHard(DynamicDispatch$Interface)" "procedure": "void DynamicDispatch.interfaceShouldNotCauseFalseNegativeHard(DynamicDispatch$Interface)"
}, },
{
"bug_type": "NULL_DEREFERENCE",
"file": "infer/tests/codetoanalyze/java/infer/InvokeDynamic.java",
"procedure": "void InvokeDynamic.invokeDynamicThenNpeBad(List)"
},
{ {
"bug_type": "RESOURCE_LEAK", "bug_type": "RESOURCE_LEAK",
"file": "infer/tests/codetoanalyze/java/infer/ResourceLeaks.java", "file": "infer/tests/codetoanalyze/java/infer/ResourceLeaks.java",
@ -489,6 +494,11 @@
"file": "infer/tests/codetoanalyze/java/infer/ResourceLeaks.java", "file": "infer/tests/codetoanalyze/java/infer/ResourceLeaks.java",
"procedure": "void ResourceLeaks.jarOutputStreamLeak()" "procedure": "void ResourceLeaks.jarOutputStreamLeak()"
}, },
{
"bug_type": "NULL_DEREFERENCE",
"file": "infer/tests/codetoanalyze/java/infer/InvokeDynamic.java",
"procedure": "int InvokeDynamic.lambda$npeInLambdaBad$1(String,String)"
},
{ {
"bug_type": "RESOURCE_LEAK", "bug_type": "RESOURCE_LEAK",
"file": "infer/tests/codetoanalyze/java/infer/CloseableAsResourceExample.java", "file": "infer/tests/codetoanalyze/java/infer/CloseableAsResourceExample.java",

@ -0,0 +1,41 @@
/*
* Copyright (c) 2016 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package codetoanalyze.java.infer;
import java.util.Collections;
import java.util.List;
public class InvokeDynamic {
void invokeDynamicThenNpeBad(List<String> list) {
Object o = null;
Collections.sort(list, (String a, String b) -> {
return b.compareTo(a);
});
o.toString();
}
void npeInLambdaBad(List<String> list) {
Collections.sort(list, (String a, String b) -> {
Object o = null;
o.toString();
return b.compareTo(a);
});
}
// we won't get this one because we don't actually translate the invocation of the lambda
void FN_npeViaCaptureBad(List<String> list) {
String s = null;
Collections.sort(list, (String a, String b) -> {
return s.compareTo(a);
});
}
}

@ -153,6 +153,10 @@ HashMapExample.java, void HashMapExample.putIntegerTwiceThenGetTwice(HashMap), 1
HashMapExample.java, void HashMapExample.putIntegerTwiceThenGetTwice(HashMap), 13, RETURN_VALUE_IGNORED HashMapExample.java, void HashMapExample.putIntegerTwiceThenGetTwice(HashMap), 13, RETURN_VALUE_IGNORED
HashMapExample.java, void HashMapExample.putIntegerTwiceThenGetTwice(HashMap), 6, RETURN_VALUE_IGNORED HashMapExample.java, void HashMapExample.putIntegerTwiceThenGetTwice(HashMap), 6, RETURN_VALUE_IGNORED
HashMapExample.java, void HashMapExample.putIntegerTwiceThenGetTwice(HashMap), 7, RETURN_VALUE_IGNORED HashMapExample.java, void HashMapExample.putIntegerTwiceThenGetTwice(HashMap), 7, RETURN_VALUE_IGNORED
InvokeDynamic.java, int InvokeDynamic.lambda$npeInLambdaBad$1(String,String), 1, ANALYSIS_STOPS
InvokeDynamic.java, int InvokeDynamic.lambda$npeInLambdaBad$1(String,String), 1, NULL_DEREFERENCE
InvokeDynamic.java, void InvokeDynamic.invokeDynamicThenNpeBad(List), 5, ANALYSIS_STOPS
InvokeDynamic.java, void InvokeDynamic.invokeDynamicThenNpeBad(List), 5, NULL_DEREFERENCE
JunitAssertion.java, void JunitAssertion.consistentAssertion(JunitAssertion$A), 1, PRECONDITION_NOT_MET JunitAssertion.java, void JunitAssertion.consistentAssertion(JunitAssertion$A), 1, PRECONDITION_NOT_MET
JunitAssertion.java, void JunitAssertion.inconsistentAssertion(JunitAssertion$A), 2, ANALYSIS_STOPS JunitAssertion.java, void JunitAssertion.inconsistentAssertion(JunitAssertion$A), 2, ANALYSIS_STOPS
JunitAssertion.java, void JunitAssertion.inconsistentAssertion(JunitAssertion$A), 2, NULL_DEREFERENCE JunitAssertion.java, void JunitAssertion.inconsistentAssertion(JunitAssertion$A), 2, NULL_DEREFERENCE

@ -30,7 +30,7 @@ depends: [
"core_extended" {>="113.33.03"} "core_extended" {>="113.33.03"}
"conf-autoconf" "conf-autoconf"
"extlib-compat" {>="1.5.4"} "extlib-compat" {>="1.5.4"}
"javalib" {>="2.3.2"} "javalib" {>="2.3.3"}
"ocamlfind" {build} "ocamlfind" {build}
"ounit" {="2.0.0"} "ounit" {="2.0.0"}
"reason" {>="1.4.0"} "reason" {>="1.4.0"}

@ -16,7 +16,7 @@
"@opam-alpha/ocaml": "4.2.3", "@opam-alpha/ocaml": "4.2.3",
"@opam-alpha/sawja": "^ 1.5.2", "@opam-alpha/sawja": "^ 1.5.2",
"@opam-alpha/atdgen": "^ 1.10.0", "@opam-alpha/atdgen": "^ 1.10.0",
"@opam-alpha/javalib": "^ 2.3.2", "@opam-alpha/javalib": "^ 2.3.3",
"@opam-alpha/extlib-compat": "1.7.0", "@opam-alpha/extlib-compat": "1.7.0",
"@opam-alpha/ounit": "2.0.0", "@opam-alpha/ounit": "2.0.0",
"@opam-alpha/ocp-indent": "1.5.3", "@opam-alpha/ocp-indent": "1.5.3",

@ -132,11 +132,11 @@
dependencies: dependencies:
fieldslib-actual "git://github.com/npm-opam/fieldslib.git#113.33.03" fieldslib-actual "git://github.com/npm-opam/fieldslib.git#113.33.03"
"@opam-alpha/javalib@^ 2.3.2", "@opam-alpha/javalib@>= 2.3.2": "@opam-alpha/javalib@^ 2.3.3", "@opam-alpha/javalib@>= 2.3.2":
version "2.3.2" version "2.3.3"
resolved javalib-2.3.2.tgz#be3b8e6f402256dad773e015430d8c129739899c resolved javalib-2.3.3.tgz#1cb16fe3bbc6998a13d3ae6725c1189989555a18
dependencies: dependencies:
javalib-actual "git://github.com/npm-opam/javalib.git#2.3.2" javalib-actual "git://github.com/npm-opam/javalib.git#2.3.3"
"@opam-alpha/js-build-tools@>= 113.33.04 < 113.34.00": "@opam-alpha/js-build-tools@>= 113.33.04 < 113.34.00":
version "113.33.4" version "113.33.4"
@ -680,12 +680,18 @@
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git" opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git" substs "https://github.com/yunxing/substs.git"
"dependency-env@git+https://github.com/reasonml/dependency-env.git", "dependency-env@https://github.com/npm-ml/dependency-env.git", "dependencyEnv@git+https://github.com/reasonml/dependency-env.git": "dependency-env@https://github.com/npm-ml/dependency-env.git", "dependency-env@https://github.com/reasonml/dependency-env.git":
version "0.0.0" version "0.0.0"
resolved dependency-env.git-b6710d7ccc0ea940ce55c4149675dd4ad6a9b94b#1dfad199e8cd9fba48513f85c1383874c7e83e5e resolved dependency-env.git-b6710d7ccc0ea940ce55c4149675dd4ad6a9b94b#1dfad199e8cd9fba48513f85c1383874c7e83e5e
dependencies: dependencies:
resolve "^1.1.7" resolve "^1.1.7"
"dependencyEnv@https://github.com/reasonml/dependency-env":
version "0.0.0"
resolved dependency-env-b6710d7ccc0ea940ce55c4149675dd4ad6a9b94b#1dfad199e8cd9fba48513f85c1383874c7e83e5e
dependencies:
resolve "^1.1.7"
"easy-format-actual@git://github.com/npm-opam/easy-format.git#1.2.0": "easy-format-actual@git://github.com/npm-opam/easy-format.git#1.2.0":
version "1.2.0" version "1.2.0"
resolved easy-format.git-955d4b4cd1748832aa7fb756c4ba1092759355de#43c15ccebcdf3fdc1412219b080226a3c8b62a54 resolved easy-format.git-955d4b4cd1748832aa7fb756c4ba1092759355de#43c15ccebcdf3fdc1412219b080226a3c8b62a54
@ -719,9 +725,9 @@
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git" opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git" substs "https://github.com/yunxing/substs.git"
"javalib-actual@git://github.com/npm-opam/javalib.git#2.3.2": "javalib-actual@git://github.com/npm-opam/javalib.git#2.3.3":
version "2.3.2" version "2.3.3"
resolved javalib.git-b767b73e51bbfb7fc3a420fbe8bb861036d39984#a763fba354b2de5bb9a7a7fd2928674aff45d4ad resolved javalib.git-e6ef415e81155658efac8ccc98c43963b611b8ec#c7b814034b9f08a77c9feaa40d6fc5fa4de29d68
dependencies: dependencies:
"@opam-alpha/camlp4" "*" "@opam-alpha/camlp4" "*"
"@opam-alpha/camlzip" ">= 1.05.0" "@opam-alpha/camlzip" ">= 1.05.0"
@ -807,7 +813,7 @@
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git" opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git" substs "https://github.com/yunxing/substs.git"
"nopam@git+https://github.com/reasonml/nopam.git", "nopam@https://github.com/yunxing/nopam.git": "nopam@https://github.com/reasonml/nopam.git", "nopam@https://github.com/yunxing/nopam.git":
version "0.0.1" version "0.0.1"
resolved nopam.git-8584695c8e2615857d4f58a0dec7bae3a9059a54#49cd1b4ccc32d588cdd3a671d4cc6d773803396b resolved nopam.git-8584695c8e2615857d4f58a0dec7bae3a9059a54#49cd1b4ccc32d588cdd3a671d4cc6d773803396b
@ -845,7 +851,7 @@
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git" opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git" substs "https://github.com/yunxing/substs.git"
"opam-installer-bin@git+https://github.com/yunxing/opam-installer-bin.git", "opam-installer-bin@https://github.com/yunxing/opam-installer-bin.git": "opam-installer-bin@https://github.com/yunxing/opam-installer-bin.git":
version "0.0.0" version "0.0.0"
resolved opam-installer-bin.git-689ede681217f76fb2f82a9f4528e192a5b543ba#b7704eda021a9fe18a9a37454868e1bbf102e0a0 resolved opam-installer-bin.git-689ede681217f76fb2f82a9f4528e192a5b543ba#b7704eda021a9fe18a9a37454868e1bbf102e0a0
dependencies: dependencies:
@ -1383,7 +1389,7 @@ resolve@^1.1.7:
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git" opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git" substs "https://github.com/yunxing/substs.git"
"substs@git+https://github.com/yunxing/substs.git", "substs@https://github.com/yunxing/substs.git": "substs@https://github.com/yunxing/substs.git":
version "0.0.1" version "0.0.1"
resolved substs.git-fd480dcdb4aed3fa9128fd819a546e3a7770040f#3a935dc6de26a5dfae899eca93a510bae55e57a4 resolved substs.git-fd480dcdb4aed3fa9128fd819a546e3a7770040f#3a935dc6de26a5dfae899eca93a510bae55e57a4
@ -1411,7 +1417,7 @@ resolve@^1.1.7:
opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git" opam-installer-bin "https://github.com/yunxing/opam-installer-bin.git"
substs "https://github.com/yunxing/substs.git" substs "https://github.com/yunxing/substs.git"
"tuareg@github:yunxing/tuareg": tuareg@yunxing/tuareg:
version "1.0.0" version "1.0.0"
resolved a90c0a2f202529a641d369c3b18b0c785a4a7e99#aa3a72a7726b1dd4fd1c809f893cc7ed6d2d420d resolved a90c0a2f202529a641d369c3b18b0c785a4a7e99#aa3a72a7726b1dd4fd1c809f893cc7ed6d2d420d

Loading…
Cancel
Save