Skip to content

Commit 6e6a357

Browse files
authored
Merge pull request #120 from maxmind/greg/max-int
Make integers up to PHP_INT_MAX real integers. Closes #119
2 parents 10e74e2 + a247437 commit 6e6a357

3 files changed

Lines changed: 21 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
CHANGELOG
22
=========
33

4+
1.10.0
5+
------------------
6+
7+
* When using the pure PHP reader, unsigned integers up to PHP_MAX_INT
8+
will now be integers in PHP rather than strings. Previously integers
9+
greater than 2^24 on 32-bit platforms and 2^56 on 64-bit platforms
10+
would be strings due to the use of `gmp` or `bcmath` to decode them.
11+
Reported by Alejandro Celaya. GitHub #119.
12+
413
1.9.0 (2021-01-07)
514
------------------
615

src/MaxMind/Db/Reader/Decoder.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*
1313
* We subtract 1 from the log to protect against precision loss.
1414
*/
15-
\define(__NAMESPACE__ . '\_MM_MAX_INT_BYTES', (log(\PHP_INT_MAX, 2) - 1) / 8);
15+
\define(__NAMESPACE__ . '\_MM_MAX_INT_BYTES', (int) ((log(\PHP_INT_MAX, 2) - 1) / 8));
1616

1717
class Decoder
1818
{
@@ -320,11 +320,17 @@ private function decodeUint(string $bytes, int $byteLength)
320320

321321
$integer = 0;
322322

323+
// PHP integers are signed. _MM_MAX_INT_BYTES is the number of
324+
// complete bytes that can be converted to an integer. However,
325+
// we can convert another byte if the leading bit is zero.
326+
$useRealInts = $byteLength <= _MM_MAX_INT_BYTES
327+
|| ($byteLength === _MM_MAX_INT_BYTES + 1 && (\ord($bytes[0]) & 0x80) === 0);
328+
323329
for ($i = 0; $i < $byteLength; ++$i) {
324330
$part = \ord($bytes[$i]);
325331

326332
// We only use gmp or bcmath if the final value is too big
327-
if ($byteLength <= _MM_MAX_INT_BYTES) {
333+
if ($useRealInts) {
328334
$integer = ($integer << 8) + $part;
329335
} elseif (\extension_loaded('gmp')) {
330336
$integer = gmp_strval(gmp_add(gmp_mul((string) $integer, '256'), $part));

tests/MaxMind/Db/Test/ReaderTest.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,8 @@ public function testDecoder(): void
6464

6565
$this->assertSame(-268435456, $record['int32']);
6666
$this->assertSame(100, $record['uint16']);
67-
$this->assertSame(\PHP_INT_MAX < 4294967295 && !\extension_loaded('maxminddb') ? '268435456' : 268435456, $record['uint32']);
68-
// @phpstan-ignore-next-line
69-
$this->assertSame(\PHP_INT_MAX > 1152921504606846976 && \extension_loaded('maxminddb') ? 1152921504606846976 : '1152921504606846976', $record['uint64']);
67+
$this->assertSame(268435456, $record['uint32']);
68+
$this->assertSame(\PHP_INT_MAX > 1152921504606846976 ? 1152921504606846976 : '1152921504606846976', $record['uint64']);
7069

7170
$uint128 = $record['uint128'];
7271

@@ -158,9 +157,8 @@ public function testGetWithPrefixLen(): void
158157
],
159158
'uint128' => \extension_loaded('maxminddb') ? '0x01000000000000000000000000000000' : '1329227995784915872903807060280344576',
160159
'uint16' => 0x64,
161-
'uint32' => \PHP_INT_MAX < 4294967295 && !\extension_loaded('maxminddb') ? '268435456' : 268435456,
162-
// @phpstan-ignore-next-line
163-
'uint64' => \PHP_INT_MAX > 1152921504606846976 && \extension_loaded('maxminddb') ? 1152921504606846976 : '1152921504606846976',
160+
'uint32' => 268435456,
161+
'uint64' => \PHP_INT_MAX > 1152921504606846976 ? 1152921504606846976 : '1152921504606846976',
164162
'utf8_string' => 'unicode! ☯ - ♫',
165163
];
166164
$tests = [

0 commit comments

Comments
 (0)