Summary: Start with tests about dynamic dispatch to test the upcoming pre-analysis. Reviewed By: ezgicicek Differential Revision: D21594496 fbshipit-source-id: 1771ea968master
parent
65d2bc692d
commit
bf97abfbd3
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public class DynamicDispatch {
|
||||
|
||||
static interface Interface {
|
||||
public Object foo();
|
||||
}
|
||||
|
||||
static class Impl implements Interface {
|
||||
@Override
|
||||
public Object foo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static void interfaceShouldNotCauseFalseNegativeEasyBad() {
|
||||
Interface i = new Impl();
|
||||
// should be a warning since Impl's implementation of foo returns null
|
||||
i.foo().toString();
|
||||
}
|
||||
|
||||
static void interfaceShouldNotCauseFalseNegativeHardOK(Interface i) {
|
||||
i.foo().toString();
|
||||
}
|
||||
|
||||
static void callWithBadImplementationBad_FN(Impl impl) {
|
||||
interfaceShouldNotCauseFalseNegativeHardOK(impl);
|
||||
}
|
||||
|
||||
static class Supertype {
|
||||
Object foo() {
|
||||
return new Object();
|
||||
}
|
||||
|
||||
Object bar() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static class Subtype extends Supertype {
|
||||
@Override
|
||||
Object foo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
Object bar() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
|
||||
static void dynamicDispatchShouldNotCauseFalseNegativeEasyBad() {
|
||||
Supertype o = new Subtype();
|
||||
// should report a warning because we know the dynamic type of o is Subtype
|
||||
o.foo().toString();
|
||||
}
|
||||
|
||||
static void dynamicDispatchShouldNotCauseFalsePositiveEasyOK() {
|
||||
Supertype o = new Subtype();
|
||||
// should not report a warning because we know the dynamic type of o is Subtype
|
||||
o.bar().toString();
|
||||
}
|
||||
|
||||
static void dynamicDispatchShouldNotReportWhenCallingSupertypeOK(Supertype o) {
|
||||
// should not report a warning because the Supertype implementation
|
||||
// of foo() does not return null
|
||||
o.foo().toString();
|
||||
}
|
||||
|
||||
static void dynamicDispatchShouldReportWhenCalledWithSubtypeParameterBad_FN(Subtype o) {
|
||||
// should report a warning because the Subtype implementation
|
||||
// of foo() returns null
|
||||
dynamicDispatchShouldNotReportWhenCallingSupertypeOK(o);
|
||||
}
|
||||
|
||||
static Object dynamicDispatchWrapperFoo(Supertype o) {
|
||||
return o.foo();
|
||||
}
|
||||
|
||||
static Object dynamicDispatchWrapperBar(Supertype o) {
|
||||
return o.bar();
|
||||
}
|
||||
|
||||
static void dynamicDispatchCallsWrapperWithSupertypeOK() {
|
||||
// Should not report because Supertype.foo() does not return null
|
||||
Supertype o = new Supertype();
|
||||
dynamicDispatchWrapperFoo(o).toString();
|
||||
}
|
||||
|
||||
static void dynamicDispatchCallsWrapperWithSupertypeBad() {
|
||||
// Should report because Supertype.bar() returns null
|
||||
Supertype o = new Supertype();
|
||||
dynamicDispatchWrapperBar(o).toString();
|
||||
}
|
||||
|
||||
static void dynamicDispatchCallsWrapperWithSubtypeBad_FN() {
|
||||
// Should report because Subtype.foo() returns null
|
||||
Supertype o = new Subtype();
|
||||
dynamicDispatchWrapperFoo(o).toString();
|
||||
}
|
||||
|
||||
static void dynamicDispatchCallsWrapperWithSubtypeOK_FP() {
|
||||
// Should not report because Subtype.bar() does not returns null
|
||||
Supertype o = new Subtype();
|
||||
dynamicDispatchWrapperBar(o).toString();
|
||||
}
|
||||
|
||||
static class WithField {
|
||||
|
||||
Supertype mField;
|
||||
|
||||
WithField(Supertype t) {
|
||||
mField = t;
|
||||
}
|
||||
|
||||
static void dispatchOnFieldOK_FP() {
|
||||
Supertype subtype = new Subtype();
|
||||
WithField object = new WithField(subtype);
|
||||
object.mField.bar().toString();
|
||||
}
|
||||
|
||||
static void dispatchOnFieldBad_FN() {
|
||||
Supertype subtype = new Subtype();
|
||||
WithField object = new WithField(subtype);
|
||||
object.mField.foo().toString();
|
||||
}
|
||||
}
|
||||
|
||||
private Object callFoo(Supertype o) {
|
||||
return o.foo();
|
||||
}
|
||||
|
||||
void dynamicResolutionWithPrivateMethodBad_FN() {
|
||||
Supertype subtype = new Subtype();
|
||||
callFoo(subtype).toString();
|
||||
}
|
||||
|
||||
Object variadicMethod(Supertype... args) {
|
||||
if (args.length == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return args[0].foo();
|
||||
}
|
||||
}
|
||||
|
||||
void dynamicResolutionWithVariadicMethodBad() {
|
||||
Supertype subtype = new Subtype();
|
||||
variadicMethod(subtype, null, null).toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
# 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.
|
||||
|
||||
TESTS_DIR = ../../..
|
||||
|
||||
INFER_OPTIONS = --pulse-only --debug-exceptions
|
||||
INFERPRINT_OPTIONS = --issues-tests
|
||||
SOURCES = $(wildcard *.java)
|
||||
|
||||
include $(TESTS_DIR)/javac.make
|
@ -0,0 +1,6 @@
|
||||
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch$WithField.dispatchOnFieldOK_FP():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch$Supertype.bar()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch$Supertype.bar()`,return from call to `Object DynamicDispatch$Supertype.bar()`,assigned,invalid access occurs here]
|
||||
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.dynamicDispatchCallsWrapperWithSubtypeOK_FP():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)` here,when calling `Object DynamicDispatch$Supertype.bar()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,return from call to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,assigned,invalid access occurs here]
|
||||
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.dynamicDispatchCallsWrapperWithSupertypeBad():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)` here,when calling `Object DynamicDispatch$Supertype.bar()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,return from call to `Object DynamicDispatch.dynamicDispatchWrapperBar(DynamicDispatch$Supertype)`,assigned,invalid access occurs here]
|
||||
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.dynamicDispatchShouldNotCauseFalseNegativeEasyBad():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch$Subtype.foo()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch$Subtype.foo()`,return from call to `Object DynamicDispatch$Subtype.foo()`,assigned,invalid access occurs here]
|
||||
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.dynamicResolutionWithVariadicMethodBad():void, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch.variadicMethod(DynamicDispatch$Supertype[])` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch.variadicMethod(DynamicDispatch$Supertype[])`,return from call to `Object DynamicDispatch.variadicMethod(DynamicDispatch$Supertype[])`,assigned,invalid access occurs here]
|
||||
codetoanalyze/java/pulse/DynamicDispatch.java, codetoanalyze.java.infer.DynamicDispatch.interfaceShouldNotCauseFalseNegativeEasyBad():void, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `Object DynamicDispatch$Impl.foo()` here,assigned,is the null pointer,use-after-lifetime part of the trace starts here,passed as argument to `Object DynamicDispatch$Impl.foo()`,return from call to `Object DynamicDispatch$Impl.foo()`,assigned,invalid access occurs here]
|
Loading…
Reference in new issue