From 04a7ae4fef14a390388b2d5cc2cbb0ab6cdc8921 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Wed, 17 Jun 2026 19:14:41 +0200 Subject: [PATCH 1/2] Fix division by zero when origWidth or origHeight is float 0.0 in BaseHandler::reproportion() and add tests --- system/Images/Handlers/BaseHandler.php | 27 ++++++++++++++++--------- tests/system/Images/BaseHandlerTest.php | 22 ++++++++++++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/system/Images/Handlers/BaseHandler.php b/system/Images/Handlers/BaseHandler.php index 9301b1573c23..79e19561c4df 100644 --- a/system/Images/Handlers/BaseHandler.php +++ b/system/Images/Handlers/BaseHandler.php @@ -720,29 +720,38 @@ public function __call(string $name, array $args = []) */ protected function reproportion() { - if (($this->width === 0 && $this->height === 0) || $this->image()->origWidth === 0 || $this->image()->origHeight === 0 || (! ctype_digit((string) $this->width) && ! ctype_digit((string) $this->height)) || ! ctype_digit((string) $this->image()->origWidth) || ! ctype_digit((string) $this->image()->origHeight)) { + $image = $this->image(); + $origWidth = (int) $image->origWidth; + $origHeight = (int) $image->origHeight; + + if (! is_numeric($this->width) || ! is_numeric($this->height)) { return; } - // Sanitize - $this->width = (int) $this->width; - $this->height = (int) $this->height; + $width = (int) $this->width; + $height = (int) $this->height; + + if (($width === 0 && $height === 0) || $origWidth === 0 || $origHeight === 0) { + return; + } + + $this->width = $width; + $this->height = $height; if ($this->masterDim !== 'width' && $this->masterDim !== 'height') { if ($this->width > 0 && $this->height > 0) { - $this->masterDim = ((($this->image()->origHeight / $this->image()->origWidth) - ($this->height / $this->width)) < 0) ? 'width' : 'height'; + $this->masterDim = ((($origHeight / $origWidth) - ($this->height / $this->width)) < 0) ? 'width' : 'height'; } else { $this->masterDim = ($this->height === 0) ? 'width' : 'height'; } - } elseif (($this->masterDim === 'width' && $this->width === 0) || ($this->masterDim === 'height' && $this->height === 0) - ) { + } elseif (($this->masterDim === 'width' && $this->width === 0) || ($this->masterDim === 'height' && $this->height === 0)) { return; } if ($this->masterDim === 'width') { - $this->height = (int) ceil($this->width * $this->image()->origHeight / $this->image()->origWidth); + $this->height = (int) ceil($this->width * $origHeight / $origWidth); } else { - $this->width = (int) ceil($this->image()->origWidth * $this->height / $this->image()->origHeight); + $this->width = (int) ceil($origWidth * $this->height / $origHeight); } } diff --git a/tests/system/Images/BaseHandlerTest.php b/tests/system/Images/BaseHandlerTest.php index 17bc3c00eb70..05e6d227985b 100644 --- a/tests/system/Images/BaseHandlerTest.php +++ b/tests/system/Images/BaseHandlerTest.php @@ -20,6 +20,7 @@ use CodeIgniter\Test\CIUnitTestCase; use org\bovigo\vfs\vfsStream; use PHPUnit\Framework\Attributes\Group; +use ReflectionMethod; /** * Test the common image processing functionality. @@ -130,4 +131,25 @@ public function testImageHandled(): void $handler->withFile($this->path); $this->assertSame($this->path, $handler->getPathname()); } + + public function testReproportionWithFloatZero(): void + { + $handler = Services::image('gd', null, false); + $handler->withFile($this->path); + + $image = $handler->getFile(); + $image->origWidth = 0.0; + $image->origHeight = 0.0; + + // Use reflection to test the protected method reproportion directly + // This should not throw a DivisionByZeroError + $expectedWidth = $handler->getWidth(); + $expectedHeight = $handler->getHeight(); + + $method = new ReflectionMethod($handler::class, 'reproportion'); + $method->invoke($handler); + + $this->assertSame($expectedWidth, $handler->getWidth()); + $this->assertSame($expectedHeight, $handler->getHeight()); + } } From 986900441ed14e64aa0555e1fdc752e6ba258326 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Wed, 17 Jun 2026 19:25:15 +0200 Subject: [PATCH 2/2] Refine reproportion() logic --- system/Images/Handlers/BaseHandler.php | 33 ++++++++++---------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/system/Images/Handlers/BaseHandler.php b/system/Images/Handlers/BaseHandler.php index 79e19561c4df..d3aff71f4d10 100644 --- a/system/Images/Handlers/BaseHandler.php +++ b/system/Images/Handlers/BaseHandler.php @@ -720,38 +720,29 @@ public function __call(string $name, array $args = []) */ protected function reproportion() { - $image = $this->image(); - $origWidth = (int) $image->origWidth; - $origHeight = (int) $image->origHeight; + $image = $this->image(); + $origW = (int) $image->origWidth; + $origH = (int) $image->origHeight; + $w = (int) $this->width; + $h = (int) $this->height; - if (! is_numeric($this->width) || ! is_numeric($this->height)) { + if (! is_numeric($this->width) || ! is_numeric($this->height) || $origW === 0 || $origH === 0 || ($w === 0 && $h === 0)) { return; } - $width = (int) $this->width; - $height = (int) $this->height; - - if (($width === 0 && $height === 0) || $origWidth === 0 || $origHeight === 0) { - return; - } - - $this->width = $width; - $this->height = $height; + $this->width = $w; + $this->height = $h; if ($this->masterDim !== 'width' && $this->masterDim !== 'height') { - if ($this->width > 0 && $this->height > 0) { - $this->masterDim = ((($origHeight / $origWidth) - ($this->height / $this->width)) < 0) ? 'width' : 'height'; - } else { - $this->masterDim = ($this->height === 0) ? 'width' : 'height'; - } - } elseif (($this->masterDim === 'width' && $this->width === 0) || ($this->masterDim === 'height' && $this->height === 0)) { + $this->masterDim = ($h === 0 || ($w > 0 && (($origH / $origW) - ($h / $w) < 0))) ? 'width' : 'height'; + } elseif (($this->masterDim === 'width' && $w === 0) || ($this->masterDim === 'height' && $h === 0)) { return; } if ($this->masterDim === 'width') { - $this->height = (int) ceil($this->width * $origHeight / $origWidth); + $this->height = (int) ceil($w * $origH / $origW); } else { - $this->width = (int) ceil($origWidth * $this->height / $origHeight); + $this->width = (int) ceil($origW * $h / $origH); } }