Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.484
diff -u -p -r1.484 form.inc
--- includes/form.inc	20 Aug 2010 01:08:18 -0000	1.484
+++ includes/form.inc	23 Aug 2010 22:12:07 -0000
@@ -766,7 +766,6 @@ function drupal_process_form($form_id, &
   // Only process the input if we have a correct form submission.
   if ($form_state['process_input']) {
     drupal_validate_form($form_id, $form, $form_state);
-
     // drupal_html_id() maintains a cache of element IDs it has seen,
     // so it can prevent duplicates. We want to be sure we reset that
     // cache when a form is processed, so scenarios that result in
@@ -1071,7 +1070,7 @@ function _form_validate(&$elements, &$fo
           $options = $elements['#options'];
         }
         if (is_array($elements['#value'])) {
-          $value = $elements['#type'] == 'checkboxes' ? array_keys($elements['#value']) : $elements['#value'];
+          $value = in_array($elements['#type'], array('checkboxes', 'tableselect')) ? array_keys($elements['#value']) : $elements['#value'];
           foreach ($value as $v) {
             if (!isset($options[$v])) {
               form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));
@@ -2024,6 +2023,56 @@ function form_type_checkboxes_value($ele
 }
 
 /**
+ * Helper function to determine the value for a tableselect form element.
+ *
+ * @param $element
+ *   The form element whose value is being populated.
+ * @param $input
+ *   The incoming input to populate the form element. If this is FALSE,
+ *   the element's default value should be returned.
+ * @return
+ *   The data that will appear in the $element_state['values'] collection
+ *   for this element. Return nothing to use the default.
+ */
+function form_type_tableselect_value($element, $input = FALSE) {
+  if ($input === FALSE) {
+    if (isset($element['#multiple']) && $element['#multiple']) {
+      $value = array();
+      $element += array('#default_value' => array());
+      foreach ($element['#default_value'] as $key) {
+        $value[$key] = $key;
+      }
+      foreach ($element['#default_value'] as $key => $flag) {
+        if ($flag) {
+          $value[$key] = $key;
+        }
+      }
+      return $value;
+    }
+    else {
+      return isset($element['#default_value']) ? $element['#default_value'] : '';
+    }
+  }
+  elseif (is_array($input)) {
+    // Programmatic form submissions use NULL to indicate that a checkbox
+    // should be unchecked; see drupal_form_submit(). We therefore remove all
+    // NULL elements from the array before constructing the return value, to
+    // simulate the behavior of web browsers (which do not send unchecked
+    // checkboxes to the server at all). This will not affect non-programmatic
+    // form submissions, since a checkbox can never legitimately be NULL.
+    foreach ($input as $key => $value) {
+      if (is_null($value)) {
+        unset($input[$key]);
+      }
+    }
+    return drupal_map_assoc($input);
+  }
+  else {
+    return $input;
+  }
+}
+
+/**
  * Helper function to determine the value for a password_confirm form
  * element.
  *
Index: modules/simpletest/tests/form.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form.test,v
retrieving revision 1.61
diff -u -p -r1.61 form.test
--- modules/simpletest/tests/form.test	18 Aug 2010 00:44:52 -0000	1.61
+++ modules/simpletest/tests/form.test	23 Aug 2010 22:12:07 -0000
@@ -616,11 +616,11 @@ class FormsElementsTableSelectFunctional
     );
 
     // Test with a valid value.
-    list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => 'row1'));
+    list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => array('row1')));
     $this->assertFalse(isset($errors['tableselect']), t('Option checker allows valid values for checkboxes.'));
 
     // Test with an invalid value.
-    list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => 'non_existing_value'));
+    list($processed_form, $form_state, $errors) = $this->formSubmitHelper($form, array('tableselect' => array('non_existing_value')));
     $this->assertTrue(isset($errors['tableselect']), t('Option checker disallows invalid values for checkboxes.'));
 
   }
