From 95fab102bf17890e4dbb575d5cd2436317a9afa6 Mon Sep 17 00:00:00 2001 From: Jules Villard Date: Tue, 11 Dec 2018 05:19:41 -0800 Subject: [PATCH] [pulse] do not destroy `this` even if asked to Summary: Some code calls `this->~Obj()` then proceeds to use fields in the current object, which previously we would report as invalid uses. Assume people know what they are doing and ignore destructor calls to `this`. Reviewed By: mbouaziz Differential Revision: D13401145 fbshipit-source-id: f6b0fb6ec --- infer/src/IR/Var.ml | 2 ++ infer/src/IR/Var.mli | 3 +++ infer/src/checkers/Pulse.ml | 3 +++ infer/tests/codetoanalyze/cpp/pulse/basics.cpp | 15 +++++++++++++++ 4 files changed, 23 insertions(+) diff --git a/infer/src/IR/Var.ml b/infer/src/IR/Var.ml index 3c2c4cf49..d615f45ac 100644 --- a/infer/src/IR/Var.ml +++ b/infer/src/IR/Var.ml @@ -42,6 +42,8 @@ let is_global = function ProgramVar pvar -> Pvar.is_global pvar | LogicalVar _ - let is_return = function ProgramVar pvar -> Pvar.is_return pvar | LogicalVar _ -> false +let is_this = function ProgramVar pvar -> Pvar.is_this pvar | LogicalVar _ -> false + let is_footprint = function ProgramVar _ -> false | LogicalVar id -> Ident.is_footprint id let is_none = function LogicalVar id -> Ident.is_none id | _ -> false diff --git a/infer/src/IR/Var.mli b/infer/src/IR/Var.mli index 8cb2fa007..72e8aac08 100644 --- a/infer/src/IR/Var.mli +++ b/infer/src/IR/Var.mli @@ -37,6 +37,9 @@ val is_global : t -> bool val is_return : t -> bool +val is_this : t -> bool +(** return whether the var is the special "this" var *) + val is_footprint : t -> bool val is_none : t -> bool diff --git a/infer/src/checkers/Pulse.ml b/infer/src/checkers/Pulse.ml index 20d78305c..61bd5c755 100644 --- a/infer/src/checkers/Pulse.ml +++ b/infer/src/checkers/Pulse.ml @@ -61,6 +61,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct match call with | Direct callee_pname when is_destructor callee_pname -> ( match actuals with + | [AccessExpression (Base (destroyed_var, _))] when Var.is_this destroyed_var -> + (* do not invalidate [this] when it is destroyed by calls to [this->~Obj()] *) + Ok astate | [AccessExpression destroyed_access] -> let destroyed_object = HilExp.AccessExpression.dereference destroyed_access in PulseDomain.invalidate diff --git a/infer/tests/codetoanalyze/cpp/pulse/basics.cpp b/infer/tests/codetoanalyze/cpp/pulse/basics.cpp index 772509981..89703b0cb 100644 --- a/infer/tests/codetoanalyze/cpp/pulse/basics.cpp +++ b/infer/tests/codetoanalyze/cpp/pulse/basics.cpp @@ -100,3 +100,18 @@ int struct_inside_loop_ok(std::vector numbers) { } return sum; } + +struct UseAfterSelfDestruct { + A a_; + int x_; + ~UseAfterSelfDestruct() { + if (x_ == 0) { + a_ = getA(); + } + } + + void reset_ok() { + this->~UseAfterSelfDestruct(); + x_ = a_.f(x_); + } +};