mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-25 20:10:23 +09:00
ANDROID: Snapshot Mainline's version of checkpatch.pl
Nothing fancy here. Keeping full history is not required. `git checkout mainline/master -- scripts/checkpatch.pl` This may need to be done periodically. Bug: 316492624 Signed-off-by: Lee Jones <joneslee@google.com> Change-Id: I4c90b50197ca7277c59e96bf332ecf795c4f3d12
This commit is contained in:
committed by
Treehugger Robot
parent
9f6f0c1de5
commit
abea1cb16e
@@ -63,6 +63,7 @@ my $min_conf_desc_length = 4;
|
||||
my $spelling_file = "$D/spelling.txt";
|
||||
my $codespell = 0;
|
||||
my $codespellfile = "/usr/share/codespell/dictionary.txt";
|
||||
my $user_codespellfile = "";
|
||||
my $conststructsfile = "$D/const_structs.checkpatch";
|
||||
my $docsfile = "$D/../Documentation/dev-tools/checkpatch.rst";
|
||||
my $typedefsfile;
|
||||
@@ -73,6 +74,8 @@ my $git_command ='export LANGUAGE=en_US.UTF-8; git';
|
||||
my $tabsize = 8;
|
||||
my ${CONFIG_} = "CONFIG_";
|
||||
|
||||
my %maybe_linker_symbol; # for externs in c exceptions, when seen in *vmlinux.lds.h
|
||||
|
||||
sub help {
|
||||
my ($exitcode) = @_;
|
||||
|
||||
@@ -130,7 +133,7 @@ Options:
|
||||
--ignore-perl-version override checking of perl version. expect
|
||||
runtime errors.
|
||||
--codespell Use the codespell dictionary for spelling/typos
|
||||
(default:/usr/share/codespell/dictionary.txt)
|
||||
(default:$codespellfile)
|
||||
--codespellfile Use this codespell dictionary
|
||||
--typedefsfile Read additional types from this file
|
||||
--color[=WHEN] Use colors 'always', 'never', or only when output
|
||||
@@ -317,7 +320,7 @@ GetOptions(
|
||||
'debug=s' => \%debug,
|
||||
'test-only=s' => \$tst_only,
|
||||
'codespell!' => \$codespell,
|
||||
'codespellfile=s' => \$codespellfile,
|
||||
'codespellfile=s' => \$user_codespellfile,
|
||||
'typedefsfile=s' => \$typedefsfile,
|
||||
'color=s' => \$color,
|
||||
'no-color' => \$color, #keep old behaviors of -nocolor
|
||||
@@ -325,9 +328,32 @@ GetOptions(
|
||||
'kconfig-prefix=s' => \${CONFIG_},
|
||||
'h|help' => \$help,
|
||||
'version' => \$help
|
||||
) or help(1);
|
||||
) or $help = 2;
|
||||
|
||||
help(0) if ($help);
|
||||
if ($user_codespellfile) {
|
||||
# Use the user provided codespell file unconditionally
|
||||
$codespellfile = $user_codespellfile;
|
||||
} elsif (!(-f $codespellfile)) {
|
||||
# If /usr/share/codespell/dictionary.txt is not present, try to find it
|
||||
# under codespell's install directory: <codespell_root>/data/dictionary.txt
|
||||
if (($codespell || $help) && which("python3") ne "") {
|
||||
my $python_codespell_dict = << "EOF";
|
||||
|
||||
import os.path as op
|
||||
import codespell_lib
|
||||
codespell_dir = op.dirname(codespell_lib.__file__)
|
||||
codespell_file = op.join(codespell_dir, 'data', 'dictionary.txt')
|
||||
print(codespell_file, end='')
|
||||
EOF
|
||||
|
||||
my $codespell_dict = `python3 -c "$python_codespell_dict" 2> /dev/null`;
|
||||
$codespellfile = $codespell_dict if (-f $codespell_dict);
|
||||
}
|
||||
}
|
||||
|
||||
# $help is 1 if either -h, --help or --version is passed as option - exitcode: 0
|
||||
# $help is 2 if invalid option is passed - exitcode: 1
|
||||
help($help - 1) if ($help);
|
||||
|
||||
die "$P: --git cannot be used with --file or --fix\n" if ($git && ($file || $fix));
|
||||
die "$P: --verbose cannot be used with --terse\n" if ($verbose && $terse);
|
||||
@@ -552,10 +578,14 @@ our $typeKernelTypedefs = qr{(?x:
|
||||
(?:__)?(?:u|s|be|le)(?:8|16|32|64)|
|
||||
atomic_t
|
||||
)};
|
||||
our $typeStdioTypedefs = qr{(?x:
|
||||
FILE
|
||||
)};
|
||||
our $typeTypedefs = qr{(?x:
|
||||
$typeC99Typedefs\b|
|
||||
$typeOtherOSTypedefs\b|
|
||||
$typeKernelTypedefs\b
|
||||
$typeKernelTypedefs\b|
|
||||
$typeStdioTypedefs\b
|
||||
)};
|
||||
|
||||
our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b};
|
||||
@@ -592,6 +622,22 @@ our $signature_tags = qr{(?xi:
|
||||
Cc:
|
||||
)};
|
||||
|
||||
our @link_tags = qw(Link Closes);
|
||||
|
||||
#Create a search and print patterns for all these strings to be used directly below
|
||||
our $link_tags_search = "";
|
||||
our $link_tags_print = "";
|
||||
foreach my $entry (@link_tags) {
|
||||
if ($link_tags_search ne "") {
|
||||
$link_tags_search .= '|';
|
||||
$link_tags_print .= ' or ';
|
||||
}
|
||||
$entry .= ':';
|
||||
$link_tags_search .= $entry;
|
||||
$link_tags_print .= "'$entry'";
|
||||
}
|
||||
$link_tags_search = "(?:${link_tags_search})";
|
||||
|
||||
our $tracing_logging_tags = qr{(?xi:
|
||||
[=-]*> |
|
||||
<[=-]* |
|
||||
@@ -674,6 +720,17 @@ sub find_standard_signature {
|
||||
return "";
|
||||
}
|
||||
|
||||
our $obsolete_archives = qr{(?xi:
|
||||
\Qfreedesktop.org/archives/dri-devel\E |
|
||||
\Qlists.infradead.org\E |
|
||||
\Qlkml.org\E |
|
||||
\Qmail-archive.com\E |
|
||||
\Qmailman.alsa-project.org/pipermail\E |
|
||||
\Qmarc.info\E |
|
||||
\Qozlabs.org/pipermail\E |
|
||||
\Qspinics.net\E
|
||||
)};
|
||||
|
||||
our @typeListMisordered = (
|
||||
qr{char\s+(?:un)?signed},
|
||||
qr{int\s+(?:(?:un)?signed\s+)?short\s},
|
||||
@@ -783,6 +840,10 @@ our %deprecated_apis = (
|
||||
"rcu_barrier_sched" => "rcu_barrier",
|
||||
"get_state_synchronize_sched" => "get_state_synchronize_rcu",
|
||||
"cond_synchronize_sched" => "cond_synchronize_rcu",
|
||||
"kmap" => "kmap_local_page",
|
||||
"kunmap" => "kunmap_local",
|
||||
"kmap_atomic" => "kmap_local_page",
|
||||
"kunmap_atomic" => "kunmap_local",
|
||||
);
|
||||
|
||||
#Create a search pattern for all these strings to speed up a loop below
|
||||
@@ -1018,7 +1079,8 @@ our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)};
|
||||
our $declaration_macros = qr{(?x:
|
||||
(?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(|
|
||||
(?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(|
|
||||
(?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(
|
||||
(?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(|
|
||||
(?:$Storage\s+)?(?:XA_STATE|XA_STATE_ORDER)\s*\(
|
||||
)};
|
||||
|
||||
our %allow_repeated_words = (
|
||||
@@ -3100,17 +3162,73 @@ sub process {
|
||||
if ($sign_off =~ /^co-developed-by:$/i) {
|
||||
if ($email eq $author) {
|
||||
WARN("BAD_SIGN_OFF",
|
||||
"Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline);
|
||||
"Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . $herecurr);
|
||||
}
|
||||
if (!defined $lines[$linenr]) {
|
||||
WARN("BAD_SIGN_OFF",
|
||||
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline);
|
||||
} elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) {
|
||||
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . $herecurr);
|
||||
} elsif ($rawlines[$linenr] !~ /^signed-off-by:\s*(.*)/i) {
|
||||
WARN("BAD_SIGN_OFF",
|
||||
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
|
||||
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . $herecurr . $rawlines[$linenr] . "\n");
|
||||
} elsif ($1 ne $email) {
|
||||
WARN("BAD_SIGN_OFF",
|
||||
"Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
|
||||
"Co-developed-by and Signed-off-by: name/email do not match\n" . $herecurr . $rawlines[$linenr] . "\n");
|
||||
}
|
||||
}
|
||||
|
||||
# check if Reported-by: is followed by a Closes: tag
|
||||
if ($sign_off =~ /^reported(?:|-and-tested)-by:$/i) {
|
||||
if (!defined $lines[$linenr]) {
|
||||
WARN("BAD_REPORTED_BY_LINK",
|
||||
"Reported-by: should be immediately followed by Closes: with a URL to the report\n" . $herecurr . "\n");
|
||||
} elsif ($rawlines[$linenr] !~ /^closes:\s*/i) {
|
||||
WARN("BAD_REPORTED_BY_LINK",
|
||||
"Reported-by: should be immediately followed by Closes: with a URL to the report\n" . $herecurr . $rawlines[$linenr] . "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Check Fixes: styles is correct
|
||||
if (!$in_header_lines &&
|
||||
$line =~ /^\s*fixes:?\s*(?:commit\s*)?[0-9a-f]{5,}\b/i) {
|
||||
my $orig_commit = "";
|
||||
my $id = "0123456789ab";
|
||||
my $title = "commit title";
|
||||
my $tag_case = 1;
|
||||
my $tag_space = 1;
|
||||
my $id_length = 1;
|
||||
my $id_case = 1;
|
||||
my $title_has_quotes = 0;
|
||||
|
||||
if ($line =~ /(\s*fixes:?)\s+([0-9a-f]{5,})\s+($balanced_parens)/i) {
|
||||
my $tag = $1;
|
||||
$orig_commit = $2;
|
||||
$title = $3;
|
||||
|
||||
$tag_case = 0 if $tag eq "Fixes:";
|
||||
$tag_space = 0 if ($line =~ /^fixes:? [0-9a-f]{5,} ($balanced_parens)/i);
|
||||
|
||||
$id_length = 0 if ($orig_commit =~ /^[0-9a-f]{12}$/i);
|
||||
$id_case = 0 if ($orig_commit !~ /[A-F]/);
|
||||
|
||||
# Always strip leading/trailing parens then double quotes if existing
|
||||
$title = substr($title, 1, -1);
|
||||
if ($title =~ /^".*"$/) {
|
||||
$title = substr($title, 1, -1);
|
||||
$title_has_quotes = 1;
|
||||
}
|
||||
}
|
||||
|
||||
my ($cid, $ctitle) = git_commit_info($orig_commit, $id,
|
||||
$title);
|
||||
|
||||
if ($ctitle ne $title || $tag_case || $tag_space ||
|
||||
$id_length || $id_case || !$title_has_quotes) {
|
||||
if (WARN("BAD_FIXES_TAG",
|
||||
"Please use correct Fixes: style 'Fixes: <12 chars of sha1> (\"<title line>\")' - ie: 'Fixes: $cid (\"$ctitle\")'\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] = "Fixes: $cid (\"$ctitle\")";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3148,13 +3266,13 @@ sub process {
|
||||
length($line) > 75 &&
|
||||
!($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ ||
|
||||
# file delta changes
|
||||
$line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ ||
|
||||
$line =~ /^\s*(?:[\w\.\-\+]*\/)++[\w\.\-\+]+:/ ||
|
||||
# filename then :
|
||||
$line =~ /^\s*(?:Fixes:|Link:|$signature_tags)/i ||
|
||||
# A Fixes: or Link: line or signature tag line
|
||||
$line =~ /^\s*(?:Fixes:|$link_tags_search|$signature_tags)/i ||
|
||||
# A Fixes:, link or signature tag line
|
||||
$commit_log_possible_stack_dump)) {
|
||||
WARN("COMMIT_LOG_LONG_LINE",
|
||||
"Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr);
|
||||
"Prefer a maximum 75 chars per line (possible unwrapped commit description?)\n" . $herecurr);
|
||||
$commit_log_long_line = 1;
|
||||
}
|
||||
|
||||
@@ -3164,6 +3282,29 @@ sub process {
|
||||
$commit_log_possible_stack_dump = 0;
|
||||
}
|
||||
|
||||
# Check for odd tags before a URI/URL
|
||||
if ($in_commit_log &&
|
||||
$line =~ /^\s*(\w+:)\s*http/ && $1 !~ /^$link_tags_search$/) {
|
||||
if ($1 =~ /^v(?:ersion)?\d+/i) {
|
||||
WARN("COMMIT_LOG_VERSIONING",
|
||||
"Patch version information should be after the --- line\n" . $herecurr);
|
||||
} else {
|
||||
WARN("COMMIT_LOG_USE_LINK",
|
||||
"Unknown link reference '$1', use $link_tags_print instead\n" . $herecurr);
|
||||
}
|
||||
}
|
||||
|
||||
# Check for misuse of the link tags
|
||||
if ($in_commit_log &&
|
||||
$line =~ /^\s*(\w+:)\s*(\S+)/) {
|
||||
my $tag = $1;
|
||||
my $value = $2;
|
||||
if ($tag =~ /^$link_tags_search$/ && $value !~ m{^https?://}) {
|
||||
WARN("COMMIT_LOG_WRONG_LINK",
|
||||
"'$tag' should be followed by a public http(s) link\n" . $herecurr);
|
||||
}
|
||||
}
|
||||
|
||||
# Check for lines starting with a #
|
||||
if ($in_commit_log && $line =~ /^#/) {
|
||||
if (WARN("COMMIT_COMMENT_SYMBOL",
|
||||
@@ -3249,6 +3390,12 @@ sub process {
|
||||
$last_git_commit_id_linenr = $linenr if ($line =~ /\bcommit\s*$/i);
|
||||
}
|
||||
|
||||
# Check for mailing list archives other than lore.kernel.org
|
||||
if ($rawline =~ m{http.*\b$obsolete_archives}) {
|
||||
WARN("PREFER_LORE_ARCHIVE",
|
||||
"Use lore.kernel.org archive links when possible - see https://lore.kernel.org/lists.html\n" . $herecurr);
|
||||
}
|
||||
|
||||
# Check for added, moved or deleted files
|
||||
if (!$reported_maintainer_file && !$in_commit_log &&
|
||||
($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ ||
|
||||
@@ -3455,47 +3602,47 @@ sub process {
|
||||
# Kconfig supports named choices), so use a word boundary
|
||||
# (\b) rather than a whitespace character (\s)
|
||||
$line =~ /^\+\s*(?:config|menuconfig|choice)\b/) {
|
||||
my $length = 0;
|
||||
my $cnt = $realcnt;
|
||||
my $ln = $linenr + 1;
|
||||
my $f;
|
||||
my $is_start = 0;
|
||||
my $is_end = 0;
|
||||
for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) {
|
||||
$f = $lines[$ln - 1];
|
||||
$cnt-- if ($lines[$ln - 1] !~ /^-/);
|
||||
$is_end = $lines[$ln - 1] =~ /^\+/;
|
||||
my $ln = $linenr;
|
||||
my $needs_help = 0;
|
||||
my $has_help = 0;
|
||||
my $help_length = 0;
|
||||
while (defined $lines[$ln]) {
|
||||
my $f = $lines[$ln++];
|
||||
|
||||
next if ($f =~ /^-/);
|
||||
last if (!$file && $f =~ /^\@\@/);
|
||||
last if ($f !~ /^[\+ ]/); # !patch context
|
||||
|
||||
if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
|
||||
$is_start = 1;
|
||||
} elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) {
|
||||
$length = -1;
|
||||
if ($f =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
|
||||
$needs_help = 1;
|
||||
next;
|
||||
}
|
||||
if ($f =~ /^\+\s*help\s*$/) {
|
||||
$has_help = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
$f =~ s/^.//;
|
||||
$f =~ s/#.*//;
|
||||
$f =~ s/^\s+//;
|
||||
next if ($f =~ /^$/);
|
||||
$f =~ s/^.//; # strip patch context [+ ]
|
||||
$f =~ s/#.*//; # strip # directives
|
||||
$f =~ s/^\s+//; # strip leading blanks
|
||||
next if ($f =~ /^$/); # skip blank lines
|
||||
|
||||
# At the end of this Kconfig block:
|
||||
# This only checks context lines in the patch
|
||||
# and so hopefully shouldn't trigger false
|
||||
# positives, even though some of these are
|
||||
# common words in help texts
|
||||
if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice|
|
||||
if|endif|menu|endmenu|source)\b/x) {
|
||||
$is_end = 1;
|
||||
if ($f =~ /^(?:config|menuconfig|choice|endchoice|
|
||||
if|endif|menu|endmenu|source)\b/x) {
|
||||
last;
|
||||
}
|
||||
$length++;
|
||||
$help_length++ if ($has_help);
|
||||
}
|
||||
if ($is_start && $is_end && $length < $min_conf_desc_length) {
|
||||
if ($needs_help &&
|
||||
$help_length < $min_conf_desc_length) {
|
||||
my $stat_real = get_stat_real($linenr, $ln - 1);
|
||||
WARN("CONFIG_DESCRIPTION",
|
||||
"please write a paragraph that describes the config symbol fully\n" . $herecurr);
|
||||
"please write a help paragraph that fully describes the config symbol\n" . "$here\n$stat_real\n");
|
||||
}
|
||||
#print "is_start<$is_start> is_end<$is_end> length<$length>\n";
|
||||
}
|
||||
|
||||
# check MAINTAINERS entries
|
||||
@@ -3591,7 +3738,7 @@ sub process {
|
||||
my $comment = "";
|
||||
if ($realfile =~ /\.(h|s|S)$/) {
|
||||
$comment = '/*';
|
||||
} elsif ($realfile =~ /\.(c|dts|dtsi)$/) {
|
||||
} elsif ($realfile =~ /\.(c|rs|dts|dtsi)$/) {
|
||||
$comment = '//';
|
||||
} elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) {
|
||||
$comment = '#';
|
||||
@@ -3618,7 +3765,7 @@ sub process {
|
||||
"'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
|
||||
}
|
||||
if ($realfile =~ m@^Documentation/devicetree/bindings/@ &&
|
||||
not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) {
|
||||
$spdx_license !~ /GPL-2\.0(?:-only)? OR BSD-2-Clause/) {
|
||||
my $msg_level = \&WARN;
|
||||
$msg_level = \&CHK if ($file);
|
||||
if (&{$msg_level}("SPDX_LICENSE_TAG",
|
||||
@@ -3628,18 +3775,23 @@ sub process {
|
||||
$fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/;
|
||||
}
|
||||
}
|
||||
if ($realfile =~ m@^include/dt-bindings/@ &&
|
||||
$spdx_license !~ /GPL-2\.0(?:-only)? OR \S+/) {
|
||||
WARN("SPDX_LICENSE_TAG",
|
||||
"DT binding headers should be licensed (GPL-2.0-only OR .*)\n" . $herecurr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# check for embedded filenames
|
||||
if ($rawline =~ /^\+.*\Q$realfile\E/) {
|
||||
if ($rawline =~ /^\+.*\b\Q$realfile\E\b/) {
|
||||
WARN("EMBEDDED_FILENAME",
|
||||
"It's generally not useful to have the filename in the file\n" . $herecurr);
|
||||
}
|
||||
|
||||
# check we are in a valid source file if not then ignore this hunk
|
||||
next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
|
||||
next if ($realfile !~ /\.(h|c|rs|s|S|sh|dtsi|dts)$/);
|
||||
|
||||
# check for using SPDX-License-Identifier on the wrong line number
|
||||
if ($realline != $checklicenseline &&
|
||||
@@ -3726,7 +3878,7 @@ sub process {
|
||||
if ($realfile =~ /\.S$/ &&
|
||||
$line =~ /^\+\s*(?:[A-Z]+_)?SYM_[A-Z]+_(?:START|END)(?:_[A-Z_]+)?\s*\(\s*\.L/) {
|
||||
WARN("AVOID_L_PREFIX",
|
||||
"Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/asm-annotations.rst\n" . $herecurr);
|
||||
"Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/core-api/asm-annotations.rst\n" . $herecurr);
|
||||
}
|
||||
|
||||
# check we are in a valid source file C or perl if not then ignore this hunk
|
||||
@@ -3902,7 +4054,7 @@ sub process {
|
||||
if ($prevline =~ /^[\+ ]};?\s*$/ &&
|
||||
$line =~ /^\+/ &&
|
||||
!($line =~ /^\+\s*$/ ||
|
||||
$line =~ /^\+\s*EXPORT_SYMBOL/ ||
|
||||
$line =~ /^\+\s*(?:EXPORT_SYMBOL|early_param)/ ||
|
||||
$line =~ /^\+\s*MODULE_/i ||
|
||||
$line =~ /^\+\s*\#\s*(?:end|elif|else)/ ||
|
||||
$line =~ /^\+[a-z_]*init/ ||
|
||||
@@ -4449,6 +4601,7 @@ sub process {
|
||||
# XXX(foo);
|
||||
# EXPORT_SYMBOL(something_foo);
|
||||
my $name = $1;
|
||||
$name =~ s/^\s*($Ident).*/$1/;
|
||||
if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ &&
|
||||
$name =~ /^${Ident}_$2/) {
|
||||
#print "FOO C name<$name>\n";
|
||||
@@ -4669,12 +4822,12 @@ sub process {
|
||||
}
|
||||
}
|
||||
|
||||
# avoid BUG() or BUG_ON()
|
||||
if ($line =~ /\b(?:BUG|BUG_ON)\b/) {
|
||||
# do not use BUG() or variants
|
||||
if ($line =~ /\b(?!AA_|BUILD_|DCCP_|IDA_|KVM_|RWLOCK_|snd_|SPIN_)(?:[a-zA-Z_]*_)?BUG(?:_ON)?(?:_[A-Z_]+)?\s*\(/) {
|
||||
my $msg_level = \&WARN;
|
||||
$msg_level = \&CHK if ($file);
|
||||
&{$msg_level}("AVOID_BUG",
|
||||
"Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr);
|
||||
"Do not crash the kernel unless it is absolutely unavoidable--use WARN_ON_ONCE() plus recovery code (if feasible) instead of BUG() or variants\n" . $herecurr);
|
||||
}
|
||||
|
||||
# avoid LINUX_VERSION_CODE
|
||||
@@ -4895,7 +5048,7 @@ sub process {
|
||||
if|for|while|switch|return|case|
|
||||
volatile|__volatile__|
|
||||
__attribute__|format|__extension__|
|
||||
asm|__asm__)$/x)
|
||||
asm|__asm__|scoped_guard)$/x)
|
||||
{
|
||||
# cpp #define statements have non-optional spaces, ie
|
||||
# if there is a space between the name and the open
|
||||
@@ -5526,6 +5679,7 @@ sub process {
|
||||
defined($stat) && defined($cond) &&
|
||||
$line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
|
||||
my ($s, $c) = ($stat, $cond);
|
||||
my $fixed_assign_in_if = 0;
|
||||
|
||||
if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
|
||||
if (ERROR("ASSIGN_IN_IF",
|
||||
@@ -5550,6 +5704,7 @@ sub process {
|
||||
$newline .= ')';
|
||||
$newline .= " {" if (defined($brace));
|
||||
fix_insert_line($fixlinenr + 1, $newline);
|
||||
$fixed_assign_in_if = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5573,8 +5728,20 @@ sub process {
|
||||
$stat_real = "[...]\n$stat_real";
|
||||
}
|
||||
|
||||
ERROR("TRAILING_STATEMENTS",
|
||||
"trailing statements should be on next line\n" . $herecurr . $stat_real);
|
||||
if (ERROR("TRAILING_STATEMENTS",
|
||||
"trailing statements should be on next line\n" . $herecurr . $stat_real) &&
|
||||
!$fixed_assign_in_if &&
|
||||
$cond_lines == 0 &&
|
||||
$fix && $perl_version_ok &&
|
||||
$fixed[$fixlinenr] =~ /^\+(\s*)((?:if|while|for)\s*$balanced_parens)\s*(.*)$/) {
|
||||
my $indent = $1;
|
||||
my $test = $2;
|
||||
my $rest = rtrim($4);
|
||||
if ($rest =~ /;$/) {
|
||||
$fixed[$fixlinenr] = "\+$indent$test";
|
||||
fix_insert_line($fixlinenr + 1, "$indent\t$rest");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5676,12 +5843,14 @@ sub process {
|
||||
$var !~ /^(?:[A-Z]+_){1,5}[A-Z]{1,3}[a-z]/ &&
|
||||
#Ignore Page<foo> variants
|
||||
$var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
|
||||
#Ignore ETHTOOL_LINK_MODE_<foo> variants
|
||||
$var !~ /^ETHTOOL_LINK_MODE_/ &&
|
||||
#Ignore SI style variants like nS, mV and dB
|
||||
#(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE)
|
||||
$var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-Z0-9_]+)?$/ &&
|
||||
#Ignore some three character SI units explicitly, like MiB and KHz
|
||||
$var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) {
|
||||
while ($var =~ m{($Ident)}g) {
|
||||
while ($var =~ m{\b($Ident)}g) {
|
||||
my $word = $1;
|
||||
next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
|
||||
if ($check) {
|
||||
@@ -5811,6 +5980,7 @@ sub process {
|
||||
$dstat !~ /$exceptions/ &&
|
||||
$dstat !~ /^\.$Ident\s*=/ && # .foo =
|
||||
$dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo
|
||||
$dstat !~ /^case\b/ && # case ...
|
||||
$dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...)
|
||||
$dstat !~ /^while\s*$Constant\s*$Constant\s*$/ && # while (...) {...}
|
||||
$dstat !~ /^for\s*$Constant$/ && # for (...)
|
||||
@@ -5883,6 +6053,9 @@ sub process {
|
||||
|
||||
# check for line continuations outside of #defines, preprocessor #, and asm
|
||||
|
||||
} elsif ($realfile =~ m@/vmlinux.lds.h$@) {
|
||||
$line =~ s/(\w+)/$maybe_linker_symbol{$1}++/ge;
|
||||
#print "REAL: $realfile\nln: $line\nkeys:", sort keys %maybe_linker_symbol;
|
||||
} else {
|
||||
if ($prevline !~ /^..*\\$/ &&
|
||||
$line !~ /^\+\s*\#.*\\$/ && # preprocessor
|
||||
@@ -6743,15 +6916,19 @@ sub process {
|
||||
}
|
||||
if ($bad_specifier ne "") {
|
||||
my $stat_real = get_stat_real($linenr, $lc);
|
||||
my $msg_level = \&WARN;
|
||||
my $ext_type = "Invalid";
|
||||
my $use = "";
|
||||
if ($bad_specifier =~ /p[Ff]/) {
|
||||
$use = " - use %pS instead";
|
||||
$use =~ s/pS/ps/ if ($bad_specifier =~ /pf/);
|
||||
} elsif ($bad_specifier =~ /pA/) {
|
||||
$use = " - '%pA' is only intended to be used from Rust code";
|
||||
$msg_level = \&ERROR;
|
||||
}
|
||||
|
||||
WARN("VSPRINTF_POINTER_EXTENSION",
|
||||
"$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n");
|
||||
&{$msg_level}("VSPRINTF_POINTER_EXTENSION",
|
||||
"$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6816,10 +6993,22 @@ sub process {
|
||||
# }
|
||||
# }
|
||||
|
||||
# strcpy uses that should likely be strscpy
|
||||
if ($line =~ /\bstrcpy\s*\(/) {
|
||||
WARN("STRCPY",
|
||||
"Prefer strscpy over strcpy - see: https://github.com/KSPP/linux/issues/88\n" . $herecurr);
|
||||
}
|
||||
|
||||
# strlcpy uses that should likely be strscpy
|
||||
if ($line =~ /\bstrlcpy\s*\(/) {
|
||||
WARN("STRLCPY",
|
||||
"Prefer strscpy over strlcpy - see: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw\@mail.gmail.com/\n" . $herecurr);
|
||||
"Prefer strscpy over strlcpy - see: https://github.com/KSPP/linux/issues/89\n" . $herecurr);
|
||||
}
|
||||
|
||||
# strncpy uses that should likely be strscpy or strscpy_pad
|
||||
if ($line =~ /\bstrncpy\s*\(/) {
|
||||
WARN("STRNCPY",
|
||||
"Prefer strscpy, strscpy_pad, or __nonstring over strncpy - see: https://github.com/KSPP/linux/issues/90\n" . $herecurr);
|
||||
}
|
||||
|
||||
# typecasts on min/max could be min_t/max_t
|
||||
@@ -6926,6 +7115,21 @@ sub process {
|
||||
"arguments for function declarations should follow identifier\n" . $herecurr);
|
||||
}
|
||||
|
||||
} elsif ($realfile =~ /\.c$/ && defined $stat &&
|
||||
$stat =~ /^\+extern struct\s+(\w+)\s+(\w+)\[\];/)
|
||||
{
|
||||
my ($st_type, $st_name) = ($1, $2);
|
||||
|
||||
for my $s (keys %maybe_linker_symbol) {
|
||||
#print "Linker symbol? $st_name : $s\n";
|
||||
goto LIKELY_LINKER_SYMBOL
|
||||
if $st_name =~ /$s/;
|
||||
}
|
||||
WARN("AVOID_EXTERNS",
|
||||
"found a file-scoped extern type:$st_type name:$st_name in .c file\n"
|
||||
. "is this a linker symbol ?\n" . $herecurr);
|
||||
LIKELY_LINKER_SYMBOL:
|
||||
|
||||
} elsif ($realfile =~ /\.c$/ && defined $stat &&
|
||||
$stat =~ /^.\s*extern\s+/)
|
||||
{
|
||||
@@ -6994,14 +7198,16 @@ sub process {
|
||||
"Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
|
||||
}
|
||||
|
||||
# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
|
||||
# check for (kv|k)[mz]alloc with multiplies that could be kmalloc_array/kvmalloc_array/kvcalloc/kcalloc
|
||||
if ($perl_version_ok &&
|
||||
defined $stat &&
|
||||
$stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
|
||||
$stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
|
||||
my $oldfunc = $3;
|
||||
my $a1 = $4;
|
||||
my $a2 = $10;
|
||||
my $newfunc = "kmalloc_array";
|
||||
$newfunc = "kvmalloc_array" if ($oldfunc eq "kvmalloc");
|
||||
$newfunc = "kvcalloc" if ($oldfunc eq "kvzalloc");
|
||||
$newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
|
||||
my $r1 = $a1;
|
||||
my $r2 = $a2;
|
||||
@@ -7018,7 +7224,7 @@ sub process {
|
||||
"Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
|
||||
$cnt == 1 &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
|
||||
$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7032,7 +7238,7 @@ sub process {
|
||||
}
|
||||
|
||||
# check for alloc argument mismatch
|
||||
if ($line =~ /\b((?:devm_)?(?:kcalloc|kmalloc_array))\s*\(\s*sizeof\b/) {
|
||||
if ($line =~ /\b((?:devm_)?((?:k|kv)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/) {
|
||||
WARN("ALLOC_ARRAY_ARGS",
|
||||
"$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
|
||||
}
|
||||
@@ -7235,6 +7441,16 @@ sub process {
|
||||
}
|
||||
}
|
||||
|
||||
# check for array definition/declarations that should use flexible arrays instead
|
||||
if ($sline =~ /^[\+ ]\s*\}(?:\s*__packed)?\s*;\s*$/ &&
|
||||
$prevline =~ /^\+\s*(?:\}(?:\s*__packed\s*)?|$Type)\s*$Ident\s*\[\s*(0|1)\s*\]\s*;\s*$/) {
|
||||
if (ERROR("FLEXIBLE_ARRAY",
|
||||
"Use C99 flexible arrays - see https://docs.kernel.org/process/deprecated.html#zero-length-and-one-element-arrays\n" . $hereprev) &&
|
||||
$1 == '0' && $fix) {
|
||||
$fixed[$fixlinenr - 1] =~ s/\[\s*0\s*\]/[]/;
|
||||
}
|
||||
}
|
||||
|
||||
# nested likely/unlikely calls
|
||||
if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
|
||||
WARN("LIKELY_MISUSE",
|
||||
@@ -7252,6 +7468,30 @@ sub process {
|
||||
}
|
||||
}
|
||||
|
||||
# Complain about RCU Tasks Trace used outside of BPF (and of course, RCU).
|
||||
our $rcu_trace_funcs = qr{(?x:
|
||||
rcu_read_lock_trace |
|
||||
rcu_read_lock_trace_held |
|
||||
rcu_read_unlock_trace |
|
||||
call_rcu_tasks_trace |
|
||||
synchronize_rcu_tasks_trace |
|
||||
rcu_barrier_tasks_trace |
|
||||
rcu_request_urgent_qs_task
|
||||
)};
|
||||
our $rcu_trace_paths = qr{(?x:
|
||||
kernel/bpf/ |
|
||||
include/linux/bpf |
|
||||
net/bpf/ |
|
||||
kernel/rcu/ |
|
||||
include/linux/rcu
|
||||
)};
|
||||
if ($line =~ /\b($rcu_trace_funcs)\s*\(/) {
|
||||
if ($realfile !~ m{^$rcu_trace_paths}) {
|
||||
WARN("RCU_TASKS_TRACE",
|
||||
"use of RCU tasks trace is incorrect outside BPF or core RCU code\n" . $herecurr);
|
||||
}
|
||||
}
|
||||
|
||||
# check for lockdep_set_novalidate_class
|
||||
if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
|
||||
$line =~ /__lockdep_no_validate__\s*\)/ ) {
|
||||
@@ -7393,6 +7633,13 @@ sub process {
|
||||
WARN("MODULE_LICENSE",
|
||||
"unknown module license " . $extracted_string . "\n" . $herecurr);
|
||||
}
|
||||
if (!$file && $extracted_string eq '"GPL v2"') {
|
||||
if (WARN("MODULE_LICENSE",
|
||||
"Prefer \"GPL\" over \"GPL v2\" - see commit bf7fbeeae6db (\"module: Cure the MODULE_LICENSE \"GPL\" vs. \"GPL v2\" bogosity\")\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\bMODULE_LICENSE\s*\(\s*"GPL v2"\s*\)/MODULE_LICENSE("GPL")/;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# check for sysctl duplicate constants
|
||||
|
||||
Reference in New Issue
Block a user