From cf6ff4e6df9526b572e5f6bc88b5980d57f88542 Mon Sep 17 00:00:00 2001 From: albertlast Date: Wed, 29 Jul 2026 21:07:05 +0200 Subject: [PATCH] Parses memory settings that carry no unit designator memoryReturnBytes() removed the last character of the value before parsing the number, on the assumption that it is always a designator. PHP's shorthand notation is optional, so a plain byte count loses its last digit: '128' reads as 12, and '2097152' reads as 209715. Graphics\Image does exactly that, passing a computed byte count with no designator, so resizing an image asks for a tenth of the memory it just worked out that it needs. The other value with no designator is '-1', which means there is no limit. It read as 0, because intval('-') is 0, so setMemoryLimit() found the current limit to be smaller than anything and set one. On a server with no memory limit, asking for 128M capped it at 128M. Only strips the last character when it is one of the designators PHP accepts, and reports "no limit" as PHP_INT_MAX so that the callers comparing it against an amount they need do not each have to special case it. The dead is_integer() check went with it; the parameter is typed string. Co-Authored-By: Claude Opus 5 --- Sources/Sapi.php | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Sources/Sapi.php b/Sources/Sapi.php index 2e6aba3779e..5ff927e1d0f 100644 --- a/Sources/Sapi.php +++ b/Sources/Sapi.php @@ -334,19 +334,28 @@ public static function setMemoryLimit(string $needed, bool $in_use = false): boo /** * Helper function to convert memory string settings to bytes * - * @param string $val The byte string, like '256M' or '1G'. + * The shorthand notation PHP accepts for these settings is optional, so the + * value may be a plain byte count with no designator at all. + * + * A negative value means there is no limit, which is reported as PHP_INT_MAX + * so that callers comparing it against an amount of memory they need do not + * have to special case it. + * + * @param string $val The byte string, like '256M', '1G' or '2097152'. * @return int The string converted to a proper integer in bytes. */ public static function memoryReturnBytes(string $val): int { - if (\is_integer($val)) { - return (int) $val; + $val = trim($val); + + // No limit at all. + if ((int) $val < 0) { + return PHP_INT_MAX; } - // Separate the number from the designator. - $val = trim($val); - $num = \intval(substr($val, 0, \strlen($val) - 1)); + // Separate the number from the designator, if there is one. $last = strtolower(substr($val, -1)); + $num = \in_array($last, ['g', 'm', 'k'], true) ? (int) substr($val, 0, -1) : (int) $val; // Convert to bytes. switch ($last) {