diff -urpN includes/menu.inc includes/menu.inc
--- includes/menu.inc	2008-11-04 12:56:36.000000000 +0200
+++ includes/menu.inc	2008-11-05 09:43:21.000000000 +0200
@@ -476,7 +476,7 @@ function _menu_load_objects(&$item, &$ma
 }
 
 /**
- * Check access to a menu item using the access callback
+ * Check access to a menu item using the access callback.
  *
  * @param $item
  *   A menu router or menu link item
@@ -488,20 +488,50 @@ function _menu_load_objects(&$item, &$ma
 function _menu_check_access(&$item, $map) {
   // Determine access callback, which will decide whether or not the current
   // user has access to this path.
-  $callback = empty($item['access_callback']) ? 0 : trim($item['access_callback']);
-  // Check for a TRUE or FALSE value.
-  if (is_numeric($callback)) {
-    $item['access'] = (bool)$callback;
+
+  // Check if this is a multiple access callback.
+  if ($item['access_callback'] == '-1') {
+    $callbacks = array();
+    foreach (unserialize($item['access_arguments']) as $callback) {
+      $callbacks[] = array(
+        'callback' => empty($callback['callback']) ? 0 : trim($callback['callback']),
+        // Serialize it again is it will be later menu_unserialize().
+        'arguments' => serialize($callback['arguments']),
+      );
+    }
   }
   else {
-    $arguments = menu_unserialize($item['access_arguments'], $map);
-    // As call_user_func_array is quite slow and user_access is a very common
-    // callback, it is worth making a special case for it.
-    if ($callback == 'user_access') {
-      $item['access'] = (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
+    // Even though this is a single access callback prepare it for the
+    // following foreach().
+    $callbacks = array(
+      array(
+        'callback' => empty($item['access_callback']) ? 0 : trim($item['access_callback']),
+        'arguments' => $item['access_arguments'],
+      ),
+    );
+  }
+
+  // If it isn't a multiple access callback, it will be executed only once.
+  foreach ($callbacks as $callback){
+    // Check for a TRUE or FALSE value.
+    if (is_numeric($callback['callback'])) {
+      $item['access'] =  (bool)$callback['callback'];
     }
     else {
-      $item['access'] = call_user_func_array($callback, $arguments);
+      $arguments = menu_unserialize($callback['arguments'], $map);
+      // As call_user_func_array is quite slow and user_access is a very common
+      // callback, it is worth making a special case for it.
+      if ($callback['callback'] == 'user_access') {
+        $item['access'] = count($arguments) == 1 ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
+      }
+      else {
+        $item['access'] = call_user_func_array($callback['callback'], $arguments);
+      }
+    }
+    // If menu has multiple access and one access is FALSE then deny access
+    // and stop checking other access callbacks.
+    if ($item['access'] == FALSE) {
+      break;
     }
   }
 }
@@ -2408,6 +2438,14 @@ function _menu_router_build($callbacks) 
     if (is_bool($item['access callback'])) {
       $item['access callback'] = intval($item['access callback']);
     }
+    // Multiple access callbacks case.
+    if (is_array($item['access callback'])) {
+      // We will store the seralized data in the access arguments field.
+      $item['access arguments'] = $item['access callback'];
+      // Mark access callback with '-1' as a sign for it to be a multiple 
+      // access callback.
+      $item['access callback'] = '-1';
+    }    
 
     $item += array(
       'access arguments' => array(),
diff -urpN modules/simpletest/tests/menu_multiple_access.info modules/simpletest/tests/menu_multiple_access.info
--- modules/simpletest/tests/menu_multiple_access.info	1970-01-01 02:00:00.000000000 +0200
+++ modules/simpletest/tests/menu_multiple_access.info	2008-11-05 10:08:40.000000000 +0200
@@ -0,0 +1,6 @@
+name = Menu multiple access callbacks
+description = "Add several access callback to a menu link to be used by simpleTest."
+package = Testing
+files[] = menu_multiple_access.module
+hidden = TRUE
+core = 7.x
diff -urpN modules/simpletest/tests/menu_multiple_access.module modules/simpletest/tests/menu_multiple_access.module
--- modules/simpletest/tests/menu_multiple_access.module	1970-01-01 02:00:00.000000000 +0200
+++ modules/simpletest/tests/menu_multiple_access.module	2008-11-05 10:13:27.000000000 +0200
@@ -0,0 +1,27 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Testing module; Add several access callback to a menu link.
+ */
+
+
+/**
+ * Implementation of hook_menu_alter().
+ * 
+ * Make the access to admin/build/block require two access callbacks.
+ */
+function menu_multiple_access_menu_alter(&$callbacks) {
+  $callbacks['admin/build/block']['access callback'] = array(
+    array(
+      'callback' => 'user_access',
+      'arguments' => array('administer blocks'),
+    ),
+    array(
+      'callback' => 'user_access',
+      'arguments' => array('administer nodes'),
+    ),
+  );
+}
+
diff -urpN modules/simpletest/tests/menu.test modules/simpletest/tests/menu.test
--- modules/simpletest/tests/menu.test	2008-09-15 23:48:09.000000000 +0300
+++ modules/simpletest/tests/menu.test	2008-11-05 10:24:07.000000000 +0200
@@ -45,3 +45,49 @@ class MenuIncTestCase extends DrupalWebT
     $this->assertEqual($name, 'changed', t('Menu name was successfully changed after rebuild.'));
   }
 }
+
+
+class MenuMultipleAccessTestCase extends DrupalWebTestCase {
+  /**
+   * Implementation of getInfo().
+   */
+  function getInfo() {
+    return array(
+      'name' => t('Multiple access callbacks tests'),
+      'description' => t('Test accessing a menu link with several access callbacks defined.'),
+      'group' => t('Menu'),
+    );
+  }
+
+  /**
+   * Implementation of setUp().
+   */
+  function setUp() {
+    // Enable dummy module that implements hook_menu_alter().
+    parent::setUp('menu_multiple_access');
+  }
+
+  /**
+   * Tests for multiple access callbacks for hook_menu().
+   */
+  function testMenuMultipleAccessCallbacks() {
+    $web_user = $this->drupalCreateUser(array('administer blocks'));
+    $this->drupalLogin($web_user);
+
+    // Rebuild the menu so the new access callback will be enabled.
+    menu_rebuild();
+
+    // Web user has only administer block permission,
+    // thus access will be denied.
+    $this->drupalGet("admin/build/block");
+    $this->assertResponse(403, t("User did not pass access check as a permission is missing."));
+
+    $admin_user = $this->drupalCreateUser(array('administer blocks', 'administer nodes'));
+    $this->drupalLogin($admin_user);
+
+    // Admin user has both required permissions, thus access will be granted.
+    $this->drupalGet("admin/build/block");
+    $this->assertResponse(200, t("User pass access check as permissions were sufficient."));
+
+  }
+}
