7586 lines · 225.6 KB · Perl
RawDownload
			if (!ctx_has_comment($first_line, $linenr)) {				CHK("UNCOMMENTED_DEFINITION",				    "$1 definition without comment\n" . $herecurr);			}		}# check for memory barriers without a comment. 		my $barriers = qr{			mb|			rmb|			wmb		}x;		my $barrier_stems = qr{			mb__before_atomic|			mb__after_atomic|			store_release|			load_acquire|			store_mb|			(?:$barriers)		}x;		my $all_barriers = qr{			(?:$barriers)|			smp_(?:$barrier_stems)|			virt_(?:$barrier_stems)		}x; 		if ($line =~ /\b(?:$all_barriers)\s*\(/) {			if (!ctx_has_comment($first_line, $linenr)) {				WARN("MEMORY_BARRIER",				     "memory barrier without comment\n" . $herecurr);			}		} 		my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x; 		if ($realfile !~ m@^include/asm-generic/@ &&		    $realfile !~ m@/barrier\.h$@ &&		    $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ &&		    $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) {			WARN("MEMORY_BARRIER",			     "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr);		} # check for waitqueue_active without a comment.		if ($line =~ /\bwaitqueue_active\s*\(/) {			if (!ctx_has_comment($first_line, $linenr)) {				WARN("WAITQUEUE_ACTIVE",				     "waitqueue_active without comment\n" . $herecurr);			}		} # check for data_race without a comment.		if ($line =~ /\bdata_race\s*\(/) {			if (!ctx_has_comment($first_line, $linenr)) {				WARN("DATA_RACE",				     "data_race without comment\n" . $herecurr);			}		} # check of hardware specific defines		if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {			CHK("ARCH_DEFINES",			    "architecture specific defines should be avoided\n" .  $herecurr);		} # check that the storage class is not after a type		if ($line =~ /\b($Type)\s+($Storage)\b/) {			WARN("STORAGE_CLASS",			     "storage class '$2' should be located before type '$1'\n" . $herecurr);		}# Check that the storage class is at the beginning of a declaration		if ($line =~ /\b$Storage\b/ &&		    $line !~ /^.\s*$Storage/ &&		    $line =~ /^.\s*(.+?)\$Storage\s/ &&		    $1 !~ /[\,\)]\s*$/) {			WARN("STORAGE_CLASS",			     "storage class should be at the beginning of the declaration\n" . $herecurr);		} # check the location of the inline attribute, that it is between# storage class and type.		if ($line =~ /\b$Type\s+$Inline\b/ ||		    $line =~ /\b$Inline\s+$Storage\b/) {			ERROR("INLINE_LOCATION",			      "inline keyword should sit between storage class and type\n" . $herecurr);		} # Check for __inline__ and __inline, prefer inline		if ($realfile !~ m@\binclude/uapi/@ &&		    $line =~ /\b(__inline__|__inline)\b/) {			if (WARN("INLINE",				 "plain inline is preferred over $1\n" . $herecurr) &&			    $fix) {				$fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/; 			}		} # Check for compiler attributes		if ($realfile !~ m@\binclude/uapi/@ &&		    $rawline =~ /\b__attribute__\s*\(\s*($balanced_parens)\s*\)/) {			my $attr = $1;			$attr =~ s/\s*\(\s*(.*)\)\s*/$1/; 			my %attr_list = (				"alias"				=> "__alias",				"aligned"			=> "__aligned",				"always_inline"			=> "__always_inline",				"assume_aligned"		=> "__assume_aligned",				"cold"				=> "__cold",				"const"				=> "__attribute_const__",				"copy"				=> "__copy",				"designated_init"		=> "__designated_init",				"externally_visible"		=> "__visible",				"format"			=> "printf|scanf",				"gnu_inline"			=> "__gnu_inline",				"malloc"			=> "__malloc",				"mode"				=> "__mode",				"no_caller_saved_registers"	=> "__no_caller_saved_registers",				"noclone"			=> "__noclone",				"noinline"			=> "noinline",				"nonstring"			=> "__nonstring",				"noreturn"			=> "__noreturn",				"packed"			=> "__packed",				"pure"				=> "__pure",				"section"			=> "__section",				"used"				=> "__used",				"weak"				=> "__weak"			); 			while ($attr =~ /\s*(\w+)\s*(${balanced_parens})?/g) {				my $orig_attr = $1;				my $params = '';				$params = $2 if defined($2);				my $curr_attr = $orig_attr;				$curr_attr =~ s/^[\s_]+|[\s_]+$//g;				if (exists($attr_list{$curr_attr})) {					my $new = $attr_list{$curr_attr};					if ($curr_attr eq "format" && $params) {						$params =~ /^\s*\(\s*(\w+)\s*,\s*(.*)/;						$new = "__$1\($2";					} else {						$new = "$new$params";					}					if (WARN("PREFER_DEFINED_ATTRIBUTE_MACRO",						 "Prefer $new over __attribute__(($orig_attr$params))\n" . $herecurr) &&					    $fix) {						my $remove = "\Q$orig_attr\E" . '\s*' . "\Q$params\E" . '(?:\s*,\s*)?';						$fixed[$fixlinenr] =~ s/$remove//;						$fixed[$fixlinenr] =~ s/\b__attribute__/$new __attribute__/;						$fixed[$fixlinenr] =~ s/\}\Q$new\E/} $new/;						$fixed[$fixlinenr] =~ s/ __attribute__\s*\(\s*\(\s*\)\s*\)//;					}				}			} 			# Check for __attribute__ unused, prefer __always_unused or __maybe_unused			if ($attr =~ /^_*unused/) {				WARN("PREFER_DEFINED_ATTRIBUTE_MACRO",				     "__always_unused or __maybe_unused is preferred over __attribute__((__unused__))\n" . $herecurr);			}		} # Check for __attribute__ weak, or __weak declarations (may have link issues)		if ($perl_version_ok &&		    $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ &&		    ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ ||		     $line =~ /\b__weak\b/)) {			ERROR("WEAK_DECLARATION",			      "Using weak declarations can have unintended link defects\n" . $herecurr);		} # check for c99 types like uint8_t used outside of uapi/ and tools/		if ($realfile !~ m@\binclude/uapi/@ &&		    $realfile !~ m@\btools/@ &&		    $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) {			my $type = $1;			if ($type =~ /\b($typeC99Typedefs)\b/) {				$type = $1;				my $kernel_type = 'u';				$kernel_type = 's' if ($type =~ /^_*[si]/);				$type =~ /(\d+)/;				$kernel_type .= $1;				if (CHK("PREFER_KERNEL_TYPES",					"Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) &&				    $fix) {					$fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/;				}			}		} # check for cast of C90 native int or longer types constants		if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) {			my $cast = $1;			my $const = $2;			my $suffix = "";			my $newconst = $const;			$newconst =~ s/${Int_type}$//;			$suffix .= 'U' if ($cast =~ /\bunsigned\b/);			if ($cast =~ /\blong\s+long\b/) {			    $suffix .= 'LL';			} elsif ($cast =~ /\blong\b/) {			    $suffix .= 'L';			}			if (WARN("TYPECAST_INT_CONSTANT",				 "Unnecessary typecast of c90 int constant - '$cast$const' could be '$const$suffix'\n" . $herecurr) &&			    $fix) {				$fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/;			}		} # check for sizeof(&)		if ($line =~ /\bsizeof\s*\(\s*\&/) {			WARN("SIZEOF_ADDRESS",			     "sizeof(& should be avoided\n" . $herecurr);		} # check for sizeof without parenthesis		if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) {			if (WARN("SIZEOF_PARENTHESIS",				 "sizeof $1 should be sizeof($1)\n" . $herecurr) &&			    $fix) {				$fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex;			}		} # check for struct spinlock declarations		if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) {			WARN("USE_SPINLOCK_T",			     "struct spinlock should be spinlock_t\n" . $herecurr);		} # check for seq_printf uses that could be seq_puts		if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) {			my $fmt = get_quoted_string($line, $rawline);			$fmt =~ s/%%//g;			if ($fmt !~ /%/) {				if (WARN("PREFER_SEQ_PUTS",					 "Prefer seq_puts to seq_printf\n" . $herecurr) &&				    $fix) {					$fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/;				}			}		} # check for vsprintf extension %p<foo> misuses		if ($perl_version_ok &&		    defined $stat &&		    $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&		    $1 !~ /^_*volatile_*$/) {			my $stat_real; 			my $lc = $stat =~ tr@\n@@;			$lc = $lc + $linenr;		        for (my $count = $linenr; $count <= $lc; $count++) {				my $specifier;				my $extension;				my $qualifier;				my $bad_specifier = "";				my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));				$fmt =~ s/%%//g; 				while ($fmt =~ /(\%[\*\d\.]*p(\w)(\w*))/g) {					$specifier = $1;					$extension = $2;					$qualifier = $3;					if ($extension !~ /[4SsBKRraEehMmIiUDdgVCbGNOxtf]/ ||					    ($extension eq "f" &&					     defined $qualifier && $qualifier !~ /^w/) ||					    ($extension eq "4" &&					     defined $qualifier && $qualifier !~ /^cc/)) {						$bad_specifier = $specifier;						last;					}					if ($extension eq "x" && !defined($stat_real)) {						if (!defined($stat_real)) {							$stat_real = get_stat_real($linenr, $lc);						}						WARN("VSPRINTF_SPECIFIER_PX",						     "Using vsprintf specifier '\%px' potentially exposes the kernel memory layout, if you don't really need the address please consider using '\%p'.\n" . "$here\n$stat_real\n");					}				}				if ($bad_specifier ne "") {					my $stat_real = get_stat_real($linenr, $lc);					my $ext_type = "Invalid";					my $use = "";					if ($bad_specifier =~ /p[Ff]/) {						$use = " - use %pS instead";						$use =~ s/pS/ps/ if ($bad_specifier =~ /pf/);					} 					WARN("VSPRINTF_POINTER_EXTENSION",					     "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n");				}			}		} # Check for misused memsets		if ($perl_version_ok &&		    defined $stat &&		    $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) { 			my $ms_addr = $2;			my $ms_val = $7;			my $ms_size = $12; 			if ($ms_size =~ /^(0x|)0$/i) {				ERROR("MEMSET",				      "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n");			} elsif ($ms_size =~ /^(0x|)1$/i) {				WARN("MEMSET",				     "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n");			}		} # Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)#		if ($perl_version_ok &&#		    defined $stat &&#		    $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {#			if (WARN("PREFER_ETHER_ADDR_COPY",#				 "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") &&#			    $fix) {#				$fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;#			}#		} # Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar)#		if ($perl_version_ok &&#		    defined $stat &&#		    $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {#			WARN("PREFER_ETHER_ADDR_EQUAL",#			     "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n")#		} # check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr#		if ($perl_version_ok &&#		    defined $stat &&#		    $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {##			my $ms_val = $7;##			if ($ms_val =~ /^(?:0x|)0+$/i) {#				if (WARN("PREFER_ETH_ZERO_ADDR",#					 "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") &&#				    $fix) {#					$fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/;#				}#			} elsif ($ms_val =~ /^(?:0xff|255)$/i) {#				if (WARN("PREFER_ETH_BROADCAST_ADDR",#					 "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") &&#				    $fix) {#					$fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/;#				}#			}#		} # 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);		} # typecasts on min/max could be min_t/max_t		if ($perl_version_ok &&		    defined $stat &&		    $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {			if (defined $2 || defined $7) {				my $call = $1;				my $cast1 = deparenthesize($2);				my $arg1 = $3;				my $cast2 = deparenthesize($7);				my $arg2 = $8;				my $cast; 				if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) {					$cast = "$cast1 or $cast2";				} elsif ($cast1 ne "") {					$cast = $cast1;				} else {					$cast = $cast2;				}				WARN("MINMAX",				     "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n");			}		} # check usleep_range arguments		if ($perl_version_ok &&		    defined $stat &&		    $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {			my $min = $1;			my $max = $7;			if ($min eq $max) {				WARN("USLEEP_RANGE",				     "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");			} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&				 $min > $max) {				WARN("USLEEP_RANGE",				     "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");			}		} # check for naked sscanf		if ($perl_version_ok &&		    defined $stat &&		    $line =~ /\bsscanf\b/ &&		    ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ &&		     $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ &&		     $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) {			my $lc = $stat =~ tr@\n@@;			$lc = $lc + $linenr;			my $stat_real = get_stat_real($linenr, $lc);			WARN("NAKED_SSCANF",			     "unchecked sscanf return value\n" . "$here\n$stat_real\n");		} # check for simple sscanf that should be kstrto<foo>		if ($perl_version_ok &&		    defined $stat &&		    $line =~ /\bsscanf\b/) {			my $lc = $stat =~ tr@\n@@;			$lc = $lc + $linenr;			my $stat_real = get_stat_real($linenr, $lc);			if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) {				my $format = $6;				my $count = $format =~ tr@%@%@;				if ($count == 1 &&				    $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) {					WARN("SSCANF_TO_KSTRTO",					     "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n");				}			}		} # check for new externs in .h files.		if ($realfile =~ /\.h$/ &&		    $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {			if (CHK("AVOID_EXTERNS",				"extern prototypes should be avoided in .h files\n" . $herecurr) &&			    $fix) {				$fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;			}		} # check for new externs in .c files.		if ($realfile =~ /\.c$/ && defined $stat &&		    $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)		{			my $function_name = $1;			my $paren_space = $2; 			my $s = $stat;			if (defined $cond) {				substr($s, 0, length($cond), '');			}			if ($s =~ /^\s*;/)			{				WARN("AVOID_EXTERNS",				     "externs should be avoided in .c files\n" .  $herecurr);			} 			if ($paren_space =~ /\n/) {				WARN("FUNCTION_ARGUMENTS",				     "arguments for function declarations should follow identifier\n" . $herecurr);			} 		} elsif ($realfile =~ /\.c$/ && defined $stat &&		    $stat =~ /^.\s*extern\s+/)		{			WARN("AVOID_EXTERNS",			     "externs should be avoided in .c files\n" .  $herecurr);		} # check for function declarations that have arguments without identifier names		if (defined $stat &&		    $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&		    $1 ne "void") {			my $args = trim($1);			while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) {				my $arg = trim($1);				if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) {					WARN("FUNCTION_ARGUMENTS",					     "function definition argument '$arg' should also have an identifier name\n" . $herecurr);				}			}		} # check for function definitions		if ($perl_version_ok &&		    defined $stat &&		    $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) {			$context_function = $1; # check for multiline function definition with misplaced open brace			my $ok = 0;			my $cnt = statement_rawlines($stat);			my $herectx = $here . "\n";			for (my $n = 0; $n < $cnt; $n++) {				my $rl = raw_line($linenr, $n);

Lines 6501–7000 of 7586. Previous lines