diff --git a/includes/form.inc b/includes/form.inc
index b55d724..956f509 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -1319,6 +1319,17 @@ function form_type_password_confirm_value($form, $edit = FALSE) {
     $form += array('#default_value' => array());
     return $form['#default_value'] + array('pass1' => '', 'pass2' => '');
   }
+  $value = array('pass1' => '', 'pass2' => '');
+  // Throw out all invalid array keys; we only allow pass1 and pass2.
+  foreach ($value as $allowed_key => $default) {
+    // These should be strings, but allow other scalars since they might be
+    // valid input in programmatic form submissions. Any nested array values
+    // are ignored.
+    if (isset($edit[$allowed_key]) && is_scalar($edit[$allowed_key])) {
+      $value[$allowed_key] = (string) $edit[$allowed_key];
+    }
+  }
+  return $value;
 }
 
 /**
@@ -1343,6 +1354,26 @@ function form_type_select_value($form, $edit = FALSE) {
     }
   }
 }
+/**
+ * Determines the value for a textarea form element.
+ *
+ * @param $form
+ *   The form element whose value is being populated.
+ * @param $edit
+ *   The incoming input to populate the form element. If this is FALSE,
+ *   NULL should be returned.
+ *
+ * @return string
+ *   The data that will appear in the $form_state['values'] collection
+ *   for this element. Return NULL to use the default.
+ */
+function form_type_textarea_value($form, $edit = FALSE) {
+  if ($edit !== FALSE) {
+    // This should be a string, but allow other scalars since they might be
+    // valid input in programmatic form submissions.
+    return is_scalar($edit) ? (string) $edit : '';
+  }
+}
 
 /**
  * Helper function to determine the value for a textfield form element.
@@ -1358,9 +1389,12 @@ function form_type_select_value($form, $edit = FALSE) {
  */
 function form_type_textfield_value($form, $edit = FALSE) {
   if ($edit !== FALSE) {
-    // Equate $edit to the form value to ensure it's marked for
-    // validation.
-    return str_replace(array("\r", "\n"), '', $edit);
+    // This should be a string, but allow other scalars since they might be
+    // valid input in programmatic form submissions.
+    if (!is_scalar($edit)) {
+      $edit = '';
+    }
+    return str_replace(array("\r", "\n"), '', (string) $edit);
   }
 }
 
diff --git a/modules/system/system.module b/modules/system/system.module
index ccc638f..16e1a7b 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -170,7 +170,9 @@ function system_elements() {
   $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => FALSE, '#process' => array('form_expand_ahah'));
   $type['image_button'] = array('#input' => TRUE, '#button_type' => 'submit', '#executes_submit_callback' => TRUE, '#process' => array('form_expand_ahah'), '#return_value' => TRUE, '#has_garbage_value' => TRUE, '#src' => NULL);
   $type['textfield'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#autocomplete_path' => FALSE, '#process' => array('form_process_autocomplete', 'form_expand_ahah'));
-  $type['password'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#process' => array('form_expand_ahah'));
+  // Use the same value callback for password as for textfield; this ensures
+  // that we only get string values.
+  $type['password'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#process' => array('form_expand_ahah'), '#value_callback' => 'form_type_textfield_value');
   $type['password_confirm'] = array('#input' => TRUE, '#process' => array('expand_password_confirm'));
   $type['textarea'] = array('#input' => TRUE, '#cols' => 60, '#rows' => 5, '#resizable' => TRUE, '#process' => array('form_expand_ahah'));
   $type['radios'] = array('#input' => TRUE, '#process' => array('expand_radios'));
