webp: avoid canvas overflow on 32-bit systems

RFC 9649 permits canvases with a width*height of up to 2^32-1.
Enforce a slightly smaller limit of 2^31-1 to avoid overflow
on 32-bit platforms.

This corrects the fix in CL 759860 to cover 32-bit platforms as well.

For golang/go#78407
For CVE-2026-33813

Change-Id: Ib380c95234b59ed0074d00d0a18de9686a6a6964
Reviewed-on: https://go-review.googlesource.com/c/image/+/780860
Reviewed-by: Nicholas Husin <husin@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Nicholas Husin <nsh@golang.org>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/webp/decode.go b/webp/decode.go
index 15dc0ee..726bebd 100644
--- a/webp/decode.go
+++ b/webp/decode.go
@@ -134,10 +134,12 @@
 			wantAlpha = (buf[0] & alphaBit) != 0
 			widthMinusOne = uint32(buf[4]) | uint32(buf[5])<<8 | uint32(buf[6])<<16
 			heightMinusOne = uint32(buf[7]) | uint32(buf[8])<<8 | uint32(buf[9])<<16
-			if uint64(widthMinusOne+1)*uint64(heightMinusOne+1) > 1<<32-1 {
+			w := uint64(widthMinusOne) + 1
+			h := uint64(heightMinusOne) + 1
+			if w*h > 1<<31-1 {
 				// The product of _Canvas Width_ and _Canvas Height_ MUST be
 				// at most 2^32 - 1.
-				// https://www.rfc-editor.org/rfc/rfc9649.html#section-2.7-12
+				// But it also needs to fit in an int, so limit it to MaxInt32.
 				return nil, image.Config{}, errInvalidFormat
 			}
 			if configOnly {
diff --git a/webp/decode_test.go b/webp/decode_test.go
index 56948ef..796a8bc 100644
--- a/webp/decode_test.go
+++ b/webp/decode_test.go
@@ -294,7 +294,7 @@
 		// Canvas Width Minus One
 		0xff, 0xff, 0x00,
 		// Canvas Height Minus One
-		0xff, 0xff, 0x00,
+		0xff, 0x7f, 0x00,
 	}
 	_, err := DecodeConfig(bytes.NewReader(data))
 	if err != errInvalidFormat {
@@ -314,16 +314,18 @@
 		// bits + Reserved
 		1 << 4, 0, 0, 0, // alpha bit set
 		// Canvas Width Minus One
-		0xfe, 0xff, 0x00,
+		0xff, 0xff, 0x00,
 		// Canvas Height Minus One
-		0xfe, 0xff, 0x00,
+		0xfe, 0x7f, 0x00,
 	}
 	cfg, err := DecodeConfig(bytes.NewReader(data))
 	if err != nil {
 		t.Fatalf("unexpected error: want nil, got %q", err)
 	}
-	if cfg.Width != 0xffff || cfg.Height != 0xffff {
-		t.Fatalf("width x height: got %v x %v, want %v x %v", cfg.Width, cfg.Height, 0xffff, 0xffff)
+	wantWidth := 0x10000
+	wantHeight := 0x7fff
+	if cfg.Width != wantWidth || cfg.Height != wantHeight {
+		t.Fatalf("width x height: got %v x %v, want %v x %v", cfg.Width, cfg.Height, wantWidth, wantHeight)
 	}
 }