diff --git a/infer/documentation/issues/AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE.md b/infer/documentation/issues/AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE.md new file mode 100644 index 000000000..c5714b9a9 --- /dev/null +++ b/infer/documentation/issues/AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE.md @@ -0,0 +1,4 @@ +\[EXPERIMENTAL\] Infer reports this issue when the ObjC autoreleasepool's size complexity of a +program increases in degree: e.g. from constant to linear or from logarithmic to quadratic. This +issue type is only reported in differential mode: i.e when we are comparing the analysis results of +two runs of infer on a file. diff --git a/infer/documentation/issues/AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE_UI_THREAD.md b/infer/documentation/issues/AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE_UI_THREAD.md new file mode 100644 index 000000000..b35486b62 --- /dev/null +++ b/infer/documentation/issues/AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE_UI_THREAD.md @@ -0,0 +1,8 @@ +\[EXPERIMENTAL\] Infer reports this issue when the ObjC autoreleasepool's complexity of the +procedure increases in degree **and** the procedure runs on the UI (main) thread. + +Infer considers a method as running on the UI thread whenever: + +- The method, one of its overrides, its class, or an ancestral class, is annotated with `@UiThread`. +- The method, or one of its overrides is annotated with `@OnEvent`, `@OnClick`, etc. +- The method or its callees call a `Litho.ThreadUtils` method such as `assertMainThread`. diff --git a/infer/documentation/issues/AUTORELEASEPOOL_SIZE_UNREACHABLE_AT_EXIT.md b/infer/documentation/issues/AUTORELEASEPOOL_SIZE_UNREACHABLE_AT_EXIT.md new file mode 100644 index 000000000..9ebaaf72a --- /dev/null +++ b/infer/documentation/issues/AUTORELEASEPOOL_SIZE_UNREACHABLE_AT_EXIT.md @@ -0,0 +1,2 @@ +\[EXPERIMENTAL\] This issue type indicates that the program's execution doesn't reach the exit +node. Hence, we cannot compute a static bound of ObjC autoreleasepool's size for the procedure. diff --git a/infer/documentation/issues/INFINITE_AUTORELEASEPOOL_SIZE.md b/infer/documentation/issues/INFINITE_AUTORELEASEPOOL_SIZE.md new file mode 100644 index 000000000..18235f4af --- /dev/null +++ b/infer/documentation/issues/INFINITE_AUTORELEASEPOOL_SIZE.md @@ -0,0 +1,2 @@ +\[EXPERIMENTAL\] This warning indicates that Infer was not able to determine a static upper bound on +the ObjC autoreleasepool's size in the procedure. By default, this issue type is disabled. diff --git a/infer/man/man1/infer-full.txt b/infer/man/man1/infer-full.txt index cade5c054..741142358 100644 --- a/infer/man/man1/infer-full.txt +++ b/infer/man/man1/infer-full.txt @@ -366,6 +366,10 @@ OPTIONS ARRAY_OUT_OF_BOUNDS_L2 (disabled by default), ARRAY_OUT_OF_BOUNDS_L3 (disabled by default), ASSIGN_POINTER_WARNING (enabled by default), + AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE (enabled by default), + AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE_UI_THREAD (enabled by + default), + AUTORELEASEPOOL_SIZE_UNREACHABLE_AT_EXIT (disabled by default), Abduction_case_not_implemented (enabled by default), Array_of_pointsto (enabled by default), Assert_failure (enabled by default), @@ -445,6 +449,7 @@ OPTIONS INFERBO_ALLOC_IS_ZERO (enabled by default), INFERBO_ALLOC_MAY_BE_BIG (enabled by default), INFERBO_ALLOC_MAY_BE_NEGATIVE (enabled by default), + INFINITE_AUTORELEASEPOOL_SIZE (disabled by default), INFINITE_EXECUTION_TIME (disabled by default), INHERENTLY_DANGEROUS_FUNCTION (enabled by default), INSECURE_INTENT_HANDLING (enabled by default), diff --git a/infer/man/man1/infer-report.txt b/infer/man/man1/infer-report.txt index 070a6844a..29445bf86 100644 --- a/infer/man/man1/infer-report.txt +++ b/infer/man/man1/infer-report.txt @@ -85,6 +85,10 @@ OPTIONS ARRAY_OUT_OF_BOUNDS_L2 (disabled by default), ARRAY_OUT_OF_BOUNDS_L3 (disabled by default), ASSIGN_POINTER_WARNING (enabled by default), + AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE (enabled by default), + AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE_UI_THREAD (enabled by + default), + AUTORELEASEPOOL_SIZE_UNREACHABLE_AT_EXIT (disabled by default), Abduction_case_not_implemented (enabled by default), Array_of_pointsto (enabled by default), Assert_failure (enabled by default), @@ -164,6 +168,7 @@ OPTIONS INFERBO_ALLOC_IS_ZERO (enabled by default), INFERBO_ALLOC_MAY_BE_BIG (enabled by default), INFERBO_ALLOC_MAY_BE_NEGATIVE (enabled by default), + INFINITE_AUTORELEASEPOOL_SIZE (disabled by default), INFINITE_EXECUTION_TIME (disabled by default), INHERENTLY_DANGEROUS_FUNCTION (enabled by default), INSECURE_INTENT_HANDLING (enabled by default), diff --git a/infer/man/man1/infer.txt b/infer/man/man1/infer.txt index 2721c7bf7..d6bac54a7 100644 --- a/infer/man/man1/infer.txt +++ b/infer/man/man1/infer.txt @@ -366,6 +366,10 @@ OPTIONS ARRAY_OUT_OF_BOUNDS_L2 (disabled by default), ARRAY_OUT_OF_BOUNDS_L3 (disabled by default), ASSIGN_POINTER_WARNING (enabled by default), + AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE (enabled by default), + AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE_UI_THREAD (enabled by + default), + AUTORELEASEPOOL_SIZE_UNREACHABLE_AT_EXIT (disabled by default), Abduction_case_not_implemented (enabled by default), Array_of_pointsto (enabled by default), Assert_failure (enabled by default), @@ -445,6 +449,7 @@ OPTIONS INFERBO_ALLOC_IS_ZERO (enabled by default), INFERBO_ALLOC_MAY_BE_BIG (enabled by default), INFERBO_ALLOC_MAY_BE_NEGATIVE (enabled by default), + INFINITE_AUTORELEASEPOOL_SIZE (disabled by default), INFINITE_EXECUTION_TIME (disabled by default), INHERENTLY_DANGEROUS_FUNCTION (enabled by default), INSECURE_INTENT_HANDLING (enabled by default), diff --git a/infer/src/atd/jsonbug.atd b/infer/src/atd/jsonbug.atd index a796095eb..4395831cb 100644 --- a/infer/src/atd/jsonbug.atd +++ b/infer/src/atd/jsonbug.atd @@ -90,6 +90,7 @@ type cost_item = { procedure_id : string; is_on_ui_thread : bool; exec_cost : cost_info; + autoreleasepool_size : cost_info; } type costs_report = cost_item list diff --git a/infer/src/base/IssueType.ml b/infer/src/base/IssueType.ml index 0d8f2cb45..23ed09cad 100644 --- a/infer/src/base/IssueType.ml +++ b/infer/src/base/IssueType.ml @@ -223,7 +223,15 @@ end = struct ; ( "EXECUTION_TIME_UNREACHABLE_AT_EXIT" , [%blob "../../documentation/issues/EXECUTION_TIME_UNREACHABLE_AT_EXIT.md"] ) ; ("INFINITE_EXECUTION_TIME", [%blob "../../documentation/issues/INFINITE_EXECUTION_TIME.md"]) - ] + ; ( "AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE" + , [%blob "../../documentation/issues/AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE.md"] ) + ; ( "AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE_UI_THREAD" + , [%blob "../../documentation/issues/AUTORELEASEPOOL_SIZE_COMPLEXITY_INCREASE_UI_THREAD.md"] + ) + ; ( "AUTORELEASEPOOL_SIZE_UNREACHABLE_AT_EXIT" + , [%blob "../../documentation/issues/AUTORELEASEPOOL_SIZE_UNREACHABLE_AT_EXIT.md"] ) + ; ( "INFINITE_AUTORELEASEPOOL_SIZE" + , [%blob "../../documentation/issues/INFINITE_AUTORELEASEPOOL_SIZE.md"] ) ] (** cost issues are already registered below.*) diff --git a/infer/src/base/costKind.ml b/infer/src/base/costKind.ml index 59ff40e10..7b2a82158 100644 --- a/infer/src/base/costKind.ml +++ b/infer/src/base/costKind.ml @@ -46,9 +46,11 @@ let to_json_cost_info c = function | AllocationCost -> assert false | AutoreleasepoolSize -> - assert false + c.Jsonbug_t.autoreleasepool_size type kind_spec = {kind: t; (* for non-diff analysis *) top_and_unreachable: bool} -let enabled_cost_kinds = [{kind= OperationCost; top_and_unreachable= true}] +let enabled_cost_kinds = + [ {kind= OperationCost; top_and_unreachable= true} + ; {kind= AutoreleasepoolSize; top_and_unreachable= false} ] diff --git a/infer/src/integration/JsonReports.ml b/infer/src/integration/JsonReports.ml index 35bbd3a88..dc36b70a9 100644 --- a/infer/src/integration/JsonReports.ml +++ b/infer/src/integration/JsonReports.ml @@ -267,7 +267,9 @@ module JsonCostsPrinter = MakeJsonListPrinter (struct ; procedure_name= Procname.get_method proc_name ; procedure_id= procedure_id_of_procname proc_name ; is_on_ui_thread - ; exec_cost= cost_info (CostDomain.get_cost_kind CostKind.OperationCost post).cost } + ; exec_cost= cost_info (CostDomain.get_cost_kind CostKind.OperationCost post).cost + ; autoreleasepool_size= + cost_info (CostDomain.get_cost_kind CostKind.AutoreleasepoolSize post).cost } in Some (Jsonbug_j.string_of_cost_item cost_item) | _ -> diff --git a/infer/tests/build_systems/differential_of_costs_report/costs_summary.json.exp b/infer/tests/build_systems/differential_of_costs_report/costs_summary.json.exp index 59041aa86..dbbaef29a 100644 --- a/infer/tests/build_systems/differential_of_costs_report/costs_summary.json.exp +++ b/infer/tests/build_systems/differential_of_costs_report/costs_summary.json.exp @@ -1 +1 @@ -{"top":{"current":2,"previous":1},"zero":{"current":0,"previous":0},"degrees":[{"degree":0,"current":6,"previous":5},{"degree":100,"current":2,"previous":3},{"degree":101,"current":2,"previous":0},{"degree":200,"current":1,"previous":2}]} \ No newline at end of file +{"top":{"current":2,"previous":1},"zero":{"current":0,"previous":0},"degrees":[{"degree":0,"current":19,"previous":16},{"degree":100,"current":2,"previous":3},{"degree":101,"current":2,"previous":0},{"degree":200,"current":1,"previous":2}]} \ No newline at end of file diff --git a/infer/tests/build_systems/incremental_analysis_cost_change/costs_summary.json.exp b/infer/tests/build_systems/incremental_analysis_cost_change/costs_summary.json.exp index a722ee9ca..7a1e48141 100644 --- a/infer/tests/build_systems/incremental_analysis_cost_change/costs_summary.json.exp +++ b/infer/tests/build_systems/incremental_analysis_cost_change/costs_summary.json.exp @@ -1 +1 @@ -{"top":{"current":0,"previous":0},"zero":{"current":0,"previous":0},"degrees":[{"degree":0,"current":3,"previous":4},{"degree":100,"current":4,"previous":1},{"degree":200,"current":0,"previous":1}]} \ No newline at end of file +{"top":{"current":0,"previous":0},"zero":{"current":0,"previous":0},"degrees":[{"degree":0,"current":10,"previous":10},{"degree":100,"current":4,"previous":1},{"degree":200,"current":0,"previous":1}]} \ No newline at end of file