[infer][models] Fixing InferAssume

Summary:
@public
Using InferBuiltins.assume previously caused an assertion failure in the analyzer. Fixed this, and fixed the implementation of the assume builtin to block when the assumed condition cannot hold.

Test Plan: Added several new tests.
master
Sam Blackshear 10 years ago
parent 695c87377e
commit f6784e3796

@ -0,0 +1,7 @@
prebuilt_jar(
name = 'models',
binary_jar = 'models.jar',
visibility = [
'PUBLIC'
]
)

@ -9,6 +9,7 @@ package android.database;
import java.io.Closeable; import java.io.Closeable;
import com.facebook.infer.models.InferUndefined; import com.facebook.infer.models.InferUndefined;
import com.facebook.infer.models.InferBuiltins;
import android.database.sqlite.SQLiteCursor; import android.database.sqlite.SQLiteCursor;
@ -27,7 +28,7 @@ public class Cursor implements Closeable {
public int getColumnIndex(String columnName) { public int getColumnIndex(String columnName) {
int index = InferUndefined.int_undefined(); int index = InferUndefined.int_undefined();
while (index < -1) {} InferBuiltins.assume(index < -1);
return index; return index;
} }

@ -8,24 +8,20 @@ package com.facebook.infer.models;
public class InferBuiltins { public class InferBuiltins {
public static void __set_file_attribute(Object o) { public native static void __set_file_attribute(Object o);
}
public static void __set_mem_attribute(Object o) { public native static void __set_mem_attribute(Object o);
}
public static void __set_lock_attribute(Object o) { public native static void __set_lock_attribute(Object o);
}
public static void _exit() { public native static void _exit();
}
private native static void __infer_assume(boolean condition);
public static void assume(boolean condition) { public static void assume(boolean condition) {
while (!condition) {} __infer_assume(condition);
} }
public static String __split_get_nth(String s, String sep, int n) { public native static String __split_get_nth(String s, String sep, int n);
return null;
}
} }

@ -5,29 +5,24 @@
package junit.framework; package junit.framework;
public class Assert { import com.facebook.infer.models.InferBuiltins;
public static void assume(boolean condition) { public class Assert {
if (!condition) {
while (true) {
}
}
}
public static void assertTrue(boolean condition) { public static void assertTrue(boolean condition) {
assume(condition); InferBuiltins.assume(condition);
} }
public static void assertTrue(String message, boolean condition) { public static void assertTrue(String message, boolean condition) {
assume(condition); InferBuiltins.assume(condition);
} }
public static void assertFalse(boolean condition) { public static void assertFalse(boolean condition) {
assume(!condition); InferBuiltins.assume(!condition);
} }
public static void assertFalse(String message, boolean condition) { public static void assertFalse(String message, boolean condition) {
assume(!condition); InferBuiltins.assume(!condition);
} }
} }

@ -2117,13 +2117,14 @@ module ModelBuiltins = struct
| _ -> raise (Exceptions.Wrong_argument_number (try assert false with Assert_failure x -> x)) | _ -> raise (Exceptions.Wrong_argument_number (try assert false with Assert_failure x -> x))
(* forces the expression passed as parameter to be assumed true at the point where this (* forces the expression passed as parameter to be assumed true at the point where this
builtin is called *) builtin is called, blocks if this causes an inconsistency *)
let execute___infer_assume let execute___infer_assume
cfg pdesc instr tenv prop path ret_ids args callee_pname loc: Builtin.ret_typ = cfg pdesc instr tenv prop path ret_ids args callee_pname loc: Builtin.ret_typ =
match args with match args with
| [(lexp, typ)] -> | [(lexp, typ)] ->
let prop_assume = Prop.conjoin_eq lexp (Sil.exp_bool true) prop in let prop_assume = Prop.conjoin_eq lexp (Sil.exp_bool true) prop in
[(prop_assume, path)] if Prover.check_inconsistency prop_assume then execute_diverge prop_assume path
else [(prop_assume, path)]
| _ -> raise (Exceptions.Wrong_argument_number (try assert false with Assert_failure x -> x)) | _ -> raise (Exceptions.Wrong_argument_number (try assert false with Assert_failure x -> x))
(* creates a named error state *) (* creates a named error state *)

@ -632,8 +632,8 @@ let method_invocation context loc pc var_opt cn ms sil_obj_opt expr_list invoke_
init init
expr_list in expr_list in
let callee_procname = let callee_procname =
if JBasics.cn_equal cn JConfig.infer_builtins_cl then let proc = Procname.from_string (JBasics.ms_name ms) in
Procname.from_string (JBasics.ms_name ms) if JBasics.cn_equal cn JConfig.infer_builtins_cl && SymExec.function_is_builtin proc then proc
else Cfg.Procdesc.get_proc_name callee_procdesc in else Cfg.Procdesc.get_proc_name callee_procdesc in
let call_idl, call_instrs = let call_idl, call_instrs =
let callee_fun = Sil.Const (Sil.Cfun callee_procname) in let callee_fun = Sil.Const (Sil.Cfun callee_procname) in

@ -1,5 +1,6 @@
ANNOTATIONS_JAR = ../annotations/annotations.jar ANNOTATIONS_JAR = ../annotations/annotations.jar
MODELS_JAR = ../lib/java/models.jar
JACKSON_JAR = ../../dependencies/java/jackson/jackson-2.2.3.jar JACKSON_JAR = ../../dependencies/java/jackson/jackson-2.2.3.jar
ANDROID_JAR = ../lib/java/android/android-19.jar ANDROID_JAR = ../lib/java/android/android-19.jar
GUAVA_JAR = ../../dependencies/java/guava/guava-10.0.1-fork.jar GUAVA_JAR = ../../dependencies/java/guava/guava-10.0.1-fork.jar
@ -16,7 +17,7 @@ TRACING_CMD = $(INFERJ) -o $(TRACING_OUT) -a tracing $(TRACING_JAVAC_CMD)
INFER_OUT = infer_out INFER_OUT = infer_out
INFER_REPORT = $(INFER_OUT)/report.csv INFER_REPORT = $(INFER_OUT)/report.csv
INFER_SOURCES = $(shell find codetoanalyze/java/infer -name "*.java") INFER_SOURCES = $(shell find codetoanalyze/java/infer -name "*.java")
INFER_JAVAC_CMD = javac -cp $(JACKSON_JAR):$(ANDROID_JAR) $(INFER_SOURCES) INFER_JAVAC_CMD = javac -cp $(JACKSON_JAR):$(ANDROID_JAR):$(MODELS_JAR) $(INFER_SOURCES)
INFER_CMD = $(INFERJ) -o $(INFER_OUT) -a infer $(INFER_JAVAC_CMD) INFER_CMD = $(INFERJ) -o $(INFER_OUT) -a infer $(INFER_JAVAC_CMD)
ERADICATE_OUT = eradicate_out ERADICATE_OUT = eradicate_out

@ -3,6 +3,7 @@ sources = glob(['**/*.java'])
dependencies = [ dependencies = [
'//infer/lib/java/android:android', '//infer/lib/java/android:android',
'//dependencies/java/jackson:jackson', '//dependencies/java/jackson:jackson',
'//infer/lib/java:models'
] ]
java_library( java_library(

@ -0,0 +1,36 @@
/*
* Copyright (c) 2013- Facebook.
* All rights reserved.
*/
package codetoanalyze.java.infer;
import com.facebook.infer.models.InferBuiltins;
public class Builtins {
void blockError() {
Object x = null;
InferBuiltins.assume(x != null);
x.toString();
}
void doNotBlockError(Object x) {
Object y = null;
InferBuiltins.assume(x != null);
y.toString();
}
void blockErrorIntAssume(Object x) {
Object y = null;
int i = 0;
InferBuiltins.assume(i != 0);
y.toString();
}
void causeError(Object x) {
InferBuiltins.assume(x == null);
x.toString();
}
}

@ -9,6 +9,7 @@
<javac srcdir="." destdir="ant_out" includeantruntime="false"> <javac srcdir="." destdir="ant_out" includeantruntime="false">
<bootclasspath> <bootclasspath>
<pathelement location="../../../../lib/java/android/android-19.jar"/> <pathelement location="../../../../lib/java/android/android-19.jar"/>
<pathelement location="../../../../lib/java/models.jar"/>
</bootclasspath> </bootclasspath>
<classpath> <classpath>
<pathelement location="../../../dependencies/java/jackson/jackson-2.2.3.jar"/> <pathelement location="../../../dependencies/java/jackson/jackson-2.2.3.jar"/>

@ -0,0 +1,53 @@
/*
* Copyright (c) 2013- Facebook.
* All rights reserved.
*/
package endtoend.java.infer;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsExactly.containsExactly;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException;
import utils.InferException;
import utils.InferResults;
public class BuiltinsTest {
public static final String SOURCE_FILE =
"infer/tests/codetoanalyze/java/infer/Builtins.java";
public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE";
private static InferResults inferResults;
@BeforeClass
public static void loadResults() throws InterruptedException, IOException {
inferResults = InferResults.loadInferResults(
BuiltinsTest.class,
SOURCE_FILE);
}
@Test
public void matchErrors()
throws IOException, InterruptedException, InferException {
String[] methods = {
"doNotBlockError",
"causeError"
};
assertThat(
"Results should contain " + NULL_DEREFERENCE,
inferResults,
containsExactly(
NULL_DEREFERENCE,
SOURCE_FILE,
methods
)
);
}
}

@ -42,6 +42,7 @@ public class InferRunner {
"/infer/lib/java/android/android-19.jar"; "/infer/lib/java/android/android-19.jar";
private static final String[] LIBRARIES = { private static final String[] LIBRARIES = {
"/infer/lib/java/models.jar",
"/infer/annotations/annotations.jar", "/infer/annotations/annotations.jar",
"/dependencies/java/guava/guava-10.0.1-fork.jar", "/dependencies/java/guava/guava-10.0.1-fork.jar",
"/dependencies/java/jackson/jackson-2.2.3.jar", "/dependencies/java/jackson/jackson-2.2.3.jar",

Loading…
Cancel
Save