diff --git includes/common.inc includes/common.inc
index bda9d52..712f6c4 100644
--- includes/common.inc
+++ includes/common.inc
@@ -2271,10 +2271,8 @@ function l($text, $path, array $options = array()) {
     'html' => FALSE,
   );
 
-  $item = menu_get_item();
-  $active_href = (($item['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT ? $item['tab_root_href'] : $item['href']);
   // Append active class.
-  if (($path == $active_href || ($path == '<front>' && drupal_is_front_page())) &&
+  if (($path == $_GET['q'] || ($path == '<front>' && drupal_is_front_page())) &&
       (empty($options['language']) || $options['language']->language == $language_url->language)) {
     $options['attributes']['class'][] = 'active';
   }
diff --git includes/menu.inc includes/menu.inc
index 3d24f1b..b28a1b3 100644
--- includes/menu.inc
+++ includes/menu.inc
@@ -971,6 +971,7 @@ function menu_tree_output($tree) {
     }
   }
 
+  $router_item = menu_get_item();
   $num_items = count($items);
   foreach ($items as $i => $data) {
     $class = array();
@@ -995,7 +996,14 @@ function menu_tree_output($tree) {
     // Set a class if the link is in the active trail.
     if ($data['link']['in_active_trail']) {
       $class[] = 'active-trail';
-      $data['localized_options']['attributes']['class'][] = 'active-trail';
+      $data['link']['localized_options']['attributes']['class'][] = 'active-trail';
+    }
+    // Normally, l() compares the href of every link with $_GET['q'] and sets
+    // the active class accordingly. But local tasks do not appear in menu
+    // trees, so if the current path is a local task, and this link is its
+    // tab root, then we have to set the class manually.
+    if ($data['link']['href'] == $router_item['tab_root_href'] && $data['link']['href'] != $_GET['q']) {
+      $data['link']['localized_options']['attributes']['class'][] = 'active';
     }
 
     // Allow menu-specific theme overrides.
@@ -1731,6 +1739,7 @@ function menu_navigation_links($menu_name, $level = 0) {
   }
 
   // Create a single level of links.
+  $router_item = menu_get_item();
   $links = array();
   foreach ($tree as $item) {
     if (!$item['link']['hidden']) {
@@ -1740,6 +1749,14 @@ function menu_navigation_links($menu_name, $level = 0) {
       $l['title'] = $item['link']['title'];
       if ($item['link']['in_active_trail']) {
         $class = ' active-trail';
+        $l['attributes']['class'][] = 'active-trail';
+      }
+      // Normally, l() compares the href of every link with $_GET['q'] and sets
+      // the active class accordingly. But local tasks do not appear in menu
+      // trees, so if the current path is a local task, and this link is its
+      // tab root, then we have to set the class manually.
+      if ($item['link']['href'] == $router_item['tab_root_href'] && $item['link']['href'] != $_GET['q']) {
+        $l['attributes']['class'][] = 'active';
       }
       // Keyed with the unique mlid to generate classes in theme_links().
       $links['menu-' . $item['link']['mlid'] . $class] = $l;
@@ -1846,6 +1863,16 @@ function menu_local_tasks($level = 0) {
             for ($p = $item['tab_parent']; ($tasks[$p]['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT; $p = $tasks[$p]['tab_parent']);
             // Use the path of the parent instead.
             $link['href'] = $tasks[$p]['href'];
+            // Mark the link as active, if the current path happens to be the
+            // path of the default local task itself (i.e., instead of its
+            // tab_parent_href or tab_root_href). Normally, links for default
+            // local tasks link to their parent, but the path of default local
+            // tasks can still be accessed directly, in which case this link
+            // would not be marked as active, since l() only compares the href
+            // with $_GET['q'].
+            if ($link['href'] != $_GET['q']) {
+              $link['localized_options']['attributes']['class'][] = 'active';
+            }
             $tabs_current[] = array(
               '#theme' => 'menu_local_task',
               '#link' => $link,
@@ -1915,6 +1942,13 @@ function menu_local_tasks($level = 0) {
           }
           // We check for the active tab.
           if ($item['path'] == $path) {
+            // Mark the link as active, if the current path is a (second-level)
+            // local task of a default local task. Since this default local task
+            // links to its parent, l() will not mark it as active, as it only
+            // compares the link's href to $_GET['q'].
+            if ($link['href'] != $_GET['q']) {
+              $link['localized_options']['attributes']['class'][] = 'active';
+            }
             $tabs_current[] = array(
               '#theme' => 'menu_local_task',
               '#link' => $link,
diff --git modules/simpletest/tests/menu.test modules/simpletest/tests/menu.test
index 7b03e84..5e4d2a5 100644
--- modules/simpletest/tests/menu.test
+++ modules/simpletest/tests/menu.test
@@ -566,18 +566,18 @@ class MenuBreadcrumbTestCase extends DrupalWebTestCase {
       'menu-test/breadcrumb/tasks' => $title,
     );
     $this->assertBreadcrumb('menu-test/breadcrumb/tasks', $trail, $title, $tree);
-    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/first', $trail, $title, $tree, FALSE);
-    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/first/first', $trail, $title, $tree, FALSE);
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/first', $trail, $title, $tree);
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/first/first', $trail, $title, $tree);
     $trail += array(
       'menu-test/breadcrumb/tasks' => t('Breadcrumbs test: Local tasks'),
     );
-    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/first/second', $trail, $title, $tree, FALSE);
-    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/second', $trail, $title, $tree, FALSE);
-    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/second/first', $trail, $title, $tree, FALSE);
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/first/second', $trail, $title, $tree);
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/second', $trail, $title, $tree);
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/second/first', $trail, $title, $tree);
     $trail += array(
       'menu-test/breadcrumb/tasks/second' => t('Second'),
     );
-    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/second/second', $trail, $title, $tree, FALSE);
+    $this->assertBreadcrumb('menu-test/breadcrumb/tasks/second/second', $trail, $title, $tree);
 
     // Verify Taxonomy administration breadcrumbs.
     $trail = $admin + array(
@@ -1043,8 +1043,8 @@ class MenuBreadcrumbTestCase extends DrupalWebTestCase {
       else {
         $xpath .= '//';
       }
-      $last_active = ($last_active ? 'and contains(@class, :class-active)' : '');
-      $xpath .= 'li[contains(@class, :class-trail)]/a[contains(@href, :href) ' . $last_active . 'and contains(text(), :title)]';
+      $xpath_last_active = ($last_active ? 'and contains(@class, :class-active)' : '');
+      $xpath .= 'li[contains(@class, :class-trail)]/a[contains(@href, :href) ' . $xpath_last_active . 'and contains(text(), :title)]';
       $args = array(
         ':class-trail' => 'active-trail',
         ':class-active' => 'active',
