Skip to content

fix(tui): prevent usize to u16 overflow in interactive renderer#38

Closed
echobt wants to merge 2 commits intomainfrom
fix/renderer-u16-overflow
Closed

fix(tui): prevent usize to u16 overflow in interactive renderer#38
echobt wants to merge 2 commits intomainfrom
fix/renderer-u16-overflow

Conversation

@echobt
Copy link
Contributor

@echobt echobt commented Feb 4, 2026

Summary

Fixes #5296 - InteractiveRenderer required_height usize to u16 cast overflow.

Problem

Unchecked cast from usize to u16 can silently truncate values exceeding 65535.

Solution

Used saturating conversion with u16::MAX cap to prevent overflow.

@greptile-apps
Copy link

greptile-apps bot commented Feb 4, 2026

Greptile Overview

Greptile Summary

This PR fixes two critical safety issues: a potential usize to u16 overflow in the TUI renderer and UTF-8 boundary violations in agent mention parsing.

Key Changes:

  • renderer.rs: Replaced unsafe as u16 cast with u16::try_from().unwrap_or(u16::MAX) and chained saturating additions to prevent overflow when calculating widget height with large item counts
  • mention.rs: Added safe_slice_up_to() and safe_slice_from() helper functions that validate UTF-8 character boundaries before slicing, preventing panics when parsing mentions with multibyte characters (CJK, emoji, etc.)
  • Comprehensive test coverage added for UTF-8 edge cases including Japanese text, emojis, and mixed-encoding scenarios

Both fixes are defensive, well-implemented, and include proper test coverage. The changes prevent potential runtime panics without altering the intended behavior.

Confidence Score: 5/5

  • This PR is safe to merge with no risks identified
  • Both fixes address real safety issues with correct implementations. The overflow protection uses proper Rust patterns (try_from + saturating operations), and the UTF-8 boundary validation follows best practices. Comprehensive test coverage validates all edge cases.
  • No files require special attention

Important Files Changed

Filename Overview
src/cortex-tui/src/interactive/renderer.rs Added saturating conversions to prevent usize to u16 overflow in required_height() calculation
src/cortex-agents/src/mention.rs Added UTF-8 boundary validation with safe_slice_up_to and safe_slice_from helper functions, comprehensive test coverage included

Sequence Diagram

sequenceDiagram
    participant User
    participant InteractiveWidget
    participant Renderer
    participant MentionParser
    
    Note over User,MentionParser: Overflow Prevention Flow
    
    User->>InteractiveWidget: Request widget with many items
    InteractiveWidget->>InteractiveWidget: Calculate required_height()
    Note over InteractiveWidget: items_count (usize) could exceed u16::MAX
    InteractiveWidget->>InteractiveWidget: u16::try_from(items_count)
    alt items_count > 65535
        InteractiveWidget->>InteractiveWidget: Return u16::MAX
    else items_count <= 65535
        InteractiveWidget->>InteractiveWidget: Return items_count as u16
    end
    InteractiveWidget->>InteractiveWidget: saturating_add(header_height)
    InteractiveWidget->>InteractiveWidget: saturating_add(search_height)
    InteractiveWidget->>InteractiveWidget: saturating_add(hints_height)
    InteractiveWidget->>InteractiveWidget: saturating_add(border_height)
    InteractiveWidget->>Renderer: Return safe height (no overflow)
    
    Note over User,MentionParser: UTF-8 Boundary Safety Flow
    
    User->>MentionParser: Parse text with multibyte chars: "日本語 @general task"
    MentionParser->>MentionParser: find_first_valid_mention()
    MentionParser->>MentionParser: Get mention.start and mention.end
    Note over MentionParser: Byte positions may not align with char boundaries
    MentionParser->>MentionParser: safe_slice_up_to(text, mention.start)
    alt mention.start is char boundary
        MentionParser->>MentionParser: Return &text[..mention.start]
    else mention.start inside multibyte char
        MentionParser->>MentionParser: Search backwards for valid boundary
        MentionParser->>MentionParser: Return &text[..valid_pos]
    end
    MentionParser->>MentionParser: safe_slice_from(text, mention.end)
    alt mention.end is char boundary
        MentionParser->>MentionParser: Return &text[mention.end..]
    else mention.end inside multibyte char
        MentionParser->>MentionParser: Search forwards for valid boundary
        MentionParser->>MentionParser: Return &text[valid_pos..]
    end
    MentionParser->>User: Return parsed result (no panic)
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

echobt added a commit that referenced this pull request Feb 4, 2026
… prevention

This PR consolidates the following fixes:
- #38: Prevent usize to u16 overflow in interactive renderer
- #42: Prevent usize to u16 overflow in card count displays
- #58: Fix cursor positioning and underflow in selection list
- #59: Fix mention popup positioning and Unicode width calculation
- #60: Improve autocomplete popup positioning and width calculation
- #64: Prevent underflow in dropdown navigation and scroll calculations
- #66: Prevent panic in HelpBrowserState when sections empty

All changes target the TUI components to improve robustness:
- Added saturating casts for u16 conversions
- Fixed cursor positioning calculations
- Added bounds checking for empty sections
- Improved Unicode width handling for popups
@echobt
Copy link
Contributor Author

echobt commented Feb 4, 2026

Consolidated into #69 - fix(tui): consolidated TUI fixes for overflow, positioning, and panic prevention

@echobt echobt closed this Feb 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant