From 1aab13dca3e5226df2977add9d96214084bcc298 Mon Sep 17 00:00:00 2001 From: xiehuanyi <74809554+xiehuanyi@users.noreply.github.com> Date: Sat, 10 Oct 2026 14:30:36 +0300 Subject: [PATCH] Reject trailing newlines in MAC addresses and regional identifiers --- src/validators/i18n/fi.py | 4 ++-- src/validators/i18n/fr.py | 2 +- src/validators/i18n/ind.py | 2 +- src/validators/mac_address.py | 2 +- tests/test_complete_values.py | 31 +++++++++++++++++++++++++++++++ 5 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 tests/test_complete_values.py diff --git a/src/validators/i18n/fi.py b/src/validators/i18n/fi.py index 534d7dc2..12fb281b 100644 --- a/src/validators/i18n/fi.py +++ b/src/validators/i18n/fi.py @@ -54,7 +54,7 @@ def fi_business_id(value: str, /): """ if not value: return False - if not re.match(_business_id_pattern(), value): + if not re.fullmatch(_business_id_pattern(), value): return False factors = [7, 9, 10, 5, 8, 4, 2] numbers = map(int, value[:7]) @@ -92,7 +92,7 @@ def fi_ssn(value: str, /, *, allow_temporal_ssn: bool = True): if not value: return False ssn_check_marks = "0123456789ABCDEFHJKLMNPRSTUVWXY" - if not (result := re.match(_ssn_pattern(ssn_check_marks), value)): + if not (result := re.fullmatch(_ssn_pattern(ssn_check_marks), value)): return False gd = result.groupdict() checksum = int(gd["date"] + gd["serial"]) diff --git a/src/validators/i18n/fr.py b/src/validators/i18n/fr.py index 10a5a2b1..e7c29332 100644 --- a/src/validators/i18n/fr.py +++ b/src/validators/i18n/fr.py @@ -93,7 +93,7 @@ def fr_ssn(value: str): """ if not value: return False - matched = re.match(_ssn_pattern(), value) + matched = re.fullmatch(_ssn_pattern(), value) if not matched: return False groups = list(matched.groups()) diff --git a/src/validators/i18n/ind.py b/src/validators/i18n/ind.py index 6ec973ea..29a58e2d 100644 --- a/src/validators/i18n/ind.py +++ b/src/validators/i18n/ind.py @@ -24,7 +24,7 @@ def ind_aadhar(value: str): (Literal[True]): If `value` is a valid aadhar card number. (ValidationError): If `value` is an invalid aadhar card number. """ - return re.match(r"^[2-9]{1}\d{3}\s\d{4}\s\d{4}$", value) + return re.fullmatch(r"^[2-9]{1}\d{3}\s\d{4}\s\d{4}$", value) @validator diff --git a/src/validators/mac_address.py b/src/validators/mac_address.py index 59542606..0173d9e8 100644 --- a/src/validators/mac_address.py +++ b/src/validators/mac_address.py @@ -33,4 +33,4 @@ def mac_address(value: str, /): if ":" in value and "-" in value: return False - return re.match(r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$", value) if value else False + return re.fullmatch(r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$", value) if value else False diff --git a/tests/test_complete_values.py b/tests/test_complete_values.py new file mode 100644 index 00000000..8e1589a7 --- /dev/null +++ b/tests/test_complete_values.py @@ -0,0 +1,31 @@ +"""Validate complete MAC addresses and regional identifiers.""" + +from typing import Callable + +import pytest + +from validators import ValidationError, mac_address +from validators.i18n.fi import fi_business_id, fi_ssn +from validators.i18n.fr import fr_ssn +from validators.i18n.ind import ind_aadhar + + +@pytest.mark.parametrize( + "validate,value", + [ + (mac_address, "01:23:45:67:ab:CD"), + (mac_address, "01-23-45-67-ab-CD"), + (fi_business_id, "0112038-9"), + (fi_ssn, "010101-0101"), + (fr_ssn, "1 84 12 76 451 089 46"), + (fr_ssn, "1 84 12 76 451 089"), + (ind_aadhar, "3675 9834 6015"), + ], +) +@pytest.mark.parametrize("suffix", ["", "\n", "\r\n", " ", "\nextra"]) +def test_complete_identifier(validate: Callable[[str], object], value: str, suffix: str): + """Accept the identifier alone and reject any trailing characters.""" + if suffix: + assert isinstance(validate(value + suffix), ValidationError) + else: + assert validate(value) is True