From 90f62f3fdf3859130cd43bff5811aacf19d1617d Mon Sep 17 00:00:00 2001 From: Abhijeet Kasurde Date: Tue, 12 Aug 2025 08:01:26 -0700 Subject: [PATCH] regex: validate input before processing (#85629) * Validated user input for match_type before processing * added new match_type 'fullmatch' Signed-off-by: Abhijeet Kasurde --- changelogs/fragments/regex_test.yml | 4 ++++ lib/ansible/plugins/test/core.py | 5 +++- lib/ansible/plugins/test/regex.yml | 24 ++++++++++++++----- .../targets/test_core/tasks/main.yml | 12 ++++++++++ 4 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 changelogs/fragments/regex_test.yml diff --git a/changelogs/fragments/regex_test.yml b/changelogs/fragments/regex_test.yml new file mode 100644 index 00000000000..64ec5e358aa --- /dev/null +++ b/changelogs/fragments/regex_test.yml @@ -0,0 +1,4 @@ +--- +minor_changes: + - regex - Document the match_type fullmatch. + - regex - Ensure that match_type is one of match, fullmatch, or search (https://github.com/ansible/ansible/pull/85629). diff --git a/lib/ansible/plugins/test/core.py b/lib/ansible/plugins/test/core.py index 8bfa46d882d..33436ed2f7d 100644 --- a/lib/ansible/plugins/test/core.py +++ b/lib/ansible/plugins/test/core.py @@ -142,6 +142,9 @@ def regex(value='', pattern='', ignorecase=False, multiline=False, match_type='s This is likely only useful for `search` and `match` which already have their own filters. """ + valid_match_types = ('search', 'match', 'fullmatch') + if match_type not in valid_match_types: + raise errors.AnsibleTemplatePluginError(f"Invalid match_type specified. Expected one of: {', '.join(valid_match_types)}.", obj=match_type) value = to_text(value, errors='surrogate_or_strict') flags = 0 if ignorecase: @@ -149,7 +152,7 @@ def regex(value='', pattern='', ignorecase=False, multiline=False, match_type='s if multiline: flags |= re.M _re = re.compile(pattern, flags=flags) - return bool(getattr(_re, match_type, 'search')(value)) + return bool(getattr(_re, match_type)(value)) @accept_args_markers diff --git a/lib/ansible/plugins/test/regex.yml b/lib/ansible/plugins/test/regex.yml index d80ca850a2e..98f512cf3d5 100644 --- a/lib/ansible/plugins/test/regex.yml +++ b/lib/ansible/plugins/test/regex.yml @@ -3,7 +3,7 @@ DOCUMENTATION: author: Ansible Core short_description: Does string match regular expression from the start description: - - Compare string against regular expression using Python's match or search functions. + - Compare string against regular expression using Python's match, fullmatch or search functions. options: _input: description: String to match. @@ -22,14 +22,26 @@ DOCUMENTATION: type: boolean default: False match_type: - description: Decide which function to be used to do the matching. + description: + - Decide which function to be used to do the matching. type: string - choices: [match, search] + choices: [match, search, fullmatch] default: search -EXAMPLES: | - url: "https://example.com/users/foo/resources/bar" - foundmatch: url is regex("example\.com/\w+/foo") +EXAMPLES: + - name: check if string matches regex + assert: + that: + - 'url is regex("example\.com/\w+/foo")' + vars: + url: "https://example.com/users/foo/resources/bar" + + - name: check if string matches regex ignoring case + assert: + that: + - 'url is regex("EXAMPLE\.COM/\w+/foo", ignorecase=True)' + vars: + url: "https://Example.com/users/foo/resources/bar" RETURN: _value: diff --git a/test/integration/targets/test_core/tasks/main.yml b/test/integration/targets/test_core/tasks/main.yml index 0e173ac5c0a..dfbd844c22f 100644 --- a/test/integration/targets/test_core/tasks/main.yml +++ b/test/integration/targets/test_core/tasks/main.yml @@ -218,6 +218,18 @@ - "'hello' is not regex('.L')" - "'hello\nAnsible' is not regex('^Ansible')" +- name: Try regex test with an invalid match_type + set_fact: + result: "{{ '1.0' is regex('.l', match_type='invalid') }}" + ignore_errors: yes + register: regex_invalid_match_type + +- name: Assert regex test raises an error when a match_type is invalid + assert: + that: + - regex_invalid_match_type is failed + - "'Invalid match_type specified.' in regex_invalid_match_type.msg" + - name: Try version tests with bad operator set_fact: result: "{{ '1.0' is version('1.0', 'equals') }}"