[infer][nullable checker] take subtyping into account when detecting pointer assignment

Reviewed By: sblackshear

Differential Revision: D6625407

fbshipit-source-id: 3bf8ea7
master
Jeremy Dubreil 7 years ago committed by Facebook Github Bot
parent 73b4409e6f
commit b089486b5a

@ -21,6 +21,18 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
type extras = Specs.summary type extras = Specs.summary
let rec is_pointer_subtype tenv typ1 typ2 =
match (typ1.Typ.desc, typ2.Typ.desc) with
| Typ.Tptr (t1, _), Typ.Tptr (t2, _) -> (
match (t1.Typ.desc, t2.Typ.desc) with
| Typ.Tstruct n1, Typ.Tstruct n2 ->
Subtype.is_known_subtype tenv n1 n2
| _ ->
Typ.equal t1 t2 || is_pointer_subtype tenv t1 t2 )
| _ ->
false
let is_non_objc_instance_method callee_pname = let is_non_objc_instance_method callee_pname =
if Typ.Procname.is_java callee_pname then not (Typ.Procname.java_is_static callee_pname) if Typ.Procname.is_java callee_pname then not (Typ.Procname.java_is_static callee_pname)
else else
@ -195,11 +207,18 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
let exec_instr ((_, checked_pnames) as astate) proc_data _ (instr: HilInstr.t) : Domain.astate = let exec_instr ((_, checked_pnames) as astate) proc_data _ (instr: HilInstr.t) : Domain.astate =
let is_pointer_assignment tenv lhs rhs = let is_pointer_assignment tenv lhs rhs =
HilExp.is_null_literal rhs
(* the rhs has type int when assigning the lhs to null *) (* the rhs has type int when assigning the lhs to null *)
|| Option.equal Typ.equal (AccessPath.get_typ lhs tenv) (HilExp.get_typ tenv rhs) if HilExp.is_null_literal rhs then true
(* the lhs and rhs have the same type in the case of pointer assignment (* the lhs and rhs have the same type in the case of pointer assignment
but the types are different when assigning the pointee *) but the types are different when assigning the pointee *)
else
match (AccessPath.get_typ lhs tenv, HilExp.get_typ tenv rhs) with
(* defensive assumption when the types are not known *)
| None, _ | _, None ->
true
(* the rhs can be a subtype of the lhs *)
| Some lhs_typ, Some rhs_typ ->
is_pointer_subtype tenv rhs_typ lhs_typ
in in
match instr with match instr with
| Call (Some ret_var, Direct callee_pname, _, _, _) | Call (Some ret_var, Direct callee_pname, _, _, _)

@ -15,10 +15,11 @@ public class NullableViolation {
class T { class T {
int x; int x;
void doSomething() {} void doSomething() {}
} }
native static @Nullable T returnsNullable(); static native @Nullable T returnsNullable();
void dereferenceNullableReturnValueBad() { void dereferenceNullableReturnValueBad() {
T t = returnsNullable(); T t = returnsNullable();
@ -84,4 +85,10 @@ public class NullableViolation {
returnsNullable().doSomething(); // does not report here returnsNullable().doSomething(); // does not report here
} }
native @Nullable Object getNullableObject();
void pointerAssignmentWithSubtype() {
Object object = getNullableObject();
object = "Hello";
}
} }

@ -245,6 +245,13 @@ typedef struct s_ {
return s; return s;
} }
- (NSArray*)pointerAssignmentWithSubtypeOkay:(NSString*)string {
NSObject* nullableObject = [self nullableMethod];
nullableObject = string;
NSArray* array = @[ nullableObject ]; // does not report here
return array;
}
@end @end
@protocol P @protocol P

Loading…
Cancel
Save