MDL-71709 libraries: upgrade to version 1.10.1 of MaxMind.

This commit is contained in:
Paul Holden 2021-07-19 17:32:09 +01:00
parent 0d0e66d37c
commit 969cbd2c7d
9 changed files with 79 additions and 25 deletions

View File

@ -1,6 +1,22 @@
CHANGELOG
=========
1.10.1 (2021-04-14)
-------------------
* Fix a `TypeError` exception in the pure PHP reader when using large
databases on 32-bit PHP builds with the `bcmath` extension. Reported
by dodo1708. GitHub #124.
1.10.0 (2021-02-09)
-------------------
* When using the pure PHP reader, unsigned integers up to PHP_MAX_INT
will now be integers in PHP rather than strings. Previously integers
greater than 2^24 on 32-bit platforms and 2^56 on 64-bit platforms
would be strings due to the use of `gmp` or `bcmath` to decode them.
Reported by Alejandro Celaya. GitHub #119.
1.9.0 (2021-01-07)
------------------

View File

@ -211,10 +211,12 @@ class Reader
if ($node === $nodeCount) {
// Record is empty
return [0, $i];
} elseif ($node > $nodeCount) {
}
if ($node > $nodeCount) {
// Record is a data pointer
return [$node, $i];
}
throw new InvalidDatabaseException(
'Invalid or corrupt database. Maximum search depth reached without finding a leaf node'
);
@ -246,6 +248,7 @@ class Reader
[, $node] = unpack('N', "\x00" . $bytes);
return $node;
case 28:
$bytes = Util::read($this->fileHandle, $baseOffset + 3 * $index, 4);
if ($index === 0) {
@ -256,11 +259,13 @@ class Reader
[, $node] = unpack('N', \chr($middle) . substr($bytes, $index, 3));
return $node;
case 32:
$bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 4);
[, $node] = unpack('N', $bytes);
return $node;
default:
throw new InvalidDatabaseException(
'Unknown record size: '
@ -312,6 +317,7 @@ class Reader
return $offset + $markerLength;
}
}
throw new InvalidDatabaseException(
"Error opening database file ($filename). " .
'Is this a valid MaxMind DB file?'

View File

@ -7,12 +7,12 @@ namespace MaxMind\Db\Reader;
// @codingStandardsIgnoreLine
use RuntimeException;
/**
/*
* @ignore
*
* We subtract 1 from the log to protect against precision loss.
*/
\define(__NAMESPACE__ . '\_MM_MAX_INT_BYTES', (log(PHP_INT_MAX, 2) - 1) / 8);
\define(__NAMESPACE__ . '\_MM_MAX_INT_BYTES', (int) ((log(\PHP_INT_MAX, 2) - 1) / 8));
class Decoder
{
@ -123,33 +123,41 @@ class Decoder
switch ($type) {
case self::_MAP:
return $this->decodeMap($size, $offset);
case self::_ARRAY:
return $this->decodeArray($size, $offset);
case self::_BOOLEAN:
return [$this->decodeBoolean($size), $offset];
}
$newOffset = $offset + $size;
$bytes = Util::read($this->fileStream, $offset, $size);
switch ($type) {
case self::_BYTES:
case self::_UTF8_STRING:
return [$bytes, $newOffset];
case self::_DOUBLE:
$this->verifySize(8, $size);
return [$this->decodeDouble($bytes), $newOffset];
case self::_FLOAT:
$this->verifySize(4, $size);
return [$this->decodeFloat($bytes), $newOffset];
case self::_INT32:
return [$this->decodeInt32($bytes, $size), $newOffset];
case self::_UINT16:
case self::_UINT32:
case self::_UINT64:
case self::_UINT128:
return [$this->decodeUint($bytes, $size), $newOffset];
default:
throw new InvalidDatabaseException(
'Unknown or unexpected type: ' . $type
@ -206,13 +214,17 @@ class Decoder
switch ($size) {
case 0:
return 0;
case 1:
case 2:
case 3:
$bytes = str_pad($bytes, 4, "\x00", STR_PAD_LEFT);
$bytes = str_pad($bytes, 4, "\x00", \STR_PAD_LEFT);
break;
case 4:
break;
default:
throw new InvalidDatabaseException(
"The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
@ -249,12 +261,16 @@ class Decoder
$packed = \chr($ctrlByte & 0x7) . $buffer;
[, $pointer] = unpack('n', $packed);
$pointer += $this->pointerBase;
break;
case 2:
$packed = "\x00" . \chr($ctrlByte & 0x7) . $buffer;
[, $pointer] = unpack('N', $packed);
$pointer += $this->pointerBase + 2048;
break;
case 3:
$packed = \chr($ctrlByte & 0x7) . $buffer;
@ -262,26 +278,26 @@ class Decoder
// first bit is 0.
[, $pointer] = unpack('N', $packed);
$pointer += $this->pointerBase + 526336;
break;
case 4:
// We cannot use unpack here as we might overflow on 32 bit
// machines
$pointerOffset = $this->decodeUint($buffer, $pointerSize);
$byteLength = $pointerSize + $this->pointerBaseByteSize;
$pointerBase = $this->pointerBase;
if ($byteLength <= _MM_MAX_INT_BYTES) {
$pointer = $pointerOffset + $this->pointerBase;
} elseif (\extension_loaded('gmp')) {
$pointer = gmp_strval(gmp_add($pointerOffset, $this->pointerBase));
} elseif (\extension_loaded('bcmath')) {
$pointer = bcadd($pointerOffset, (string) $this->pointerBase);
if (\PHP_INT_MAX - $pointerBase >= $pointerOffset) {
$pointer = $pointerOffset + $pointerBase;
} else {
throw new RuntimeException(
'The gmp or bcmath extension must be installed to read this database.'
'The database offset is too large to be represented on your platform.'
);
}
break;
default:
throw new InvalidDatabaseException(
'Unexpected pointer size ' . $pointerSize
@ -291,6 +307,7 @@ class Decoder
return [$pointer, $offset];
}
// @phpstan-ignore-next-line
private function decodeUint(string $bytes, int $byteLength)
{
if ($byteLength === 0) {
@ -299,11 +316,17 @@ class Decoder
$integer = 0;
// PHP integers are signed. _MM_MAX_INT_BYTES 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 <= _MM_MAX_INT_BYTES
|| ($byteLength === _MM_MAX_INT_BYTES + 1 && (\ord($bytes[0]) & 0x80) === 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 ($byteLength <= _MM_MAX_INT_BYTES) {
if ($useRealInts) {
$integer = ($integer << 8) + $part;
} elseif (\extension_loaded('gmp')) {
$integer = gmp_strval(gmp_add(gmp_mul((string) $integer, '256'), $part));

View File

@ -24,6 +24,7 @@ class Util
return $value;
}
}
throw new InvalidDatabaseException(
'The MaxMind DB file contains bad data'
);

View File

@ -112,9 +112,16 @@ you are using an autoloader, no changes to your code should be necessary.
First install [libmaxminddb](https://github.com/maxmind/libmaxminddb) as
described in its [README.md
file](https://github.com/maxmind/libmaxminddb/blob/master/README.md#installing-from-a-tarball).
After successfully installing libmaxmindb, run the following commands from the
top-level directory of this distribution:
file](https://github.com/maxmind/libmaxminddb/blob/main/README.md#installing-from-a-tarball).
After successfully installing libmaxmindb, you may install the extension
from [pecl](https://pecl.php.net/package/maxminddb):
```
pecl install maxminddb
```
Alternatively, you may install it from the source. To do so, run the following
commands from the top-level directory of this distribution:
```
cd ext

View File

@ -28,16 +28,16 @@ function mmdb_autoload($class): void
$namespace_map = ['MaxMind\\Db\\' => __DIR__ . '/src/MaxMind/Db/'];
foreach ($namespace_map as $prefix => $dir) {
/* First swap out the namespace prefix with a directory... */
// First swap out the namespace prefix with a directory...
$path = str_replace($prefix, $dir, $class);
/* replace the namespace separator with a directory separator... */
// replace the namespace separator with a directory separator...
$path = str_replace('\\', '/', $path);
/* and finally, add the PHP file extension to the result. */
// and finally, add the PHP file extension to the result.
$path = $path . '.php';
/* $path should now contain the path to a PHP file defining $class */
// $path should now contain the path to a PHP file defining $class
if (file_exists($path)) {
include $path;
}

View File

@ -21,14 +21,15 @@
"ext-maxminddb": "A C-based database decoder that provides significantly faster lookups"
},
"conflict": {
"ext-maxminddb": "<1.9.0,>=2.0.0"
"ext-maxminddb": "<1.10.1,>=2.0.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "*",
"phpunit/phpunit": ">=8.0.0,<10.0.0",
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpcov": ">=6.0.0",
"squizlabs/php_codesniffer": "3.*"
"squizlabs/php_codesniffer": "3.*",
"phpstan/phpstan": "*"
},
"autoload": {
"psr-4": {

View File

@ -4,7 +4,7 @@ GeoIP2 PHP API
No changes from the upstream version have been made, it is recommended by upstream
to install these depdencies via composer - but the composer installation is bundled
with a load of test files, shell scripts etc (and we don't use composer to manage
'production depdendencies') so we have to do it manually.
'production dependencies') so we have to do it manually.
Information
-----------
@ -36,4 +36,4 @@ mv MaxMind-DB-Reader-php-X.Y.Z/autoload.php /path/to/moodle/lib/maxmind/MaxMind/
5) Run unit tests on iplookup/tests/geoip_test.php.
6) Update maxmind/GeoIp2 and maxmind/MaxMin versions in lib/thirdpartylibs.xml
6) Update maxmind/GeoIp2 and maxmind/MaxMind versions in lib/thirdpartylibs.xml

View File

@ -247,7 +247,7 @@
<location>maxmind/MaxMind</location>
<name>MaxMind DB Reader API</name>
<license>Apache 2.0</license>
<version>1.9.0</version>
<version>1.10.1</version>
</library>
<library>
<location>ltiprovider</location>