Skip to content

Commit 62b7265

Browse files
oschwaldclaude
andcommitted
Skip the pure-PHP DoS tests when the extension is loaded
These tests assert the pure-PHP decoder's "exceeds the maximum payload size" message. When the maxminddb extension is loaded, Reader decodes through libmaxminddb, which reports different text, so the assertions failed. They also fed the large amplification and fan-out fixtures to the extension's decoder, which on a libmaxminddb without the fix would exhaust memory. Skip them when the extension is loaded. The extension path is covered safely by ExtensionDosTest, which probes a small fixture first and runs the large fixtures only against a libmaxminddb that enforces the limits. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent e711d95 commit 62b7265

1 file changed

Lines changed: 20 additions & 0 deletions

File tree

tests/MaxMind/Db/Test/ReaderTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,24 @@ public function testBrokenDataPointer(): void
291291
$reader->get('1.1.1.16');
292292
}
293293

294+
// The DoS and payload-limit tests below assert the pure-PHP decoder's
295+
// messages, so they skip when the maxminddb extension is loaded: that path
296+
// decodes through libmaxminddb, which reports different text, and
297+
// ExtensionDosTest covers it. Skipping also keeps the large amplification
298+
// and fan-out fixtures away from a possibly-unpatched extension, whose
299+
// decoder would otherwise exhaust memory.
300+
private function skipIfExtensionLoaded(): void
301+
{
302+
if (\extension_loaded('maxminddb')) {
303+
$this->markTestSkipped(
304+
'covers the pure-PHP decoder; the extension path is covered by ExtensionDosTest'
305+
);
306+
}
307+
}
308+
294309
public function testPayloadAmplificationDosIsRejected(): void
295310
{
311+
$this->skipIfExtensionLoaded();
296312
// An array of pointers to one large value. The value count stays low,
297313
// but a reader that copies each target materializes the value once per
298314
// pointer. The produced-payload byte budget rejects it.
@@ -304,6 +320,7 @@ public function testPayloadAmplificationDosIsRejected(): void
304320

305321
public function testStringPayloadAmplificationDosIsRejected(): void
306322
{
323+
$this->skipIfExtensionLoaded();
307324
// The string variant, so the UTF-8 path is charged as well as bytes.
308325
$this->expectException(InvalidDatabaseException::class);
309326
$this->expectExceptionMessage("The MaxMind DB file's data section exceeds the maximum payload size");
@@ -313,6 +330,7 @@ public function testStringPayloadAmplificationDosIsRejected(): void
313330

314331
public function testWorstCasePayloadAmplificationDosIsRejected(): void
315332
{
333+
$this->skipIfExtensionLoaded();
316334
// The worst case keeps the produced payload just under the byte budget
317335
// while fanning out through tens of thousands of pointers, so a bound
318336
// on decoded values rejects it.
@@ -332,6 +350,7 @@ public function testPayloadAtLimitDecodes(): void
332350

333351
public function testPayloadOverLimitIsRejected(): void
334352
{
353+
$this->skipIfExtensionLoaded();
335354
// One byte past the limit must be rejected.
336355
$this->expectException(InvalidDatabaseException::class);
337356
$this->expectExceptionMessage("The MaxMind DB file's data section exceeds the maximum payload size");
@@ -341,6 +360,7 @@ public function testPayloadOverLimitIsRejected(): void
341360

342361
public function testMetadataPayloadLimitIsRejectedOnOpen(): void
343362
{
363+
$this->skipIfExtensionLoaded();
344364
// Metadata is decoded while opening the database, so the same bound
345365
// must guard that path.
346366
$this->expectException(InvalidDatabaseException::class);

0 commit comments

Comments
 (0)