qrcode: add a helper to get the allocated QR icon size
What changed, and why it matters
This commit is a small code cleanup in the QR-code display module of the Blockstream Jade hardware wallet firmware. It extracts a repeated size-calculation into a helper function and replaces a variable with the hard-coded value 32 (the number of bits in a uint32_t). There is no change in behavior and no security fix.
No security action required; treat as routine refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch adds qrcode_get_icon_data_size(width, height) in main/qrcode.c/h and uses it inside qrcode_toIcon(). It also replaces bits_per_uint (sizeof(uint32_t)*8) with the literal 32 in qrcode_toIcon() and qrcode_toFragmentsIcons(). The allocation arithmetic is unchanged: num_uints = (num_pixels / 32) + 1, then JADE_CALLOC_PREFER_SPIRAM(num_uints, sizeof(uint32_t)). No bounds checks, callers, or data handling are modified.
Changed components
main/qrcode.cmain/qrcode.hInspect captured patch +18 / −11
diff --git a/main/qrcode.c b/main/qrcode.c
index 69a16fe..0693a85 100644
--- a/main/qrcode.c
+++ b/main/qrcode.c
@@ -940,6 +940,15 @@ bool qrcode_getModule(QRCode* qrcode, uint8_t x, uint8_t y)
return (qrcode->modules[offset >> 3] & (1 << (7 - (offset & 0x07)))) != 0;
}
+size_t qrcode_get_icon_data_size(const uint16_t width, const uint16_t height)
+{
+ // Icon data is stored one bit per pixel, in uint32's
+ // Note: we add one for any final partially filled uint32
+ const size_t num_pixels = width * height;
+ const size_t num_uints = (num_pixels / 32) + 1;
+ return num_uints * sizeof(uint32_t);
+}
+
void qrcode_toIcon(QRCode* qrcode, Icon* icon, const uint8_t scale)
{
JADE_ASSERT(qrcode);
@@ -949,11 +958,9 @@ void qrcode_toIcon(QRCode* qrcode, Icon* icon, const uint8_t scale)
icon->width = qrcode->size * scale;
icon->height = qrcode->size * scale;
- // Icon data is stored one bit per pixel, in uint32's
- // Note: we add one for any final partially filled uint32
- const uint8_t bits_per_uint = sizeof(uint32_t) * 8;
- const size_t num_pixels = icon->width * icon->height;
- const size_t num_uints = (num_pixels / bits_per_uint) + 1;
+ const size_t num_bytes = qrcode_get_icon_data_size(icon->width, icon->height);
+ const size_t num_uints = num_bytes / sizeof(uint32_t);
+
icon->data = JADE_CALLOC_PREFER_SPIRAM(num_uints, sizeof(uint32_t));
uint64_t val = 0;
@@ -965,8 +972,8 @@ void qrcode_toIcon(QRCode* qrcode, Icon* icon, const uint8_t scale)
// scaling
for (uint8_t i = 0; i < scale; i++) {
- const uint32_t elem = val / bits_per_uint;
- const uint32_t bit = val % bits_per_uint;
+ const uint32_t elem = val / 32;
+ const uint32_t bit = val % 32;
JADE_ASSERT(elem < num_uints);
icon->data[elem] |= paint << bit;
@@ -1019,9 +1026,8 @@ bool qrcode_toFragmentsIcons(
// Icon data is stored one bit per pixel, in uint32's
// Note: we add one for any final partially filled uint32
- const uint8_t bits_per_uint = sizeof(uint32_t) * 8;
const size_t num_pixels = icon_size * icon_size;
- const size_t num_uints = (num_pixels / bits_per_uint) + 1;
+ const size_t num_uints = (num_pixels / 32) + 1;
for (size_t i = 0; i < *num_icons_out; ++i) {
// Create fragment icon
@@ -1048,8 +1054,8 @@ bool qrcode_toFragmentsIcons(
JADE_ASSERT(dest_pixel < num_pixels);
// Copy single module->pixel ie. single bit
- const uint32_t dest_elem = dest_pixel / bits_per_uint;
- const uint8_t dest_bit = dest_pixel % bits_per_uint;
+ const uint32_t dest_elem = dest_pixel / 32;
+ const uint8_t dest_bit = dest_pixel % 32;
JADE_ASSERT(dest_elem < num_uints);
bool paint = qrcode_getModule(qrcode, src_x, src_y);
diff --git a/main/qrcode.h b/main/qrcode.h
index 61151d7..dde59c5 100644
--- a/main/qrcode.h
+++ b/main/qrcode.h
@@ -80,6 +80,7 @@ int8_t qrcode_initBytes(QRCode* qrcode, uint8_t* modules, uint8_t version, uint8
bool qrcode_getModule(QRCode* qrcode, uint8_t x, uint8_t y);
+size_t qrcode_get_icon_data_size(uint16_t width, uint16_t height);
void qrcode_toIcon(QRCode* qrcode, Icon* icon, uint8_t scale);
void qrcode_freeIcon(Icon* icon);
Why this scored 12/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.