=== modified file 'includes/menu.inc'
--- includes/menu.inc	2008-07-10 10:58:01 +0000
+++ includes/menu.inc	2008-07-28 16:18:53 +0000
@@ -603,6 +603,9 @@ function _menu_item_localize(&$item, $ma
  */
 function _menu_translate(&$router_item, $map, $to_arg = FALSE) {
   $path_map = $map;
+  if (!preg_match($router_item['mask'], implode($map, '/'))) {
+    return FALSE;
+  }
   if (!_menu_load_objects($router_item, $map)) {
     // An error occurred loading an object.
     $router_item['access'] = FALSE;
@@ -686,6 +689,9 @@ function _menu_link_translate(&$item) {
     $item['localized_options'] = $item['options'];
   }
   else {
+    if (!preg_match($item['mask'], $item['link_path'])) {
+      return FALSE;
+    }
     $map = explode('/', $item['link_path']);
     _menu_link_map_translate($map, $item['to_arg_functions']);
     $item['href'] = implode('/', $map);
@@ -870,7 +876,7 @@ function menu_tree_all_data($menu_name =
       // LEFT JOIN since there is no match in {menu_router} for an external
       // link.
       $data['tree'] = menu_tree_data(db_query("
-        SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, ml.*
+        SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, m.mask, ml.*
         FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path
         WHERE ml.menu_name = '%s'" . $where . "
         ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args), $parents);
@@ -977,7 +983,7 @@ function menu_tree_page_data($menu_name 
         // LEFT JOIN since there is no match in {menu_router} for an external
         // link.
         $data['tree'] = menu_tree_data(db_query("
-          SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, ml.*
+          SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, m.mask, ml.*
           FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path
           WHERE ml.menu_name = '%s' AND ml.plid IN (" . $placeholders . ")
           ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args), $parents);
@@ -2241,6 +2247,10 @@ function _menu_link_parents_set(&$item, 
  * Helper function to build the router table based on the data from hook_menu.
  */
 function _menu_router_build($callbacks) {
+  static $mask_map = array(
+    array('+' => '[^/]*', '%' => '\d+', '%d' => '\d+', '%c' => '\w+', '%t' => '[0-9a-zA-Z_]'),
+    array('+' => '.*', '%d' => '\d+', '%c' => '\w+', '%t' => '[0-9a-zA-Z_]', '%d+' => '[\d/]*', '%c+' => '[\w/]*', '%t+' => '[0-9a-zA-Z_]'),
+  );
   // First pass: separate callbacks from paths, making paths ready for
   // matching. Calculate fitness, and fill some default values.
   $menu = array();
@@ -2386,26 +2396,51 @@ function _menu_router_build($callbacks) 
       'position' => '',
       'tab_parent' => '',
       'tab_root' => $path,
-      'path' => $path,
+      'mask' = > '|^'. str_replace('%', '\d+*', preg_quote($path)) . '$|',
     );
-
+    if (isset($item['mask']) && !preg_match('|^(^\W).+\1[a-zA-Z]*$|')) {
+      $mask = explode('/', $item['mask']);
+      $mask_length = count($mask) - 1;
+      $postfix = '';
+      $item['mask'] = '#^(?:';
+      foreach ($mask as $k => &$mask_part) {
+        $last = ($k == $mask_length);
+        if (isset($mask_map[$last][$mask_part])) {
+          $mask_part = $mask_map[$last][$mask_part];
+        }
+        elseif (isset($parts[$k]) && $parts[$k] != '%') {
+          $mask_part = $parts[$k];
+        }
+        if (isset($parts[$k])) {
+          $prefix = $k ? '/' : '';
+        }
+        else {
+          // If we are past the last router path part then all the parts are
+          // optional, so we wrap them in conditional non grouping blocks.
+          $prefix = '(?:/';
+          $postfix .= ')?';
+        }
+        $item['mask'] .= $prefix . $mask_part;
+      }
+      $item['mask'] .= $postfix .')$#';
+    }
     $title_arguments = $item['title arguments'] ? serialize($item['title arguments']) : '';
     db_query("INSERT INTO {menu_router}
       (path, load_functions, to_arg_functions, access_callback,
       access_arguments, page_callback, page_arguments, fit,
       number_parts, tab_parent, tab_root,
       title, title_callback, title_arguments,
-      type, block_callback, description, position, weight)
+      type, block_callback, description, position, weight, mask)
       VALUES ('%s', '%s', '%s', '%s',
       '%s', '%s', '%s', %d,
       %d, '%s', '%s',
       '%s', '%s', '%s',
-      %d, '%s', '%s', '%s', %d)",
+      %d, '%s', '%s', '%s', %d, '%s')",
       $path, $item['load_functions'], $item['to_arg_functions'], $item['access callback'],
       serialize($item['access arguments']), $item['page callback'], serialize($item['page arguments']), $item['_fit'],
       $item['_number_parts'], $item['tab_parent'], $item['tab_root'],
       $item['title'], $item['title callback'], $title_arguments,
-      $item['type'], $item['block callback'], $item['description'], $item['position'], $item['weight']);
+      $item['type'], $item['block callback'], $item['description'], $item['position'], $item['weight'], $item['mask']);
   }
   // Sort the masks so they are in order of descending fit, and store them.
   $masks = array_keys($masks);

=== modified file 'modules/taxonomy/taxonomy.module'
--- modules/taxonomy/taxonomy.module	2008-07-24 16:25:17 +0000
+++ modules/taxonomy/taxonomy.module	2008-07-28 17:24:23 +0000
@@ -154,6 +154,7 @@ function taxonomy_menu() {
     'page callback' => 'taxonomy_term_page',
     'page arguments' => array(2),
     'access arguments' => array('access content'),
+    'mask' =>  '#^taxonomy/term/((((\d+[+ ])+)|((\d+,)*))\d+(/\d+(/page|/feed)?)?)$#',
     'type' => MENU_CALLBACK,
   );
 

=== modified file 'modules/taxonomy/taxonomy.pages.inc'
--- modules/taxonomy/taxonomy.pages.inc	2008-04-14 17:48:33 +0000
+++ modules/taxonomy/taxonomy.pages.inc	2008-07-28 15:34:16 +0000
@@ -64,9 +64,6 @@ function taxonomy_term_page($str_tids = 
 
           node_feed($items, $channel);
           break;
-
-        default:
-          drupal_not_found();
       }
     }
     else {

