Skip to content

Commit f9b6f2b

Browse files
jvillardfacebook-github-bot
authored andcommitted
[Topl] add doc and change TOPL -> Topl
Summary: Copied the documentation from a document created by rgrig (thanks!!). Reviewed By: rgrig Differential Revision: D27325829 fbshipit-source-id: 118e1a2be
1 parent 6f83c45 commit f9b6f2b

File tree

46 files changed

+258
-59
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+258
-59
lines changed

infer/documentation/checkers/Topl.md

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Topl
2+
3+
## What is it?
4+
5+
Topl is an analysis framework, built on top of Infer, for statically finding violations of temporal properties. Many analyses can be encoded as temporal properties supported by Topl, such as taint analysis. As a simple example, suppose that we don't want a value returned by method `source()` to be sent as an argument to a method `sink()`. This can be specified as follows:
6+
7+
```
8+
property Taint
9+
prefix "Main"
10+
start -> start: *
11+
start -> tracking: source(Ret) => x := Ret
12+
tracking -> error: sink(Arg, VoidRet) when x == Arg
13+
```
14+
15+
This specifies an automaton called `Taint` that has three states (`start`, `tracking`, `error`). Two of those states (`start` and `error`) have special meaning; other states (`tracking`) can have any names. The first transition (`start → tracking`) is taken when a method called `source()` is called, and its return value is stored in a register called `x`; the second transition (`tracking → error`) is taken when a method called `sink()` is called, but only if its argument equals what was previously saved in register `x`.
16+
This property is violated in the following Java code:
17+
18+
```
19+
public class Main {
20+
static void f() { g(tito(source())); }
21+
static void g(Object x) { h(x); }
22+
static void h(Object x) { sink(x); }
23+
static Object tito(Object x) { return x; }
24+
static Object source() { return "dirty"; }
25+
static void sink(Object x) {}
26+
}
27+
```
28+
29+
Note that `source()` and `sink()` are not called from the same method, and that the “dirty” object is passed around a few times before finally reaching the sink. Assuming that the property is in a file `taint.topl` and the Java code in a file `Main.java`, you can invoke Infer with the following command:
30+
31+
```
32+
infer --topl --topl-properties taint.topl -- javac Main.java
33+
```
34+
35+
It will display the following error:
36+
37+
```
38+
Main.java:2: error: Topl Error
39+
property Taint reaches state error.
40+
1. public class Main {
41+
2. > static void f() { g(tito(source())); }
42+
3. static void g(Object x) { h(x); }
43+
4. static void h(Object x) { sink(x); }
44+
```
45+
46+
To get a full trace, use the command
47+
48+
```
49+
infer explore
50+
```
51+
52+
## Specifying Properties
53+
54+
A property is a nondeterministic automaton that can remember values in registers. An execution that drives the automaton from the start state to the error state will make Infer report an issue, and the trace that it produces will indicate which parts of the program drive which transitions of the automaton.
55+
56+
The general form of a property is the following:
57+
58+
```
59+
property *Name
60+
* message "Optional error message" // This line can be missing
61+
prefix "Prefix" // There can be zero, one, or more prefix declarations
62+
sourceState -> targetState: *Pattern*(Arg1,...,ArgN,Ret) when *Condition* => *Action*
63+
```
64+
65+
The property name and the optional error message are used for reporting issues. The prefix declarations are used to simplify Patterns. The core of the property is the list of transitions.
66+
67+
Each transition has a source state and a target state. The special transition label * means that the transition is always taken. Typically, there is a transition
68+
69+
```
70+
start -> start: *
71+
```
72+
73+
meaning that the property can start anywhere, not just at the beginning of a method.
74+
75+
Otherwise, the label on a transition contains:
76+
77+
* a *Pattern*, which indicates what kind of instruction in the program drives this transition;
78+
* a list of transition variable bindings (above named Arg1, ..., but any identifier starting with uppercase letters works);
79+
* possibly a boolean Condition, which can refer to transition variables and to registers;
80+
* possibly and Action, which is a list sequence of assignments of the form *register* := *TransitionVariable* (registers do not need to be declared, and any identifier starting with a lowercase letter works).
81+
82+
There are two types of patterns:
83+
84+
* a regex that matches method names
85+
* if the regex uses non-letters (such as dots) it must be within double-quotes; otherwise, double quotes are optional
86+
* the prefix declarations are used to add potential prefixes to the regex. The combine regex is essentially “(prefix_regex_a | prefix_regex_b) transition_pattern_regex“
87+
* for a method with n arguments, there must be n+1 transition variables to get a match. The first n transition variables get bound to the argument values, and the last transition variable gets bound to the return value. *This is true even for the case in which the return type is void*.
88+
* the special keyword **#ArrayWrite**. In that case, there should be two transition variables like “(Array, Index)” — Array gets bound to the array object, and Index gets bound to the index at which the write happens.
89+
90+
For several examples, see https://github.com/facebook/infer/tree/master/infer/tests/codetoanalyze/java/topl
91+
92+
## Limitations
93+
94+
* By design, some problems may be missed. Topl is built on Pulse, which attempts to minimize false positives, at the cost of sometimes having false negatives.
95+
* Analysis time increases exponentially with the number of registers used in properties.
96+
* In theory, there should be no significant slowdown if registers belong to different properties, but the implementation is not yet optimized.
97+
* If there are many registers within the same property, then the slowdown is unavoidable (without some significant breakthrough). However, the maximum number of registers we ever used for one practical property was 3.

