diff --git a/jmespath/functions.py b/jmespath/functions.py index 627b569d..e0164689 100644 --- a/jmespath/functions.py +++ b/jmespath/functions.py @@ -212,6 +212,14 @@ def _func_to_number(self, arg): @signature({'types': ['array', 'string']}, {'types': []}) def _func_contains(self, subject, search): + # A non-string can never be a substring of a string. The array case + # already returns False for a non-matching search of any type, but + # ``search in subject`` raises TypeError when subject is a string and + # search is not, so guard it explicitly (spec: contains('foobar', 123) + # -> false). + if (isinstance(subject, STRING_TYPE) + and not isinstance(search, STRING_TYPE)): + return False return search in subject @signature({'types': ['string', 'array', 'object']}) diff --git a/tests/compliance/functions.json b/tests/compliance/functions.json index 7b554450..b1536f4f 100644 --- a/tests/compliance/functions.json +++ b/tests/compliance/functions.json @@ -115,6 +115,18 @@ "expression": "contains('abc', 'd')", "result": false }, + { + "expression": "contains('foobar', `123`)", + "result": false + }, + { + "expression": "contains('foobar', `true`)", + "result": false + }, + { + "expression": "contains('foobar', `null`)", + "result": false + }, { "expression": "contains(`false`, 'd')", "error": "invalid-type"