From f628cc695c680469c441394511a72b3b3912dd7f Mon Sep 17 00:00:00 2001 From: Mark Rowe Date: Mon, 7 Jul 2025 22:25:22 -0700 Subject: [ObjC] Avoid leaking SymbolQueue `SymbolQueue`'s lifetime was being managed via `new` / `delete`. This was error-prone in the face of code that can a) throw exceptions, or b) return early. Typically the solution would be to move to `std::unique_ptr` and call it a day, but nothing is ever easy. The `SymbolQueue`s created by `ObjCProcessor` are intended to live for the duration of `ProcessObjCData` and `ProcessCFStrings` methods. Since they are used multiple levels down the call tree, the active `SymbolQueue` is stored as a member variable on `ObjCProcessor`. Switching to `std::unique_ptr` would ensure that the `SymbolQueue` is destroyed, but would leave a dangling pointer in the member variable. To address this I'm introducing a `ScopedSingleton` class that provides a thread-local singleton whose lifetime is controlled by a guard object. `ProcessObjCData` / `ProcessCFStrings` call `ScopedSymbolQueue::Make` and store the returned guard object in a local. Code that accesses the symbol queue uses `ScopedSymbolQueue::Get` to retrieve the current instance. The guard object ensures the `SymbolQueue` is deleted and the `current` pointer is cleared no matter how the scope is exited. A better longer-term design is to introduce a class for processing the Objective-C runtime metadata and a class for processing constants such as `CFString`s. These could directly own the symbol queue so it would be accessible to any member functions that define symbols. This is a more involved refactoring than I have time for right now. --- objectivec/objc.h | 1 - 1 file changed, 1 deletion(-) (limited to 'objectivec/objc.h') diff --git a/objectivec/objc.h b/objectivec/objc.h index 61df2b0d..6d194971 100644 --- a/objectivec/objc.h +++ b/objectivec/objc.h @@ -286,7 +286,6 @@ namespace BinaryNinja { // TODO(WeiN76LQh): this is to avoid a bug with defining a classes protocol list in the DSC plugin. Remove once fixed bool m_skipClassBaseProtocols; - SymbolQueue* m_symbolQueue; std::map m_classes; std::map m_categories; std::map m_protocols; -- cgit v1.3.1