diff options
author | Ryan Ofsky <ryan@ofsky.org> | 2023-03-23 10:29:35 -0400 |
---|---|---|
committer | Ryan Ofsky <ryan@ofsky.org> | 2023-04-21 06:53:23 -0400 |
commit | 398c3719b02197ad92fded20f6ff83b364747297 (patch) | |
tree | efaea4b0c9c5befe6bd0968cfef714e122d457ee /test/lint/run-lint-format-strings.py | |
parent | c63c8a159060e5ab1e896aa6808602bcc55eae29 (diff) | |
download | bitcoin-398c3719b02197ad92fded20f6ff83b364747297.tar.xz |
lint: Fix lint-format-strings false positives when format specifiers have argument positions
Do not error on valid format specifications like strprintf("arg2=%2$s arg1=%1$s arg2=%2$s", arg1, arg2);
Needed to avoid lint error in upcoming commit: https://cirrus-ci.com/task/4755032734695424?logs=lint#L221
Additionally tested with python -m doctest test/lint/run-lint-format-strings.py
Diffstat (limited to 'test/lint/run-lint-format-strings.py')
-rwxr-xr-x | test/lint/run-lint-format-strings.py | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/test/lint/run-lint-format-strings.py b/test/lint/run-lint-format-strings.py index 91915f05f9..d1896dba84 100755 --- a/test/lint/run-lint-format-strings.py +++ b/test/lint/run-lint-format-strings.py @@ -241,20 +241,32 @@ def count_format_specifiers(format_string): 3 >>> count_format_specifiers("foo %d bar %i foo %% foo %*d foo") 4 + >>> count_format_specifiers("foo %5$d") + 5 + >>> count_format_specifiers("foo %5$*7$d") + 7 """ assert type(format_string) is str format_string = format_string.replace('%%', 'X') - n = 0 - in_specifier = False - for i, char in enumerate(format_string): - if char == "%": - in_specifier = True + n = max_pos = 0 + for m in re.finditer("%(.*?)[aAcdeEfFgGinopsuxX]", format_string, re.DOTALL): + # Increase the max position if the argument has a position number like + # "5$", otherwise increment the argument count. + pos_num, = re.match(r"(?:(^\d+)\$)?", m.group(1)).groups() + if pos_num is not None: + max_pos = max(max_pos, int(pos_num)) + else: n += 1 - elif char in "aAcdeEfFgGinopsuxX": - in_specifier = False - elif in_specifier and char == "*": + + # Increase the max position if there is a "*" width argument with a + # position like "*7$", and increment the argument count if there is a + # "*" width argument with no position. + star, star_pos_num = re.match(r"(?:.*?(\*(?:(\d+)\$)?)|)", m.group(1)).groups() + if star_pos_num is not None: + max_pos = max(max_pos, int(star_pos_num)) + elif star is not None: n += 1 - return n + return max(n, max_pos) def main(): |