diff --git a/src/wp-includes/load.php b/src/wp-includes/load.php
index ae5ada388d..312fecbe88 100644
--- a/src/wp-includes/load.php
+++ b/src/wp-includes/load.php
@@ -1425,33 +1425,210 @@ function is_ssl() {
 }
 
 /**
- * Converts a shorthand byte value to an integer byte value.
+ * Returns byte size represented in a numeric php.ini directive.
+ *
+ * Directives in php.ini may use a string representation of a number of bytes
+ * or a "shorthand" byte size to reference larger values. Multiple numeric
+ * php.ini directive use these shorthands even when they don't refer bytes.
+ *
+ * Example:
+ *
+ *     wp_convert_hr_to_bytes( "1m" ) == 1048576
+ *     wp_convert_hr_to_bytes( "2K" ) == 2048 // 2 * 1024
+ *     wp_convert_hr_to_bytes( "0.5g" ) == 0
+ *     wp_convert_hr_to_bytes( "14.6e-13g" ) == 15032385536 // 14 * 1024^3
+ *     wp_convert_hr_to_bytes( "-813k" ) == 0;
+ *     wp_convert_hr_to_bytes( "boat" ) == 0;
+ *
+ *     // This gives an answer, but it's _wrong_ because
+ *     // the underlying mechanism in PHP overflowed and
+ *     // the real return value depends on whether PHP
+ *     // was built with 64-bit support.
+ *     wp_convert_hr_to_bytes( "9223372036854775807g" ) == ??
+ *
+ * Notes:
+ *  - Suffix units are case-insensitive and are always determined
+ *    by looking at the last character in the input string.
+ *  - Suffix units k/m/g report powers of 1024. PHP and the IEC disagree
+ *    on the meaning of "kilobyte," "megabyte," and "gigabyte."
+ *  - This function will not fail; it stops parsing after finding
+ *    the last consecutive digit at the front of the trimmed string.
+ *  - Invalid string representations return a value of 0.
+ *  - This code mirrors the computation inside PHP and should only
+ *    change its output if PHP redefines how it parses numeric php.ini
+ *    directive. If you think something is wrong or should be
+ *    refactored it probably shouldn't be. Consult `zend_operators.c`
+ *    in the PHP-SRC repository for more info; specifically
+ *    `zend_atol()` and `_is_numeric_string_ex()`.
+ *  - As noted in the PHP documentation, any numeric value that overflows
+ *    an integer for the platform on which PHP is built will break.
  *
  * @since 2.3.0
  * @since 4.6.0 Moved from media.php to load.php.
+ * @since 6.1.0 Mirrors size calculation in PHP.
  *
  * @link https://www.php.net/manual/en/function.ini-get.php
  * @link https://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
+ * @link https://en.wikipedia.org/wiki/Byte#Multiple-byte_units
  *
- * @param string $value A (PHP ini) byte value, either shorthand or ordinary.
- * @return int An integer byte value.
+ * @param string $value A numeric php.ini directive's byte value,
+ *                      either shorthand or ordinary, as returned
+ *                      by a call to `ini_get()`.
+ * @return int          Parsed numeric value represented by given string.
  */
 function wp_convert_hr_to_bytes( $value ) {
-	$value = strtolower( trim( $value ) );
-	$bytes = (int) $value;
+	// Number of bytes in input string; we're only assessing 7-bit ASCII/Unicode characters.
+	$strlen = strlen( $value );
 
-	if ( false !== strpos( $value, 'g' ) ) {
-		$bytes *= GB_IN_BYTES;
-	} elseif ( false !== strpos( $value, 'm' ) ) {
-		$bytes *= MB_IN_BYTES;
-	} elseif ( false !== strpos( $value, 'k' ) ) {
-		$bytes *= KB_IN_BYTES;
+	// Count (of bytes) represented by value string.
+	$scalar = 0;
+
+	// Sign of number represented by input, either positive (1) or negative (-1).
+	$sign = 1;
+
+	// Numeric base of digits; determined by string prefix (e.g. "0x" or "0").
+	$base = 10;
+
+	// Index into input string as we walk through it and analyze each character.
+	$i = 0;
+
+	// Trim leading whitespace.
+	for ( ; $i < $strlen; $i++ ) {
+		switch ( $value[ $i ] ) {
+			case ' ':
+			case '\t':
+			case '\r':
+			case '\v':
+			case '\f':
+				break;
+
+			default:
+				break 2;
+		}
+	}
+
+	// Handle optional sign indicator.
+	switch ( $value[ $i ] ) {
+		case '+':
+			$i++;
+			break;
+
+		case '-':
+			$sign = -1;
+			$i++;
+			break;
+	}
+
+	// Determine base for digit conversion, if not decimal.
+	$base_a = $value[ $i ];
+	$base_b = $i + 1 < $strlen ? $value[ $i + 1 ] : '';
+
+	if ( '0' === $base_a && ( 'x' === $base_b || 'X' === $base_b ) ) {
+		$base = 16;
+		$i   += 2;
+	} elseif ( '0' === $base_a && ctype_digit( $base_b ) ) {
+		$base = 8;
+		++$i;
 	}
 
-	// Deal with large (float) values which run into the maximum integer size.
-	return min( $bytes, PHP_INT_MAX );
+	// Trim leading zeros.
+	for ( ; $i < $strlen; $i++ ) {
+		if ( '0' !== $value[ $i ] ) {
+			break;
+		}
+	}
+
+	// Numeric values for scanned digits.
+	$digits = array(
+		'0' => 0,
+		'1' => 1,
+		'2' => 2,
+		'3' => 3,
+		'4' => 4,
+		'5' => 5,
+		'6' => 6,
+		'7' => 7,
+		'8' => 8,
+		'9' => 9,
+		'A' => 10,
+		'a' => 10,
+		'B' => 11,
+		'b' => 11,
+		'C' => 12,
+		'c' => 12,
+		'D' => 13,
+		'd' => 13,
+		'E' => 14,
+		'e' => 14,
+		'F' => 15,
+		'f' => 15,
+	);
+
+	/*
+	 * Build the scalar value by eating the
+	 * next sequence of contiguous digits.
+	 */
+	for ( ; $i < $strlen; $i++ ) {
+		$c = $value[ $i ];
+
+		/*
+		 * Only digits recognized in this base system can be used.
+		 * Once we find an unrecognized digit we abort and move
+		 * on to the next step in parsing the size suffix.
+		 */
+		if ( ! isset( $digits[ $c ] ) || $digits[ $c ] >= $base ) {
+			break;
+		}
+
+		$scalar = $scalar * $base + $digits[ $c ];
+	}
+
+	/*
+	 * Clamp the parsed digits to an integer value as PHP does internally.
+	 * See `strtol()`/`LONG_MAX` for 32-bit systems and `strtoll()`/`LLONG_MAX` for 64-bit.
+	 */
+	if ( $sign > 0 && $scalar >= PHP_INT_MAX ) {
+		$scalar = PHP_INT_MAX;
+	} elseif ( $sign < 0 && $scalar >= -PHP_INT_MIN ) {
+		$scalar = PHP_INT_MIN;
+	} elseif ( $sign < 0 ) {
+		$scalar = -$scalar;
+	}
+
+	/*
+	 * Do not use WP constants here (GB_IN_BYTES, MB_IN_BYTES, KB_IN_BYTES)
+	 * since they are re-definable; PHP shorthand values are hard-coded
+	 * in PHP itself and stay the same regardless of these constants.
+	 *
+	 * Note that we can overflow here, as happens in PHP itself.
+	 * Overflow results will likely not match PHP's value, but
+	 * will likely break in most cases anyway and so leaving
+	 * this loose is the best we can do until and unless PHP
+	 * makes a more concrete choice on how to handle overflow.
+	 *
+	 * Fallthrough preserved to match structure and behavior in PHP.
+	 */
+	switch ( $value[ $strlen - 1 ] ) {
+		case 'g':
+		case 'G':
+			$scalar *= 1024;
+			// Fallthrough.
+
+		case 'm':
+		case 'M':
+			$scalar *= 1024;
+			// Fallthrough.
+
+		case 'k':
+		case 'K':
+			$scalar *= 1024;
+			// Fallthrough.
+	}
+
+	return (int) $scalar;
 }
 
+
 /**
  * Determines whether a PHP ini value is changeable at runtime.
  *
