Skip to content

Commit 77f9112

Browse files
Cerberus Merlincedelavergne-ledger
authored andcommitted
fix: Integer wrap in external-plugin review pair count causes out-of-bounds writes in ui_approve_tx
1 parent 9373cce commit 77f9112

3 files changed

Lines changed: 28 additions & 7 deletions

File tree

src/features/sign_tx/logic_sign_tx.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,14 +366,22 @@ __attribute__((noinline)) static uint16_t finalize_parsing_helper(const txContex
366366
PRINTF("pluginFinalize.result %d successful\n", pluginFinalize.result);
367367
// Handle the right interface
368368
switch (pluginFinalize.uiType) {
369-
case ETH_UI_TYPE_GENERIC:
369+
case ETH_UI_TYPE_GENERIC: {
370+
size_t total_items = (size_t) pluginFinalize.numScreens +
371+
(size_t) pluginProvideInfo.additionalScreens;
372+
if (total_items > MAX_PLUGIN_UI_ITEMS) {
373+
PRINTF("Too many plugin screens requested\n");
374+
report_finalize_error();
375+
error = SWO_NO_RESPONSE;
376+
goto end;
377+
}
370378
// Use the dedicated ETH plugin UI
371379
tmpContent.txContent.dataPresent = false;
372380
// Add the number of screens + the number of additional screens to get the total
373381
// number of screens needed.
374-
dataContext.tokenContext.pluginUiMaxItems =
375-
pluginFinalize.numScreens + pluginProvideInfo.additionalScreens;
382+
dataContext.tokenContext.pluginUiMaxItems = (uint8_t) total_items;
376383
break;
384+
}
377385

378386
// TODO: needs to be removed from the plugin SDK altogether
379387
case ETH_UI_TYPE_AMOUNT_ADDRESS:

src/nbgl/ui_approve_tx.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ static bool setTagValuePairs(bool displayNetwork, bool fromPlugin) {
9494
for (pairIndex = 0; pairIndex < dataContext.tokenContext.pluginUiMaxItems; pairIndex++) {
9595
// for the next dataContext.tokenContext.pluginUiMaxItems items, get tag/value from
9696
// plugin_ui_get_item_internal()
97+
if (nbPairs >= g_pairsList->nbPairs) {
98+
return false;
99+
}
97100
dataContext.tokenContext.pluginUiCurrentItem = pairIndex;
98101
if (!plugin_ui_get_item_internal((uint8_t *) plugin_buffers[counter].title,
99102
TAG_MAX_LEN,
@@ -216,8 +219,8 @@ static bool setTagValuePairs(bool displayNetwork, bool fromPlugin) {
216219
* transaction
217220
* @return The number of g_pairs to display
218221
*/
219-
static uint8_t getNbPairs(bool displayNetwork, bool fromPlugin) {
220-
uint8_t nbPairs = 0;
222+
static size_t getNbPairs(bool displayNetwork, bool fromPlugin) {
223+
size_t nbPairs = 0;
221224

222225
// Setup data to display
223226
if (fromPlugin) {
@@ -277,7 +280,7 @@ static uint8_t getNbPairs(bool displayNetwork, bool fromPlugin) {
277280
static bool ux_init(bool fromPlugin, uint8_t title_len, uint8_t finish_len) {
278281
uint64_t chain_id = 0;
279282
uint16_t buf_size = 0;
280-
uint8_t nbPairs = 0;
283+
size_t nbPairs = 0;
281284
bool displayNetwork = false;
282285

283286
chain_id = get_tx_chain_id();
@@ -287,9 +290,13 @@ static bool ux_init(bool fromPlugin, uint8_t title_len, uint8_t finish_len) {
287290
}
288291
// Compute the number of g_pairs to display
289292
nbPairs = getNbPairs(displayNetwork, fromPlugin);
293+
if (nbPairs > UINT8_MAX) {
294+
PRINTF("Error: Too many review pairs: %u\n", (unsigned) nbPairs);
295+
goto error;
296+
}
290297

291298
// Initialize the buffers
292-
if (!ui_pairs_init(nbPairs)) {
299+
if (!ui_pairs_init((uint8_t) nbPairs)) {
293300
// Initialization failed, cleanup and return
294301
goto error;
295302
}

src/shared_context.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99

1010
#define PLUGIN_ID_LENGTH 30
1111

12+
// Maximum number of plugin-driven items that can be added to the transaction review.
13+
// The review builder counts pluginUiMaxItems plus up to 3 fixed pairs (From, Network,
14+
// Max fees) into a uint8_t (g_pairsList->nbPairs and the cast at ui_pairs_init).
15+
// Bound the source so the sum never overflows the 8-bit pair counter.
16+
#define MAX_PLUGIN_UI_ITEMS (UINT8_MAX - 3)
17+
1218
// Address length
1319
#define ADDRESS_LENGTH_HEX (ADDRESS_LENGTH * 2) // 2 hex chars per byte
1420
#define ADDRESS_LENGTH_STR (ADDRESS_LENGTH_HEX + 1) // + '\0'

0 commit comments

Comments
 (0)