infer/man/man1/infer-analyze.txt

+3-3
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,9 @@ OPTIONS
411411
(Conversely: --no-starvation-only)
412412

413413
--topl
414-
Activates: checker topl: Detects errors based on user-provided
415-
state machines describing multi-object monitors. (Conversely:
416-
--no-topl)
414+
Activates: checker topl: Detect errors based on user-provided
415+
state machines describing temporal properties over multiple
416+
objects. (Conversely: --no-topl)
417417

418418
--topl-only
419419
Activates: Enable topl and disable all other checkers (Conversely:

infer/man/man1/infer-full.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -1257,9 +1257,9 @@ OPTIONS
12571257
@ThreadSafe See also infer-analyze(1).
12581258

12591259
--topl
1260-
Activates: checker topl: Detects errors based on user-provided
1261-
state machines describing multi-object monitors. (Conversely:
1262-
--no-topl) See also infer-analyze(1).
1260+
Activates: checker topl: Detect errors based on user-provided
1261+
state machines describing temporal properties over multiple
1262+
objects. (Conversely: --no-topl) See also infer-analyze(1).
12631263

12641264
--topl-only
12651265
Activates: Enable topl and disable all other checkers (Conversely:
@@ -2126,7 +2126,7 @@ INTERNAL OPTIONS
21262126
scheduler. (Conversely: --no-trace-ondemand)
21272127

21282128
--trace-topl
2129-
Activates: Detailed tracing information during TOPL analysis
2129+
Activates: Detailed tracing information during Topl analysis
21302130
(Conversely: --no-trace-topl)
21312131

21322132
--tv-commit commit

infer/man/man1/infer.txt

+3-3
Original file line numberDiff line numberDiff line change
@@ -1257,9 +1257,9 @@ OPTIONS
12571257
@ThreadSafe See also infer-analyze(1).
12581258

12591259
--topl
1260-
Activates: checker topl: Detects errors based on user-provided
1261-
state machines describing multi-object monitors. (Conversely:
1262-
--no-topl) See also infer-analyze(1).
1260+
Activates: checker topl: Detect errors based on user-provided
1261+
state machines describing temporal properties over multiple
1262+
objects. (Conversely: --no-topl) See also infer-analyze(1).
12631263

12641264
--topl-only
12651265
Activates: Enable topl and disable all other checkers (Conversely:

infer/src/backend/dune

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
(:standard -open Core -open IStdlib -open IStd -open OpenSource -open
1111
ATDGenerated -open IBase -open IR -open Absint -open Biabduction -open BO
1212
-open Nullsafe -open Pulselib -open Checkers -open Costlib -open Quandary
13-
-open TOPLlib -open Concurrency -open Labs -open Dotnet))
13+
-open Topllib -open Concurrency -open Labs -open Dotnet))
1414
(libraries core memtrace IStdlib ATDGenerated IBase IR Absint Biabduction
15-
Nullsafe BO Checkers Costlib Quandary TOPLlib Concurrency Labs Dotnet)
15+
Nullsafe BO Checkers Costlib Quandary Topllib Concurrency Labs Dotnet)
1616
(preprocess
1717
(pps ppx_compare ppx_fields_conv ppx_yojson_conv)))
1818

