Skip to content

Commit 398c371

Browse files
committed
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
1 parent c63c8a1 commit 398c371

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

test/lint/run-lint-format-strings.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -241,20 +241,32 @@ def count_format_specifiers(format_string):
241241
3
242242
>>> count_format_specifiers("foo %d bar %i foo %% foo %*d foo")
243243
4
244+
>>> count_format_specifiers("foo %5$d")
245+
5
246+
>>> count_format_specifiers("foo %5$*7$d")
247+
7
244248
"""
245249
assert type(format_string) is str
246250
format_string = format_string.replace('%%', 'X')
247-
n = 0
248-
in_specifier = False
249-
for i, char in enumerate(format_string):
250-
if char == "%":
251-
in_specifier = True
251+
n = max_pos = 0
252+
for m in re.finditer("%(.*?)[aAcdeEfFgGinopsuxX]", format_string, re.DOTALL):
253+
# Increase the max position if the argument has a position number like
254+
# "5$", otherwise increment the argument count.
255+
pos_num, = re.match(r"(?:(^\d+)\$)?", m.group(1)).groups()
256+
if pos_num is not None:
257+
max_pos = max(max_pos, int(pos_num))
258+
else:
252259
n += 1
253-
elif char in "aAcdeEfFgGinopsuxX":
254-
in_specifier = False
255-
elif in_specifier and char == "*":
260+
261+
# Increase the max position if there is a "*" width argument with a
262+
# position like "*7$", and increment the argument count if there is a
263+
# "*" width argument with no position.
264+
star, star_pos_num = re.match(r"(?:.*?(\*(?:(\d+)\$)?)|)", m.group(1)).groups()
265+
if star_pos_num is not None:
266+
max_pos = max(max_pos, int(star_pos_num))
267+
elif star is not None:
256268
n += 1
257-
return n
269+
return max(n, max_pos)
258270

259271

260272
def main():

0 commit comments

Comments
 (0)