Commit 15bca6e4 authored by Dries's avatar Dries

- Patch #803212 by effulgentsia, Heine: protection against forgery of input...

- Patch #803212 by effulgentsia, Heine: protection against forgery of input selection value doesn't work with checkboxes.
parent d99623f8
......@@ -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);
}
......
......@@ -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();
}
}
......
......@@ -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.'));
}
}
/**
......
......@@ -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',
......@@ -860,6 +868,35 @@ function _form_test_disabled_elements_submit($form, &$form_state) {
exit();
}
/**
* 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.
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment