What changed, and why it matters
This commit adds a hard cap on how many files the device will list from its SD card when loading multi-signature Bitcoin wallet data. It also tightens up null-pointer and length checks while scanning directories. The likely goal is to prevent a malicious or accidentally overstuffed SD card from crashing the wallet or causing memory corruption when it reads a huge directory listing.
Verify that FATFS_MAX_FILE_NUMBER is defined and sized to match the g_fileList array dimensions used by the two GUI callers; confirm the change is backported to release firmware and that no other callers of FatfsGetFileName() remain unupdated.
Security signals we found
Unbounded directory listing now bounded by FATFS_MAX_FILE_NUMBER
Null-pointer guards added for fileName, number, and path parameters
Length checks added before copying filenames into caller buffers
Simulator copy operation changed from strcpy to snprintf
Callers updated in Bitcoin-only multisig SD-card file listing code paths
Evidence from the diff
FatfsGetFileName() gains a maxCount parameter and callers in the multisig wallet creation/SD-card-read flows now pass FATFS_MAX_FILE_NUMBER. The loop now stops at maxCount, initializes *number to 0, and adds guard checks for NULL fileName/number and zero maxCount/maxLen. The simulator implementation also switches from strcpy to snprintf and checks that each fileName[] slot is non-NULL before writing. These are defensive hardening changes against unbounded directory iteration and potential buffer/heap issues.
Changed components
src/user_fatfs.c - FatfsGetFileName() directory scannersrc/user_fatfs.h - function signaturesrc/ui/gui_widgets/btc_only/multi_sig/gui_create_multisig_wallet_widgets.c - xpub file listingsrc/ui/gui_widgets/btc_only/multi_sig/gui_multisig_read_sdcard_widgets.c - multisig config file listingui_simulator/simulator_storage.c - simulator implementation of FatfsGetFileName()Inspect captured patch +31 / −14
### src/ui/gui_widgets/btc_only/multi_sig/gui_create_multisig_wallet_widgets.c
@@ -808,9 +808,9 @@ void ListMicroCardXpubFile(void)
uint32_t number = 0;
const char *suffix = ".json";
#ifdef COMPILE_SIMULATOR
- FatfsGetFileName("C:/assets/sd", g_fileList, BUFFER_SIZE_32, &number, suffix);
+ FatfsGetFileName("C:/assets/sd", g_fileList, BUFFER_SIZE_32, &number, suffix, FATFS_MAX_FILE_NUMBER);
#else
- FatfsGetFileName("0:", g_fileList, BUFFER_SIZE_32, &number, suffix);
+ FatfsGetFileName("0:", g_fileList, BUFFER_SIZE_32, &number, suffix, FATFS_MAX_FILE_NUMBER);
#endif
if (number == 0) {
return;
### src/ui/gui_widgets/btc_only/multi_sig/gui_multisig_read_sdcard_widgets.c
@@ -124,9 +124,9 @@ void ListMicroCardMultisigConfigFile(void)
}
printf("suffix is %s\r\n", suffix);
#ifdef COMPILE_SIMULATOR
- FatfsGetFileName("C:/assets/sd", g_fileList, BUFFER_SIZE_128, &number, suffix);
+ FatfsGetFileName("C:/assets/sd", g_fileList, BUFFER_SIZE_128, &number, suffix, FATFS_MAX_FILE_NUMBER);
#else
- FatfsGetFileName("0:", g_fileList, BUFFER_SIZE_128, &number, suffix);
+ FatfsGetFileName("0:", g_fileList, BUFFER_SIZE_128, &number, suffix, FATFS_MAX_FILE_NUMBER);
#endif
if (number == 0) {
lv_obj_t *img = GuiCreateImg(parent, &imgFile);
### src/user_fatfs.c
@@ -277,27 +277,31 @@ void FatfsDirectoryListing(char *ptr)
}
#endif
-void FatfsGetFileName(const char *path, char *fileName[], uint32_t maxLen, uint32_t *number, const char *contain)
+void FatfsGetFileName(const char *path, char *fileName[], uint32_t maxLen, uint32_t *number, const char *contain, uint32_t maxCount)
{
FRESULT res;
DIR dir;
FILINFO fno;
uint32_t count = 0;
+ *number = 0;
+ if (fileName == NULL || maxCount == 0) {
+ return;
+ }
+
res = f_opendir(&dir, path);
if (res != FR_OK) {
- *number = 0;
return;
}
- while (1) {
+ while (count < maxCount) {
res = f_readdir(&dir, &fno);
if (res != FR_OK || fno.fname[0] == 0) {
break;
}
if (!(fno.fattrib & AM_DIR)) {
- if (!strstr(fno.fname, contain) || (fno.fname[0] == '.') ||
+ if ((contain != NULL && !strstr(fno.fname, contain)) || (fno.fname[0] == '.') ||
(FatfsFileGetSize(fno.fname) > MAX_FILE_SIZE_LIST) ||
(strnlen_s(fno.fname, maxLen) >= maxLen)) {
continue;
### src/user_fatfs.h
@@ -45,7 +45,7 @@ void FatfsError(FRESULT errNum);
uint32_t FatfsGetSize(const char *path);
bool FatfsFileExist(const char *path);
char *FatfsFileRead(const TCHAR* path);
-void FatfsGetFileName(const char *path, char *fileName[], uint32_t maxLen, uint32_t *number, const char *contain);
+void FatfsGetFileName(const char *path, char *fileName[], uint32_t maxLen, uint32_t *number, const char *contain, uint32_t maxCount);
uint8_t *FatfsFileReadBytes(const TCHAR* path, uint32_t* readBytes);
#endif /* _USER_FATFS_H */
### ui_simulator/simulator_model.h
@@ -31,7 +31,7 @@ int FatfsFileWrite(const char* path, const uint8_t *data, uint32_t len);
int32_t read_qrcode();
char *FatfsFileRead(const char* path);
uint8_t *FatfsFileReadBytes(const char* path, uint32_t* readBytes);
-void FatfsGetFileName(const char *path, char *fileName[], uint32_t maxLen, uint32_t *number, const char *contain);
+void FatfsGetFileName(const char *path, char *fileName[], uint32_t maxLen, uint32_t *number, const char *contain, uint32_t maxCount);
uint32_t GetCurrentStampTime(void);
bool FatfsFileExist(const char *path);
bool GetEnsName(const char *addr, char *name);
### ui_simulator/simulator_storage.c
@@ -556,26 +556,39 @@ int32_t SE_DeriveKey(uint8_t slot, const uint8_t *authKey)
return 0;
}
-void FatfsGetFileName(const char *path, char *fileName[], uint32_t maxLen, uint32_t *number, const char *contain)
+void FatfsGetFileName(const char *path, char *fileName[], uint32_t maxLen, uint32_t *number, const char *contain, uint32_t maxCount)
{
lv_fs_dir_t dir;
char fname[256];
uint32_t count = 0;
+
+ if (number == NULL) {
+ return;
+ }
+ *number = 0;
+ if (path == NULL || fileName == NULL || maxLen == 0 || maxCount == 0) {
+ return;
+ }
+
lv_fs_res_t res = lv_fs_dir_open(&dir, path);
if (res != LV_FS_RES_OK) {
return;
}
- while (lv_fs_dir_read(&dir, fname) == LV_FS_RES_OK) {
+ while (count < maxCount && lv_fs_dir_read(&dir, fname) == LV_FS_RES_OK) {
if (strlen(fname) == 0) {
break;
}
- if (contain != NULL && !strstr(fname, contain)) {
+ if ((contain != NULL && !strstr(fname, contain)) || strlen(fname) >= maxLen) {
continue;
}
+ if (fileName[count] == NULL) {
+ break;
+ }
+
printf("fname = %s\n", fname);
- strcpy(fileName[count], fname);
+ snprintf(fileName[count], maxLen, "%s", fname);
count++;
}
lv_fs_dir_close(&dir);Why this scored 44/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.