@@ -288,15 +288,17 @@ static u32 RemoveBDRIEntry(const BDRIFsHeader* fs_header, const u32 fs_header_of
288288 if (BDRIWrite (fht_offset + hash_bucket * sizeof (u32 ), sizeof (u32 ), & (file_entry .hash_bucket_next_index )) != FR_OK )
289289 return 1 ;
290290 } else {
291+ u32 prev_hash_index = 0 ;
291292 do {
292293 if (index_hash == 0 ) // This shouldn't happen if the entry was properly added
293294 break ;
294295
296+ prev_hash_index = index_hash ;
295297 if (BDRIRead (fet_offset + index_hash * sizeof (TdbFileEntry ) + 0x28 , sizeof (u32 ), & index_hash ) != FR_OK )
296298 return 1 ;
297299 } while (index_hash != index );
298300
299- if ((index_hash != 0 ) && BDRIWrite (fet_offset + index_hash * sizeof (TdbFileEntry ) + 0x28 , sizeof (u32 ), & (file_entry .hash_bucket_next_index )) != FR_OK )
301+ if ((prev_hash_index != 0 ) && BDRIWrite (fet_offset + prev_hash_index * sizeof (TdbFileEntry ) + 0x28 , sizeof (u32 ), & (file_entry .hash_bucket_next_index )) != FR_OK )
300302 return 1 ;
301303 }
302304
@@ -322,16 +324,26 @@ static u32 RemoveBDRIEntry(const BDRIFsHeader* fs_header, const u32 fs_header_of
322324 return 1 ;
323325 } while (getfatindex (fat_entry [1 ]) != 0 );
324326
325- fat_entry [1 ] |= next_free_index ;
327+ // Bug fix: use buildfatuv to explicitly clear Bit 31 (the multi-block flag).
328+ // If the tail of the freed chain is a multi-block node start, Bit 31 is already
329+ // set in fat_entry[1]. A plain |= would keep it set, corrupting the free list.
330+ fat_entry [1 ] = buildfatuv (next_free_index , false);
326331
327- if ((BDRIWrite (fat_offset + fat_index * FAT_ENTRY_SIZE , FAT_ENTRY_SIZE , fat_entry ) != FR_OK ) ||
328- (BDRIRead (fat_offset + next_free_index * FAT_ENTRY_SIZE , FAT_ENTRY_SIZE , fat_entry ) != FR_OK ))
332+ if (BDRIWrite (fat_offset + fat_index * FAT_ENTRY_SIZE , FAT_ENTRY_SIZE , fat_entry ) != FR_OK )
329333 return 1 ;
330334
331- fat_entry [0 ] = buildfatuv (fat_index , false);
335+ // Bug fix: guard against next_free_index == 0 (freed entry was the last free
336+ // block). Without this guard, FAT[0] (the free-list sentinel) gets corrupted
337+ // by a stray back-pointer write.
338+ if (next_free_index != 0 ) {
339+ if (BDRIRead (fat_offset + next_free_index * FAT_ENTRY_SIZE , FAT_ENTRY_SIZE , fat_entry ) != FR_OK )
340+ return 1 ;
332341
333- if (BDRIWrite (fat_offset + next_free_index * FAT_ENTRY_SIZE , FAT_ENTRY_SIZE , fat_entry ) != FR_OK )
334- return 1 ;
342+ fat_entry [0 ] = buildfatuv (fat_index , false);
343+
344+ if (BDRIWrite (fat_offset + next_free_index * FAT_ENTRY_SIZE , FAT_ENTRY_SIZE , fat_entry ) != FR_OK )
345+ return 1 ;
346+ }
335347
336348 return 0 ;
337349}
0 commit comments