|
|
|
/*
|
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package codetoanalyze.java.infer;
|
|
|
|
|
|
|
|
import java.util.Iterator;
|
|
|
|
|
|
|
|
public class AnalysisStops {
|
|
|
|
|
|
|
|
private native Object externalFunc();
|
|
|
|
|
|
|
|
public void skipPointerDerefMayCauseLocalFalseNegativeBad() {
|
|
|
|
Object ret = externalFunc();
|
|
|
|
ret.toString();
|
|
|
|
int i = 1 / 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Object skipPointerDerefPreventsSpecInferenceRetObj() {
|
|
|
|
Object ret = externalFunc();
|
|
|
|
ret.toString();
|
|
|
|
return new Object();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void skipPointerDerefMayCauseCalleeFalsePositiveOk() {
|
|
|
|
Object o = skipPointerDerefPreventsSpecInferenceRetObj();
|
|
|
|
o.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
private int skipPointerDerefPreventsSpecInferenceRetZero() {
|
|
|
|
Object ret = externalFunc();
|
|
|
|
ret.toString();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void skipPointerDerefMayCauseCalleeFalseNegativeBad() {
|
|
|
|
int ret = skipPointerDerefPreventsSpecInferenceRetZero();
|
|
|
|
int i = 1 / ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void divideByParam(int i) {
|
|
|
|
int j = 1 / i;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void skipPointerDerefMayCauseInterprocFalseNegativeBad() {
|
|
|
|
int i = skipPointerDerefPreventsSpecInferenceRetZero();
|
|
|
|
divideByParam(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
private String castExternalPreventsSpecInference() {
|
|
|
|
return (String) externalFunc();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void castFailureOnUndefinedObjMayCauseFalseNegativeBad() {
|
|
|
|
castExternalPreventsSpecInference();
|
|
|
|
int i = 1 / 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void callOnCastUndefinedObjMayCauseFalseNegativeBad() {
|
|
|
|
String s = castExternalPreventsSpecInference();
|
|
|
|
s.toString();
|
|
|
|
int i = 1 / 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static class MyObj {
|
|
|
|
Object f;
|
|
|
|
MyObj rec;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
public int retOne() {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int retZero() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private native MyObj externalFunc2();
|
|
|
|
|
|
|
|
public void callOnUndefinedObjMayCauseFalseNegativeBad() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
int i = 1 / ret.retZero();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void callOnUndefinedObjMayCauseFalsePositiveOk() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
int i = 1 / ret.retOne();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void fieldWriteOnUndefinedObjMayCauseFalseNegativeBad() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
ret.f = new Object();
|
|
|
|
int i = 1 / 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void fieldWriteOnUndefinedObjMayCauseFalsePositiveOk() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
ret.f = new Object();
|
|
|
|
ret.f.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void fieldReadOnUndefinedObjMayCauseFalseNegativeBad() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
Object o = ret.f;
|
|
|
|
int i = 1 / 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void fieldReadOnUndefinedObjMayCauseFalsePositiveOk() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
Object o = ret.f;
|
|
|
|
o.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void recursiveAngelicTypesMayCauseFalseNegativeBad() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
MyObj rec1 = ret.rec;
|
|
|
|
MyObj rec2 = rec1.rec;
|
|
|
|
int i = 1 / 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void recursiveAngelicTypesMayCauseFalsePositiveOk() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
MyObj rec1 = ret.rec;
|
|
|
|
rec1.rec.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void infiniteMaterializationMayCauseFalseNegativeBad(boolean b) {
|
|
|
|
MyObj rec = externalFunc2();
|
|
|
|
while (b) {
|
|
|
|
rec = rec.rec;
|
|
|
|
}
|
|
|
|
int i = 1 / 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void infiniteMaterializationMayCauseFalsePositiveOk(boolean b) {
|
|
|
|
MyObj rec = externalFunc2();
|
|
|
|
while (b) {
|
|
|
|
rec = rec.rec;
|
|
|
|
}
|
|
|
|
rec.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void primitiveFieldOfAngelicObjMayCauseFalseNegativeBad() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
if (ret.i == 0) {
|
|
|
|
int i = 1 / 0;
|
|
|
|
} else {
|
|
|
|
int i = 1 / 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void primitiveFieldOfAngelicObjMayCauseFalsePositiveOk() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
if (ret.i != 0) {
|
|
|
|
int i = 1 / ret.i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void heapFieldOfAngelicObjMayCauseFalseNegativeBad() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
Object obj = ret.f;
|
|
|
|
if (obj == ret.f) {
|
|
|
|
int i = 1 / 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void heapFieldOfAngelicObjMayCauseFalsePositiveOk() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
Object obj = ret.f;
|
|
|
|
if (obj != ret.f) {
|
|
|
|
int i = 1 / 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void fieldReadAferCastMayCauseFalseNegativeBad(Iterator<MyObj> iter) {
|
|
|
|
MyObj ret = iter.next();
|
|
|
|
Object obj = ret.f;
|
|
|
|
obj.toString();
|
|
|
|
int i = ret.i;
|
|
|
|
if (i == 7) {
|
|
|
|
int j = 1 / 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void derefParamOk(MyObj obj) {
|
|
|
|
Object f = obj.f;
|
|
|
|
f.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void fieldReadInCalleeMayCauseFalsePositiveOk() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
derefParamOk(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void fieldReadInCalleeMayCauseFalseNegativeBad() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
ret.f = null;
|
|
|
|
derefParamOk(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void fieldReadInCalleeWithAngelicObjFieldMayCauseFalsePositiveOk() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
derefParamOk(ret.rec);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void fieldReadInCalleeWithAngelicObjFieldMayCauseFalseNegativeBad() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
ret.rec.f = null;
|
|
|
|
derefParamOk(ret.rec);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void accessPathOnParamOk(MyObj obj) {
|
|
|
|
MyObj ret = obj.rec;
|
|
|
|
Object f = ret.f;
|
|
|
|
f.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void accessPathInCalleeMayCauseFalsePositiveOk() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
accessPathOnParamOk(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void accessPathInCalleeMayCauseFalseNegativeBad() {
|
|
|
|
MyObj ret = externalFunc2();
|
|
|
|
ret.rec.f = null;
|
|
|
|
accessPathOnParamOk(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void FN_skipFunctionInLoopMayCauseFalseNegativeBad() {
|
|
|
|
Object o = null;
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
externalFunc();
|
|
|
|
}
|
|
|
|
o.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// will fail to find error unless spec inference succeeds for all callees
|
|
|
|
public void specInferenceMayFailAndCauseFalseNegativeBad(boolean b, Iterator<MyObj> iter) {
|
|
|
|
skipPointerDerefMayCauseLocalFalseNegativeBad();
|
|
|
|
skipPointerDerefPreventsSpecInferenceRetObj();
|
|
|
|
skipPointerDerefPreventsSpecInferenceRetZero();
|
|
|
|
skipPointerDerefMayCauseCalleeFalseNegativeBad();
|
|
|
|
skipPointerDerefMayCauseInterprocFalseNegativeBad();
|
|
|
|
castFailureOnUndefinedObjMayCauseFalseNegativeBad();
|
|
|
|
callOnCastUndefinedObjMayCauseFalseNegativeBad();
|
|
|
|
callOnUndefinedObjMayCauseFalseNegativeBad();
|
|
|
|
callOnUndefinedObjMayCauseFalsePositiveOk();
|
|
|
|
fieldWriteOnUndefinedObjMayCauseFalseNegativeBad();
|
|
|
|
fieldWriteOnUndefinedObjMayCauseFalsePositiveOk();
|
|
|
|
fieldReadOnUndefinedObjMayCauseFalseNegativeBad();
|
|
|
|
fieldReadOnUndefinedObjMayCauseFalsePositiveOk();
|
|
|
|
recursiveAngelicTypesMayCauseFalseNegativeBad();
|
|
|
|
recursiveAngelicTypesMayCauseFalsePositiveOk();
|
|
|
|
infiniteMaterializationMayCauseFalseNegativeBad(b);
|
|
|
|
infiniteMaterializationMayCauseFalsePositiveOk(b);
|
|
|
|
primitiveFieldOfAngelicObjMayCauseFalsePositiveOk();
|
|
|
|
primitiveFieldOfAngelicObjMayCauseFalseNegativeBad();
|
|
|
|
heapFieldOfAngelicObjMayCauseFalsePositiveOk();
|
|
|
|
heapFieldOfAngelicObjMayCauseFalseNegativeBad();
|
|
|
|
fieldReadAferCastMayCauseFalseNegativeBad(iter);
|
|
|
|
fieldReadInCalleeMayCauseFalsePositiveOk();
|
|
|
|
fieldReadInCalleeWithAngelicObjFieldMayCauseFalsePositiveOk();
|
|
|
|
accessPathInCalleeMayCauseFalsePositiveOk();
|
|
|
|
int i = 1 / 0;
|
|
|
|
}
|
|
|
|
}
|