7976 lines · 239.6 KB · Perl
RawDownload
				$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 !~ /^c(?:[hlbc]|hR)$/)) {						$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 $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;					} 					&{$msg_level}("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)/;#				}#			}#		}# strcpy uses that should likely be strscpy		if ($line =~ /\bstrcpy\s*\(/ && !is_userspace($realfile)) {			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*\(/ && !is_userspace($realfile)) {			WARN("STRLCPY",			     "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*\(/ && !is_userspace($realfile)) {			WARN("STRNCPY",			     "Prefer strscpy, strscpy_pad, or __nonstring over strncpy - see: https://github.com/KSPP/linux/issues/90\n" . $herecurr);		} # ethtool_sprintf uses that should likely be ethtool_puts		if ($line =~ /\bethtool_sprintf\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {			if (WARN("PREFER_ETHTOOL_PUTS",				 "Prefer ethtool_puts over ethtool_sprintf with only two arguments\n" . $herecurr) &&			    $fix) {				$fixed[$fixlinenr] =~ s/\bethtool_sprintf\s*\(\s*($FuncArg)\s*,\s*($FuncArg)/ethtool_puts($1, $7)/;			}		} 		# use $rawline because $line loses %s via sanitization and thus we can't match against it.		if ($rawline =~ /\bethtool_sprintf\s*\(\s*$FuncArg\s*,\s*\"\%s\"\s*,\s*$FuncArg\s*\)/) {			if (WARN("PREFER_ETHTOOL_PUTS",				 "Prefer ethtool_puts over ethtool_sprintf with standalone \"%s\" specifier\n" . $herecurr) &&			    $fix) {				$fixed[$fixlinenr] =~ s/\bethtool_sprintf\s*\(\s*($FuncArg)\s*,\s*"\%s"\s*,\s*($FuncArg)/ethtool_puts($1, $7)/;			}		}  # 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 function description of usleep_range().\n" . "$here\n$stat\n");			} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&				 $min > $max) {				WARN("USLEEP_RANGE",				     "usleep_range args reversed, use min then max;  see function description of usleep_range().\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 =~ /^\+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+/)		{			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);				$herectx .=  $rl . "\n";				$ok = 1 if ($rl =~ /^[ \+]\{/);				$ok = 1 if ($rl =~ /\{/ && $n == 0);				last if $rl =~ /^[ \+].*\{/;			}			if (!$ok) {				ERROR("OPEN_BRACE",				      "open brace '{' following function definitions go on the next line\n" . $herectx);			}		} # checks for new __setup's		if ($rawline =~ /\b__setup\("([^"]*)"/) {			my $name = $1; 			if (!grep(/$name/, @setup_docs)) {				CHK("UNDOCUMENTED_SETUP",				    "__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.txt\n" . $herecurr);			}		} # check for pointless casting of alloc functions		if ($line =~ /\*\s*\)\s*$allocFunctions\b/) {			WARN("UNNECESSARY_CASTS",			     "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);		} # alloc style# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)		if ($perl_version_ok &&		    $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {			CHK("ALLOC_SIZEOF_STRUCT",			    "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);		} # check for (kv|k)[mz]alloc that could be kmalloc_obj/kvmalloc_obj/kzalloc_obj/kvzalloc_obj		if ($perl_version_ok &&		    defined $stat &&		    $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*,/) {			my $oldfunc = $3;			my $a1 = $4;			my $newfunc = "kmalloc_obj";			$newfunc = "kvmalloc_obj" if ($oldfunc eq "kvmalloc");			$newfunc = "kvzalloc_obj" if ($oldfunc eq "kvzalloc");			$newfunc = "kzalloc_obj" if ($oldfunc eq "kzalloc"); 			if ($a1 =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/) {				my $cnt = statement_rawlines($stat);				my $herectx = get_stat_here($linenr, $cnt, $here); 				if (WARN("ALLOC_WITH_SIZEOF",					 "Prefer $newfunc over $oldfunc with sizeof\n" . $herectx) &&				    $cnt == 1 &&				    $fix) {					$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*,/$1 = $newfunc($a1,/;				}			}		}  # check for (kv|k)[mz]alloc with multiplies that could be kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs		if ($perl_version_ok &&		    defined $stat &&		    $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_objs";			$newfunc = "kvmalloc_objs" if ($oldfunc eq "kvmalloc");			$newfunc = "kvzalloc_objs" if ($oldfunc eq "kvzalloc");			$newfunc = "kzalloc_objs" if ($oldfunc eq "kzalloc");			my $r1 = $a1;			my $r2 = $a2;			if ($a1 =~ /^sizeof\s*\S/) {				$r1 = $a2;				$r2 = $a1;			}			if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ &&			    !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) {				my $cnt = statement_rawlines($stat);				my $herectx = get_stat_here($linenr, $cnt, $here); 				if (WARN("ALLOC_WITH_MULTIPLY",					 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&				    $cnt == 1 &&				    $fix) {					my $sized = trim($r2);					$sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;					$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;				}			}		} # check for krealloc arg reuse		if ($perl_version_ok &&		    $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*($Lval)\s*,/ &&		    $1 eq $3) {			WARN("KREALLOC_ARG_REUSE",			     "Reusing the krealloc arg is almost always a bug\n" . $herecurr);		} # check for alloc argument mismatch		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);		} # check for multiple semicolons		if ($line =~ /;\s*;\s*$/) {			if (WARN("ONE_SEMICOLON",				 "Statements terminations use 1 semicolon\n" . $herecurr) &&			    $fix) {				$fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g;			}		} # check for #defines like: 1 << <digit> that could be BIT(digit), it is not exported to uapi		if ($realfile !~ m@^include/uapi/@ &&		    $line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) {			my $ull = "";			$ull = "_ULL" if (defined($1) && $1 =~ /ll/i);			if (CHK("BIT_MACRO",				"Prefer using the BIT$ull macro\n" . $herecurr) &&			    $fix) {				$fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/;			}		} # check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too)		if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}/) {			WARN("IS_ENABLED_CONFIG",			     "IS_ENABLED($1) is normally used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr);		} # check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE		if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(${CONFIG_}[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) {			my $config = $1;			if (WARN("PREFER_IS_ENABLED",				 "Prefer IS_ENABLED(<FOO>) to ${CONFIG_}<FOO> || ${CONFIG_}<FOO>_MODULE\n" . $herecurr) &&			    $fix) {				$fixed[$fixlinenr] = "\+#if IS_ENABLED($config)";			}		} # check for /* fallthrough */ like comment, prefer fallthrough;		my @fallthroughs = (			'fallthrough',			'@fallthrough@',			'lint -fallthrough[ \t]*',			'intentional(?:ly)?[ \t]*fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)',			'(?:else,?\s*)?FALL(?:S | |-)?THR(?:OUGH|U|EW)[ \t.!]*(?:-[^\n\r]*)?',			'Fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',			'fall(?:s | |-)?thr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',		    );		if ($raw_comment ne '') {			foreach my $ft (@fallthroughs) {				if ($raw_comment =~ /$ft/) {					my $msg_level = \&WARN;					$msg_level = \&CHK if ($file);					&{$msg_level}("PREFER_FALLTHROUGH",						      "Prefer 'fallthrough;' over fallthrough comment\n" . $herecurr);					last;				}			}		} # check for switch/default statements without a break;		if ($perl_version_ok &&		    defined $stat &&		    $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) {			my $cnt = statement_rawlines($stat);			my $herectx = get_stat_here($linenr, $cnt, $here); 			WARN("DEFAULT_NO_BREAK",			     "switch default: should use break\n" . $herectx);		} # check for gcc specific __FUNCTION__		if ($line =~ /\b__FUNCTION__\b/) {			if (WARN("USE_FUNC",				 "__func__ should be used instead of gcc specific __FUNCTION__\n"  . $herecurr) &&			    $fix) {				$fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g;			}		} # check for uses of __DATE__, __TIME__, __TIMESTAMP__		while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) {			ERROR("DATE_TIME",			      "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr);		} # check for use of yield()		if ($line =~ /\byield\s*\(\s*\)/) {			WARN("YIELD",			     "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n"  . $herecurr);		} # check for comparisons against true and false		if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) {			my $lead = $1;			my $arg = $2;			my $test = $3;			my $otype = $4;			my $trail = $5;			my $op = "!"; 			($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i); 			my $type = lc($otype);			if ($type =~ /^(?:true|false)$/) {

Lines 7001–7500 of 7976. Previous lines