diff --git a/modules/field/field.form.inc b/modules/field/field.form.inc
index 5154f6331ae015239cf372ca6cab389ee261ce45..3e41b04085a1e47b404b1151c2478d6fbe8fb180 100644
--- a/modules/field/field.form.inc
+++ b/modules/field/field.form.inc
@@ -131,11 +131,6 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode,
  * - drag-n-drop value reordering
  */
 function field_multiple_value_form($field, $instance, $langcode, $items, &$form, &$form_state) {
-  // This form has its own multistep persistance.
-  if ($form_state['rebuild']) {
-    $form_state['input'] = array();
-  }
-
   $field_name = $field['field_name'];
 
   // Determine the number of widgets to display.
diff --git a/modules/field/tests/field.test b/modules/field/tests/field.test
index dc56f4eb5fd0494cd39c839bfb4b6a0d9e83e056..f79ebd0b600595f6adbe57191c1756c36e568b09 100644
--- a/modules/field/tests/field.test
+++ b/modules/field/tests/field.test
@@ -1557,23 +1557,21 @@ class FieldFormTestCase extends FieldTestCase {
       do {
         $weight = mt_rand(-$delta_range, $delta_range);
       } while (in_array($weight, $weights));
-      $weights[] = $weight;
       $value = mt_rand(1, 127);
       $edit["$this->field_name[$langcode][$delta][value]"] = $value;
       $edit["$this->field_name[$langcode][$delta][_weight]"] = $weight;
       // We'll need three slightly different formats to check the values.
-      $values[$weight] = $value;
+      $values[$delta] = $value;
+      $weights[$delta] = $weight;
       $field_values[$weight]['value'] = (string)$value;
       $pattern[$weight] = "<input [^>]*value=\"$value\" [^>]*";
     }
 
     // Press 'add more' button -> 4 widgets
     $this->drupalPost(NULL, $edit, t('Add another item'));
-    ksort($values);
-    $values = array_values($values);
     for ($delta = 0; $delta <= $delta_range; $delta++) {
       $this->assertFieldByName("$this->field_name[$langcode][$delta][value]", $values[$delta], "Widget $delta is displayed and has the right value");
-      $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $delta, "Widget $delta has the right weight");
+      $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $weights[$delta], "Widget $delta has the right weight");
     }
     ksort($pattern);
     $pattern = implode('.*', array_values($pattern));
@@ -1627,12 +1625,12 @@ class FieldFormTestCase extends FieldTestCase {
       do {
         $weight = mt_rand(-$delta_range, $delta_range);
       } while (in_array($weight, $weights));
-      $weights[] = $weight;
       $value = mt_rand(1, 127);
       $edit["$this->field_name[$langcode][$delta][value]"] = $value;
       $edit["$this->field_name[$langcode][$delta][_weight]"] = $weight;
       // We'll need three slightly different formats to check the values.
-      $values[$weight] = $value;
+      $values[$delta] = $value;
+      $weights[$delta] = $weight;
       $field_values[$weight]['value'] = (string)$value;
       $pattern[$weight] = "<input [^>]*value=\"$value\" [^>]*";
     }
@@ -1641,11 +1639,9 @@ class FieldFormTestCase extends FieldTestCase {
     $commands = $this->drupalPostAJAX(NULL, $edit, $this->field_name . '_add_more');
     $this->content = $commands[1]['data'];
 
-    ksort($values);
-    $values = array_values($values);
     for ($delta = 0; $delta <= $delta_range; $delta++) {
       $this->assertFieldByName("$this->field_name[$langcode][$delta][value]", $values[$delta], "Widget $delta is displayed and has the right value");
-      $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $delta, "Widget $delta has the right weight");
+      $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $weights[$delta], "Widget $delta has the right weight");
     }
     ksort($pattern);
     $pattern = implode('.*', array_values($pattern));
diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test
index 87dd698d8a80a47c65cf0bb9ea499e18663af954..b19ca765571a4d8c5c889968dd319d310e8617cc 100644
--- a/modules/simpletest/tests/form.test
+++ b/modules/simpletest/tests/form.test
@@ -849,3 +849,69 @@ class FormsProgrammaticTestCase extends DrupalWebTestCase {
     }
   }
 }
+
+
+/**
+ * Tests rebuilding of arbitrary forms by altering them.
+ */
+class FormsArbitraryRebuildTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Rebuild arbitrary forms',
+      'description' => 'Tests altering forms to be rebuilt so there are multiple steps.',
+      'group' => 'Form API',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('form_test');
+    // Auto-create a field for testing.
+    $field = array(
+      'field_name' => 'test_multiple',
+      'type' => 'text',
+      'cardinality' => -1,
+      'translatable' => FALSE,
+    );
+    field_create_field($field);
+
+    $instance = array(
+      'object_type' => 'node',
+      'field_name' => 'test_multiple',
+      'bundle' => 'page',
+      'label' => 'Test a multiple valued field',
+      'widget' => array(
+        'type' => 'text_textfield',
+        'weight' => 0,
+      ),
+    );
+    field_create_instance($instance);
+  }
+
+  /**
+   * Tests a basic rebuild with the user registration form.
+   */
+  function testUserRegistrationRebuild() {
+    $edit = array(
+      'name' => 'foo',
+      'mail' => 'bar@example.com',
+    );
+    $this->drupalPost('user/register', $edit, 'Rebuild');
+    $this->assertText('Form rebuilt.');
+    $this->assertFieldByName('name', 'foo', 'Entered user name has been kept.');
+    $this->assertFieldByName('mail', 'bar@example.com', 'Entered mail address has been kept.');
+  }
+
+  /**
+   * Tests a rebuild caused by a multiple value field.
+   */
+  function testUserRegistrationMultipleField() {
+    $edit = array(
+      'name' => 'foo',
+      'mail' => 'bar@example.com',
+    );
+    $this->drupalPost('user/register', $edit, t('Add another item'), array('query' => array('field' => TRUE)));
+    $this->assertText('Test a multiple valued field', 'Form has been rebuilt.');
+    $this->assertFieldByName('name', 'foo', 'Entered user name has been kept.');
+    $this->assertFieldByName('mail', 'bar@example.com', 'Entered mail address has been kept.');
+  }
+}
diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module
index f944d709f900fe523a4965df710bd8899d4ffd46..7be851d2c55cf3484fcdf8dcc1c3a6cfadf662ee 100644
--- a/modules/simpletest/tests/form_test.module
+++ b/modules/simpletest/tests/form_test.module
@@ -922,3 +922,30 @@ function form_test_programmatic_form_validate($form, &$form_state) {
 function form_test_programmatic_form_submit($form, &$form_state) {
   $form_state['storage']['programmatic_form_submit'] = $form_state['values']['submitted_field'];
 }
+
+
+/**
+ * Implements hook_form_FORM_ID_alter() for the registration form.
+ */
+function form_test_form_user_register_form_alter(&$form, &$form_state) {
+  $form['test_rebuild'] = array(
+    '#type' => 'submit',
+    '#value' => t('Rebuild'),
+    '#submit' => array('form_test_user_register_form_rebuild'),
+  );
+  // If requested, add the test field by attaching the node page form.
+  if (!empty($_REQUEST['field'])) {
+    $node = (object)array('type' => 'page');
+    field_attach_form('node', $node, $form, $form_state);
+    // The form API requires the builder function to set rebuilding, so do so.
+    $form['#builder_function'] = 'form_test_user_register_form_rebuild';
+  }
+}
+
+/**
+ * Submit callback that just lets the form rebuild.
+ */
+function form_test_user_register_form_rebuild($form, &$form_state) {
+  drupal_set_message('Form rebuilt.');
+  $form_state['rebuild'] = TRUE;
+}