From 83e28324e1a0ce3970dd854393d2431123a909d3 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Tue, 12 Mar 2024 23:38:54 +0900 Subject: [PATCH] Remove format function The format function allowed too arbitrary access to the values being formatted, and this behavior caused information leakage in some cases. Closes-Bug: #2048114 Change-Id: Id7ec5f267314bb7166ca64802ab47d768bb5eb89 --- .../notes/bug-2048114-0968eea052838381.yaml | 12 +++++++ yaql/standard_library/strings.py | 33 ------------------- yaql/tests/test_regex.py | 7 ++-- yaql/tests/test_strings.py | 4 --- 4 files changed, 16 insertions(+), 40 deletions(-) create mode 100644 releasenotes/notes/bug-2048114-0968eea052838381.yaml diff --git a/releasenotes/notes/bug-2048114-0968eea052838381.yaml b/releasenotes/notes/bug-2048114-0968eea052838381.yaml new file mode 100644 index 0000000..732bcba --- /dev/null +++ b/releasenotes/notes/bug-2048114-0968eea052838381.yaml @@ -0,0 +1,12 @@ +--- +upgrade: + - | + The format YAQL function has been removed, because of its vulnability. See + the security section to find more details. + +security: + - | + ``_: The format YAQL + function has been removed, because it allowed too arbitrary data access + which results in data leak. Users can replace the format function by + ``+`` operator and ``str`` YAQL function. diff --git a/yaql/standard_library/strings.py b/yaql/standard_library/strings.py index 084c699..eadc62b 100644 --- a/yaql/standard_library/strings.py +++ b/yaql/standard_library/strings.py @@ -564,38 +564,6 @@ def replace_with_dict(string, str_func, replacements, count=-1): return string -@specs.parameter('__format_string', yaqltypes.String()) -@specs.extension_method -def format_(__format_string, *args, **kwargs): - """:yaql:format - - Returns a string formatted with positional and keyword arguments. - - :signature: string.format([args], {kwargs}) - :receiverArg string: input string for formatting. Can be passed only as - first positional argument if used as a function. Can contain literal - text or replacement fields marked by braces {}. Every replacement field - should contain either the numeric index of a positional argument or the - name of a keyword argument - :argType string: string - :arg [args]: values for replacements for numeric markers - :argType [args]: chain of strings - :arg {kwargs}: values for keyword replacements - :argType {kwargs}: chain of key-value arguments, where values are strings - :returnValue: string - - .. code:: - - yaql> "abc{0}ab{1}abc".format(" ", ",") - "abc ab,abc" - yaql> "abc{foo}ab{bar}abc".format(foo => " ", bar => ",") - "abc ab,abc" - yaql> format("abc{0}ab{foo}abc", ' ', foo => ",") - "abc ab,abc" - """ - return __format_string.format(*args, **kwargs) - - @specs.parameter('left', yaqltypes.String()) @specs.parameter('right', int) @specs.name('#operator_*') @@ -1045,7 +1013,6 @@ def register(context): context.register_function(trim_right) context.register_function(replace) context.register_function(replace_with_dict) - context.register_function(format_) context.register_function(is_empty) context.register_function(string_by_int) context.register_function(int_by_string) diff --git a/yaql/tests/test_regex.py b/yaql/tests/test_regex.py index 9495326..0234456 100644 --- a/yaql/tests/test_regex.py +++ b/yaql/tests/test_regex.py @@ -50,9 +50,10 @@ class TestRegex(yaql.tests.TestCase): '24.16 = 24(2-4) + 16(5-7)', self.eval( r"regex(`(\d+)\.?(\d+)?`).search("r"'aa24.16bb', " - r"format('{0} = {1}({2}-{3}) + {4}({5}-{6})', " - r"$.value, $2.value, $2.start, $2.end, " - r"$3.value, $3.start, $3.end))")) + r"$.value + ' = ' + " + r"$2.value + '(' + str($2.start) + '-' + str($2.end) + ') + ' " + r"+ $3.value + '(' + str($3.start) + '-' + str($3.end) + ')')" + )) def test_search_all(self): self.assertEqual( diff --git a/yaql/tests/test_strings.py b/yaql/tests/test_strings.py index 4af8812..e631049 100644 --- a/yaql/tests/test_strings.py +++ b/yaql/tests/test_strings.py @@ -118,10 +118,6 @@ class TestStrings(yaql.tests.TestCase): def test_concat_func(self): self.assertEqual('abc', self.eval("concat(a, b, c)")) - def test_format(self): - self.assertEqual('a->b', self.eval("'{0}->{x}'.format(a, x => b)")) - self.assertEqual('a->b', self.eval("format('{0}->{x}', a, x => b)")) - def test_trim(self): self.assertEqual('x', self.eval("' x '.trim()")) self.assertEqual('x', self.eval("'abxba'.trim(ab)"))