fix(core): scope `trezorui_api.confirm_with_info()` layouts
What changed, and why it matters
This update fixes a memory issue in Trezor hardware wallets that could crash the device (out-of-memory) when confirming very large pieces of on-screen data. The fix ensures a temporary screen-layout object is explicitly released after use, rather than lingering in memory. It is a reliability/availability fix rather than a direct theft-of-funds vulnerability.
Treat as a reliability/DoS-hardening fix. Include in firmware release notes and regression tests for large-message confirmation flows. No immediate user action beyond applying the firmware update is needed.
Security signals we found
Out-of-memory (OOM) crash fixed
Resource lifetime management improved
Context-manager scoping of native/Rust layout object
Large input data confirmation path affected
Issue references #6780 and #5472
Evidence from the diff
The commit changes four UI layout implementations (bolt, caesar, delizia, eckhart) so that trezorui_api.confirm_with_info() is used as a context manager (with ... as layout_obj:). This explicitly drops the internal Rust-backed layout object once the interaction completes. Previously the object lifetime was implicit, which could keep the layout and its cloned large input data alive long enough to exhaust RAM on T3T1 during large input confirmation flows. The changelog labels it as fixing an out-of-memory failure.
Changed components
core/src/trezor/ui/layouts/bolt/__init__.pycore/src/trezor/ui/layouts/caesar/__init__.pycore/src/trezor/ui/layouts/delizia/__init__.pycore/src/trezor/ui/layouts/eckhart/__init__.pytrezorui_api.confirm_with_info()T3T1 device firmwareInspect captured patch +31 / −42
diff --git a/core/.changelog.d/6780.fixed b/core/.changelog.d/6780.fixed
new file mode 100644
index 00000000..96d3fff6
--- /dev/null
+++ b/core/.changelog.d/6780.fixed
@@ -0,0 +1 @@
+Fix out-of-memory failure when confirming large input data.
diff --git a/core/src/trezor/ui/layouts/bolt/__init__.py b/core/src/trezor/ui/layouts/bolt/__init__.py
index 6b33a306..25b35aaa 100644
--- a/core/src/trezor/ui/layouts/bolt/__init__.py
+++ b/core/src/trezor/ui/layouts/bolt/__init__.py
@@ -645,16 +645,13 @@ async def should_show_more(
Raises ActionCancelled if the user cancels.
"""
- result = await interact(
- trezorui_api.confirm_with_info(
- title=title,
- items=items,
- verb=confirm or TR.buttons__confirm,
- verb_info=button_text,
- ),
- br_name,
- br_code,
- )
+ with trezorui_api.confirm_with_info(
+ title=title,
+ items=items,
+ verb=confirm or TR.buttons__confirm,
+ verb_info=button_text,
+ ) as layout_obj:
+ result = await interact(layout_obj, br_name, br_code)
if result is CONFIRMED:
return False
diff --git a/core/src/trezor/ui/layouts/caesar/__init__.py b/core/src/trezor/ui/layouts/caesar/__init__.py
index 8c24981c..0c126aa9 100644
--- a/core/src/trezor/ui/layouts/caesar/__init__.py
+++ b/core/src/trezor/ui/layouts/caesar/__init__.py
@@ -724,17 +724,14 @@ async def should_show_more(
if button_text not in (DOWN_ARROW, ""):
button_text = INFO_ICON
- result = await interact(
- trezorui_api.confirm_with_info(
- title=title,
- items=para,
- verb=confirm or TR.buttons__confirm,
- verb_cancel=verb_cancel,
- verb_info=button_text, # use info icon by default
- ),
- br_name,
- br_code,
- )
+ with trezorui_api.confirm_with_info(
+ title=title,
+ items=para,
+ verb=confirm or TR.buttons__confirm,
+ verb_cancel=verb_cancel,
+ verb_info=button_text, # use info icon by default
+ ) as layout_obj:
+ result = await interact(layout_obj, br_name, br_code)
if result is CONFIRMED:
return False
diff --git a/core/src/trezor/ui/layouts/delizia/__init__.py b/core/src/trezor/ui/layouts/delizia/__init__.py
index f548c316..ac9b99c2 100644
--- a/core/src/trezor/ui/layouts/delizia/__init__.py
+++ b/core/src/trezor/ui/layouts/delizia/__init__.py
@@ -664,17 +664,14 @@ async def should_show_more(
"""
button_text = button_text or TR.buttons__show_all # def_arg
- result = await interact(
- trezorui_api.confirm_with_info(
- title=title,
- subtitle=subtitle,
- items=para,
- verb=(TR.buttons__confirm if confirm is None else confirm),
- verb_info=button_text,
- ),
- br_name,
- br_code,
- )
+ with trezorui_api.confirm_with_info(
+ title=title,
+ subtitle=subtitle,
+ items=para,
+ verb=(TR.buttons__confirm if confirm is None else confirm),
+ verb_info=button_text,
+ ) as layout_obj:
+ result = await interact(layout_obj, br_name, br_code)
if result is CONFIRMED:
return False
diff --git a/core/src/trezor/ui/layouts/eckhart/__init__.py b/core/src/trezor/ui/layouts/eckhart/__init__.py
index 7076931a..0d00b5d2 100644
--- a/core/src/trezor/ui/layouts/eckhart/__init__.py
+++ b/core/src/trezor/ui/layouts/eckhart/__init__.py
@@ -673,16 +673,13 @@ async def should_show_more(
if confirm is None or not isinstance(confirm, str):
confirm = TR.buttons__confirm
- result = await interact(
- trezorui_api.confirm_with_info(
- title=title,
- items=para,
- verb=confirm,
- verb_info=button_text,
- ),
- br_name,
- br_code,
- )
+ with trezorui_api.confirm_with_info(
+ title=title,
+ items=para,
+ verb=confirm,
+ verb_info=button_text,
+ ) as layout_obj:
+ result = await interact(layout_obj, br_name, br_code)
if result is CONFIRMED:
return False
Why this scored 60/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.