From 6ed446232cfb26bc0041529c5f10f1d3a2ae3003 Mon Sep 17 00:00:00 2001
From: Pieter Frenssen <pieter@frenssen.be>
Date: Thu, 13 Sep 2012 17:12:14 +0200
Subject: [PATCH 1/2] Issue #1783704 by pfrenssen: Test that paths can be
 matched to large patterns in drupal_match_path().

---
 modules/simpletest/tests/path.test | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/modules/simpletest/tests/path.test b/modules/simpletest/tests/path.test
index a506349..d1c1cab 100644
--- a/modules/simpletest/tests/path.test
+++ b/modules/simpletest/tests/path.test
@@ -124,6 +124,26 @@ class DrupalMatchPathTestCase extends DrupalWebTestCase {
       ),
     );
   }
+
+  /**
+   * Tests that paths can be matched to large patterns.
+   */
+  function testDrupalMatchPathLargePattern() {
+    // Create a large patterns string.
+    $patterns = array();
+    for ($i = 0 ; $i < 20000 ; $i++) {
+      $patterns[] = "node/$i";
+    }
+    $patterns = implode("\n", $patterns);
+
+    // Try a matching path.
+    $result = drupal_match_path('node/19999', $patterns);
+    $this->assertTrue($result, t('A matching path was found in a large patterns string.'));
+
+    // Try a non-matching path.
+    $result = drupal_match_path('node/20000', $patterns);
+    $this->assertFalse($result, t('A non-matching path was not found in a large patterns string.'));
+  }
 }
 
 /**
-- 
1.7.12


From c8d100fd0bc5be014beb387921f3f81cd4573453 Mon Sep 17 00:00:00 2001
From: Pieter Frenssen <pieter@frenssen.be>
Date: Thu, 13 Sep 2012 17:15:15 +0200
Subject: [PATCH 2/2] Issue #1783704 by pfrenssen: Make sure
 drupal_match_path() does not fail on large matching
 patterns.

---
 includes/path.inc | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/includes/path.inc b/includes/path.inc
index 411a7a7..39513a5 100644
--- a/includes/path.inc
+++ b/includes/path.inc
@@ -326,9 +326,21 @@ function drupal_match_path($path, $patterns) {
       '\1' . preg_quote(variable_get('site_frontpage', 'node'), '/') . '\2'
     );
     $patterns_quoted = preg_quote($patterns, '/');
-    $regexps[$patterns] = '/^(' . preg_replace($to_replace, $replacements, $patterns_quoted) . ')$/';
+    $regexps[$patterns] = preg_replace($to_replace, $replacements, $patterns_quoted);
   }
-  return (bool)preg_match($regexps[$patterns], $path);
+
+  // Process large patterns in 16K chunks to avoid preg_match() from consuming
+  // too much memory.
+  $process = $regexps[$patterns];
+  do {
+    $split = strlen($process) > 16384 ? strpos($process, '|', 16384) : strlen($process);
+    if ((bool)preg_match('/^(' . substr($process, 0 , $split) . ')$/', $path)) {
+      return TRUE;
+    }
+    $process = $split ? substr($process, $split + 1) : FALSE;
+  } while ($process);
+
+  return FALSE;
 }
 
 /**
-- 
1.7.12

