Skip to content
Snippets Groups Projects
checkpatch.pl 121 KiB
Newer Older
  • Learn to ignore specific revisions
  • 					$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 ($^V && $^V ge 5.10.0 &&
    		    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.txt\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.txt\n" . "$here\n$stat\n");
    			}
    		}
    
    
    # check for naked sscanf
    		if ($^V && $^V ge 5.10.0 &&
    		    defined $stat &&
    		    $stat =~ /\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 = raw_line($linenr, 0);
    		        for (my $count = $linenr + 1; $count <= $lc; $count++) {
    				$stat_real = $stat_real . "\n" . raw_line($count, 0);
    			}
    			WARN("NAKED_SSCANF",
    			     "unchecked sscanf return value\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[$linenr - 1] =~ 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*;/ &&
    			    $function_name ne 'uninitialized_var')
    			{
    
    				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);
    
    		}
    
    # 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/kernel-parameters.txt\n" . $herecurr);
    
    
    # check for pointless casting of kmalloc return
    
    		if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\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 ($^V && $^V ge 5.10.0 &&
    		    $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][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 krealloc arg reuse
    		if ($^V && $^V ge 5.10.0 &&
    		    $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) {
    			WARN("KREALLOC_ARG_REUSE",
    			     "Reusing the krealloc arg is almost always a bug\n" . $herecurr);
    		}
    
    
    # check for alloc argument mismatch
    		if ($line =~ /\b(kcalloc|kmalloc_array)\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[$linenr - 1] =~ s/(\s*;\s*){2,}$/;/g;
    			}
    
    		}
    
    # check for switch/default statements without a break;
    		if ($^V && $^V ge 5.10.0 &&
    		    defined $stat &&
    		    $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) {
    			my $ctx = '';
    			my $herectx = $here . "\n";
    			my $cnt = statement_rawlines($stat);
    			for (my $n = 0; $n < $cnt; $n++) {
    				$herectx .= raw_line($linenr, $n) . "\n";
    			}
    			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[$linenr - 1] =~ s/\b__FUNCTION__\b/__func__/g;
    			}
    
    # 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)$/) {
    				if (("$test" eq "==" && "$type" eq "true") ||
    				    ("$test" eq "!=" && "$type" eq "false")) {
    					$op = "";
    				}
    
    				CHK("BOOL_COMPARISON",
    				    "Using comparison to $otype is error prone\n" . $herecurr);
    
    ## maybe suggesting a correct construct would better
    ##				    "Using comparison to $otype is error prone.  Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr);
    
    			}
    		}
    
    
    # check for semaphores initialized locked
    		if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
    
    			WARN("CONSIDER_COMPLETION",
    			     "consider using a completion\n" . $herecurr);
    
    # recommend kstrto* over simple_strto* and strict_strto*
    		if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) {
    
    			WARN("CONSIDER_KSTRTO",
    
    			     "$1 is obsolete, use k$3 instead\n" . $herecurr);
    
    # check for __initcall(), use device_initcall() explicitly please
    		if ($line =~ /^.\s*__initcall\s*\(/) {
    
    			WARN("USE_DEVICE_INITCALL",
    			     "please use device_initcall() instead of __initcall()\n" . $herecurr);
    
    # check for various ops structs, ensure they are const.
    		my $struct_ops = qr{acpi_dock_ops|
    				address_space_operations|
    				backlight_ops|
    				block_device_operations|
    				dentry_operations|
    				dev_pm_ops|
    				dma_map_ops|
    				extent_io_ops|
    				file_lock_operations|
    				file_operations|
    				hv_ops|
    				ide_dma_ops|
    				intel_dvo_dev_ops|
    				item_operations|
    				iwl_ops|
    				kgdb_arch|
    				kgdb_io|
    				kset_uevent_ops|
    				lock_manager_operations|
    				microcode_ops|
    				mtrr_ops|
    				neigh_ops|
    				nlmsvc_binding|
    				pci_raw_ops|
    				pipe_buf_operations|
    				platform_hibernation_ops|
    				platform_suspend_ops|
    				proto_ops|
    				rpc_pipe_ops|
    				seq_operations|
    				snd_ac97_build_ops|
    				soc_pcmcia_socket_ops|
    				stacktrace_ops|
    				sysfs_ops|
    				tty_operations|
    				usb_mon_operations|
    				wd_ops}x;
    
    		if ($line !~ /\bconst\b/ &&
    
    		    $line =~ /\bstruct\s+($struct_ops)\b/) {
    
    			WARN("CONST_STRUCT",
    			     "struct $1 should normally be const\n" .
    
    
    # use of NR_CPUS is usually wrong
    # ignore definitions of NR_CPUS and usage to define arrays as likely right
    		if ($line =~ /\bNR_CPUS\b/ &&
    
    		    $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
    		    $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
    
    		    $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
    		    $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
    		    $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/)
    
    			WARN("NR_CPUS",
    			     "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
    
    # Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong.
    		if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) {
    			ERROR("DEFINE_ARCH_HAS",
    			      "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr);
    		}
    
    
    # check for %L{u,d,i} in strings
    		my $string;
    		while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
    			$string = substr($rawline, $-[1], $+[1] - $-[1]);
    
    			$string =~ s/%%/__/g;
    
    			if ($string =~ /(?<!%)%L[udi]/) {
    
    				WARN("PRINTF_L",
    				     "\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr);
    
    
    # whine mightly about in_atomic
    		if ($line =~ /\bin_atomic\s*\(/) {
    			if ($realfile =~ m@^drivers/@) {
    
    				ERROR("IN_ATOMIC",
    				      "do not use in_atomic in drivers\n" . $herecurr);
    
    			} elsif ($realfile !~ m@^kernel/@) {
    
    				WARN("IN_ATOMIC",
    				     "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
    
    
    # check for lockdep_set_novalidate_class
    		if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
    		    $line =~ /__lockdep_no_validate__\s*\)/ ) {
    			if ($realfile !~ m@^kernel/lockdep@ &&
    			    $realfile !~ m@^include/linux/lockdep@ &&
    			    $realfile !~ m@^drivers/base/core@) {
    
    				ERROR("LOCKDEP",
    				      "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
    
    
    		if ($line =~ /debugfs_create_file.*S_IWUGO/ ||
    		    $line =~ /DEVICE_ATTR.*S_IWUGO/ ) {
    
    			WARN("EXPORTED_WORLD_WRITABLE",
    			     "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
    
    	}
    
    	# If we have no input at all, then there is nothing to report on
    	# so just keep quiet.
    	if ($#rawlines == -1) {
    		exit(0);
    
    	# In mailback mode only produce a report in the negative, for
    	# things that appear to be patches.
    	if ($mailback && ($clean == 1 || !$is_patch)) {
    		exit(0);
    	}
    
    	# This is not a patch, and we are are in 'no-patch' mode so
    	# just keep quiet.
    	if (!$chk_patch && !$is_patch) {
    		exit(0);
    	}
    
    	if (!$is_patch) {
    
    		ERROR("NOT_UNIFIED_DIFF",
    		      "Does not appear to be a unified-diff format patch\n");
    
    	}
    	if ($is_patch && $chk_signoff && $signoff == 0) {
    
    		ERROR("MISSING_SIGN_OFF",
    		      "Missing Signed-off-by: line(s)\n");
    
    	print report_dump();
    
    	if ($summary && !($clean == 1 && $quiet == 1)) {
    		print "$filename " if ($summary_file);
    
    		print "total: $cnt_error errors, $cnt_warn warnings, " .
    			(($check)? "$cnt_chk checks, " : "") .
    			"$cnt_lines lines checked\n";
    		print "\n" if ($quiet == 0);
    
    
    		if ($^V lt 5.10.0) {
    			print("NOTE: perl $^V is not modern enough to detect all possible issues.\n");
    			print("An upgrade to at least perl v5.10.0 is suggested.\n\n");
    		}
    
    
    		# If there were whitespace errors which cleanpatch can fix
    		# then suggest that.
    		if ($rpt_cleaners) {
    			print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
    			print "      scripts/cleanfile\n\n";
    
    	hash_show_words(\%use_type, "Used");
    	hash_show_words(\%ignore_type, "Ignored");
    
    	if ($clean == 0 && $fix && "@rawlines" ne "@fixed") {
    		my $newfile = $filename . ".EXPERIMENTAL-checkpatch-fixes";
    		my $linecount = 0;
    		my $f;
    
    		open($f, '>', $newfile)
    		    or die "$P: Can't open $newfile for write\n";
    		foreach my $fixed_line (@fixed) {
    			$linecount++;
    			if ($file) {
    				if ($linecount > 3) {
    					$fixed_line =~ s/^\+//;
    					print $f $fixed_line. "\n";
    				}
    			} else {
    				print $f $fixed_line . "\n";
    			}
    		}
    		close($f);
    
    		if (!$quiet) {
    			print << "EOM";
    Wrote EXPERIMENTAL --fix correction(s) to '$newfile'
    
    Do _NOT_ trust the results written to this file.
    Do _NOT_ submit these changes without inspecting them for correctness.
    
    This EXPERIMENTAL file is simply a convenience to help rewrite patches.
    No warranties, expressed or implied...
    
    EOM
    		}
    	}
    
    
    	if ($clean == 1 && $quiet == 0) {
    
    		print "$vname has no obvious style problems and is ready for submission.\n"
    
    	}
    	if ($clean == 0 && $quiet == 0) {
    
    		print << "EOM";
    $vname has style problems, please review.
    
    If any of these errors are false positives, please report
    them to the maintainer, see CHECKPATCH in MAINTAINERS.
    EOM
    
    	return $clean;
    }