Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

checkpatch: add new warnings to author signoff checks.

The author signed-off-by checks are currently very vague. Cases like same
name or same address are not handled separately.

For example, running checkpatch on commit be6577af0cef ("parisc: Add
atomic64_set_release() define to avoid CPU soft lockups"), gives:

WARNING: Missing Signed-off-by: line by nominal patch author
'John David Anglin <dave.anglin@bell.net>'

The signoff line was:
"Signed-off-by: Dave Anglin <dave.anglin@bell.net>"

Clearly the author has signed off but with a slightly different version
of his name. A more appropriate warning would have been to point out
at the name mismatch instead.

Previously, the values assumed by $authorsignoff were either 0 or 1
to indicate whether a proper sign off by author is present.
Extended the checks to handle four new cases.

$authorsignoff values now denote the following:

0: Missing sign off by patch author.

1: Sign off present and identical.

2: Addresses and names match, but comments differ.
"James Watson(JW) <james@gmail.com>", "James Watson <james@gmail.com>"

3: Addresses match, but names are different.
"James Watson <james@gmail.com>", "James <james@gmail.com>"

4: Names match, but addresses are different.
"James Watson <james@watson.com>", "James Watson <james@gmail.com>"

5: Names match, addresses excluding subaddress details (RFC 5233) match.
"James Watson <james@gmail.com>", "James Watson <james+a@gmail.com>"

Also introduced a new message type FROM_SIGN_OFF_MISMATCH
for cases 2, 3, 4 and 5.

Suggested-by: Joe Perches <joe@perches.com>
Signed-off-by: Dwaipayan Ray <dwaipayanray1@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Joe Perches <joe@perches.com>
Link: https://lore.kernel.org/linux-kernel-mentees/c1ca28e77e8e3bfa7aadf3efa8ed70f97a9d369c.camel@perches.com/
Link: https://lkml.kernel.org/r/20201007192029.551744-1-dwaipayanray1@gmail.com
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Dwaipayan Ray and committed by
Linus Torvalds
48ca2d8a c70735c2

+77 -16
+77 -16
scripts/checkpatch.pl
··· 1181 1181 } 1182 1182 } 1183 1183 1184 + $comment = trim($comment); 1184 1185 $name = trim($name); 1185 1186 $name =~ s/^\"|\"$//g; 1186 - $name =~ s/(\s*\([^\)]+\))\s*//; 1187 - if (defined($1)) { 1187 + if ($name =~ s/(\s*\([^\)]+\))\s*//) { 1188 1188 $name_comment = trim($1); 1189 1189 } 1190 1190 $address = trim($address); ··· 1199 1199 } 1200 1200 1201 1201 sub format_email { 1202 - my ($name, $address) = @_; 1202 + my ($name, $name_comment, $address, $comment) = @_; 1203 1203 1204 1204 my $formatted_email; 1205 1205 1206 + $name_comment = trim($name_comment); 1207 + $comment = trim($comment); 1206 1208 $name = trim($name); 1207 1209 $name =~ s/^\"|\"$//g; 1208 1210 $address = trim($address); ··· 1217 1215 if ("$name" eq "") { 1218 1216 $formatted_email = "$address"; 1219 1217 } else { 1220 - $formatted_email = "$name <$address>"; 1218 + $formatted_email = "$name$name_comment <$address>"; 1221 1219 } 1222 - 1220 + $formatted_email .= "$comment"; 1223 1221 return $formatted_email; 1224 1222 } 1225 1223 ··· 1227 1225 my ($email) = @_; 1228 1226 1229 1227 my ($email_name, $name_comment, $email_address, $comment) = parse_email($email); 1230 - return format_email($email_name, $email_address); 1228 + return format_email($email_name, $name_comment, $email_address, $comment); 1231 1229 } 1232 1230 1233 1231 sub same_email_addresses { 1234 - my ($email1, $email2) = @_; 1232 + my ($email1, $email2, $match_comment) = @_; 1235 1233 1236 1234 my ($email1_name, $name1_comment, $email1_address, $comment1) = parse_email($email1); 1237 1235 my ($email2_name, $name2_comment, $email2_address, $comment2) = parse_email($email2); 1238 1236 1237 + if ($match_comment != 1) { 1238 + return $email1_name eq $email2_name && 1239 + $email1_address eq $email2_address; 1240 + } 1239 1241 return $email1_name eq $email2_name && 1240 - $email1_address eq $email2_address; 1242 + $email1_address eq $email2_address && 1243 + $name1_comment eq $name2_comment && 1244 + $comment1 eq $comment2; 1241 1245 } 1242 1246 1243 1247 sub which { ··· 2373 2365 my $signoff = 0; 2374 2366 my $author = ''; 2375 2367 my $authorsignoff = 0; 2368 + my $author_sob = ''; 2376 2369 my $is_patch = 0; 2377 2370 my $is_binding_patch = -1; 2378 2371 my $in_header_lines = $file ? 0 : 1; ··· 2701 2692 if ($line =~ /^\s*signed-off-by:\s*(.*)/i) { 2702 2693 $signoff++; 2703 2694 $in_commit_log = 0; 2704 - if ($author ne '') { 2705 - if (same_email_addresses($1, $author)) { 2695 + if ($author ne '' && $authorsignoff != 1) { 2696 + if (same_email_addresses($1, $author, 1)) { 2706 2697 $authorsignoff = 1; 2698 + } else { 2699 + my $ctx = $1; 2700 + my ($email_name, $email_comment, $email_address, $comment1) = parse_email($ctx); 2701 + my ($author_name, $author_comment, $author_address, $comment2) = parse_email($author); 2702 + 2703 + if ($email_address eq $author_address && $email_name eq $author_name) { 2704 + $author_sob = $ctx; 2705 + $authorsignoff = 2; 2706 + } elsif ($email_address eq $author_address) { 2707 + $author_sob = $ctx; 2708 + $authorsignoff = 3; 2709 + } elsif ($email_name eq $author_name) { 2710 + $author_sob = $ctx; 2711 + $authorsignoff = 4; 2712 + 2713 + my $address1 = $email_address; 2714 + my $address2 = $author_address; 2715 + 2716 + if ($address1 =~ /(\S+)\+\S+(\@.*)/) { 2717 + $address1 = "$1$2"; 2718 + } 2719 + if ($address2 =~ /(\S+)\+\S+(\@.*)/) { 2720 + $address2 = "$1$2"; 2721 + } 2722 + if ($address1 eq $address2) { 2723 + $authorsignoff = 5; 2724 + } 2725 + } 2707 2726 } 2708 2727 } 2709 2728 } ··· 2788 2751 } 2789 2752 2790 2753 my ($email_name, $name_comment, $email_address, $comment) = parse_email($email); 2791 - my $suggested_email = format_email(($email_name, $email_address)); 2754 + my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment)); 2792 2755 if ($suggested_email eq "") { 2793 2756 ERROR("BAD_SIGN_OFF", 2794 2757 "Unrecognized email address: '$email'\n" . $herecurr); ··· 2798 2761 $dequoted =~ s/" </ </; 2799 2762 # Don't force email to have quotes 2800 2763 # Allow just an angle bracketed address 2801 - if (!same_email_addresses($email, $suggested_email)) { 2764 + if (!same_email_addresses($email, $suggested_email, 0)) { 2802 2765 WARN("BAD_SIGN_OFF", 2803 - "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr); 2766 + "email address '$email' might be better as '$suggested_email'\n" . $herecurr); 2804 2767 } 2805 2768 } 2806 2769 ··· 6980 6943 if ($signoff == 0) { 6981 6944 ERROR("MISSING_SIGN_OFF", 6982 6945 "Missing Signed-off-by: line(s)\n"); 6983 - } elsif (!$authorsignoff) { 6984 - WARN("NO_AUTHOR_SIGN_OFF", 6985 - "Missing Signed-off-by: line by nominal patch author '$author'\n"); 6946 + } elsif ($authorsignoff != 1) { 6947 + # authorsignoff values: 6948 + # 0 -> missing sign off 6949 + # 1 -> sign off identical 6950 + # 2 -> names and addresses match, comments mismatch 6951 + # 3 -> addresses match, names different 6952 + # 4 -> names match, addresses different 6953 + # 5 -> names match, addresses excluding subaddress details (refer RFC 5233) match 6954 + 6955 + my $sob_msg = "'From: $author' != 'Signed-off-by: $author_sob'"; 6956 + 6957 + if ($authorsignoff == 0) { 6958 + ERROR("NO_AUTHOR_SIGN_OFF", 6959 + "Missing Signed-off-by: line by nominal patch author '$author'\n"); 6960 + } elsif ($authorsignoff == 2) { 6961 + CHK("FROM_SIGN_OFF_MISMATCH", 6962 + "From:/Signed-off-by: email comments mismatch: $sob_msg\n"); 6963 + } elsif ($authorsignoff == 3) { 6964 + WARN("FROM_SIGN_OFF_MISMATCH", 6965 + "From:/Signed-off-by: email name mismatch: $sob_msg\n"); 6966 + } elsif ($authorsignoff == 4) { 6967 + WARN("FROM_SIGN_OFF_MISMATCH", 6968 + "From:/Signed-off-by: email address mismatch: $sob_msg\n"); 6969 + } elsif ($authorsignoff == 5) { 6970 + WARN("FROM_SIGN_OFF_MISMATCH", 6971 + "From:/Signed-off-by: email subaddress mismatch: $sob_msg\n"); 6972 + } 6986 6973 } 6987 6974 } 6988 6975