Issue #3379102 by phenaproxima, Wim Leers, borisson_: Add validation constraint to type: label + type: text: disallow control characters

merge-requests/4607/head
Lauri Eskola 2023-08-17 23:33:59 +03:00
parent ded815fbe0
commit 3a661cf7be
No known key found for this signature in database
GPG Key ID: 382FC0F5B0DF53F8
5 changed files with 104 additions and 8 deletions

View File

@ -64,13 +64,11 @@ label:
translatable: true
constraints:
Regex:
# Forbid any kind of line ending:
# - Windows: `\r\n`
# - old macOS: `\r`
# - *nix: `\n`
pattern: '/(\r\n|\r|\n)/'
# Forbid any kind of control character.
# @see https://stackoverflow.com/a/66587087
pattern: '/([^\PC])/u'
match: false
message: 'Labels are not allowed to span multiple lines.'
message: 'Labels are not allowed to span multiple lines or contain control characters.'
required_label:
type: label
@ -93,6 +91,18 @@ text:
type: string
label: 'Text'
translatable: true
constraints:
Regex:
# Disallow all control characters except for tabs (ASCII 9, 0x09) as well
# as carriage returns (ASCII 13, 0x0D) and line feeds (ASCII 10, 0x0A),
# which are used for line endings:
# - Windows: `\r\n`
# - old macOS: `\r`
# - *nix: `\n`
# @see https://stackoverflow.com/a/66587087
pattern: '/([^\PC\x09\x0a\x0d])/u'
match: false
message: 'Text is not allowed to contain control characters, only visible characters.'
# A UUID.
uuid:

View File

@ -86,7 +86,7 @@ class BlockValidationTest extends ConfigEntityValidationTestBase {
// key, it is impossible for the generic ::testLabelValidation()
// implementation in the base class to know at which property to expect a
// validation error. Hence it is hardcoded in this case.
$this->assertValidationErrors(['settings.label' => "Labels are not allowed to span multiple lines."]);
$this->assertValidationErrors(['settings.label' => "Labels are not allowed to span multiple lines or contain control characters."]);
}
}

View File

@ -119,6 +119,15 @@ views.field.numeric:
format_plural_string:
type: plural_label
label: 'Plural variants'
constraints:
Regex:
# Normally, labels cannot contain invisible control characters. In this particular
# case, an invisible character (ASCII 3, 0x03) is used to encode translation
# information, so carve out an exception for that only.
# @see \Drupal\views\Plugin\views\field\NumericField
pattern: '/([^\PC\x03])/u'
match: false
message: 'Labels are not allowed to span multiple lines or contain control characters.'
prefix:
type: label
label: 'Prefix'

View File

@ -318,7 +318,7 @@ abstract class ConfigEntityValidationTestBase extends KernelTestBase {
}
static::setLabel($this->entity, "Multi\nLine");
$this->assertValidationErrors([$this->entity->getEntityType()->getKey('label') => "Labels are not allowed to span multiple lines."]);
$this->assertValidationErrors([$this->entity->getEntityType()->getKey('label') => "Labels are not allowed to span multiple lines or contain control characters."]);
}
/**

View File

@ -72,4 +72,81 @@ class SimpleConfigValidationTest extends KernelTestBase {
$this->assertSame("'invalid_key' is not a supported key.", (string) $violations[0]->getMessage());
}
/**
* Data provider for ::testSpecialCharacters().
*
* @return array[]
* The test cases.
*/
public function providerSpecialCharacters(): array {
$data = [];
for ($code_point = 0; $code_point < 32; $code_point++) {
$data["label $code_point"] = [
'system.site',
'name',
mb_chr($code_point),
'Labels are not allowed to span multiple lines or contain control characters.',
];
$data["text $code_point"] = [
'system.maintenance',
'message',
mb_chr($code_point),
'Text is not allowed to contain control characters, only visible characters.',
];
}
// Line feeds (ASCII 10) and carriage returns (ASCII 13) are used to create
// new lines, so they are allowed in text data, along with tabs (ASCII 9).
$data['text 9'][3] = $data['text 10'][3] = $data['text 13'][3] = NULL;
// Ensure emoji are allowed.
$data['emoji in label'] = [
'system.site',
'name',
'😎',
NULL,
];
$data['emoji in text'] = [
'system.maintenance',
'message',
'🤓',
NULL,
];
return $data;
}
/**
* Tests that special characters are not allowed in labels or text data.
*
* @param string $config_name
* The name of the simple config to test with.
* @param string $property
* The config property in which to embed a control character.
* @param string $character
* A special character to embed.
* @param string|null $expected_error_message
* The expected validation error message, if any.
*
* @dataProvider providerSpecialCharacters
*/
public function testSpecialCharacters(string $config_name, string $property, string $character, ?string $expected_error_message): void {
$config = $this->config($config_name)
->set($property, "This has a special character: $character");
$violations = $this->container->get('config.typed')
->createFromNameAndData($config->getName(), $config->get())
->validate();
if ($expected_error_message === NULL) {
$this->assertCount(0, $violations);
}
else {
$code_point = mb_ord($character);
$this->assertCount(1, $violations, "Character $code_point did not raise a constraint violation.");
$this->assertSame($property, $violations[0]->getPropertyPath());
$this->assertSame($expected_error_message, (string) $violations[0]->getMessage());
}
}
}