[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