Skip to content

Static LookupResult caches in VisitorBase cause stale AST pointers across translation units #1837

Description

@Elvand-Lie

Summary

GetCladTapePush(), GetCladTapePop(), GetCladTapeBack(), and GetCladZeroInit() in VisitorBase each use a function-local static variable to cache their LookupResult:

LookupResult& VisitorBase::GetCladTapePush() {
    static clad_compat::llvm_Optional<LookupResult> Result{};
    if (!Result)
      Result = LookupCladTapeMethod("push");
    return clad_compat::llvm_Optional_GetValue(Result);
}

LookupResult objects hold pointers into AST structures that are specific to a particular Sema/ASTContext. Because static locals persist for the entire process lifetime, these cached results survive across translation units.

Impact

In single-compilation plugin use, this is benign (there is only one TU per process). However, in interactive/Cling environments where multiple translation units are processed within the same process, the cached LookupResult from TU #1 is reused for TU #2, where the AST pointers it holds are dangling. This can lead to:

  • Use-after-free on AST nodes
  • Silent wrong-code generation
  • Hard-to-diagnose crashes in the Sema layer

Suggested fix

Replace the four static caches with per-instance llvm::Optional<LookupResult> members on VisitorBase.

Files affected:

  • include/clad/Differentiator/VisitorBase.h
  • lib/Differentiator/VisitorBase.cpp

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions