diff options
author | Xin LI <delphij@FreeBSD.org> | 2020-10-01 18:58:06 +0000 |
---|---|---|
committer | Xin LI <delphij@FreeBSD.org> | 2020-10-01 18:58:06 +0000 |
commit | 9a7010f2e4113816007f50005963cfe77adafa93 (patch) | |
tree | 08de0bd73b54c71fe59855c39cb0f66bc227f325 | |
parent | 6a550fd843f892a861f310356dd4227896f70d45 (diff) | |
download | src-test2-9a7010f2e4113816007f50005963cfe77adafa93.tar.gz src-test2-9a7010f2e4113816007f50005963cfe77adafa93.zip |
MFS r366305: MFC r366064, r366065, r366215
sbin/fsck_msdosfs: Fix an integer overflow on 32-bit platforms
Approved by: re (gjb)
Notes
Notes:
svn path=/releng/12.2/; revision=366338
-rw-r--r-- | sbin/fsck_msdosfs/dir.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/sbin/fsck_msdosfs/dir.c b/sbin/fsck_msdosfs/dir.c index 6bdc3b4d0f94..471f6cc0335e 100644 --- a/sbin/fsck_msdosfs/dir.c +++ b/sbin/fsck_msdosfs/dir.c @@ -388,7 +388,8 @@ static int checksize(struct fat_descriptor *fat, u_char *p, struct dosDirEntry *dir) { int ret = FSOK; - size_t physicalSize; + size_t chainsize; + u_int64_t physicalSize; struct bootblock *boot; boot = fat_get_boot(fat); @@ -401,9 +402,9 @@ checksize(struct fat_descriptor *fat, u_char *p, struct dosDirEntry *dir) } else { if (!fat_is_valid_cl(fat, dir->head)) return FSERROR; - ret = checkchain(fat, dir->head, &physicalSize); + ret = checkchain(fat, dir->head, &chainsize); /* - * Upon return, physicalSize would hold the chain length + * Upon return, chainsize would hold the chain length * that checkchain() was able to validate, but if the user * refused the proposed repair, it would be unsafe to * proceed with directory entry fix, so bail out in that @@ -412,11 +413,17 @@ checksize(struct fat_descriptor *fat, u_char *p, struct dosDirEntry *dir) if (ret == FSERROR) { return (FSERROR); } - physicalSize *= boot->ClusterSize; + /* + * The maximum file size on FAT32 is 4GiB - 1, which + * will occupy a cluster chain of exactly 4GiB in + * size. On 32-bit platforms, since size_t is 32-bit, + * it would wrap back to 0. + */ + physicalSize = (u_int64_t)chainsize * boot->ClusterSize; } if (physicalSize < dir->size) { - pwarn("size of %s is %u, should at most be %zu\n", - fullpath(dir), dir->size, physicalSize); + pwarn("size of %s is %u, should at most be %ju\n", + fullpath(dir), dir->size, (uintmax_t)physicalSize); if (ask(1, "Truncate")) { dir->size = physicalSize; p[28] = (u_char)physicalSize; |