Skip to content

Commit

Permalink
[transitive-access] new config method_name_regex
Browse files Browse the repository at this point in the history
Summary:
we want to be able to catch a family of method names using regex. This is
very similar to class_name_regex (without notion of subclass this time).

Reviewed By: geralt-encore

Differential Revision:
D60436928

Privacy Context Container: L1122176

fbshipit-source-id: 06acb4a64a714f2fe2279dfa5007abc582099a07
  • Loading branch information
davidpichardie authored and facebook-github-bot committed Jul 30, 2024
1 parent 6a57530 commit d47d9b3
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 4 deletions.
11 changes: 9 additions & 2 deletions infer/src/pulse/PulseTransitiveAccessChecker.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ end = struct
{ class_names: string list option [@yojson.option]
; method_names: string list option [@yojson.option]
; class_name_regex: regexp_type option [@yojson.option]
; method_name_regex: regexp_type option [@yojson.option]
; annotations: string list option [@yojson.option] }
[@@deriving of_yojson]

Expand Down Expand Up @@ -96,16 +97,22 @@ end = struct
(fun class_name _ -> regexp_match regexp (Typ.Name.name class_name))
class_name )
in
let match_method_name_regex regexp = regexp_match regexp method_name in
let check_one_procname_spec spec =
match spec with
| {class_names= None; method_names= None; class_name_regex= None; annotations= None} ->
| { class_names= None
; method_names= None
; class_name_regex= None
; method_name_regex= None
; annotations= None } ->
false
| {class_names; method_names; class_name_regex; annotations} ->
| {class_names; method_names; class_name_regex; method_name_regex; annotations} ->
let map_or_true = Option.value_map ~default:true in
map_or_true class_names ~f:match_class_name
&& map_or_true method_names ~f:(function mn ->
List.mem ~equal:String.equal mn method_name )
&& map_or_true class_name_regex ~f:match_class_name_regex
&& map_or_true method_name_regex ~f:match_method_name_regex
&& map_or_true annotations ~f:(procname_has_annotation procname)
in
List.exists specs ~f:check_one_procname_spec
Expand Down
33 changes: 31 additions & 2 deletions infer/tests/codetoanalyze/hack/pulse/global_access.hack
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ class Parent1 extends Parent2 {
return 42;
}

public function very_suspicious(): int {
return 42;
}

public function extremely_suspicious(): int {
return 42;
}

public function not_suspicious(): int {
return 42;
}

public function fine(): int {
return 42;
}
Expand Down Expand Up @@ -114,6 +126,18 @@ final class GlobalAccess extends Parent1 {
return $a->foo();
}

public function call7_is_entry_bad(ExtendsUnsafeInterface $a): int {
return $a->very_suspicious();
}

public function call8_is_entry_bad(ExtendsUnsafeInterface $a): int {
return $a->extremely_suspicious();
}

public function call9_is_entry_ok(ExtendsUnsafeInterface $a): int {
return $a->not_suspicious();
}

public static function gen_closure1(A $a): (function(): int) {
return () ==> $a->get();
}
Expand Down Expand Up @@ -149,9 +173,12 @@ final class DoesNotInheritEvenHandler extends EventNotHandler {
interface Unsafe {
public function dangerous(): int;
public function suspicious(): int;
public function extremely_suspicious(): int;
public function very_suspicious(): int;
public function not_suspicious(): int;
public function fine(): int;
}
interface I extends Unsafe {}
interface ExtendsUnsafeInterface extends Unsafe {}

final class ImplementUnsafe extends Parent1 implements Unsafe {
public function indirect_other_is_not_entry_ok(A $a): int {
Expand All @@ -160,7 +187,9 @@ final class ImplementUnsafe extends Parent1 implements Unsafe {

}

class ImplementUnsafeByTransitivity extends Parent1 implements I {
class ImplementUnsafeByTransitivity
extends Parent1
implements ExtendsUnsafeInterface {
public function indirect_other_is_not_entry_ok(A $a): int {
return $a->get();
}
Expand Down
2 changes: 2 additions & 0 deletions infer/tests/codetoanalyze/hack/pulse/issues.exp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ global_access.hack, GlobalAccess::GlobalAccess.call1_is_entry_bad, 1, PULSE_TRAN
global_access.hack, GlobalAccess::GlobalAccess.call2_is_entry_bad, 1, PULSE_TRANSITIVE_ACCESS, no_bucket, ERROR, [access occurs here]
global_access.hack, GlobalAccess::GlobalAccess.call3_is_entry_bad, 1, PULSE_TRANSITIVE_ACCESS, no_bucket, ERROR, [access occurs here], {GlobalAccess::VeryUnsafe}
global_access.hack, GlobalAccess::GlobalAccess.call6_is_entry_bad, 1, PULSE_TRANSITIVE_ACCESS, no_bucket, ERROR, [access occurs here], {GlobalAccess::ContainsABadPatternInside}
global_access.hack, GlobalAccess::GlobalAccess.call7_is_entry_bad, 1, PULSE_TRANSITIVE_ACCESS, no_bucket, ERROR, [access occurs here]
global_access.hack, GlobalAccess::GlobalAccess.call8_is_entry_bad, 1, PULSE_TRANSITIVE_ACCESS, no_bucket, ERROR, [access occurs here]
global_access.hack, GlobalAccess::GlobalAccess.call7_is_entry_with_closures_bad, 6, PULSE_TRANSITIVE_ACCESS, no_bucket, ERROR, [when calling `Closure$GlobalAccess::GlobalAccess::gen_closure1.__invoke` here,when calling `GlobalAccess::A.get` here,access occurs here], {call7_is_entry_with_closures_bad:8:"Closure":"Unresolved",call7_is_entry_with_closures_bad:7:"Closure":"ResolvedUsingDynamicType",call7_is_entry_with_closures_bad:6:"Closure":"ResolvedUsingDynamicType"}, {GlobalAccess::Unknown,HackMixed}
global_access.hack, GlobalAccess::GlobalAccess.call7_is_entry_with_closures_bad, 7, PULSE_TRANSITIVE_ACCESS, no_bucket, ERROR, [when calling `Closure$GlobalAccess::GlobalAccess::gen_closure2.__invoke` here,when calling `GlobalAccess::A.get` here,access occurs here], {call7_is_entry_with_closures_bad:8:"Closure":"Unresolved",call7_is_entry_with_closures_bad:7:"Closure":"ResolvedUsingDynamicType",call7_is_entry_with_closures_bad:6:"Closure":"ResolvedUsingDynamicType"}, {GlobalAccess::Unknown,HackMixed}
global_access.hack, GlobalAccess::EventHandler2.indirect_empty_does_not_extend_bad, 1, PULSE_TRANSITIVE_ACCESS, no_bucket, ERROR, [when calling `GlobalAccess::A.get` here,access occurs here], {GlobalAccess::Unknown}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
"class_names": ["GlobalAccess::Unsafe", "GlobalAccess::VeryUnsafe"],
"method_names": ["dangerous", "suspicious"]
},
{
"class_names": ["GlobalAccess::Unsafe"],
"method_name_regex": "y_suspicious$"
},
{ "class_name_regex": "BadPattern" }
],
"procnames_to_skip": [
Expand Down

0 comments on commit d47d9b3

Please sign in to comment.