Changeset View
Changeset View
Standalone View
Standalone View
test/lint/lint-format-strings.py
Show First 20 Lines • Show All 214 Lines • ▼ Show 20 Lines | for i, char in enumerate(format_string): | ||||
n += 1 | n += 1 | ||||
elif char in "aAcdeEfFgGinopsuxX": | elif char in "aAcdeEfFgGinopsuxX": | ||||
in_specifier = False | in_specifier = False | ||||
elif in_specifier and char == "*": | elif in_specifier and char == "*": | ||||
n += 1 | n += 1 | ||||
return n | return n | ||||
def main(): | def main(args_in): | ||||
""" Return a string output with information on string format errors | |||||
>>> main(["printit", "test/lint/lint-format-strings-tests.txt"]) | |||||
0 | |||||
>>> main(["printme", "test/lint/lint-format-strings-tests.txt"]) | |||||
test/lint/lint-format-strings-tests.txt: Expected 1 argument(s) after format string but found 2 argument(s): printme("%d", 1, 2) | |||||
test/lint/lint-format-strings-tests.txt: Expected 2 argument(s) after format string but found 3 argument(s): printme("%a %b", 1, 2, "anything") | |||||
test/lint/lint-format-strings-tests.txt: Expected 1 argument(s) after format string but found 0 argument(s): printme("%d") | |||||
test/lint/lint-format-strings-tests.txt: Expected 3 argument(s) after format string but found 2 argument(s): printme("%a%b%z", 1, "anything") | |||||
1 | |||||
>>> main(["printme", "test/lint/lint-format-strings-tests-skip-arguments.txt"]) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 2 argument(s): printme(skipped, "%d", 1) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 4 argument(s): printme(skipped, "%a%b%z", 1, "anything", 3) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 3 argument(s): printme(skipped, "%d", 1, 2) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 1 argument(s): printme(skipped, "%d") | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 3 argument(s): printme(skip1, skip2, "%d", 1) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 5 argument(s): printme(skip1, skip2, "%a%b%z", 1, "anything", 3) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 4 argument(s): printme(skip1, skip2, "%d", 1, 2) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 2 argument(s): printme(skip1, skip2, "%d") | |||||
1 | |||||
>>> main(["--skip-arguments=1", "printme", "test/lint/lint-format-strings-tests-skip-arguments.txt"]) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 1 argument(s) after format string but found 2 argument(s): printme(skipped, "%d", 1, 2) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 1 argument(s) after format string but found 0 argument(s): printme(skipped, "%d") | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 2 argument(s): printme(skip1, skip2, "%d", 1) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 4 argument(s): printme(skip1, skip2, "%a%b%z", 1, "anything", 3) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 3 argument(s): printme(skip1, skip2, "%d", 1, 2) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 1 argument(s): printme(skip1, skip2, "%d") | |||||
1 | |||||
>>> main(["--skip-arguments=2", "printme", "test/lint/lint-format-strings-tests-skip-arguments.txt"]) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 2 argument(s): printme(skipped, "%a%b%z", 1, "anything", 3) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 0 argument(s) after format string but found 1 argument(s): printme(skipped, "%d", 1, 2) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Could not parse function call string "printme(...)": printme(skipped, "%d") | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 1 argument(s) after format string but found 2 argument(s): printme(skip1, skip2, "%d", 1, 2) | |||||
test/lint/lint-format-strings-tests-skip-arguments.txt: Expected 1 argument(s) after format string but found 0 argument(s): printme(skip1, skip2, "%d") | |||||
1 | |||||
""" | |||||
parser = argparse.ArgumentParser(description="This program checks that the number of arguments passed " | parser = argparse.ArgumentParser(description="This program checks that the number of arguments passed " | ||||
"to a variadic format string function matches the number of format " | "to a variadic format string function matches the number of format " | ||||
"specifiers in the format string.") | "specifiers in the format string.") | ||||
parser.add_argument("--skip-arguments", type=int, help="number of arguments before the format string " | parser.add_argument("--skip-arguments", type=int, help="number of arguments before the format string " | ||||
"argument (e.g. 1 in the case of fprintf)", default=0) | "argument (e.g. 1 in the case of fprintf)", default=0) | ||||
parser.add_argument( | parser.add_argument( | ||||
"function_name", help="function name (e.g. fprintf)", default=None) | "function_name", help="function name (e.g. fprintf)", default=None) | ||||
parser.add_argument("file", type=argparse.FileType( | parser.add_argument("file", type=argparse.FileType( | ||||
"r", encoding="utf-8"), nargs="*", help="C++ source code file (e.g. foo.cpp)") | "r", encoding="utf-8"), nargs="*", help="C++ source code file (e.g. foo.cpp)") | ||||
args = parser.parse_args() | args = parser.parse_args(args_in) | ||||
exit_code = 0 | exit_code = 0 | ||||
for f in args.file: | for f in args.file: | ||||
for function_call_str in parse_function_calls(args.function_name, f.read()): | for function_call_str in parse_function_calls(args.function_name, f.read()): | ||||
parts = parse_function_call_and_arguments( | parts = parse_function_call_and_arguments( | ||||
args.function_name, function_call_str) | args.function_name, function_call_str) | ||||
relevant_function_call_str = unescape("".join(parts))[:512] | relevant_function_call_str = unescape("".join(parts))[:512] | ||||
if (f.name, relevant_function_call_str) in FALSE_POSITIVES: | if (f.name, relevant_function_call_str) in FALSE_POSITIVES: | ||||
continue | continue | ||||
if len(parts) < 3 + args.skip_arguments: | if len(parts) < 3 + args.skip_arguments: | ||||
exit_code = 1 | exit_code = 1 | ||||
print("{}: Could not parse function call string \"{}(...)\": {}".format( | print("{}: Could not parse function call string \"{}(...)\": {}".format( | ||||
f.name, args.function_name, relevant_function_call_str)) | f.name, args.function_name, relevant_function_call_str)) | ||||
continue | continue | ||||
argument_count = len(parts) - 3 - args.skip_arguments | argument_count = len(parts) - 3 - args.skip_arguments | ||||
format_str = parse_string_content(parts[1 + args.skip_arguments]) | format_str = parse_string_content(parts[1 + args.skip_arguments]) | ||||
format_specifier_count = count_format_specifiers(format_str) | format_specifier_count = count_format_specifiers(format_str) | ||||
if format_specifier_count != argument_count: | if format_specifier_count != argument_count: | ||||
exit_code = 1 | exit_code = 1 | ||||
print("{}: Expected {} argument(s) after format string but found {} argument(s): {}".format( | print("{}: Expected {} argument(s) after format string but found {} argument(s): {}".format( | ||||
f.name, format_specifier_count, argument_count, relevant_function_call_str)) | f.name, format_specifier_count, argument_count, relevant_function_call_str)) | ||||
continue | continue | ||||
sys.exit(exit_code) | return exit_code | ||||
if __name__ == "__main__": | if __name__ == "__main__": | ||||
main() | sys.exit(main(sys.argv[1:])) |