================ @@ -0,0 +1,600 @@ +======================== +Lifetime Safety Analysis +======================== + +.. contents:: + :local: + +Introduction +============ + +Clang Lifetime Safety Analysis is a C++ language extension which warns about +potential dangling pointer defects in code. The analysis aims to detect +when a pointer, reference or view type (such as ``std::string_view``) refers to an object +that is no longer alive, a condition that leads to use-after-free bugs and +security vulnerabilities. Common examples include pointers to stack variables +that have gone out of scope, fields holding views to stack-allocated objects +(dangling-field), returning pointers/references to stack variables +(return stack address) or iterators into container elements invalidated by +container operations (e.g., ``std::vector::push_back``) + +The analysis design is inspired by `Polonius, the Rust borrow checker <https://github.com/rust-lang/polonius>`_, +but adapted to C++ idioms and constraints, such as the lack of exclusivity enforcement (alias-xor-mutability). +Further details on the analysis method can be found in the `RFC on Discourse <https://discourse.llvm.org/t/rfc-intra-procedural-lifetime-analysis-in-clang/86291/>`_. + +This is compile-time analysis; there is no run-time overhead. +It tracks pointer validity through intra-procedural data-flow analysis. While it does +not require lifetime annotations to get started, in their absence, the analysis +treats function calls optimistically, assuming no lifetime effects, thereby potentially missing dangling pointer issues. As more functions are annotated +with attributes like `clang::lifetimebound <https://clang.llvm.org/docs/AttributeReference.html#lifetimebound>`_, `gsl::Owner <https://clang.llvm.org/docs/AttributeReference.html#gsl-owner>`_, and +`gsl::Pointer <https://clang.llvm.org/docs/AttributeReference.html#gsl-pointer>`_, the analysis can see through these lifetime contracts and enforce +lifetime safety at call sites with higher accuracy. This approach supports +gradual adoption in existing codebases. + +.. note:: + This analysis is designed for bug finding, not verification. It may miss some + lifetime issues and can produce false positives. It does not guarantee the + +Getting Started +---------------- + +.. code-block:: c++ + + #include <string> + #include <string_view> + + void simple_dangle() { + std::string_view v; + { + std::string s = "hello"; + v = s; // warning: object whose reference is captured does not live long enough + } // note: destroyed here + std::cout << v; // note: later used here + } + +This example demonstrates +a basic use-after-scope bug. The ``std::string_view`` object ``v`` holds a +reference to ``s``, a ``std::string``. The lifetime of ``s`` ends at the end of +the inner block, causing ``v`` to become a dangling reference. +The analysis flags the assignment ``v = s`` as defective because ``s`` is +destroyed while ``v`` is still alive and points to ``s``, and adds a note +to where ``v`` is used after ``s`` has been destroyed. + +Running The Analysis +-------------------- + +To run the analysis, compile with the ``-Wlifetime-safety-permissive`` flag, e.g. + +.. code-block:: bash + + clang -c -Wlifetime-safety-permissive example.cpp + +This flag enables a core set of lifetime safety checks. For more fine-grained +control over warnings, see :ref:`warning_flags`. + +Lifetime Annotations +==================== + +While lifetime analysis can detect many issues without annotations, its +precision increases significantly when types and functions are annotated with +lifetime contracts. These annotations clarify ownership semantics and lifetime +dependencies, enabling the analysis to reason more accurately about pointer +validity across function calls. + +Owner and Pointer Types +----------------------- + +Lifetime analysis distinguishes between types that own the data they point to +(Owners) and types that are non-owning views or references to data owned by +others (Pointers). This distinction is made using GSL-style attributes: + +* ``[[gsl::Owner]]``: For types that manage the lifetime of a resource, + like ``std::string``, ``std::vector``, ``std::unique_ptr``. +* ``[[gsl::Pointer]]``: For non-owning types that borrow resources, + like ``std::string_view``, or raw pointers (which are + implicitly treated as pointers). + +Many common STL types, such as ``std::string_view`` and container iterators, +are automatically recognized as Pointers or Owners. You can annotate your own +types using these attributes: + +.. code-block:: c++ + + #include <string> + #include <string_view> + + // Owner type + struct [[gsl::Owner]] MyObj { + std::string Data = "Hello"; + }; + + // View type + struct [[gsl::Pointer]] View { + std::string_view SV; + View() = default; + View(const MyObj& O) : SV(O.Data) {} + void use() const {} + }; + + void test() { + View v; + { + MyObj o; + v = o; // warning: object whose reference is captured does not live long enough + } // note: destroyed here + v.use(); // note: later used here + } + +Without these annotations, the analysis may not be able to determine whether a +type is owning or borrowing, which can affect analysis precision. For more +details on these attributes, see the Clang attribute reference for +`gsl::Owner <https://clang.llvm.org/docs/AttributeReference.html#gsl-owner>`_ and +`gsl::Pointer <https://clang.llvm.org/docs/AttributeReference.html#gsl-pointer>`_. + +LifetimeBound +------------- + +The ``[[clang::lifetimebound]]`` attribute can be applied to function parameters +or to the implicit ``this`` parameter of a method (by placing it after the +method declarator). It indicates that the returned pointer or reference becomes +invalid when the attributed parameter or ``this`` object is destroyed. +This is crucial for functions that return views or references to their +arguments. + +.. code-block:: c++ + + #include <string> + #include <string_view> + + struct MyOwner { + std::string s; + std::string_view getView() const [[clang::lifetimebound]] { return s; } + }; + + void test_lifetimebound() { + std::string_view sv; + sv = MyOwner().getView(); // getView() is called on a temporary MyOwner + // warning: object whose reference is captured does not live long enough + // note: destroyed here + (void)sv; // note: later used here + } + +Without ``[[clang::lifetimebound]]`` on ``getView()``, the analysis would not +know that the value returned by ``getView()`` depends on the temporary +``MyOwner`` object, and it would not be able to diagnose the dangling ``sv``. + +For more details, see `lifetimebound <https://clang.llvm.org/docs/AttributeReference.html#lifetimebound>`_. + +NoEscape +-------- + +The ``[[clang::noescape]]`` attribute can be applied to function parameters of +pointer or reference type. It indicates that the function will not allow the +parameter to escape its scope, for example, by returning it or assigning it to +a field or global variable. This is useful for parameters passed to callbacks +or visitors that are only used during the call and not stored. + +For more details, see `noescape <https://clang.llvm.org/docs/AttributeReference.html#noescape>`_. + +Checks Performed +================ + + +.. raw:: html + + <style> + /* Align text to left and add red/green colors */ + table.colored-code-table td, table.colored-code-table th { text-align: left !important; } + table.colored-code-table td:first-child, table.colored-code-table th:first-child { background-color: #ffeaea !important; } + table.colored-code-table td:nth-child(2), table.colored-code-table th:nth-child(2) { background-color: #eafaea !important; } + table.colored-code-table td .highlight, table.colored-code-table td pre { background-color: transparent !important; border: none !important; } + + div.bad-code { background-color: #ffeaea !important; padding: 5px; border-left: 4px solid #ff6b6b; text-align: left !important; } + div.bad-code .highlight, div.bad-code pre { background-color: transparent !important; border: none !important; } + + div.good-code { background-color: #eafaea !important; padding: 5px; border-left: 4px solid #51cf66; text-align: left !important; } + div.good-code .highlight, div.good-code pre { background-color: transparent !important; border: none !important; } + </style> + +Use after scope +--------------- + +This scenario occurs when a pointer or reference outlives ---------------- usx95 wrote:
SG. Done. https://github.com/llvm/llvm-project/pull/183058 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