infer/src/base/Checker.ml

+6-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ type t =
3737
| SIOF
3838
| SelfInBlock
3939
| Starvation
40-
| TOPL
40+
| Topl
4141
| Uninit
4242
[@@deriving equal, enumerate]
4343

@@ -409,12 +409,14 @@ let config_unsafe checker =
409409
; cli_flags= Some {deprecated= []; show_in_help= true}
410410
; enabled_by_default= true
411411
; activates= [] }
412-
| TOPL ->
412+
| Topl ->
413413
{ id= "topl"
414-
; kind= UserFacing {title= "TOPL"; markdown_body= ""}
414+
; kind=
415+
UserFacing {title= "Topl"; markdown_body= [%blob "../../documentation/checkers/Topl.md"]}
415416
; support= supports_clang_and_java_experimental
416417
; short_documentation=
417-
"Detects errors based on user-provided state machines describing multi-object monitors."
418+
"Detect errors based on user-provided state machines describing temporal properties over \
419+
multiple objects."
418420
; cli_flags= Some {deprecated= []; show_in_help= true}
419421
; enabled_by_default= false
420422
; activates= [Pulse] }

infer/src/base/Checker.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type t =
3636
| SIOF
3737
| SelfInBlock
3838
| Starvation
39-
| TOPL
39+
| Topl
4040
| Uninit
4141
[@@deriving equal, enumerate]
4242

infer/src/base/Config.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2500,7 +2500,7 @@ and trace_ondemand =
25002500

25012501

25022502
and trace_topl =
2503-
CLOpt.mk_bool ~long:"trace-topl" "Detailed tracing information during TOPL analysis"
2503+
CLOpt.mk_bool ~long:"trace-topl" "Detailed tracing information during Topl analysis"
25042504

25052505

25062506
and tv_commit =

infer/src/base/IssueType.ml

+4-1
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,10 @@ let complexity_increase ~kind ~is_on_ui_thread =
920920
register_cost ~kind ~is_on_ui_thread "%s_COMPLEXITY_INCREASE"
921921

922922

923-
let topl_error = register ~id:"TOPL_ERROR" Error TOPL ~user_documentation:"Experimental."
923+
let topl_error =
924+
register ~id:"TOPL_ERROR" Error Topl
925+
~user_documentation:"A violation of a Topl property (user-specified)."
926+
924927

925928
let uninitialized_value =
926929
register ~id:"UNINITIALIZED_VALUE" Error Uninit

infer/src/dune.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ let infertop_stanza =
9999
(modes byte_complete)
100100
(modules Infertop)
101101
(flags (:standard -open Core -open IStdlib -open IStd))
102-
(libraries %s utop Absint ASTLanguage ATDGenerated Backend IBase Biabduction BO Checkers Concurrency Costlib CStubs IR IStdlib Labs Dotnet Nullsafe Pulselib Quandary Integration TestDeterminators TOPLlib UnitTests)
102+
(libraries %s utop Absint ASTLanguage ATDGenerated Backend IBase Biabduction BO Checkers Concurrency Costlib CStubs IR IStdlib Labs Dotnet Nullsafe Pulselib Quandary Integration TestDeterminators Topllib UnitTests)
103103
(link_flags (-linkall -warn-error -31))
104104
(preprocess (pps ppx_compare))
105105
(promote (until-clean) (into ../bin))

infer/src/pulse/PulseAbductiveDomain.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ type t =
9999
[@@deriving compare, equal, yojson_of]
100100

101101
let pp f {post; pre; topl; path_condition; skipped_calls} =
102-
F.fprintf f "@[<v>%a@;%a@;PRE=[%a]@;skipped_calls=%a@;TOPL=%a@]" PathCondition.pp path_condition
102+
F.fprintf f "@[<v>%a@;%a@;PRE=[%a]@;skipped_calls=%a@;Topl=%a@]" PathCondition.pp path_condition
103103
PostDomain.pp post PreDomain.pp pre SkippedCalls.pp skipped_calls PulseTopl.pp_state topl
104104

