[PATCH] cmd: read: fix unsigned overflow bypassing range check
Naveen Kumar Chaudhary
naveen.osdev at gmail.com
Wed Jul 8 16:33:04 CEST 2026
The bounds check in do_rw() was written as:
if (cnt + blk > limit)
with cnt and blk declared as uint (unsigned int) and limit as ulong.
C's usual arithmetic conversions are applied per binary operator, so
"cnt + blk" is evaluated entirely in unsigned int and wraps modulo
2^32 before the result is widened for the comparison against limit.
With cnt = 0xFFFFFFFF and blk = 1 the sum wraps to 0 and the guard
passes, allowing blk_dread()/blk_dwrite() to be issued with a 4 GiB
transfer count that runs past the partition (or, when no partition
is selected, the entire device).
Rewrite the check as two comparisons that do not overflow:
if (blk > limit || cnt > limit - blk)
The subtraction is performed in ulong (limit's type), so no truncation
occurs, and the two sub-conditions cover both "start block past end"
and "count would push us past end" failure modes.
Signed-off-by: Naveen Kumar Chaudhary <naveen.osdev at gmail.com>
---
cmd/read.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmd/read.c b/cmd/read.c
index 8e21f004423..efc255ce85d 100644
--- a/cmd/read.c
+++ b/cmd/read.c
@@ -46,7 +46,7 @@ do_rw(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
limit = ~0;
}
- if (cnt + blk > limit) {
+ if (blk > limit || cnt > limit - blk) {
printf("%s out of range\n", cmdtp->name);
unmap_sysmem(ptr);
return 1;
--
2.43.0
More information about the U-Boot
mailing list