MDL-80635 libraries: Upgrade GeoIP2 and Maxmind DB Reader

- GeoIP2 PHP API 3.0.0
- MaxMind DB Reader API 1.11.1

Signed-off-by: Daniel Ziegenberg <[email protected]>
This commit is contained in:
Daniel Ziegenberg
2024-05-17 15:56:36 +02:00
parent f49d120761
commit ab7a137afa
46 changed files with 2213 additions and 905 deletions
+90 -29
View File
@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace MaxMind\Db\Reader;
// @codingStandardsIgnoreLine
use RuntimeException;
class Decoder
{
@@ -13,20 +12,19 @@ class Decoder
* @var resource
*/
private $fileStream;
/**
* @var int
*/
private $pointerBase;
/**
* @var float
*/
private $pointerBaseByteSize;
/**
* This is only used for unit testing.
*
* @var bool
*/
private $pointerTestHack;
/**
* @var bool
*/
@@ -44,8 +42,8 @@ class Decoder
private const _UINT64 = 9;
private const _UINT128 = 10;
private const _ARRAY = 11;
private const _CONTAINER = 12;
private const _END_MARKER = 13;
// 12 is the container type
// 13 is the end marker type
private const _BOOLEAN = 14;
private const _FLOAT = 15;
@@ -60,7 +58,6 @@ class Decoder
$this->fileStream = $fileStream;
$this->pointerBase = $pointerBase;
$this->pointerBaseByteSize = $pointerBase > 0 ? log($pointerBase, 2) / 8 : 0;
$this->pointerTestHack = $pointerTestHack;
$this->switchByteOrder = $this->isPlatformLittleEndian();
@@ -111,6 +108,9 @@ class Decoder
return $this->decodeByType($type, $offset, $size);
}
/**
* @param int<0, max> $size
*/
private function decodeByType(int $type, int $offset, int $size): array
{
switch ($type) {
@@ -188,7 +188,13 @@ class Decoder
{
// This assumes IEEE 754 doubles, but most (all?) modern platforms
// use them.
[, $double] = unpack('E', $bytes);
$rc = unpack('E', $bytes);
if ($rc === false) {
throw new InvalidDatabaseException(
'Could not unpack a double value from the given bytes.'
);
}
[, $double] = $rc;
return $double;
}
@@ -197,7 +203,13 @@ class Decoder
{
// This assumes IEEE 754 floats, but most (all?) modern platforms
// use them.
[, $float] = unpack('G', $bytes);
$rc = unpack('G', $bytes);
if ($rc === false) {
throw new InvalidDatabaseException(
'Could not unpack a float value from the given bytes.'
);
}
[, $float] = $rc;
return $float;
}
@@ -224,7 +236,13 @@ class Decoder
);
}
[, $int] = unpack('l', $this->maybeSwitchByteOrder($bytes));
$rc = unpack('l', $this->maybeSwitchByteOrder($bytes));
if ($rc === false) {
throw new InvalidDatabaseException(
'Could not unpack a 32bit integer value from the given bytes.'
);
}
[, $int] = $rc;
return $int;
}
@@ -247,19 +265,31 @@ class Decoder
$pointerSize = (($ctrlByte >> 3) & 0x3) + 1;
$buffer = Util::read($this->fileStream, $offset, $pointerSize);
$offset = $offset + $pointerSize;
$offset += $pointerSize;
switch ($pointerSize) {
case 1:
$packed = \chr($ctrlByte & 0x7) . $buffer;
[, $pointer] = unpack('n', $packed);
$rc = unpack('n', $packed);
if ($rc === false) {
throw new InvalidDatabaseException(
'Could not unpack an unsigned short value from the given bytes (pointerSize is 1).'
);
}
[, $pointer] = $rc;
$pointer += $this->pointerBase;
break;
case 2:
$packed = "\x00" . \chr($ctrlByte & 0x7) . $buffer;
[, $pointer] = unpack('N', $packed);
$rc = unpack('N', $packed);
if ($rc === false) {
throw new InvalidDatabaseException(
'Could not unpack an unsigned long value from the given bytes (pointerSize is 2).'
);
}
[, $pointer] = $rc;
$pointer += $this->pointerBase + 2048;
break;
@@ -269,7 +299,13 @@ class Decoder
// It is safe to use 'N' here, even on 32 bit machines as the
// first bit is 0.
[, $pointer] = unpack('N', $packed);
$rc = unpack('N', $packed);
if ($rc === false) {
throw new InvalidDatabaseException(
'Could not unpack an unsigned long value from the given bytes (pointerSize is 3).'
);
}
[, $pointer] = $rc;
$pointer += $this->pointerBase + 526336;
break;
@@ -284,7 +320,7 @@ class Decoder
if (\PHP_INT_MAX - $pointerBase >= $pointerOffset) {
$pointer = $pointerOffset + $pointerBase;
} else {
throw new RuntimeException(
throw new \RuntimeException(
'The database offset is too large to be represented on your platform.'
);
}
@@ -307,32 +343,39 @@ class Decoder
return 0;
}
$integer = 0;
// PHP integers are signed. PHP_INT_SIZE - 1 is the number of
// complete bytes that can be converted to an integer. However,
// we can convert another byte if the leading bit is zero.
$useRealInts = $byteLength <= \PHP_INT_SIZE - 1
|| ($byteLength === \PHP_INT_SIZE && (\ord($bytes[0]) & 0x80) === 0);
if ($useRealInts) {
$integer = 0;
for ($i = 0; $i < $byteLength; ++$i) {
$part = \ord($bytes[$i]);
$integer = ($integer << 8) + $part;
}
return $integer;
}
// We only use gmp or bcmath if the final value is too big
$integerAsString = '0';
for ($i = 0; $i < $byteLength; ++$i) {
$part = \ord($bytes[$i]);
// We only use gmp or bcmath if the final value is too big
if ($useRealInts) {
$integer = ($integer << 8) + $part;
} elseif (\extension_loaded('gmp')) {
$integer = gmp_strval(gmp_add(gmp_mul((string) $integer, '256'), $part));
if (\extension_loaded('gmp')) {
$integerAsString = gmp_strval(gmp_add(gmp_mul($integerAsString, '256'), $part));
} elseif (\extension_loaded('bcmath')) {
$integer = bcadd(bcmul((string) $integer, '256'), (string) $part);
$integerAsString = bcadd(bcmul($integerAsString, '256'), (string) $part);
} else {
throw new RuntimeException(
throw new \RuntimeException(
'The gmp or bcmath extension must be installed to read this database.'
);
}
}
return $integer;
return $integerAsString;
}
private function sizeFromCtrlByte(int $ctrlByte, int $offset): array
@@ -349,10 +392,22 @@ class Decoder
if ($size === 29) {
$size = 29 + \ord($bytes);
} elseif ($size === 30) {
[, $adjust] = unpack('n', $bytes);
$rc = unpack('n', $bytes);
if ($rc === false) {
throw new InvalidDatabaseException(
'Could not unpack an unsigned short value from the given bytes.'
);
}
[, $adjust] = $rc;
$size = 285 + $adjust;
} else {
[, $adjust] = unpack('N', "\x00" . $bytes);
$rc = unpack('N', "\x00" . $bytes);
if ($rc === false) {
throw new InvalidDatabaseException(
'Could not unpack an unsigned long value from the given bytes.'
);
}
[, $adjust] = $rc;
$size = $adjust + 65821;
}
@@ -368,7 +423,13 @@ class Decoder
{
$testint = 0x00FF;
$packed = pack('S', $testint);
$rc = unpack('v', $packed);
if ($rc === false) {
throw new InvalidDatabaseException(
'Could not unpack an unsigned short value from the given bytes.'
);
}
return $testint === current(unpack('v', $packed));
return $testint === current($rc);
}
}