diff --git a/src/evo/netinfo.h b/src/evo/netinfo.h index 3ea51992b79e..28d92364481b 100644 --- a/src/evo/netinfo.h +++ b/src/evo/netinfo.h @@ -195,13 +195,13 @@ class NetInfoEntry public: NetInfoEntry() = default; - NetInfoEntry(const DomainPort& domain) + explicit NetInfoEntry(const DomainPort& domain) { if (!domain.IsValid()) return; m_type = NetInfoType::Domain; m_data = domain; } - NetInfoEntry(const CService& service) + explicit NetInfoEntry(const CService& service) { if (!service.IsValid()) return; m_type = NetInfoType::Service; diff --git a/src/wallet/bip39.cpp b/src/wallet/bip39.cpp index 40d7fd0b70d9..39b4f244975c 100644 --- a/src/wallet/bip39.cpp +++ b/src/wallet/bip39.cpp @@ -96,12 +96,11 @@ bool CMnemonic::Check(const SecureString& mnemonic) SecureString ssCurrentWord; SecureVector bits(32 + 1); - - uint32_t ki, nBitsCount{}; + uint32_t nBitsCount{}; for (size_t i = 0; i < mnemonic.size(); ++i) { - ssCurrentWord = ""; + ssCurrentWord.resize(0); // we resize ssCurrentWord instead recreating to avoid new allocations while (i + ssCurrentWord.size() < mnemonic.size() && mnemonic[i + ssCurrentWord.size()] != ' ') { if (ssCurrentWord.size() >= 9) { return false; @@ -115,7 +114,7 @@ bool CMnemonic::Check(const SecureString& mnemonic) return false; } if (ssCurrentWord == wordlist[nWordIndex]) { // word found on index nWordIndex - for (ki = 0; ki < 11; ki++) { + for (uint32_t ki = 0; ki < 11; ki++) { if (nWordIndex & (1 << (10 - ki))) { bits[nBitsCount / 8] |= 1 << (7 - (nBitsCount % 8)); } diff --git a/test/lint/all-lint.py b/test/lint/all-lint.py index 40274fcc41e4..e8d7299f2a1d 100755 --- a/test/lint/all-lint.py +++ b/test/lint/all-lint.py @@ -15,7 +15,7 @@ exit_code = 0 mod_path = Path(__file__).parent -lints = glob(f"{mod_path}/lint-*") +lints = glob(f"{mod_path}/lint-*.py") if which("parallel") and which("column"): logfile = "parallel_out.log" command = ["parallel", "--jobs", "100%", "--will-cite", "--joblog", logfile, ":::"] + lints diff --git a/test/lint/lint-cppcheck-dash.py b/test/lint/lint-cppcheck-dash.py new file mode 100755 index 000000000000..798d1fb48e14 --- /dev/null +++ b/test/lint/lint-cppcheck-dash.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2019 The Bitcoin Core developers +# Copyright (c) 2025 The Dash Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# +# Run cppcheck for dash specific files + +import multiprocessing +import os +import re +import subprocess +import sys + +os.environ['LC_ALL'] = 'C' + +ENABLED_CHECKS = ( + "Class '.*' has a constructor with 1 argument that is not explicit.", + "Struct '.*' has a constructor with 1 argument that is not explicit.", + "Function parameter '.*' should be passed by const reference.", + "Comparison of modulo result is predetermined", + "Local variable '.*' shadows outer argument", + "Redundant initialization for '.*'. The initialized value is overwritten before it is read.", + "Dereferencing '.*' after it is deallocated / released", + "The scope of the variable '.*' can be reduced.", + "Parameter '.*' can be declared with const", + "Variable '.*' can be declared with const", + "Variable '.*' is assigned a value that is never used.", + "Unused variable", + "The function '.*' overrides a function in a base class but is not marked with a 'override' specifier.", + # Enable to catch all warnings + # ".*", +) + +IGNORED_WARNINGS = ( + "src/bls/bls.h:.* Struct 'CBLSIdImplicit' has a constructor with 1 argument that is not explicit.", + "src/rpc/masternode.cpp:.*:21: warning: Consider using std::copy algorithm instead of a raw loop.", # UniValue doesn't support std::copy + "src/cachemultimap.h:.*: warning: Variable 'mapIt' can be declared as reference to const", + "src/evo/simplifiedmns.cpp:.*:20: warning: Consider using std::copy algorithm instead of a raw loop.", + "src/llmq/commitment.cpp.* warning: Consider using std::all_of or std::none_of algorithm instead of a raw loop. [useStlAlgorithm]", + "src/rpc/.*cpp:.*: note: Function pointer used here.", + "src/masternode/sync.cpp:.*: warning: Variable 'pnode' can be declared as pointer to const [constVariableReference]", + "src/wallet/bip39.cpp.*: warning: The scope of the variable 'ssCurrentWord' can be reduced. [variableScope]", + "src/.*:.*: warning: Local variable '_' shadows outer function [shadowFunction]", + + "src/stacktraces.cpp:.*: .*: Parameter 'info' can be declared as pointer to const", + "src/stacktraces.cpp:.*: note: You might need to cast the function pointer here", + + "[note|warning]: Return value 'state.Invalid(.*)' is always false", + "note: Calling function 'Invalid' returns 0", + "note: Shadow variable", + + # General catchall, for some reason any value named 'hash' is viewed as never used. + "Variable 'hash' is assigned a value that is never used.", + + # The following can be useful to ignore when the catch all is used + # "Consider performing initialization in initialization list.", + "Consider using std::transform algorithm instead of a raw loop.", + "Consider using std::accumulate algorithm instead of a raw loop.", + "Consider using std::any_of algorithm instead of a raw loop.", + "Consider using std::copy_if algorithm instead of a raw loop.", + # "Consider using std::count_if algorithm instead of a raw loop.", + # "Consider using std::find_if algorithm instead of a raw loop.", + # "Member variable '.*' is not initialized in the constructor.", + + "unusedFunction", + "unknownMacro", + "unusedStructMember", +) + +def main(): + warnings = [] + exit_code = 0 + + try: + subprocess.check_output(['cppcheck', '--version']) + except FileNotFoundError: + print("Skipping cppcheck linting since cppcheck is not installed.") + sys.exit(0) + + with open('test/util/data/non-backported.txt', 'r', encoding='utf-8') as f: + patterns = [line.strip() for line in f if line.strip()] + + files_output = subprocess.check_output(['git', 'ls-files', '--'] + patterns, universal_newlines=True, encoding="utf8") + files = [f.strip() for f in files_output.splitlines() if f.strip()] + + enabled_regexp = '|'.join(ENABLED_CHECKS) + ignored_regexp = '|'.join(IGNORED_WARNINGS) + files_regexp = '|'.join(re.escape(f) for f in files) + + script_dir = os.path.dirname(os.path.abspath(__file__)) + cache_dir = os.environ.get('CACHE_DIR') + if cache_dir: + cppcheck_dir = os.path.join(cache_dir, 'cppcheck') + else: + cppcheck_dir = os.path.join(script_dir, '.cppcheck') + os.makedirs(cppcheck_dir, exist_ok=True) + + cppcheck_cmd = [ + 'cppcheck', + '--enable=all', + '--inline-suppr', + '--suppress=missingIncludeSystem', + f'--cppcheck-build-dir={cppcheck_dir}', + '-j', str(multiprocessing.cpu_count()), + '--language=c++', + '--std=c++20', + '--template=gcc', + '-D__cplusplus', + '-DENABLE_WALLET', + '-DCLIENT_VERSION_BUILD', + '-DCLIENT_VERSION_IS_RELEASE', + '-DCLIENT_VERSION_MAJOR', + '-DCLIENT_VERSION_MINOR', + '-DCOPYRIGHT_YEAR', + '-DDEBUG', + '-DUSE_EPOLL', + '-DCHAR_BIT=8', + '-I', 'src/', + '-q', + ] + files + + dependencies_output = subprocess.run( + cppcheck_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + ) + + unique_sorted_lines = sorted(set(dependencies_output.stdout.splitlines())) + for line in unique_sorted_lines: + if re.search(enabled_regexp, line) and not re.search(ignored_regexp, line) and re.search(files_regexp, line): + warnings.append(line) + + if warnings: + print('\n'.join(warnings)) + print() + print("Advice not applicable in this specific case? Add an exception by updating") + print(f"IGNORED_WARNINGS in {__file__}") + # Uncomment to enforce the linter / comment to run locally + exit_code = 1 + + sys.exit(exit_code) + +if __name__ == "__main__": + main() diff --git a/test/lint/lint-cppcheck-dash.sh b/test/lint/lint-cppcheck-dash.sh deleted file mode 100755 index c396142abff3..000000000000 --- a/test/lint/lint-cppcheck-dash.sh +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2019 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -# - -export LC_ALL=C - -ENABLED_CHECKS=( - "Class '.*' has a constructor with 1 argument that is not explicit." - "Struct '.*' has a constructor with 1 argument that is not explicit." - "Function parameter '.*' should be passed by const reference." - "Comparison of modulo result is predetermined" - "Local variable '.*' shadows outer argument" - "Redundant initialization for '.*'. The initialized value is overwritten before it is read." - "Dereferencing '.*' after it is deallocated / released" - "The scope of the variable '.*' can be reduced." - "Parameter '.*' can be declared with const" - "Variable '.*' can be declared with const" - "Variable '.*' is assigned a value that is never used." - "Unused variable" - "The function '.*' overrides a function in a base class but is not marked with a 'override' specifier." -# Enable to catch all warnings - ".*" -) - -IGNORED_WARNINGS=( - "src/bls/bls.h:.* Struct 'CBLSIdImplicit' has a constructor with 1 argument that is not explicit." - "src/rpc/masternode.cpp:.*:21: warning: Consider using std::copy algorithm instead of a raw loop." # UniValue doesn't support std::copy - "src/cachemultimap.h:.*: warning: Variable 'mapIt' can be declared as reference to const" - "src/evo/simplifiedmns.cpp:.*:20: warning: Consider using std::copy algorithm instead of a raw loop." - "src/llmq/commitment.cpp.* warning: Consider using std::all_of or std::none_of algorithm instead of a raw loop. \[useStlAlgorithm\]" - "src/rpc/.*cpp:.*: note: Function pointer used here." - "src/masternode/sync.cpp:.*: warning: Variable 'pnode' can be declared as pointer to const \[constVariableReference\]" - "src/wallet/bip39.cpp.*: warning: The scope of the variable 'ssCurrentWord' can be reduced. \[variableScope\]" - "src/.*:.*: warning: Local variable '_' shadows outer function \[shadowFunction\]" - - "src/stacktraces.cpp:.*: .*: Parameter 'info' can be declared as pointer to const" - "src/stacktraces.cpp:.*: note: You might need to cast the function pointer here" - - "[note|warning]: Return value 'state.Invalid(.*)' is always false" - "note: Calling function 'Invalid' returns 0" - "note: Shadow variable" - -# General catchall, for some reason any value named 'hash' is viewed as never used. - "Variable 'hash' is assigned a value that is never used." - -# The following can be useful to ignore when the catch all is used -# "Consider performing initialization in initialization list." - "Consider using std::transform algorithm instead of a raw loop." - "Consider using std::accumulate algorithm instead of a raw loop." - "Consider using std::any_of algorithm instead of a raw loop." - "Consider using std::copy_if algorithm instead of a raw loop." -# "Consider using std::count_if algorithm instead of a raw loop." -# "Consider using std::find_if algorithm instead of a raw loop." -# "Member variable '.*' is not initialized in the constructor." - - "unusedFunction" - "unknownMacro" - "unusedStructMember" -) - -# We should attempt to update this with all dash specific code -# shellcheck disable=SC2046 -FILES=$(git ls-files -- $(cat test/util/data/non-backported.txt)) - - -if ! command -v cppcheck > /dev/null; then - echo "Skipping cppcheck linting since cppcheck is not installed." - exit 0 -fi - -function join_array { - local IFS="$1" - shift - echo "$*" -} - -ENABLED_CHECKS_REGEXP=$(join_array "|" "${ENABLED_CHECKS[@]}") -IGNORED_WARNINGS_REGEXP=$(join_array "|" "${IGNORED_WARNINGS[@]}") -FILES_REGEXP=$(join_array "|" "${FILES[@]}") -SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -# Check if CACHE_DIR is set and non-empty, otherwise use default .cppcheck/ directory -if [[ -n "$CACHE_DIR" ]]; then - CPPCHECK_DIR=$CACHE_DIR/cppcheck/ -else - CPPCHECK_DIR=$SCRIPT_DIR/.cppcheck/ -fi -if [ ! -d "$CPPCHECK_DIR" ] -then - mkdir -p "$CPPCHECK_DIR" -fi -WARNINGS=$(echo "${FILES}" | \ - xargs cppcheck --enable=all --inline-suppr --suppress=missingIncludeSystem --cppcheck-build-dir="$CPPCHECK_DIR" -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++20 --template=gcc -D__cplusplus -DENABLE_WALLET -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCOPYRIGHT_YEAR -DDEBUG -DUSE_EPOLL -DCHAR_BIT=8 -I src/ -q 2>&1 | sort -u | \ - grep -E "${ENABLED_CHECKS_REGEXP}" | \ - grep -vE "${IGNORED_WARNINGS_REGEXP}" | \ - grep -E "${FILES_REGEXP}") - -if [[ ${WARNINGS} != "" ]]; then - echo "${WARNINGS}" - echo - echo "Advice not applicable in this specific case? Add an exception by updating" - echo "IGNORED_WARNINGS in $0" - # Uncomment to enforce the linter / comment to run locally - exit 1 -fi -exit 0