bootloader: extract formatting helpers
What changed, and why it matters
This commit is a simple code cleanup: it moves a handful of string-formatting helpers (for pairing codes, progress percentages, hash display, timers, and unknown-command messages) out of the main bootloader file into a new dedicated file, and adds unit tests for them. The actual formatting logic is unchanged, and there is no indication of any security fix or behavior change.
No security action required; this is a refactoring change. Normal code-review approval is sufficient.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change extracts five snprintf-based formatting routines from bootloader.c into a new bootloader_format.c/h module. The call sites in bootloader.c are updated to use the new wrappers, and a cmocka-based unit-test file is added. The format strings, argument types, and buffer sizes remain identical to the original inline code. No vulnerability is introduced or patched.
Changed components
src/bootloader/bootloader.csrc/bootloader/bootloader_format.csrc/bootloader/bootloader_format.htest/unit-test/test_bootloader_format.cInspect captured patch +147 / −12
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9f2867e..deb4e45 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -86,6 +86,7 @@ set(DBB-BOOTLOADER-SOURCES
${CMAKE_SOURCE_DIR}/src/pukcc/curve_p256.c
${CMAKE_SOURCE_DIR}/src/pukcc/pukcc.c
${CMAKE_SOURCE_DIR}/src/bootloader/bootloader.c
+ ${CMAKE_SOURCE_DIR}/src/bootloader/bootloader_format.c
${CMAKE_SOURCE_DIR}/src/bootloader/startup.c
${CMAKE_SOURCE_DIR}/src/bootloader/mpu_regions.c
${CMAKE_SOURCE_DIR}/src/random.c
diff --git a/src/bootloader/bootloader.c b/src/bootloader/bootloader.c
index 3be4ff3..3ebbd7b 100644
--- a/src/bootloader/bootloader.c
+++ b/src/bootloader/bootloader.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
#include "bootloader.h"
+#include "bootloader_format.h"
#include "bootloader_version.h"
#include "mpu_regions.h"
#include "pac_ext.h"
@@ -354,7 +355,7 @@ void bootloader_render_ble_confirm_screen(bool confirmed)
memcpy(&pairing_code_int, &bootloader_pairing_code_bytes[0], sizeof(pairing_code_int));
pairing_code_int %= 1000000;
char code_str[10] = {0};
- snprintf(code_str, sizeof(code_str), "%06u", (unsigned)pairing_code_int);
+ bootloader_format_pairing_code(code_str, sizeof(code_str), pairing_code_int);
UG_ClearBuffer();
uint16_t check_width = IMAGE_DEFAULT_CHECKMARK_HEIGHT + IMAGE_DEFAULT_CHECKMARK_HEIGHT / 2 - 1;
if (confirmed) {
@@ -377,7 +378,7 @@ static void _render_progress(float progress)
_load_logo();
if (progress > 0) {
char label[5] = {0};
- snprintf(label, sizeof(label), "%2d%%", (int)(100 * progress));
+ bootloader_format_progress(label, sizeof(label), progress);
UG_PutString(0, SCREEN_HEIGHT - 9 * 2, label);
_load_progress_bar(progress);
} else {
@@ -410,20 +411,13 @@ static void _render_hash(const char* title, const uint8_t* hash)
UG_S16 timer_str_width = 0;
// 4 lines à 16 chars, 3 newline chars, one null terminator.
char hash_multiline[4 * 16 + 3 + 1] = {0};
- snprintf(
- hash_multiline,
- sizeof(hash_multiline),
- "%.16s\n%.16s\n%.16s\n%.16s",
- &hash_hex[0],
- &hash_hex[16],
- &hash_hex[32],
- &hash_hex[48]);
+ bootloader_format_hash_multiline(hash_multiline, sizeof(hash_multiline), hash_hex);
for (uint8_t i = 1; i <= seconds; i++) {
UG_ClearBuffer();
UG_PutString(0, 0, title);
- snprintf(timer_buf, sizeof(timer_buf), "%ds", seconds - i);
+ bootloader_format_timer(timer_buf, sizeof(timer_buf), seconds - i);
UG_MeasureString(&timer_str_width, NULL, timer_buf);
UG_PutString(
SCREEN_WIDTH - timer_str_width, SCREEN_HEIGHT - f_regular->char_height, timer_buf);
@@ -917,7 +911,7 @@ static size_t _api_command(const uint8_t* input, uint8_t* output, const size_t m
len = _report_status(OP_STATUS_ERR_INVALID_CMD, output);
_loading_ready = false;
char msg[100];
- snprintf(msg, 100, "Command: %u unknown", input[0]);
+ bootloader_format_unknown_command(msg, sizeof(msg), input[0]);
_render_message(msg, 1000);
break;
}
diff --git a/src/bootloader/bootloader_format.c b/src/bootloader/bootloader_format.c
new file mode 100644
index 0000000..f743e4f
--- /dev/null
+++ b/src/bootloader/bootloader_format.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: Apache-2.0
+
+#include "bootloader/bootloader_format.h"
+
+#include <stdio.h>
+
+void bootloader_format_pairing_code(char* out, size_t out_len, uint32_t pairing_code)
+{
+ snprintf(out, out_len, "%06u", (unsigned)pairing_code);
+}
+
+void bootloader_format_progress(char* out, size_t out_len, float progress)
+{
+ snprintf(out, out_len, "%2d%%", (int)(100 * progress));
+}
+
+void bootloader_format_hash_multiline(char* out, size_t out_len, const char* hash_hex)
+{
+ snprintf(
+ out,
+ out_len,
+ "%.16s\n%.16s\n%.16s\n%.16s",
+ &hash_hex[0],
+ &hash_hex[16],
+ &hash_hex[32],
+ &hash_hex[48]);
+}
+
+void bootloader_format_timer(char* out, size_t out_len, uint8_t seconds)
+{
+ snprintf(out, out_len, "%ds", seconds);
+}
+
+void bootloader_format_unknown_command(char* out, size_t out_len, uint8_t command)
+{
+ snprintf(out, out_len, "Command: %u unknown", command);
+}
diff --git a/src/bootloader/bootloader_format.h b/src/bootloader/bootloader_format.h
new file mode 100644
index 0000000..8733707
--- /dev/null
+++ b/src/bootloader/bootloader_format.h
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef BOOTLOADER_FORMAT_H
+#define BOOTLOADER_FORMAT_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+void bootloader_format_pairing_code(char* out, size_t out_len, uint32_t pairing_code);
+void bootloader_format_progress(char* out, size_t out_len, float progress);
+void bootloader_format_hash_multiline(char* out, size_t out_len, const char* hash_hex);
+void bootloader_format_timer(char* out, size_t out_len, uint8_t seconds);
+void bootloader_format_unknown_command(char* out, size_t out_len, uint8_t command);
+
+#endif
diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt
index 3e7d56c..d1fe71e 100644
--- a/test/unit-test/CMakeLists.txt
+++ b/test/unit-test/CMakeLists.txt
@@ -29,6 +29,8 @@ else()
# Tests
set(TEST_LIST
+ bootloader_format
+ ""
cleanup
"-Wl,--wrap=util_cleanup_32"
gestures
@@ -70,6 +72,9 @@ else()
target_include_directories(${EXE} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
+ if(TEST_NAME STREQUAL "bootloader_format")
+ target_sources(${EXE} PRIVATE ${CMAKE_SOURCE_DIR}/src/bootloader/bootloader_format.c)
+ endif()
add_test(NAME test_${TEST_NAME} COMMAND ${EXE})
endforeach()
endif()
diff --git a/test/unit-test/test_bootloader_format.c b/test/unit-test/test_bootloader_format.c
new file mode 100644
index 0000000..bba6d9c
--- /dev/null
+++ b/test/unit-test/test_bootloader_format.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: Apache-2.0
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <cmocka.h>
+
+#include "bootloader/bootloader_format.h"
+
+static void test_pairing_code(void** state)
+{
+ (void)state;
+ char out[10];
+
+ bootloader_format_pairing_code(out, sizeof(out), 42);
+ assert_string_equal(out, "000042");
+
+ bootloader_format_pairing_code(out, sizeof(out), 999999);
+ assert_string_equal(out, "999999");
+}
+
+static void test_progress(void** state)
+{
+ (void)state;
+ char out[5];
+
+ bootloader_format_progress(out, sizeof(out), 0.01f);
+ assert_string_equal(out, " 1%");
+
+ bootloader_format_progress(out, sizeof(out), 0.42f);
+ assert_string_equal(out, "42%");
+
+ bootloader_format_progress(out, sizeof(out), 1.0f);
+ assert_string_equal(out, "100%");
+}
+
+static void test_hash_multiline(void** state)
+{
+ (void)state;
+ const char* hash_hex =
+ "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f";
+ char out[4 * 16 + 3 + 1];
+
+ bootloader_format_hash_multiline(out, sizeof(out), hash_hex);
+ assert_string_equal(
+ out,
+ "0001020304050607\n"
+ "08090a0b0c0d0e0f\n"
+ "1011121314151617\n"
+ "18191a1b1c1d1e1f");
+}
+
+static void test_timer(void** state)
+{
+ (void)state;
+ char out[4];
+
+ bootloader_format_timer(out, sizeof(out), 9);
+ assert_string_equal(out, "9s");
+}
+
+static void test_unknown_command(void** state)
+{
+ (void)state;
+ char out[100];
+
+ bootloader_format_unknown_command(out, sizeof(out), 42);
+ assert_string_equal(out, "Command: 42 unknown");
+}
+
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_pairing_code),
+ cmocka_unit_test(test_progress),
+ cmocka_unit_test(test_hash_multiline),
+ cmocka_unit_test(test_timer),
+ cmocka_unit_test(test_unknown_command),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
Why this scored 15/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.