From 540f851e8d9e6aa730602f0cf47f7fb99a8d59ad Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Fri, 25 Mar 2016 14:41:58 +0100 Subject: [PATCH] Fix an infinite loop when all 65536 requests are done Also use a CSPRNG for generating random numbers (fallback to paragonie/random_compat for PHP 5) --- composer.json | 3 ++- lib/DefaultResolver.php | 14 ++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 3b7e7e6..4e3d19b 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,8 @@ "amphp/amp": "^1", "amphp/cache": "^0.1", "amphp/file": "^0.1", - "daverandom/libdns": "^1" + "daverandom/libdns": "^1", + "paragonie/random_compat": "^1" }, "require-dev": { "phpunit/phpunit": "^4.8", diff --git a/lib/DefaultResolver.php b/lib/DefaultResolver.php index 3466ba6..e4aaf24 100644 --- a/lib/DefaultResolver.php +++ b/lib/DefaultResolver.php @@ -21,7 +21,6 @@ class DefaultResolver implements Resolver { private $encoder; private $decoder; private $arrayCache; - private $requestIdCounter; private $pendingRequests; private $serverIdMap; private $serverUriMap; @@ -36,7 +35,6 @@ class DefaultResolver implements Resolver { $this->encoder = (new EncoderFactory)->create(); $this->decoder = (new DecoderFactory)->create(); $this->arrayCache = new ArrayCache; - $this->requestIdCounter = 1; $this->pendingRequests = []; $this->serverIdMap = []; $this->serverUriMap = []; @@ -159,11 +157,15 @@ class DefaultResolver implements Resolver { $server = $this->loadExistingServer($uri) ?: $this->loadNewServer($uri); // Get the next available request ID + if (\count($this->pendingRequests) > MAX_REQUEST_ID / 2) { + // throttle DNS requests as long as too many requests are active + return \Amp\pipe(\Amp\Pause(100), function () use ($uri, $name, $type) { + return $this->doRequest($uri, $name, $type); + }); + } + do { - $requestId = $this->requestIdCounter++; - if ($this->requestIdCounter >= MAX_REQUEST_ID) { - $this->requestIdCounter = 1; - } + $requestId = random_int(0, MAX_REQUEST_ID - 1); } while (isset($this->pendingRequests[$requestId])); // Create question record