Commit 0ef9ecf7 authored by catch's avatar catch
Browse files

Issue #2642110 by beejeebus: Add recursion protection to LoggerChannell()

parent 2aa26f3f
......@@ -19,6 +19,26 @@
class LoggerChannel implements LoggerChannelInterface {
use LoggerTrait;
/**
* Maximum call depth to self::log() for a single log message.
*
* It's very easy for logging channel code to call out to other library code
* that will create log messages. In that case, we will recurse back in to
* LoggerChannel::log() multiple times while processing a single originating
* message. To prevent infinite recursion, we track the call depth and bail
* out at LoggerChannel::MAX_CALL_DEPTH iterations.
*
* @var int
*/
const MAX_CALL_DEPTH = 5;
/**
* Number of times LoggerChannel::log() has been called for a single message.
*
* @var int
*/
protected $callDepth = 0;
/**
* The name of the channel of this logger instance.
*
......@@ -77,6 +97,11 @@ public function __construct($channel) {
* {@inheritdoc}
*/
public function log($level, $message, array $context = array()) {
if ($this->callDepth == self::MAX_CALL_DEPTH) {
return;
}
$this->callDepth++;
// Merge in defaults.
$context += array(
'channel' => $this->channel,
......@@ -115,6 +140,8 @@ public function log($level, $message, array $context = array()) {
foreach ($this->sortLoggers() as $logger) {
$logger->log($level, $message, $context);
}
$this->callDepth--;
}
/**
......
......@@ -12,6 +12,8 @@
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Psr\Log\LoggerInterface;
use Psr\Log\LoggerTrait;
/**
* @coversDefaultClass \Drupal\Core\Logger\LoggerChannel
......@@ -54,6 +56,21 @@ public function testLog(callable $expected, Request $request = NULL, AccountInte
$channel->log(rand(0, 7), $message);
}
/**
* Tests LoggerChannel::log() recursion protection.
*
* @covers ::log
*/
public function testLogRecursionProtection() {
$channel = new LoggerChannel('test');
$logger = $this->getMock('Psr\Log\LoggerInterface');
$logger->expects($this->exactly(LoggerChannel::MAX_CALL_DEPTH))
->method('log');
$channel->addLogger($logger);
$channel->addLogger(new NaughtyRecursiveLogger($channel));
$channel->log(rand(0, 7), $this->randomMachineName());
}
/**
* Tests LoggerChannel::addLoggers().
*
......@@ -129,3 +146,19 @@ function ($context) {
}
}
class NaughtyRecursiveLogger implements LoggerInterface {
use LoggerTrait;
protected $channel;
protected $message;
public function __construct(LoggerChannel $channel) {
$this->channel = $channel;
}
public function log($level, $message, array $context = []) {
$this->channel->log(rand(0, 7), $message, $context);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment