diff options
author | Val Packett <val@packett.cool> | 2023-10-13 15:35:01 -0300 |
---|---|---|
committer | Namjae Jeon <linkinjeon@kernel.org> | 2023-10-17 17:19:37 +0900 |
commit | ee604338e10059e22f5fe24b7ec695f09666084c (patch) | |
tree | 3b36c76dcfc13d684e167274a22fbffde0723e03 | |
parent | a1d5b15f47dcfeda53ff7ac05ee5ffdc84779ca0 (diff) | |
download | exfatprogs-ee604338e10059e22f5fe24b7ec695f09666084c.tar.gz |
lib: avoid int promotion in checksum causing signed overflow
This fixes UBSan errors during fsck like:
exfat_dir.c:522:54: runtime error: signed integer overflow: 2147483647 + 95
cannot be represented in type 'int'
Signed-off-by: Val Packett <val@packett.cool>
Acked-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
-rw-r--r-- | lib/exfat_dir.c | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/lib/exfat_dir.c b/lib/exfat_dir.c index ec06454..8a02bfc 100644 --- a/lib/exfat_dir.c +++ b/lib/exfat_dir.c @@ -525,12 +525,17 @@ void exfat_calc_dentry_checksum(struct exfat_dentry *dentry, bytes = (uint8_t *)dentry; - *checksum = ((*checksum << 15) | (*checksum >> 1)) + bytes[0]; - *checksum = ((*checksum << 15) | (*checksum >> 1)) + bytes[1]; + /* use += to avoid promotion to int; UBSan complaints about signed overflow */ + *checksum = (*checksum << 15) | (*checksum >> 1); + *checksum += bytes[0]; + *checksum = (*checksum << 15) | (*checksum >> 1); + *checksum += bytes[1]; i = primary ? 4 : 2; - for (; i < sizeof(*dentry); i++) - *checksum = ((*checksum << 15) | (*checksum >> 1)) + bytes[i]; + for (; i < sizeof(*dentry); i++) { + *checksum = (*checksum << 15) | (*checksum >> 1); + *checksum += bytes[i]; + } } static uint16_t calc_dentry_set_checksum(struct exfat_dentry *dset, int dcount) @@ -559,8 +564,11 @@ uint16_t exfat_calc_name_hash(struct exfat *exfat, ch = exfat->upcase_table[le16_to_cpu(name[i])]; ch = cpu_to_le16(ch); - chksum = ((chksum << 15) | (chksum >> 1)) + (ch & 0xFF); - chksum = ((chksum << 15) | (chksum >> 1)) + (ch >> 8); + /* use += to avoid promotion to int; UBSan complaints about signed overflow */ + chksum = (chksum << 15) | (chksum >> 1); + chksum += ch & 0xFF; + chksum = (chksum << 15) | (chksum >> 1); + chksum += ch >> 8; } return chksum; } |