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