fix(console): audit fixes — HiDPI, fold UX, stop-confirm, RPC-trace UAF

From the console-tab audit:
- HiDPI: the "New output" pill (140x24 + margin/rounding/border) and the JSON
  indent-guide thickness were hand-drawn in raw px; scale them by dpiScale().
- Fold triangle: size it from the DPI/density-scaled gutter width (not the
  zoomed font) and center it in the gutter band so glyph and clickable cell
  stay aligned; only draw/handle it in the unfiltered view (folding_active_) —
  in a filtered flat view a click silently flipped the collapsed flag with no
  visible effect and the glyph disagreed with the rendered block.
- Selection: ignore left-clicks in the gutter (< output_origin_.x) so toggling
  a fold no longer clears the user's active text selection.
- 'stop' confirmation: promote the function-local static to a member and reset
  it in clear(), so a toolbar/context-menu clear between the two 'stop's can't
  leave a stale arm that skips the shutdown warning.
- RPC-trace callback: dereference the console pointer under the mutex (not
  after releasing it) so ~ConsoleTab can't destroy the object mid-call —
  closing a latent use-after-free on shutdown (fires on RPC worker threads).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-12 17:45:51 -05:00
parent 232b81f8ee
commit 4f71c18884
2 changed files with 39 additions and 24 deletions

View File

@@ -150,6 +150,7 @@ private:
std::vector<std::string> command_history_;
int history_index_ = -1;
char input_buffer_[4096] = {0};
bool stop_confirm_pending_ = false; // 'stop' typed once, awaiting a confirming second 'stop'
// (log-ingestion cursors + result queue moved to the ConsoleCommandExecutor)
// Auto-scroll state machine (pin-to-bottom, wheel-up cooldown, new-line backlog count).
@@ -173,6 +174,7 @@ private:
mutable int filter_match_count_ = 0; // lines matching the text filter (for the toolbar)
std::string context_token_; // hash/address under the cursor at right-click
mutable std::vector<int> visible_indices_; // Cached for selection mapping
bool folding_active_ = true; // fold UI shown only in the unfiltered (foldable) view
// Wrap layout for the visible lines (segments + per-line heights + cumulative Y),
// recomputed each frame by the pure BuildConsoleLayout (console_text_layout.h) and