VOLUME_ReadFATSuperblock division by zero fix
Rein Klazes
rklazes at xs4all.nl
Thu Oct 28 12:17:19 CDT 2004
Hi,
Problem with division by zero in the File Open dialog still exists.
Changelog:
dlls/kernel : volume.c
In VOLUME_ReadFATSuperblock:
- do not test on the JMP instruction: most boot blocks have
that;
- test instead on the "FAT" strings first, before the size
calculation;
- do some parameter checking to prevent arithmetic errors;
- use meaningful names instead of block offsets;
- add some ERRor logging of some unexpected situations.
(based on a rejected patch from Vincent Beron)
Rein.
--
Rein Klazes
rklazes at xs4all.nl
-------------- next part --------------
--- wine/dlls/kernel/volume.c 2004-08-12 09:56:00.000000000 +0200
+++ mywine/dlls/kernel/volume.c 2004-10-28 18:07:52.000000000 +0200
@@ -491,29 +491,58 @@ static enum fs_type VOLUME_ReadFATSuperb
size != SUPERBLOCK_SIZE)
return FS_ERROR;
- if (buff[0] == 0xE9 || (buff[0] == 0xEB && buff[2] == 0x90))
+ /* FIXME: do really all FAT have their name beginning with
+ * "FAT" ? (At least FAT12, FAT16 and FAT32 have :)
+ */
+ if (!memcmp(buff+0x36, "FAT", 3) || !memcmp(buff+0x52, "FAT", 3))
{
/* guess which type of FAT we have */
- unsigned int sz, nsect, nclust;
- sz = GETWORD(buff, 0x16);
- if (!sz) sz = GETLONG(buff, 0x24);
- nsect = GETWORD(buff, 0x13);
- if (!nsect) nsect = GETLONG(buff, 0x20);
- nsect -= GETWORD(buff, 0x0e) + buff[0x10] * sz +
- (GETWORD(buff, 0x11) * 32 + (GETWORD(buff, 0x0b) - 1)) / GETWORD(buff, 0x0b);
- nclust = nsect / buff[0x0d];
-
+ int reasonable;
+ unsigned int sectors,
+ sect_per_fat,
+ total_sectors,
+ num_boot_sectors,
+ num_fats,
+ num_root_dir_ents,
+ bytes_per_sector,
+ sectors_per_cluster,
+ nclust;
+ sect_per_fat = GETWORD(buff, 0x16);
+ if (!sect_per_fat) sect_per_fat = GETLONG(buff, 0x24);
+ total_sectors = GETWORD(buff, 0x13);
+ if (!total_sectors)
+ total_sectors = GETLONG(buff, 0x20);
+ num_boot_sectors = GETWORD(buff, 0x0e);
+ num_fats = buff[0x10];
+ num_root_dir_ents = GETWORD(buff, 0x11);
+ bytes_per_sector = GETWORD(buff, 0x0b);
+ sectors_per_cluster = buff[0x0d];
+ /* check if the parameters are reasonable and will not cause
+ * arithmetic errors in the calculation */
+ reasonable = num_boot_sectors < 16 &&
+ num_fats < 16 &&
+ bytes_per_sector >= 512 && bytes_per_sector % 512 == 0 &&
+ sectors_per_cluster > 1;
+ if( !reasonable) {
+ ERR("FAT fs has incorrect parameters: bootsects %d nfats %d bpsect %d spclust %d\n"
+ ,num_boot_sectors, num_fats, bytes_per_sector,
+ sectors_per_cluster);
+ return FS_UNKNOWN;
+ }
+ sectors = total_sectors - num_boot_sectors - num_fats * sect_per_fat -
+ (num_root_dir_ents * 32 + bytes_per_sector - 1) / bytes_per_sector;
+ nclust = sectors / sectors_per_cluster;
+ if ((buff[0x42] == 0x28 || buff[0x42] == 0x29) &&
+ !memcmp(buff+0x52, "FAT", 3)) return FS_FAT32;
if (nclust < 65525)
{
- if (buff[0x26] == 0x29 && !memcmp(buff+0x36, "FAT", 3))
- {
- /* FIXME: do really all FAT have their name beginning with
- * "FAT" ? (At least FAT12, FAT16 and FAT32 have :)
- */
+ if ((buff[0x26] == 0x28 || buff[0x26] == 0x29) &&
+ !memcmp(buff+0x36, "FAT", 3))
return FS_FAT1216;
- }
}
- else if (!memcmp(buff+0x52, "FAT", 3)) return FS_FAT32;
+ ERR("Failed to fully recognize a FAT filesystem. 0x%02x 0x%02x '%s' '%s'\n",
+ buff[0x26], buff[0x42],
+ debugstr_an(buff+0x36,5), debugstr_an(buff+0x42,5));
}
return FS_UNKNOWN;
}
More information about the wine-patches
mailing list