summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2010-06-05 13:18:09 +0000
committerDries Buytaert <dries@buytaert.net>2010-06-05 13:18:09 +0000
commit15bca6e4623e0344c4165b5e9ac6f4502e6f2481 (patch)
treeeeef66305263aee2569ea3b63754864e5fb1a421
parentd99623f8a1cc6b2845a40ab1f4cc8f6e57bbd056 (diff)
downloadbrdo-15bca6e4623e0344c4165b5e9ac6f4502e6f2481.tar.gz
brdo-15bca6e4623e0344c4165b5e9ac6f4502e6f2481.tar.bz2
- Patch #803212 by effulgentsia, Heine: protection against forgery of input selection value doesn't work with checkboxes.
-rw-r--r--includes/common.inc4
-rw-r--r--includes/form.inc9
-rw-r--r--modules/simpletest/tests/form.test13
-rw-r--r--modules/simpletest/tests/form_test.module37
4 files changed, 56 insertions, 7 deletions
diff --git a/includes/common.inc b/includes/common.inc
index 211695c8e..a301f3404 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -2481,7 +2481,9 @@ function drupal_exit($destination = NULL) {
* An associative array.
*/
function drupal_map_assoc($array, $function = NULL) {
- $array = array_combine($array, $array);
+ // array_combine() fails with empty arrays:
+ // http://bugs.php.net/bug.php?id=34857.
+ $array = !empty($array) ? array_combine($array, $array) : array();
if (is_callable($function)) {
$array = array_map($function, $array);
}
diff --git a/includes/form.inc b/includes/form.inc
index c1ba70bf4..3cd6bca81 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -941,7 +941,7 @@ function _form_validate(&$elements, &$form_state, $form_id = NULL) {
$options = $elements['#options'];
}
if (is_array($elements['#value'])) {
- $value = $elements['#type'] == 'checkboxes' ? array_keys(array_filter($elements['#value'])) : $elements['#value'];
+ $value = $elements['#type'] == 'checkboxes' ? 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.'));
@@ -1804,11 +1804,8 @@ function form_type_checkboxes_value($element, $input = FALSE) {
}
return $value;
}
- // If the checkboxes are enabled, and NULL input is submitted, it means
- // they're intentionally unchecked, so we need to return an empty array to
- // prevent the default value from being used.
- elseif (!isset($input) && empty($element['#disabled'])) {
- return array();
+ else {
+ return is_array($input) ? drupal_map_assoc($input) : array();
}
}
diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test
index 2cba9863a..fb46d94e5 100644
--- a/modules/simpletest/tests/form.test
+++ b/modules/simpletest/tests/form.test
@@ -207,6 +207,19 @@ class FormsTestCase extends DrupalWebTestCase {
}
}
}
+
+ /**
+ * Test Form API protections against input forgery.
+ *
+ * @see _form_test_input_forgery()
+ */
+ function testInputForgery() {
+ $this->drupalGet('form-test/input-forgery');
+ $checkbox = $this->xpath('//input[@name="checkboxes[two]"]');
+ $checkbox[0]['value'] = 'FORGERY';
+ $this->drupalPost(NULL, array('checkboxes[one]' => TRUE, 'checkboxes[two]' => TRUE), t('Submit'));
+ $this->assertText('An illegal choice has been detected.', t('Input forgery was detected.'));
+ }
}
/**
diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module
index 94d10faee..6a1cb3258 100644
--- a/modules/simpletest/tests/form_test.module
+++ b/modules/simpletest/tests/form_test.module
@@ -101,6 +101,14 @@ function form_test_menu() {
'type' => MENU_CALLBACK,
);
+ $items['form-test/input-forgery'] = array(
+ 'title' => t('Form test'),
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('_form_test_input_forgery'),
+ 'access callback' => TRUE,
+ 'type' => MENU_CALLBACK,
+ );
+
$items['form-test/form-rebuild-preserve-values'] = array(
'title' => 'Form values preservation during rebuild test',
'page callback' => 'drupal_get_form',
@@ -861,6 +869,35 @@ function _form_test_disabled_elements_submit($form, &$form_state) {
}
/**
+ * Build a form to test input forgery of enabled elements.
+ */
+function _form_test_input_forgery($form, &$form_state) {
+ // For testing that a user can't submit a value not matching one of the
+ // allowed options.
+ $form['checkboxes'] = array(
+ '#type' => 'checkboxes',
+ '#options' => array(
+ 'one' => 'One',
+ 'two' => 'Two',
+ ),
+ );
+
+ $form['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Submit'),
+ );
+ return $form;
+}
+
+/**
+ * Return the form values via JSON.
+ */
+function _form_test_input_forgery_submit($form, &$form_state) {
+ drupal_json_output($form_state['values']);
+ exit();
+}
+
+/**
* Form builder for testing preservation of values during a rebuild.
*/
function form_test_form_rebuild_preserve_values_form($form, &$form_state) {