105105

infer/src/pulse/PulseTopl.ml

+3-3
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ let get env x =
246246
| Some v ->
247247
v
248248
| None ->
249-
L.die InternalError "TOPL: Cannot find %s. Should be caught by static checks" x
249+
L.die InternalError "Topl: Cannot find %s. Should be caught by static checks" x
250250

251251

252252
let set = List.Assoc.add ~equal:String.equal
@@ -378,7 +378,7 @@ let dummy_tenv = Tenv.create ()
378378

379379
let is_unsat_expensive path_condition pruned =
380380
let _path_condition, unsat, _new_eqs =
381-
(* Not enabling dynamic type reasoning in TOPL for now *)
381+
(* Not enabling dynamic type reasoning in Topl for now *)
382382
PathCondition.is_unsat_expensive dummy_tenv
383383
~get_dynamic_type:(fun _ -> None)
384384
(Constraint.prune_path pruned path_condition)
@@ -614,6 +614,6 @@ let report_errors proc_desc err_log state =
614614
let loc = Procdesc.get_loc proc_desc in
615615
let ltr = make_trace 0 [] q in
616616
let message = Format.asprintf "%a" ToplAutomaton.pp_message_of_state (a, q.post.vertex) in
617-
Reporting.log_issue proc_desc err_log ~loc ~ltr TOPL IssueType.topl_error message
617+
Reporting.log_issue proc_desc err_log ~loc ~ltr Topl IssueType.topl_error message
618618
in
619619
List.iter ~f:report_simple_state state

infer/src/pulse/dune

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
(public_name infer.Pulselib)
99
(flags
1010
(:standard -open Core -open IR -open IStdlib -open IStd -open ATDGenerated
11-
-open IBase -open Absint -open BO -open TOPLlib -open Nullsafe))
12-
(libraries core IStdlib ATDGenerated IBase IR Absint BO TOPLlib Nullsafe)
11+
-open IBase -open Absint -open BO -open Topllib -open Nullsafe))
12+
(libraries core IStdlib ATDGenerated IBase IR Absint BO Topllib Nullsafe)
1313
(preprocess
1414
(pps ppx_yojson_conv ppx_compare ppx_variants_conv)))

infer/src/topl/Topl.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ let properties = lazy (List.concat_map ~f:parse Config.topl_properties)
2525

2626
let automaton () = ToplAutomaton.make (Lazy.force properties)
2727

28-
let is_active () = Config.is_checker_enabled TOPL && not (List.is_empty (Lazy.force properties))
28+
let is_active () = Config.is_checker_enabled Topl && not (List.is_empty (Lazy.force properties))

infer/src/topl/ToplAutomaton.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
open! IStd
99

10-
(* An automaton is a different representation for a set of TOPL properties: states and transitions
10+
(* An automaton is a different representation for a set of Topl properties: states and transitions
1111
are identified by nonnegative integers; and transitions are grouped by their source. Also, the
1212
meaning of transition labels does not depend on context (e.g., prefixes are now included).
1313

infer/src/topl/dune

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
(modules ToplParser))
1111

1212
(library
13-
(name TOPLlib)
14-
(public_name infer.TOPLlib)
13+
(name Topllib)
14+
(public_name infer.Topllib)
1515
(flags
1616
(:standard -open Core -open IR -open IStdlib -open IStd -open ATDGenerated
1717
-open IBase -open Absint -open Biabduction))

scripts/toplevel_init

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ open Pulselib;;
2929
open Checkers;;
3030
open Costlib;;
3131
open Quandary;;
32-
open TOPLlib;;
32+
open Topllib;;
3333
open Concurrency;;
3434
open Labs;;
3535
open OpenSource;;

website/docs/all-issue-types.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2230,7 +2230,7 @@ These annotations can be found at `com.facebook.infer.annotation.*`.
22302230

22312231
Reported as "Topl Error" by [topl](/docs/next/checker-topl).
22322232

2233-
Experimental.
2233+
A violation of a Topl property (user-specified).
22342234
## UNINITIALIZED_VALUE
22352235

22362236
Reported as "Uninitialized Value" by [uninit](/docs/next/checker-uninit).

0 commit comments

Comments
 (0)