fix(core): avoid integer underflow in `VerticalMenu::place`
What changed, and why it matters
This commit fixes a potential integer underflow bug in the Trezor hardware wallet's user interface code. The bug occurred when calculating the number of separators between menu buttons. If the menu had zero buttons, the code would try to subtract 1 from 0, causing an underflow. The fix restructures the loop so the separator is only considered after the first button, avoiding the subtraction entirely. This is a defensive fix in Rust UI code that likely prevents a crash or undefined behavior during screen layout.
Treat as a low-risk hardening fix. Review whether `VerticalMenu` can ever be instantiated with zero buttons in production firmware, and verify the fix does not alter visual spacing for normal menus. No immediate security response appears necessary unless an empty-menu code path is reachable from user input.
Security signals we found
Integer underflow in layout calculation
Potential panic in UI component during screen rendering
Defensive Rust code hardening
No explicit security claim in commit message
Evidence from the diff
In VerticalMenu::place, the original code computed n_seps = self.buttons.len() - 1. If buttons is empty, this subtraction underflows a usize, which in Rust debug builds panics and in release builds wraps to usize::MAX. The loop then compares i < n_seps, which for an empty menu would be 0 < MAX, but the .take(self.n_items) iterator would produce no items, so the body would not execute. However, the underflow itself is still a latent panic/wrap hazard. The patch removes the subtraction by moving the separator split after the first button (using if i > 0), eliminating the underflow condition. The change is small and defensive.
Changed components
core/embed/rust/src/ui/layout_delizia/component/vertical_menu.rsTrezor Core UI layout system (delizia layout)VerticalMenu componentInspect captured patch +4 / −5
diff --git a/core/embed/rust/src/ui/layout_delizia/component/vertical_menu.rs b/core/embed/rust/src/ui/layout_delizia/component/vertical_menu.rs
index e30c7cb29..0d910d30a 100644
--- a/core/embed/rust/src/ui/layout_delizia/component/vertical_menu.rs
+++ b/core/embed/rust/src/ui/layout_delizia/component/vertical_menu.rs
@@ -228,15 +228,14 @@ impl Component for VerticalMenu {
self.n_items = n_items as usize;
let mut remaining = bounds;
- let n_seps = self.buttons.len() - 1;
for (i, button) in self.buttons.iter_mut().take(self.n_items).enumerate() {
- let (area_button, new_remaining) = remaining.split_top(MENU_BUTTON_HEIGHT);
- button.place(area_button);
- remaining = new_remaining;
- if i < n_seps {
+ if i > 0 {
let (_area_sep, new_remaining) = remaining.split_top(MENU_SEP_HEIGHT);
remaining = new_remaining;
}
+ let (area_button, new_remaining) = remaining.split_top(MENU_BUTTON_HEIGHT);
+ button.place(area_button);
+ remaining = new_remaining;
}
bounds
}
Why this scored 35/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.