From 2141be24c88bf68a9f7911d76da1d89120df948c Mon Sep 17 00:00:00 2001 From: Amir Yeganemehr Date: Sun, 21 Jun 2026 16:07:36 +0000 Subject: [PATCH] Fix stack overflow on self-referential compression pointer --- lib/Message.php | 8 ++++++-- tests/MessageTest.php | 7 +++++++ tests/Resources/wire/wire_test.data10 | 13 +++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 tests/Resources/wire/wire_test.data10 diff --git a/lib/Message.php b/lib/Message.php index 54a483a..de4bc4f 100644 --- a/lib/Message.php +++ b/lib/Message.php @@ -138,8 +138,12 @@ public static function encodeName(string $name): string return $res; } - public static function decodeName(string $string, int &$offset = 0): string + public static function decodeName(string $string, int &$offset = 0, int $depth = 0): string { + if ($depth > 127) { + throw new \UnexpectedValueException('DNS name has too many compression pointers'); + } + $len = ord($string[$offset]); ++$offset; @@ -163,7 +167,7 @@ public static function decodeName(string $string, int &$offset = 0): string $offset += $len; $len = ord($string[$offset]); if ($len & 0b11000000) { - $name .= self::decodeName($string, $offset); + $name .= self::decodeName($string, $offset, $depth + 1); break; } diff --git a/tests/MessageTest.php b/tests/MessageTest.php index 79b215b..44e6c4f 100644 --- a/tests/MessageTest.php +++ b/tests/MessageTest.php @@ -27,6 +27,7 @@ use Badcow\DNS\ResourceRecord; use Badcow\DNS\UnsetValueException; use PHPUnit\Framework\TestCase; +use UnexpectedValueException; class MessageTest extends TestCase { @@ -266,6 +267,12 @@ public function testWire8(): void $this->assertEquals($expectation, $msg->toWire()); } + public function testWire10(): void + { + $this->expectException(UnexpectedValueException::class); + Message::fromWire($this->getWireTestData(10)); + } + /** * @throws UnsupportedTypeException * @throws \Exception diff --git a/tests/Resources/wire/wire_test.data10 b/tests/Resources/wire/wire_test.data10 new file mode 100644 index 0000000..1e90202 --- /dev/null +++ b/tests/Resources/wire/wire_test.data10 @@ -0,0 +1,13 @@ +# HEADER SECTION +30 99 # ID +01 00 # FLAGS +00 01 # QDCOUNT=1 +00 00 # ANCOUNT=0 +00 00 # NSCOUNT=0 +00 00 # ARCOUNT=0 + +# QUESTION SECTION +01 61 # QNAME label: len=1, "a" +c0 0c # compression pointer -> offset 0x0C (12) = start of QNAME +00 01 # QTYPE=A +00 01 # QCLASS=IN