From ee604338e10059e22f5fe24b7ec695f09666084c Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 13 Oct 2023 15:35:01 -0300 Subject: 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 Acked-by: Hyunchul Lee Signed-off-by: Namjae Jeon --- lib/exfat_dir.c | 20 ++++++++++++++------ 1 file 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; } -- cgit v1.2.3