Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions includes/fields/class-acf-field-text.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ function render_field_presentation_settings( $field ) {
*/
function validate_value( $valid, $value, $field, $input ) {

// Check maxlength
if ( isset( $field['maxlength'] ) && $field['maxlength'] && ( acf_strlen( $value ) > $field['maxlength'] ) ) {
// Check maxlength. A non-scalar value (e.g. an array from a crafted submission) is not valid text, so skip the string length check.
if ( isset( $field['maxlength'] ) && $field['maxlength'] && is_scalar( $value ) && ( acf_strlen( $value ) > $field['maxlength'] ) ) {
/* translators: %d: the maximum number of characters */
return sprintf( __( 'Value must not exceed %d characters', 'secure-custom-fields' ), $field['maxlength'] );
}
Expand Down
4 changes: 2 additions & 2 deletions includes/fields/class-acf-field-textarea.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ function format_value( $value, $post_id, $field ) {
*/
function validate_value( $valid, $value, $field, $input ) {

// Check maxlength.
if ( $field['maxlength'] && ( acf_strlen( $value ) > $field['maxlength'] ) ) {
// Check maxlength. A non-scalar value (e.g. an array from a crafted submission) is not valid text, so skip the string length check.
if ( $field['maxlength'] && is_scalar( $value ) && ( acf_strlen( $value ) > $field['maxlength'] ) ) {
/* translators: %d: the maximum number of characters */
return sprintf( __( 'Value must not exceed %d characters', 'secure-custom-fields' ), $field['maxlength'] );
}
Expand Down
32 changes: 32 additions & 0 deletions tests/php/includes/fields/test-class-acf-field-text.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,36 @@ public function test_get_rest_schema_casts_maxlength_to_int() {
$this->assertArrayHasKey( 'maxLength', $schema );
$this->assertSame( 25, $schema['maxLength'] ); // Should be int, not string.
}

/**
* Test validate_value with a non-scalar value and maxlength set.
*
* A crafted submission (e.g. `acf[field_key][]=x`) can deliver an array to a
* text field. The maxlength check must not run a string operation on it, which
* would emit an "Array to string conversion" warning.
*/
public function test_validate_value_array_with_maxlength_does_not_convert() {
$field = $this->get_field( array( 'maxlength' => 10 ) );

$caught = null;
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler -- Capturing the conversion notice deterministically for this regression test.
set_error_handler(
static function ( $errno, $errstr ) use ( &$caught ) {
if ( false !== strpos( $errstr, 'Array to string conversion' ) ) {
$caught = $errstr;
}
return true;
}
);

try {
$valid = $this->field_instance->validate_value( true, array( 'x' ), $field, 'acf[field_text_test]' );
} finally {
restore_error_handler();
}

$this->assertNull( $caught, 'maxlength check must not trigger an array-to-string conversion' );
// A non-scalar value is not valid text, so the passed $valid state is preserved.
$this->assertTrue( $valid );
}
}
32 changes: 32 additions & 0 deletions tests/php/includes/fields/test-class-acf-field-textarea.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,36 @@ public function test_get_rest_schema() {
$this->assertIsArray( $schema );
$this->assertContains( 'string', $schema['type'] );
}

/**
* Test validate_value with a non-scalar value and maxlength set.
*
* A crafted submission (e.g. `acf[field_key][]=x`) can deliver an array to a
* textarea field. The maxlength check must not run a string operation on it,
* which would emit an "Array to string conversion" warning.
*/
public function test_validate_value_array_with_maxlength_does_not_convert() {
$field = $this->get_field( array( 'maxlength' => 10 ) );

$caught = null;
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler -- Capturing the conversion notice deterministically for this regression test.
set_error_handler(
static function ( $errno, $errstr ) use ( &$caught ) {
if ( false !== strpos( $errstr, 'Array to string conversion' ) ) {
$caught = $errstr;
}
return true;
}
);

try {
$valid = $this->field_instance->validate_value( true, array( 'x' ), $field, 'acf[field_textarea_test]' );
} finally {
restore_error_handler();
}

$this->assertNull( $caught, 'maxlength check must not trigger an array-to-string conversion' );
// A non-scalar value is not valid text, so the passed $valid state is preserved.
$this->assertTrue( $valid );
}
}
Loading