aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVal Packett <val@packett.cool>2023-10-13 15:35:01 -0300
committerNamjae Jeon <linkinjeon@kernel.org>2023-10-17 17:19:37 +0900
commitee604338e10059e22f5fe24b7ec695f09666084c (patch)
tree3b36c76dcfc13d684e167274a22fbffde0723e03
parenta1d5b15f47dcfeda53ff7ac05ee5ffdc84779ca0 (diff)
downloadexfatprogs-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.c20
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;
}