aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xtest/lint/lint-format-strings.py98
-rwxr-xr-xtest/lint/lint-format-strings.sh44
2 files changed, 98 insertions, 44 deletions
diff --git a/test/lint/lint-format-strings.py b/test/lint/lint-format-strings.py
new file mode 100755
index 0000000000..5a36da11fd
--- /dev/null
+++ b/test/lint/lint-format-strings.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2018-2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#
+
+"""
+Lint format strings: This program checks that the number of arguments passed
+to a variadic format string function matches the number of format specifiers
+in the format string.
+"""
+
+import subprocess
+import re
+import sys
+
+FUNCTION_NAMES_AND_NUMBER_OF_LEADING_ARGUMENTS = [
+ 'FatalError,0',
+ 'fprintf,1',
+ 'tfm::format,1', # Assuming tfm::::format(std::ostream&, ...
+ 'LogConnectFailure,1',
+ 'LogPrint,1',
+ 'LogPrintf,0',
+ 'printf,0',
+ 'snprintf,2',
+ 'sprintf,1',
+ 'strprintf,0',
+ 'vfprintf,1',
+ 'vprintf,1',
+ 'vsnprintf,1',
+ 'vsprintf,1',
+ 'WalletLogPrintf,0',
+]
+RUN_LINT_FILE = 'test/lint/run-lint-format-strings.py'
+
+def check_doctest():
+ command = [
+ 'python3',
+ '-m',
+ 'doctest',
+ RUN_LINT_FILE,
+ ]
+ try:
+ subprocess.run(command, check = True)
+ except subprocess.CalledProcessError:
+ sys.exit(1)
+
+def get_matching_files(function_name):
+ command = [
+ 'git',
+ 'grep',
+ '--full-name',
+ '-l',
+ function_name,
+ '--',
+ '*.c',
+ '*.cpp',
+ '*.h',
+ ]
+ try:
+ return subprocess.check_output(command, stderr = subprocess.STDOUT).decode('utf-8').splitlines()
+ except subprocess.CalledProcessError as e:
+ if e.returncode > 1: # return code is 1 when match is empty
+ print(e.output.decode('utf-8'), end='')
+ sys.exit(1)
+ return []
+
+def main():
+ exit_code = 0
+ check_doctest()
+ for s in FUNCTION_NAMES_AND_NUMBER_OF_LEADING_ARGUMENTS:
+ function_name, skip_arguments = s.split(',')
+ matching_files = get_matching_files(function_name)
+
+ matching_files_filtered = []
+ for matching_file in matching_files:
+ if not re.search('^src/(leveldb|secp256k1|minisketch|tinyformat|univalue|test/fuzz/strprintf.cpp)', matching_file):
+ matching_files_filtered.append(matching_file)
+ matching_files_filtered.sort()
+
+ run_lint_args = [
+ RUN_LINT_FILE,
+ '--skip-arguments',
+ skip_arguments,
+ function_name,
+ ]
+ run_lint_args.extend(matching_files_filtered)
+
+ try:
+ subprocess.run(run_lint_args, check = True)
+ except subprocess.CalledProcessError:
+ exit_code = 1
+
+ sys.exit(exit_code)
+
+if __name__ == '__main__':
+ main()
diff --git a/test/lint/lint-format-strings.sh b/test/lint/lint-format-strings.sh
deleted file mode 100755
index 73730f16b3..0000000000
--- a/test/lint/lint-format-strings.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright (c) 2018-2020 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#
-# Lint format strings: This program checks that the number of arguments passed
-# to a variadic format string function matches the number of format specifiers
-# in the format string.
-
-export LC_ALL=C
-
-FUNCTION_NAMES_AND_NUMBER_OF_LEADING_ARGUMENTS=(
- "FatalError,0"
- "fprintf,1"
- "tfm::format,1" # Assuming tfm::::format(std::ostream&, ...
- "LogConnectFailure,1"
- "LogPrint,1"
- "LogPrintf,0"
- "printf,0"
- "snprintf,2"
- "sprintf,1"
- "strprintf,0"
- "vfprintf,1"
- "vprintf,1"
- "vsnprintf,1"
- "vsprintf,1"
- "WalletLogPrintf,0"
-)
-
-EXIT_CODE=0
-if ! python3 -m doctest "test/lint/run-lint-format-strings.py"; then
- EXIT_CODE=1
-fi
-for S in "${FUNCTION_NAMES_AND_NUMBER_OF_LEADING_ARGUMENTS[@]}"; do
- IFS="," read -r FUNCTION_NAME SKIP_ARGUMENTS <<< "${S}"
- for MATCHING_FILE in $(git grep --full-name -l "${FUNCTION_NAME}" -- "*.c" "*.cpp" "*.h" | sort | grep -vE "^src/(leveldb|secp256k1|minisketch|tinyformat|univalue|test/fuzz/strprintf.cpp)"); do
- MATCHING_FILES+=("${MATCHING_FILE}")
- done
- if ! "test/lint/run-lint-format-strings.py" --skip-arguments "${SKIP_ARGUMENTS}" "${FUNCTION_NAME}" "${MATCHING_FILES[@]}"; then
- EXIT_CODE=1
- fi
-done
-exit ${EXIT_CODE}