From 52885f0ade390e2a657f3c5707b5aa467dcf4c71 Mon Sep 17 00:00:00 2001 From: Joseph Bielawski Date: Tue, 31 Mar 2015 10:41:35 +0200 Subject: [PATCH 01/24] [DoctrineBridge] Add missing variable declaration in testcase --- .../Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php b/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php index 5185a75998..55991dbf4f 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ContainerAwareEventManagerTest.php @@ -16,6 +16,9 @@ use Symfony\Component\DependencyInjection\Container; class ContainerAwareEventManagerTest extends \PHPUnit_Framework_TestCase { + private $container; + private $evm; + protected function setUp() { $this->container = new Container(); From 195c57e1f50765aff33137689b16e126a689056a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 16 Mar 2015 15:12:02 +0100 Subject: [PATCH 02/24] Safe escaping of fragments for eval() --- .../Component/HttpKernel/HttpCache/Esi.php | 62 +++++++++---------- .../HttpKernel/Tests/HttpCache/EsiTest.php | 4 +- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php index 54e841530f..58b6265656 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php @@ -29,6 +29,10 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; class Esi { private $contentTypes; + private $phpEscapeMap = array( + array('', '', '', ''), + ); /** * Constructor. @@ -158,10 +162,34 @@ class Esi // we don't use a proper XML parser here as we can have ESI tags in a plain text response $content = $response->getContent(); - $content = str_replace(array('', ''), $content); - $content = preg_replace_callback('##', array($this, 'handleEsiIncludeTag'), $content); - $content = preg_replace('#]*(?:/|#', '', $content); $content = preg_replace('#.*?#', '', $content); + $content = preg_replace('#]*(?:/|#', '', $content); + + $chunks = preg_split('##', $content, -1, PREG_SPLIT_DELIM_CAPTURE); + $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); + + $i = 1; + while (isset($chunks[$i])) { + $options = array(); + preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER); + foreach ($matches as $set) { + $options[$set[1]] = $set[2]; + } + + if (!isset($options['src'])) { + throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.'); + } + + $chunks[$i] = sprintf('esi->handle($this, %s, %s, %s) ?>'."\n", + var_export($options['src'], true), + var_export(isset($options['alt']) ? $options['alt'] : '', true), + isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false' + ); + ++$i; + $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); + ++$i; + } + $content = implode('', $chunks); $response->setContent($content); $response->headers->set('X-Body-Eval', 'ESI'); @@ -214,32 +242,4 @@ class Esi } } } - - /** - * Handles an ESI include tag (called internally). - * - * @param array $attributes An array containing the attributes. - * - * @return string The response content for the include. - * - * @throws \RuntimeException - */ - private function handleEsiIncludeTag($attributes) - { - $options = array(); - preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $attributes[1], $matches, PREG_SET_ORDER); - foreach ($matches as $set) { - $options[$set[1]] = $set[2]; - } - - if (!isset($options['src'])) { - throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.'); - } - - return sprintf('esi->handle($this, %s, %s, %s) ?>'."\n", - var_export($options['src'], true), - var_export(isset($options['alt']) ? $options['alt'] : '', true), - isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false' - ); - } } diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php index ad400c69ae..d1411f016b 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php @@ -124,10 +124,10 @@ class EsiTest extends \PHPUnit_Framework_TestCase $esi = new Esi(); $request = Request::create('/'); - $response = new Response('foo <%= "lala" %>'); + $response = new Response(''); $esi->process($request, $response); - $this->assertEquals('foo php die("foo"); ?>= "lala" %>', $response->getContent()); + $this->assertEquals('php cript language=php>', $response->getContent()); } /** From 6c73f0ce9302a0091bbfbb96f317e400ce16ef84 Mon Sep 17 00:00:00 2001 From: James Gilliland Date: Tue, 17 Feb 2015 11:56:59 -0600 Subject: [PATCH 03/24] isFromTrustedProxy to confirm request came from a trusted proxy. --- .../Component/HttpFoundation/Request.php | 13 +++++-- .../HttpFoundation/Tests/RequestTest.php | 38 ++++++++++++------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index de798de27a..75ef72d0c7 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -791,7 +791,7 @@ class Request { $ip = $this->server->get('REMOTE_ADDR'); - if (!self::$trustedProxies) { + if (!$this->isFromTrustedProxy()) { return array($ip); } @@ -957,7 +957,7 @@ class Request */ public function getPort() { - if (self::$trustedProxies) { + if ($this->isFromTrustedProxy()) { if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && $port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT])) { return $port; } @@ -1138,7 +1138,7 @@ class Request */ public function isSecure() { - if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) { + if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) { return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1')); } @@ -1166,7 +1166,7 @@ class Request */ public function getHost() { - if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) { + if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) { $elements = explode(',', $host); $host = $elements[count($elements) - 1]; @@ -1853,4 +1853,9 @@ class Request return false; } + + private function isFromTrustedProxy() + { + return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies); + } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index e8639d7be0..a1a123426b 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -722,35 +722,37 @@ class RequestTest extends \PHPUnit_Framework_TestCase 'HTTP_X_FORWARDED_PROTO' => 'https', 'HTTP_X_FORWARDED_PORT' => '8443', )); - $port = $request->getPort(); - - $this->assertEquals(8443, $port, 'With PROTO and PORT set PORT takes precedence.'); + $this->assertEquals(80, $request->getPort(), 'With PROTO and PORT on untrusted connection server value takes precedence.'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $this->assertEquals(8443, $request->getPort(), 'With PROTO and PORT set PORT takes precedence.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'https', )); - $port = $request->getPort(); - - $this->assertEquals(443, $port, 'With only PROTO set getPort() defaults to 443.'); + $this->assertEquals(80, $request->getPort(), 'With only PROTO set getPort() ignores trusted headers on untrusted connection.'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $this->assertEquals(443, $request->getPort(), 'With only PROTO set getPort() defaults to 443.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'http', )); - $port = $request->getPort(); - - $this->assertEquals(80, $port, 'If X_FORWARDED_PROTO is set to HTTP return 80.'); + $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() ignores trusted headers on untrusted connection.'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() returns port of the original request.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'On', )); - $port = $request->getPort(); - $this->assertEquals(443, $port, 'With only PROTO set and value is On, getPort() defaults to 443.'); + $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is On, getPort() ignores trusted headers on untrusted connection.'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is On, getPort() defaults to 443.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => '1', )); - $port = $request->getPort(); - $this->assertEquals(443, $port, 'With only PROTO set and value is 1, getPort() defaults to 443.'); + $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is 1, getPort() ignores trusted headers on untrusted connection.'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is 1, getPort() defaults to 443.'); $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( 'HTTP_X_FORWARDED_PROTO' => 'something-else', @@ -1020,6 +1022,8 @@ class RequestTest extends \PHPUnit_Framework_TestCase $request->headers->set('X_FORWARDED_PROTO', 'https'); Request::setTrustedProxies(array('1.1.1.1')); + $this->assertFalse($request->isSecure()); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); $this->assertTrue($request->isSecure()); Request::setTrustedProxies(array()); @@ -1455,7 +1459,15 @@ class RequestTest extends \PHPUnit_Framework_TestCase $this->assertEquals(443, $request->getPort()); $this->assertTrue($request->isSecure()); + // trusted proxy via setTrustedProxies() + Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2')); + $this->assertEquals('3.3.3.3', $request->getClientIp()); + $this->assertEquals('example.com', $request->getHost()); + $this->assertEquals(80, $request->getPort()); + $this->assertFalse($request->isSecure()); + // check various X_FORWARDED_PROTO header values + Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2')); $request->headers->set('X_FORWARDED_PROTO', 'ssl'); $this->assertTrue($request->isSecure()); From dcd79710330d126216f324855689cdbe3e4275f0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 1 Apr 2015 16:26:15 +0200 Subject: [PATCH 04/24] updated CHANGELOG for 2.3.27 --- CHANGELOG-2.3.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG-2.3.md b/CHANGELOG-2.3.md index 12b4efd248..675302718a 100644 --- a/CHANGELOG-2.3.md +++ b/CHANGELOG-2.3.md @@ -7,6 +7,16 @@ in 2.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.3.0...v2.3.1 +* 2.3.27 (2015-04-01) + + * security #14167 CVE-2015-2308 (nicolas-grekas) + * security #14166 CVE-2015-2309 (neclimdul) + * bug #14010 Replace GET parameters when changed in form (WouterJ) + * bug #13991 [Dependency Injection] Improve PhpDumper Performance for huge Containers (BattleRattle) + * bug #13997 [2.3+][Form][DoctrineBridge] Improved loading of entities and documents (guilhermeblanco) + * bug #13953 [Translation][MoFileLoader] fixed load empty translation. (aitboudad) + * bug #13912 [DependencyInjection] Highest precedence for user parameters (lyrixx) + * 2.3.26 (2015-03-17) * bug #13927 Fixing wrong variable name from #13519 (weaverryan) From a7dcf0c15f9e3bdc112a25b6e40b7d3a1105299f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 1 Apr 2015 16:28:11 +0200 Subject: [PATCH 05/24] update CONTRIBUTORS for 2.3.27 --- CONTRIBUTORS.md | 57 ++++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 09feceb7b6..d773ad7ebb 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -11,8 +11,8 @@ Symfony is the result of the work of many people who made the code better - Jordi Boggiano (seldaek) - Johannes S (johannes) - Kris Wallsmith (kriswallsmith) - - Christophe Coevoet (stof) - Nicolas Grekas (nicolas-grekas) + - Christophe Coevoet (stof) - Jakub Zalas (jakubzalas) - Pascal Borreli (pborreli) - Hugo Hamon (hhamon) @@ -21,9 +21,9 @@ Symfony is the result of the work of many people who made the code better - Ryan Weaver (weaverryan) - Lukas Kahwe Smith (lsmith) - Romain Neutron (romain) + - Christian Flothmann (xabbuh) - Jeremy Mikola (jmikola) - Jean-François Simon (jfsimon) - - Christian Flothmann (xabbuh) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - Martin Hasoň (hason) @@ -37,16 +37,16 @@ Symfony is the result of the work of many people who made the code better - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - Bulat Shakirzyanov (avalanche123) + - Abdellatif Ait boudad (aitboudad) - Francis Besset (francisbesset) - Saša Stamenković (umpirsky) - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik + - Kévin Dunglas (dunglas) + - Sarah Khalil (saro0h) - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) - - Kévin Dunglas (dunglas) - Florin Patan (florinpatan) - - Abdellatif Ait Boudad (aitboudad) - - Sarah Khalil (saro0h) - Eric Clemmons (ericclemmons) - Andrej Hudec (pulzarraider) - Deni @@ -61,13 +61,14 @@ Symfony is the result of the work of many people who made the code better - Daniel Holmes (dholmes) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) + - Kevin Bond (kbond) - John Wards (johnwards) - Fran Moreno (franmomu) - - Antoine Hérault (herzult) - - Kevin Bond (kbond) - - Toni Uebernickel (havvg) - Luis Cordova (cordoval) + - Antoine Hérault (herzult) + - Toni Uebernickel (havvg) - Arnaud Le Blanc (arnaud-lb) + - Gábor Egyed (1ed) - Tim Nagel (merk) - Brice BERNARD (brikou) - marc.weistroff @@ -78,7 +79,6 @@ Symfony is the result of the work of many people who made the code better - Colin Frei - Jérôme Tamarelle (gromnan) - Adrien Brault (adrienbrault) - - Gábor Egyed (1ed) - excelwebzone - Jacob Dreesen (jdreesen) - Fabien Pennequin (fabienpennequin) @@ -93,26 +93,29 @@ Symfony is the result of the work of many people who made the code better - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - David Buchmann (dbu) + - Guilherme Blanco (guilhermeblanco) - Jérémy DERUSSÉ (jderusse) - Pablo Godel (pgodel) - Eric GELOEN (gelo) - Jérémie Augustin (jaugustin) - Rafael Dohms (rdohms) - - Guilherme Blanco (guilhermeblanco) - Tigran Azatyan (tigranazatyan) - Javier Eguiluz (javier.eguiluz) - Arnaud Kleinpeter (nanocom) - Richard Shank (iampersistent) + - Dariusz Ruminski - Clemens Tolboom - Helmer Aaviksoo - Sebastiaan Stok (sstok) - Hiromi Hishida (77web) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) + - Issei Murasawa (issei_m) - Amal Raghav (kertz) - Jonathan Ingram (jonathaningram) - Artur Kotyrba - Rouven Weßling (realityking) + - Andréia Bohner (andreia) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) - Dorian Villet (gnutix) @@ -123,14 +126,12 @@ Symfony is the result of the work of many people who made the code better - Benjamin Dulau (dbenjamin) - Matthias Pigulla (mpdude) - Andreas Hucks (meandmymonkey) - - Andréia Bohner (andreia) - Noel Guilbert (noel) - Joel Wurtz (brouznouf) - Charles Sarrazin (csarrazi) - bronze1man - sun (sun) - Larry Garfield (crell) - - Issei Murasawa (issei_m) - Martin Schuhfuß (usefulthink) - Thomas Rabaix (rande) - Matthieu Bontemps (mbontemps) @@ -163,6 +164,7 @@ Symfony is the result of the work of many people who made the code better - Xavier Montaña Carreras (xmontana) - Michele Orselli (orso) - Chris Wilkinson (thewilkybarkid) + - Joshua Thijssen - Xavier Perez - Arjen Brouwer (arjenjb) - Katsuhiro OGAWA @@ -181,16 +183,18 @@ Symfony is the result of the work of many people who made the code better - Jeremy Livingston (jeremylivingston) - Nikita Konstantinov - Wodor Wodorski + - Matthieu Auger (matthieuauger) - julien pauli (jpauli) - Beau Simensen (simensen) - Robert Kiss (kepten) + - John Kary (johnkary) - Ruben Gonzalez (rubenrua) - Kim Hemsø Rasmussen (kimhemsoe) - Florian Lonqueu-Brochard (florianlb) - Tom Van Looy (tvlooy) - Wouter Van Hecke - - Joshua Thijssen - Peter Kruithof (pkruithof) + - Vladimir Reznichenko (kalessil) - Michael Holm (hollo) - Warnar Boekkooi (boekkooi) - Marc Weistroff (futurecat) @@ -222,7 +226,6 @@ Symfony is the result of the work of many people who made the code better - Marco Pivetta (ocramius) - Ricard Clau (ricardclau) - Erin Millard - - John Kary (johnkary) - Matthew Lewinski (lewinski) - alquerci - Francesco Levorato @@ -232,7 +235,6 @@ Symfony is the result of the work of many people who made the code better - Inal DJAFAR (inalgnu) - Christian Gärtner (dagardner) - Felix Labrecque - - Vladimir Reznichenko (kalessil) - Yaroslav Kiliba - Sébastien Lavoie (lavoiesl) - Terje Bråten @@ -283,7 +285,6 @@ Symfony is the result of the work of many people who made the code better - Brian King - Michel Salib (michelsalib) - geoffrey - - Matthieu Auger (matthieuauger) - Lorenz Schori - Jeanmonod David (jeanmonod) - Jan Schumann @@ -309,7 +310,6 @@ Symfony is the result of the work of many people who made the code better - Christian Schmidt - Marcin Sikoń (marphi) - franek (franek) - - Dariusz Ruminski - Adam Harvey - Diego Saint Esteben (dii3g0) - Alex Bakhturin @@ -336,6 +336,7 @@ Symfony is the result of the work of many people who made the code better - mmoreram - Markus Lanthaler (lanthaler) - Vicent Soria Durá (vicentgodella) + - Anthony Ferrara - Ioan Negulescu - Jakub Škvára (jskvara) - Daniel Beyer @@ -343,9 +344,11 @@ Symfony is the result of the work of many people who made the code better - alexpods - Erik Trapman (eriktrapman) - De Cock Xavier (xdecock) + - Scott Arciszewski - Norbert Orzechowicz (norzechowicz) - Tobias Nyholm (tobias) - Matthijs van den Bos (matthijs) + - Loick Piera (pyrech) - Lenard Palko - Nils Adermann (naderman) - Gábor Fási @@ -371,9 +374,11 @@ Symfony is the result of the work of many people who made the code better - Zach Badgett (zachbadgett) - Aurélien Fredouelle - Pavel Campr (pcampr) + - Maxime Steinhausser (ogizanagi) - Disquedur - Geoffrey Tran (geoff) - Jan Behrens + - Mantas Var (mvar) - Sebastian Krebs - Christopher Davis (chrisguitarguy) - Thomas Lallement (raziel057) @@ -387,6 +392,7 @@ Symfony is the result of the work of many people who made the code better - Max Rath (drak3) - Stéphane Escandell (sescandell) - Sinan Eldem + - Alexandre Dupuy (satchette) - Nahuel Cuesta (ncuesta) - Chris Boden (cboden) - Asmir Mustafic (goetas) @@ -484,7 +490,6 @@ Symfony is the result of the work of many people who made the code better - Xavier Lacot (xavier) - Olivier Maisonneuve (olineuve) - Francis Turmel (fturmel) - - Loick Piera (pyrech) - cgonzalez - Ben - Jayson Xu (superjavason) @@ -506,6 +511,7 @@ Symfony is the result of the work of many people who made the code better - Fabian Vogler (fabian) - Korvin Szanto - Maksim Kotlyar (makasim) + - Ivan Kurnosov - Neil Ferreira - Dmitry Parnas (parnas) - DQNEO @@ -516,6 +522,7 @@ Symfony is the result of the work of many people who made the code better - David Romaní - Patrick Allaert - Gustavo Falco (gfalco) + - Matt Robinson (inanimatt) - Aleksey Podskrebyshev - David Marín Carreño (davefx) - Jörn Lang (j.lang) @@ -580,6 +587,7 @@ Symfony is the result of the work of many people who made the code better - Michael Tibben - Sander Marechal - Radosław Benkel + - Marcos Sánchez - ttomor - Mei Gwilym (meigwilym) - Michael H. Arieli (excelwebzone) @@ -622,6 +630,7 @@ Symfony is the result of the work of many people who made the code better - nacho - Piotr Antosik (antek88) - Artem Lopata + - Samuel ROZE (sroze) - Marcos Quesada (marcos_quesada) - Matthew Vickery (mattvick) - Dan Finnie @@ -675,6 +684,7 @@ Symfony is the result of the work of many people who made the code better - Yannick - Eduardo García Sanz (coma) - Sebastian Grodzicki (sgrodzicki) + - Michael Lee (zerustech) - Roy Van Ginneken - David de Boer (ddeboer) - Gilles Doge (gido) @@ -721,6 +731,7 @@ Symfony is the result of the work of many people who made the code better - Malaney J. Hill - Christian Flach (cmfcmf) - Cédric Girard (enk_) + - Lars Ambrosius Wallenborn (larsborn) - Oriol Mangas Abellan (oriolman) - Sebastian Göttschkes (sgoettschkes) - Tatsuya Tsuruoka @@ -847,6 +858,7 @@ Symfony is the result of the work of many people who made the code better - Gunnar Lium (gunnarlium) - Tiago Garcia (tiagojsag) - Artiom + - Jakub Simon - Bouke Haarsma - Martin Eckhardt - Denis Zunke @@ -876,7 +888,6 @@ Symfony is the result of the work of many people who made the code better - Vasily Khayrulin (sirian) - Stefan Koopmanschap (skoop) - Stefan Hüsges (tronsha) - - Ivan Kurnosov - stloyd - Chris Tickner - Andrew Coulton @@ -905,7 +916,6 @@ Symfony is the result of the work of many people who made the code better - Julius Beckmann - Romain Dorgueil - Grayson Koonce (breerly) - - Matt Robinson (inanimatt) - Karim Cassam Chenaï (ka) - Nicolas Bastien (nicolas_bastien) - Andy Stanberry @@ -992,6 +1002,7 @@ Symfony is the result of the work of many people who made the code better - grifx - Robert Campbell - Matt Lehner + - Hidde Wieringa - Hein Zaw Htet™ - Ruben Kruiswijk - Michael J @@ -1048,9 +1059,7 @@ Symfony is the result of the work of many people who made the code better - Muriel (metalmumu) - Michaël Perrin (michael.perrin) - Michael Pohlers (mick_the_big) - - Mantas Var (mvar) - Cayetano Soriano Gallego (neoshadybeat) - - Maxime Steinhausser (ogizanagi) - Pablo Monterde Perez (plebs) - Jimmy Leger (redpanda) - Cyrille Jouineau (tuxosaurus) @@ -1128,6 +1137,7 @@ Symfony is the result of the work of many people who made the code better - Brian Freytag - Skorney - mieszko4 + - Neophy7e - Arrilot - Markus Staab - Pierre-Louis LAUNAY @@ -1140,6 +1150,8 @@ Symfony is the result of the work of many people who made the code better - Sema - Thorsten Hallwas - Michael Squires + - Norman Soetbeer + - Benjamin Long - Matt Janssen - Peter Gribanov - kwiateusz @@ -1235,6 +1247,7 @@ Symfony is the result of the work of many people who made the code better - Vincent (vincent1870) - Eugene Babushkin (warl) - Xavier Amado (xamado) + - Jesper Søndergaard Pedersen (zerrvox) - Florent Cailhol - szymek - craigmarvelley From ce4aab1508dd9642906fc9a120e0d8763e689896 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 1 Apr 2015 16:28:26 +0200 Subject: [PATCH 06/24] updated VERSION for 2.3.27 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 5e4fac51cd..e6363872e8 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -60,12 +60,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.3.27-DEV'; + const VERSION = '2.3.27'; const VERSION_ID = '20327'; const MAJOR_VERSION = '2'; const MINOR_VERSION = '3'; const RELEASE_VERSION = '27'; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; /** * Constructor. From feb48c26b3e4294294e0f12cc21b022fd636551a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 1 Apr 2015 17:29:10 +0200 Subject: [PATCH 07/24] bumped Symfony version to 2.3.28 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index e6363872e8..42a3f3b3f6 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -60,12 +60,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.3.27'; - const VERSION_ID = '20327'; + const VERSION = '2.3.28-DEV'; + const VERSION_ID = '20328'; const MAJOR_VERSION = '2'; const MINOR_VERSION = '3'; - const RELEASE_VERSION = '27'; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = '28'; + const EXTRA_VERSION = 'DEV'; /** * Constructor. From 06f92fc2d5707dc0ea749cf948281d759e8b0cbf Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 16 Mar 2015 15:12:02 +0100 Subject: [PATCH 08/24] Safe escaping of fragments for eval() --- .../Component/HttpKernel/HttpCache/Ssi.php | 56 +++++++++---------- .../HttpKernel/Tests/HttpCache/SsiTest.php | 4 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php b/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php index 1fc203e595..7bb54cff62 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php @@ -23,6 +23,10 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; class Ssi implements SurrogateInterface { private $contentTypes; + private $phpEscapeMap = array( + array('', '', '', ''), + ); /** * Constructor. @@ -122,8 +126,30 @@ class Ssi implements SurrogateInterface // we don't use a proper XML parser here as we can have SSI tags in a plain text response $content = $response->getContent(); - $content = str_replace(array('', ''), $content); - $content = preg_replace_callback('##', array($this, 'handleIncludeTag'), $content); + + $chunks = preg_split('##', $content, -1, PREG_SPLIT_DELIM_CAPTURE); + $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); + + $i = 1; + while (isset($chunks[$i])) { + $options = array(); + preg_match_all('/(virtual)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER); + foreach ($matches as $set) { + $options[$set[1]] = $set[2]; + } + + if (!isset($options['virtual'])) { + throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.'); + } + + $chunks[$i] = sprintf('surrogate->handle($this, %s, \'\', false) ?>'."\n", + var_export($options['virtual'], true) + ); + ++$i; + $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); + ++$i; + } + $content = implode('', $chunks); $response->setContent($content); $response->headers->set('X-Body-Eval', 'SSI'); @@ -166,30 +192,4 @@ class Ssi implements SurrogateInterface } } } - - /** - * Handles an SSI include tag (called internally). - * - * @param array $attributes An array containing the attributes. - * - * @return string The response content for the include. - * - * @throws \RuntimeException - */ - private function handleIncludeTag($attributes) - { - $options = array(); - preg_match_all('/(virtual)="([^"]*?)"/', $attributes[1], $matches, PREG_SET_ORDER); - foreach ($matches as $set) { - $options[$set[1]] = $set[2]; - } - - if (!isset($options['virtual'])) { - throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.'); - } - - return sprintf('surrogate->handle($this, %s, \'\', false) ?>'."\n", - var_export($options['virtual'], true) - ); - } } diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php index bb208cd86c..07b70dcee8 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/SsiTest.php @@ -113,10 +113,10 @@ class SsiTest extends \PHPUnit_Framework_TestCase $ssi = new Ssi(); $request = Request::create('/'); - $response = new Response('foo <%= "lala" %>'); + $response = new Response(''); $ssi->process($request, $response); - $this->assertEquals('foo php die("foo"); ?>= "lala" %>', $response->getContent()); + $this->assertEquals('php cript language=php>', $response->getContent()); } /** From 4eb695a40e7d1467e8c929540e9f0368c31f7487 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 1 Apr 2015 18:54:41 +0200 Subject: [PATCH 09/24] updated CHANGELOG for 2.6.6 --- CHANGELOG-2.6.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG-2.6.md b/CHANGELOG-2.6.md index 56fd84de3c..8bd1c85aff 100644 --- a/CHANGELOG-2.6.md +++ b/CHANGELOG-2.6.md @@ -7,6 +7,26 @@ in 2.6 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.6.0...v2.6.1 +* 2.6.6 (2015-04-01) + + * security #14167 CVE-2015-2308 (nicolas-grekas) + * security #14166 CVE-2015-2309 (neclimdul) + * bug #14126 [VarDumper] Fix toggle action to see source excerpt (nicolas-grekas) + * bug #14114 [VarDumper] Fix dumping references as properties (nicolas-grekas) + * bug #14074 [VarDumper] Fix dumping ThrowingCasterException (nicolas-grekas) + * bug #12948 [Form] [TwigBridge] Bootstrap layout whitespace control (mvar) + * bug #14046 [Security] StringUtils::equals() arguments in RememberMe Cookie based implementation are confused (zerkms) + * bug #14010 Replace GET parameters when changed in form (WouterJ) + * bug #13991 [Dependency Injection] Improve PhpDumper Performance for huge Containers (BattleRattle) + * bug #13886 [FrameworkBundle][debug:config] added support for dynamic configurations... (aitboudad) + * bug #14013 [DependencyInjection] prevent inlining service configurators (xabbuh) + * bug #14012 [DomCrawler] Improve namespace discovery performance (jakzal) + * bug #13997 [2.3+][Form][DoctrineBridge] Improved loading of entities and documents (guilhermeblanco) + * bug #13978 [WebProfilerBundle] Fix javascript toolbar on IE8 (romainneutron) + * bug #13987 [WebProfilerBundle] fixed undefined buttons variable. (aitboudad) + * bug #13953 [Translation][MoFileLoader] fixed load empty translation. (aitboudad) + * bug #13912 [DependencyInjection] Highest precedence for user parameters (lyrixx) + * 2.6.5 (2015-03-17) * bug #13944 [HttpKernel] UriSigner::buildUrl - default params for http_build_query (Jakub Simon) From 48c9e835a877adfb023b8b6d033d9dd14f342b4b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 1 Apr 2015 18:55:26 +0200 Subject: [PATCH 10/24] updated VERSION for 2.6.6 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 97406d1bc4..d1442149b0 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -60,12 +60,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.6.6-DEV'; + const VERSION = '2.6.6'; const VERSION_ID = '20606'; const MAJOR_VERSION = '2'; const MINOR_VERSION = '6'; const RELEASE_VERSION = '6'; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; /** * Constructor. From de02c5f9623ad2599d063aed910958c52711c21d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 1 Apr 2015 20:51:37 +0200 Subject: [PATCH 11/24] bumped Symfony version to 2.6.7 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index d1442149b0..4680ed54ba 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -60,12 +60,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.6.6'; - const VERSION_ID = '20606'; + const VERSION = '2.6.7-DEV'; + const VERSION_ID = '20607'; const MAJOR_VERSION = '2'; const MINOR_VERSION = '6'; - const RELEASE_VERSION = '6'; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = '7'; + const EXTRA_VERSION = 'DEV'; /** * Constructor. From 9d6c0b1c30724a99c1732d3b3bd0951d7f007a6f Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Thu, 2 Apr 2015 11:50:50 +0200 Subject: [PATCH 12/24] Fix the AJAX profiling The fix for IE8 which does not have the addEventListener method on XMLHttpRequest broke the feature for modern browsers because it was checking the existence on the wrong object. It is a method on the instance, not on the "class", and so should be checked on the prototype. --- .../Resources/views/Profiler/base_js.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index 502ee36fcd..070c7888bc 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -196,7 +196,7 @@ } {% if excluded_ajax_paths is defined %} - if (window.XMLHttpRequest && XMLHttpRequest.addEventListener) { + if (window.XMLHttpRequest && XMLHttpRequest.prototype.addEventListener) { var proxied = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { From dbd02b087175c7817a39d047c6f6e237b8adeca5 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 2 Apr 2015 13:05:24 +0200 Subject: [PATCH 13/24] Use specialized config methods instead of the generic ifTrue() method --- .../FrameworkBundle/DependencyInjection/Configuration.php | 7 ++----- .../TwigBundle/DependencyInjection/Configuration.php | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 2de60489a8..08bcc1c19d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -69,10 +69,7 @@ class Configuration implements ConfigurationInterface ->booleanNode('test')->end() ->scalarNode('default_locale')->defaultValue('en')->end() ->arrayNode('trusted_hosts') - ->beforeNormalization() - ->ifTrue(function ($v) { return is_string($v); }) - ->then(function ($v) { return array($v); }) - ->end() + ->beforeNormalization()->ifString()->then(function ($v) { return array($v); })->end() ->prototype('scalar')->end() ->end() ->end() @@ -263,7 +260,7 @@ class Configuration implements ConfigurationInterface ->addDefaultChildrenIfNoneSet() ->prototype('scalar')->defaultValue('FrameworkBundle:Form')->end() ->validate() - ->ifTrue(function ($v) {return !in_array('FrameworkBundle:Form', $v); }) + ->ifNotInArray(array('FrameworkBundle:Form')) ->then(function ($v) { return array_merge(array('FrameworkBundle:Form'), $v); }) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php index a20ca8c1a8..8cc114ab29 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php @@ -58,7 +58,7 @@ class Configuration implements ConfigurationInterface ->prototype('scalar')->defaultValue('form_div_layout.html.twig')->end() ->example(array('MyBundle::form.html.twig')) ->validate() - ->ifTrue(function ($v) { return !in_array('form_div_layout.html.twig', $v); }) + ->ifNotInArray(array('form_div_layout.html.twig')) ->then(function ($v) { return array_merge(array('form_div_layout.html.twig'), $v); }) From 15ef182b9971472aa30753da6349c0d28f477d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Thu, 2 Apr 2015 14:57:42 +0200 Subject: [PATCH 14/24] [Debug] Made code in ErrorHandler easier to read --- src/Symfony/Component/Debug/ErrorHandler.php | 162 ++++++++++--------- 1 file changed, 84 insertions(+), 78 deletions(-) diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index 48e4a2d69e..280d5f8abc 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -356,69 +356,71 @@ class ErrorHandler $throw = $this->thrownErrors & $type & $level; $type &= $level | $this->screamedErrors; - if ($type && ($log || $throw)) { - if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && ($this->scopedErrors & $type)) { - $e = $context; // Whatever the signature of the method, - unset($e['GLOBALS'], $context); // $context is always a reference in 5.3 - $context = $e; - } + if (!$type || (!$log && !$throw)) { + return $type && $log; + } - if ($throw) { - if (($this->scopedErrors & $type) && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) { - // Checking for class existence is a work around for https://bugs.php.net/42098 - $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context); - } else { - $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line); - } + if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && ($this->scopedErrors & $type)) { + $e = $context; // Whatever the signature of the method, + unset($e['GLOBALS'], $context); // $context is always a reference in 5.3 + $context = $e; + } - if (PHP_VERSION_ID <= 50407 && (PHP_VERSION_ID >= 50400 || PHP_VERSION_ID <= 50317)) { - // Exceptions thrown from error handlers are sometimes not caught by the exception - // handler and shutdown handlers are bypassed before 5.4.8/5.3.18. - // We temporarily re-enable display_errors to prevent any blank page related to this bug. - - $throw->errorHandlerCanary = new ErrorHandlerCanary(); - } - - throw $throw; - } - - // For duplicated errors, log the trace only once - $e = md5("{$type}/{$line}/{$file}\x00{$message}", true); - $trace = true; - - if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) { - $trace = false; + if ($throw) { + if (($this->scopedErrors & $type) && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) { + // Checking for class existence is a work around for https://bugs.php.net/42098 + $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context); } else { - $this->loggedTraces[$e] = 1; + $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line); } - $e = compact('type', 'file', 'line', 'level'); + if (PHP_VERSION_ID <= 50407 && (PHP_VERSION_ID >= 50400 || PHP_VERSION_ID <= 50317)) { + // Exceptions thrown from error handlers are sometimes not caught by the exception + // handler and shutdown handlers are bypassed before 5.4.8/5.3.18. + // We temporarily re-enable display_errors to prevent any blank page related to this bug. - if ($type & $level) { - if ($this->scopedErrors & $type) { - $e['context'] = $context; - if ($trace) { - $e['stack'] = debug_backtrace(true); // Provide object - } - } elseif ($trace) { - $e['stack'] = debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false); - } + $throw->errorHandlerCanary = new ErrorHandlerCanary(); } - if ($this->isRecursive) { - $log = 0; - } elseif (self::$stackedErrorLevels) { - self::$stackedErrors[] = array($this->loggers[$type], $message, $e); - } else { - try { - $this->isRecursive = true; - $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e); - $this->isRecursive = false; - } catch (\Exception $e) { - $this->isRecursive = false; + throw $throw; + } - throw $e; + // For duplicated errors, log the trace only once + $e = md5("{$type}/{$line}/{$file}\x00{$message}", true); + $trace = true; + + if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) { + $trace = false; + } else { + $this->loggedTraces[$e] = 1; + } + + $e = compact('type', 'file', 'line', 'level'); + + if ($type & $level) { + if ($this->scopedErrors & $type) { + $e['context'] = $context; + if ($trace) { + $e['stack'] = debug_backtrace(true); // Provide object } + } elseif ($trace) { + $e['stack'] = debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : false); + } + } + + if ($this->isRecursive) { + $log = 0; + } elseif (self::$stackedErrorLevels) { + self::$stackedErrors[] = array($this->loggers[$type], $message, $e); + } else { + try { + $this->isRecursive = true; + $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e); + $this->isRecursive = false; + } catch (\Exception $e) { + $this->isRecursive = false; + + throw $e; } } @@ -487,40 +489,44 @@ class ErrorHandler public static function handleFatalError(array $error = null) { self::$reservedMemory = ''; + $handler = set_error_handler('var_dump', 0); $handler = is_array($handler) ? $handler[0] : null; restore_error_handler(); - if ($handler instanceof self) { - if (null === $error) { - $error = error_get_last(); - } - try { - while (self::$stackedErrorLevels) { - static::unstackErrors(); - } - } catch (\Exception $exception) { - // Handled below - } + if (!$handler instanceof self) { + return; + } - if ($error && ($error['type'] & (E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR))) { - // Let's not throw anymore but keep logging - $handler->throwAt(0, true); + if (null === $error) { + $error = error_get_last(); + } - if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { - $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false); - } else { - $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true); - } - } elseif (!isset($exception)) { - return; + try { + while (self::$stackedErrorLevels) { + static::unstackErrors(); } + } catch (\Exception $exception) { + // Handled below + } - try { - $handler->handleException($exception, $error); - } catch (FatalErrorException $e) { - // Ignore this re-throw + if ($error && ($error['type'] & (E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR))) { + // Let's not throw anymore but keep logging + $handler->throwAt(0, true); + + if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { + $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false); + } else { + $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true); } + } elseif (!isset($exception)) { + return; + } + + try { + $handler->handleException($exception, $error); + } catch (FatalErrorException $e) { + // Ignore this re-throw } } From a95f7f38af2c7c6ce8266cf162a6eaff9bbcc45b Mon Sep 17 00:00:00 2001 From: stloyd Date: Tue, 31 Mar 2015 15:09:45 +0200 Subject: [PATCH 15/24] Fix some phpdocs for Twig extensions & templating helpers --- src/Symfony/Bridge/Twig/Extension/CodeExtension.php | 3 +++ src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php | 3 +++ src/Symfony/Bridge/Twig/Extension/RoutingExtension.php | 4 +--- src/Symfony/Bridge/Twig/Extension/SecurityExtension.php | 4 +--- src/Symfony/Bridge/Twig/Extension/TranslationExtension.php | 4 +--- src/Symfony/Bridge/Twig/Extension/YamlExtension.php | 4 +--- .../FrameworkBundle/Templating/Helper/ActionsHelper.php | 4 +--- .../Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php | 4 +--- .../FrameworkBundle/Templating/Helper/RequestHelper.php | 4 +--- .../Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php | 4 +--- .../FrameworkBundle/Templating/Helper/SessionHelper.php | 4 +--- .../FrameworkBundle/Templating/Helper/TranslatorHelper.php | 4 +--- .../SecurityBundle/Templating/Helper/LogoutUrlHelper.php | 4 +--- .../SecurityBundle/Templating/Helper/SecurityHelper.php | 4 +--- src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php | 3 +++ src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php | 4 +--- 16 files changed, 22 insertions(+), 39 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 4a0c1e9c76..b5f619d327 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -210,6 +210,9 @@ class CodeExtension extends \Twig_Extension }, $text); } + /** + * {@inheritdoc} + */ public function getName() { return 'code'; diff --git a/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php b/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php index 4d9919d16c..1da12aaf5e 100644 --- a/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php @@ -81,6 +81,9 @@ class HttpKernelExtension extends \Twig_Extension return new ControllerReference($controller, $attributes, $query); } + /** + * {@inheritdoc} + */ public function getName() { return 'http_kernel'; diff --git a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php index 237c36c190..7469183e75 100644 --- a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php @@ -89,9 +89,7 @@ class RoutingExtension extends \Twig_Extension } /** - * Returns the name of the extension. - * - * @return string The extension name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php b/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php index edba0e7b8b..49863a4e3f 100644 --- a/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php @@ -52,9 +52,7 @@ class SecurityExtension extends \Twig_Extension } /** - * Returns the name of the extension. - * - * @return string The extension name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php index 0fde3a675d..f1f2fbd20b 100644 --- a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php @@ -99,9 +99,7 @@ class TranslationExtension extends \Twig_Extension } /** - * Returns the name of the extension. - * - * @return string The extension name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php index 63d658da3b..fc9bf0e9e3 100644 --- a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php @@ -56,9 +56,7 @@ class YamlExtension extends \Twig_Extension } /** - * Returns the name of the extension. - * - * @return string The extension name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php index d4a855d53b..8f0d54eada 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php @@ -58,9 +58,7 @@ class ActionsHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php index 94a9af0cc0..e7042e0dc3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php @@ -205,9 +205,7 @@ class CodeHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php index 9f001f7f3f..b7fbfcdca7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php @@ -59,9 +59,7 @@ class RequestHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php index 830e5c9019..d54caaf395 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php @@ -50,9 +50,7 @@ class RouterHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php index c4362df1db..675fe9dc90 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php @@ -62,9 +62,7 @@ class SessionHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php index 30816d736f..2c2641a885 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php @@ -50,9 +50,7 @@ class TranslatorHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php index 1fef75ca09..9514ebf616 100644 --- a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php +++ b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php @@ -114,9 +114,7 @@ class LogoutUrlHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/SecurityHelper.php b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/SecurityHelper.php index 7ca0e7bb66..a43f2b446d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/SecurityHelper.php +++ b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/SecurityHelper.php @@ -48,9 +48,7 @@ class SecurityHelper extends Helper } /** - * Returns the canonical name of this helper. - * - * @return string The canonical name + * {@inheritdoc} */ public function getName() { diff --git a/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php b/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php index 3b08bd6859..76f4dff5c3 100644 --- a/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php +++ b/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php @@ -62,6 +62,9 @@ class ActionsExtension extends \Twig_Extension ); } + /** + * {@inheritdoc} + */ public function getName() { return 'actions'; diff --git a/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php b/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php index 929680597c..4f40c7a0d8 100644 --- a/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php +++ b/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php @@ -68,9 +68,7 @@ class AssetsExtension extends \Twig_Extension } /** - * Returns the name of the extension. - * - * @return string The extension name + * {@inheritdoc} */ public function getName() { From b56a804f9395b8d6f147660b733bdc64a19fa8e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Thu, 2 Apr 2015 21:18:30 +0200 Subject: [PATCH 16/24] [Debug] Renamed "context" key to "scope_vars" to avoid any ambiguity --- src/Symfony/Component/Debug/ErrorHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index 280d5f8abc..a8f865a399 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -399,7 +399,7 @@ class ErrorHandler if ($type & $level) { if ($this->scopedErrors & $type) { - $e['context'] = $context; + $e['scope_vars'] = $context; if ($trace) { $e['stack'] = debug_backtrace(true); // Provide object } From 6f5e95b762ae0c00585a814efbec7cc6b46b47ce Mon Sep 17 00:00:00 2001 From: Gerben Wijnja Date: Fri, 3 Apr 2015 01:10:26 +0200 Subject: [PATCH 17/24] [StringUtil] Fixed singularification of 'movies' The word 'movies' was singularified to 'movy'. There seem to be only two words ending in 'ovies', which are 'movies' and 'anchovies'. The singular of the latter is 'anchovy'. All other words ending in 'vies' singularify to 'vy', so the word 'movies' is an exception to the general rule. --- src/Symfony/Component/PropertyAccess/StringUtil.php | 3 +++ src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php | 1 + 2 files changed, 4 insertions(+) diff --git a/src/Symfony/Component/PropertyAccess/StringUtil.php b/src/Symfony/Component/PropertyAccess/StringUtil.php index 5fa1b1734f..2160f0f422 100644 --- a/src/Symfony/Component/PropertyAccess/StringUtil.php +++ b/src/Symfony/Component/PropertyAccess/StringUtil.php @@ -60,6 +60,9 @@ class StringUtil // indices (index), appendices (appendix), prices (price) array('seci', 4, false, true, array('ex', 'ix', 'ice')), + // movies (movie) + array('seivom', 6, true, true, 'movie'), + // babies (baby) array('sei', 3, false, true, 'y'), diff --git a/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php b/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php index 7c6376dbd6..73922cd72a 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php @@ -99,6 +99,7 @@ class StringUtilTest extends \PHPUnit_Framework_TestCase array('men', 'man'), array('mice', 'mouse'), array('moves', 'move'), + array('movies', 'movie'), array('nebulae', 'nebula'), array('neuroses', array('neuros', 'neurose', 'neurosis')), array('oases', array('oas', 'oase', 'oasis')), From 9d0c0aeebad1f1c51cd2102660c81691c96f1cee Mon Sep 17 00:00:00 2001 From: Diego Saint Esteben Date: Tue, 31 Mar 2015 21:58:16 -0300 Subject: [PATCH 18/24] Added missing changelog entry --- src/Symfony/Component/VarDumper/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/Symfony/Component/VarDumper/CHANGELOG.md diff --git a/src/Symfony/Component/VarDumper/CHANGELOG.md b/src/Symfony/Component/VarDumper/CHANGELOG.md new file mode 100644 index 0000000000..6b08aa77ac --- /dev/null +++ b/src/Symfony/Component/VarDumper/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +2.7.0 +----- + + * deprecated Cloner\Data::getLimitedClone(). Use withMaxDepth, withMaxItemsPerDepth or withRefHandles instead. From 126514f2a3c8ae312f7c0dd2d5cd974388b7819b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Thu, 2 Apr 2015 18:36:00 +0200 Subject: [PATCH 19/24] [Debug] Rework a bit the PHP doc --- src/Symfony/Component/Debug/ErrorHandler.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index a8f865a399..715c99eee2 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -240,7 +240,7 @@ class ErrorHandler } /** - * Sets the error levels that are to be thrown. + * Sets the PHP error levels that should throw an exception when a PHP error occurs. * * @param int $levels A bit field of E_* constants for thrown errors * @param bool $replace Replace or amend the previous value @@ -263,7 +263,7 @@ class ErrorHandler } /** - * Sets the error levels that are logged or thrown with their local scope. + * Sets the PHP error levels for which local variables are preserved. * * @param int $levels A bit field of E_* constants for scoped errors * @param bool $replace Replace or amend the previous value @@ -282,7 +282,7 @@ class ErrorHandler } /** - * Sets the error levels that are logged with their stack trace. + * Sets the PHP error levels for which stack trace is preserved. * * @param int $levels A bit field of E_* constants for traced errors * @param bool $replace Replace or amend the previous value From dc282ec6790057910fe32bada246b51f07ecd775 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 3 Apr 2015 09:48:36 +0200 Subject: [PATCH 20/24] [Debug] Tweak docblocks --- src/Symfony/Component/Debug/ErrorHandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index 715c99eee2..75c9caef71 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -240,7 +240,7 @@ class ErrorHandler } /** - * Sets the PHP error levels that should throw an exception when a PHP error occurs. + * Sets the PHP error levels that throw an exception when a PHP error occurs. * * @param int $levels A bit field of E_* constants for thrown errors * @param bool $replace Replace or amend the previous value @@ -282,7 +282,7 @@ class ErrorHandler } /** - * Sets the PHP error levels for which stack trace is preserved. + * Sets the PHP error levels for which the stack trace is preserved. * * @param int $levels A bit field of E_* constants for traced errors * @param bool $replace Replace or amend the previous value From 24b780e1ed1466be57aada52e02b34852a3985fb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 3 Apr 2015 09:54:01 +0200 Subject: [PATCH 21/24] Revert "Added missing changelog entry" This reverts commit 9d0c0aeebad1f1c51cd2102660c81691c96f1cee. --- src/Symfony/Component/VarDumper/CHANGELOG.md | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 src/Symfony/Component/VarDumper/CHANGELOG.md diff --git a/src/Symfony/Component/VarDumper/CHANGELOG.md b/src/Symfony/Component/VarDumper/CHANGELOG.md deleted file mode 100644 index 6b08aa77ac..0000000000 --- a/src/Symfony/Component/VarDumper/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -CHANGELOG -========= - -2.7.0 ------ - - * deprecated Cloner\Data::getLimitedClone(). Use withMaxDepth, withMaxItemsPerDepth or withRefHandles instead. From ab370409fec31d4c434bbf2b4c29de4724702011 Mon Sep 17 00:00:00 2001 From: Hugo Hamon Date: Thu, 2 Apr 2015 17:40:28 +0200 Subject: [PATCH 22/24] [FrameworkBundle] fixes displaying of deprecation notices. --- .../Resources/config/debug_prod.xml | 2 +- .../views/Collector/logger.html.twig | 34 +++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml index 39266eab03..9d70124fbe 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml @@ -16,7 +16,7 @@ - + null null true null diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig index 4ab569020f..4ae5063064 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig @@ -88,10 +88,13 @@ {% if collector.logs %}
    - {% for log in collector.logs if priority >= 0 and log.priority >= priority or priority < 0 and log.context.type|default(0) == priority %} -
  • - {{ logger.display_message(loop.index, log) }} -
  • + {% for log in collector.logs %} + {% set is_deprecation = log.context.level is defined and log.context.type is defined and (constant('E_DEPRECATED') == log.context.type or constant('E_USER_DEPRECATED') == log.context.type) %} + {% if priority == '-100' ? is_deprecation : log.priority >= priority %} +
  • + {{ logger.display_message(loop.index, log, is_deprecation) }} +
  • + {% endif %} {% else %}
  • No logs available for this priority.
  • {% endfor %} @@ -104,15 +107,18 @@ {% endblock %} -{% macro display_message(log_index, log) %} - {% if log.context.level is defined and log.context.type is defined and (constant('E_DEPRECATED') == log.context.type or constant('E_USER_DEPRECATED') == log.context.type) %} - DEPRECATION - {{ log.message }} - {% set id = 'sf-call-stack-' ~ log_index %} - - - + - - {% for index, call in log.context.stack if index > 1 %} +{% macro display_message(log_index, log, is_deprecation) %} + {% if is_deprecation %} + {% set stack = log.context.stack|default([]) %} + + {% if stack %} + + + + + + {% endif %} + + {% for index, call in stack if index > 1 %} {% if index == 2 %} {% endif %} {% endfor %} From 02cda0595c23a1811f2004295cd6abfb91f301cf Mon Sep 17 00:00:00 2001 From: Luis Cordova Date: Sun, 29 Mar 2015 03:09:29 -0500 Subject: [PATCH 23/24] [Enhancement] netbeans - force interactive shell when limited detection --- src/Symfony/Component/Console/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index fa14441421..9daff3f301 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -855,7 +855,7 @@ class Application $input->setInteractive(false); } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('dialog')) { $inputStream = $this->getHelperSet()->get('dialog')->getInputStream(); - if (!@posix_isatty($inputStream)) { + if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) { $input->setInteractive(false); } } From 40ab7ef349751d3d7a9526780abf2ed8b227eb6e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 3 Apr 2015 07:27:47 +0200 Subject: [PATCH 24/24] [HttpKernel] Embed the original exception as previous to bounced exceptions --- .../HttpKernel/EventListener/ExceptionListener.php | 13 ++++++++++++- .../Tests/EventListener/ExceptionListenerTest.php | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php index a54fe45e9f..b1c1982f45 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php @@ -72,7 +72,18 @@ class ExceptionListener implements EventSubscriberInterface // set handling to false otherwise it wont be able to handle further more $handling = false; - // throwing $e, not $exception, is on purpose: fixing error handling code paths is the most important + $wrapper = $e; + + while ($prev = $wrapper->getPrevious()) { + if ($exception === $wrapper = $prev) { + throw $e; + } + } + + $prev = new \ReflectionProperty('Exception', 'previous'); + $prev->setAccessible(true); + $prev->setValue($wrapper, $exception); + throw $e; } diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php index 86244df0fc..8fb00f51c1 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php @@ -57,6 +57,7 @@ class ExceptionListenerTest extends \PHPUnit_Framework_TestCase $this->fail('RuntimeException expected'); } catch (\RuntimeException $e) { $this->assertSame('bar', $e->getMessage()); + $this->assertSame('foo', $e->getPrevious()->getMessage()); } } @@ -77,6 +78,7 @@ class ExceptionListenerTest extends \PHPUnit_Framework_TestCase $this->fail('RuntimeException expected'); } catch (\RuntimeException $e) { $this->assertSame('bar', $e->getMessage()); + $this->assertSame('foo', $e->getPrevious()->getMessage()); } $this->assertEquals(3, $logger->countErrors());