@@ -995,7 +995,7 @@ static const char *gpg_sig_headers[] = {
995995 "gpgsig-sha256" ,
996996};
997997
998- static int do_sign_commit (struct strbuf * buf , const char * keyid )
998+ int sign_with_header (struct strbuf * buf , const char * keyid )
999999{
10001000 struct strbuf sig = STRBUF_INIT ;
10011001 int inspos , copypos ;
@@ -1035,31 +1035,48 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid)
10351035 return 0 ;
10361036}
10371037
1038+
1039+
10381040int parse_signed_commit (const struct commit * commit ,
1039- struct strbuf * payload , struct strbuf * signature )
1041+ struct strbuf * payload , struct strbuf * signature ,
1042+ const struct git_hash_algo * algop )
10401043{
1041-
10421044 unsigned long size ;
10431045 const char * buffer = get_commit_buffer (commit , & size );
1044- int in_signature , saw_signature = -1 ;
1045- const char * line , * tail ;
1046- const char * gpg_sig_header = gpg_sig_headers [hash_algo_by_ptr (the_hash_algo )];
1047- int gpg_sig_header_len = strlen (gpg_sig_header );
1046+ int ret = parse_buffer_signed_by_header (buffer , size , payload , signature , algop );
1047+
1048+ unuse_commit_buffer (commit , buffer );
1049+ return ret ;
1050+ }
1051+
1052+ int parse_buffer_signed_by_header (const char * buffer ,
1053+ unsigned long size ,
1054+ struct strbuf * payload ,
1055+ struct strbuf * signature ,
1056+ const struct git_hash_algo * algop )
1057+ {
1058+ int in_signature = 0 , saw_signature = 0 , other_signature = 0 ;
1059+ const char * line , * tail , * p ;
1060+ const char * gpg_sig_header = gpg_sig_headers [hash_algo_by_ptr (algop )];
10481061
10491062 line = buffer ;
10501063 tail = buffer + size ;
1051- in_signature = 0 ;
1052- saw_signature = 0 ;
10531064 while (line < tail ) {
10541065 const char * sig = NULL ;
10551066 const char * next = memchr (line , '\n' , tail - line );
10561067
10571068 next = next ? next + 1 : tail ;
10581069 if (in_signature && line [0 ] == ' ' )
10591070 sig = line + 1 ;
1060- else if (starts_with (line , gpg_sig_header ) &&
1061- line [gpg_sig_header_len ] == ' ' )
1062- sig = line + gpg_sig_header_len + 1 ;
1071+ else if (skip_prefix (line , gpg_sig_header , & p ) &&
1072+ * p == ' ' ) {
1073+ sig = line + strlen (gpg_sig_header ) + 1 ;
1074+ other_signature = 0 ;
1075+ }
1076+ else if (starts_with (line , "gpgsig" ))
1077+ other_signature = 1 ;
1078+ else if (other_signature && line [0 ] != ' ' )
1079+ other_signature = 0 ;
10631080 if (sig ) {
10641081 strbuf_add (signature , sig , next - sig );
10651082 saw_signature = 1 ;
@@ -1068,12 +1085,12 @@ int parse_signed_commit(const struct commit *commit,
10681085 if (* line == '\n' )
10691086 /* dump the whole remainder of the buffer */
10701087 next = tail ;
1071- strbuf_add (payload , line , next - line );
1088+ if (!other_signature )
1089+ strbuf_add (payload , line , next - line );
10721090 in_signature = 0 ;
10731091 }
10741092 line = next ;
10751093 }
1076- unuse_commit_buffer (commit , buffer );
10771094 return saw_signature ;
10781095}
10791096
@@ -1082,57 +1099,67 @@ int remove_signature(struct strbuf *buf)
10821099 const char * line = buf -> buf ;
10831100 const char * tail = buf -> buf + buf -> len ;
10841101 int in_signature = 0 ;
1085- const char * sig_start = NULL ;
1086- const char * sig_end = NULL ;
1102+ struct sigbuf {
1103+ const char * start ;
1104+ const char * end ;
1105+ } sigs [2 ], * sigp = & sigs [0 ];
1106+ int i ;
1107+ const char * orig_buf = buf -> buf ;
1108+
1109+ memset (sigs , 0 , sizeof (sigs ));
10871110
10881111 while (line < tail ) {
10891112 const char * next = memchr (line , '\n' , tail - line );
10901113 next = next ? next + 1 : tail ;
10911114
10921115 if (in_signature && line [0 ] == ' ' )
1093- sig_end = next ;
1116+ sigp -> end = next ;
10941117 else if (starts_with (line , "gpgsig" )) {
10951118 int i ;
10961119 for (i = 1 ; i < GIT_HASH_NALGOS ; i ++ ) {
10971120 const char * p ;
10981121 if (skip_prefix (line , gpg_sig_headers [i ], & p ) &&
10991122 * p == ' ' ) {
1100- sig_start = line ;
1101- sig_end = next ;
1123+ sigp -> start = line ;
1124+ sigp -> end = next ;
11021125 in_signature = 1 ;
11031126 }
11041127 }
11051128 } else {
11061129 if (* line == '\n' )
11071130 /* dump the whole remainder of the buffer */
11081131 next = tail ;
1132+ if (in_signature && sigp - sigs != ARRAY_SIZE (sigs ))
1133+ sigp ++ ;
11091134 in_signature = 0 ;
11101135 }
11111136 line = next ;
11121137 }
11131138
1114- if (sig_start )
1115- strbuf_remove (buf , sig_start - buf -> buf , sig_end - sig_start );
1139+ for (i = ARRAY_SIZE (sigs ) - 1 ; i >= 0 ; i -- )
1140+ if (sigs [i ].start )
1141+ strbuf_remove (buf , sigs [i ].start - orig_buf , sigs [i ].end - sigs [i ].start );
11161142
1117- return sig_start != NULL ;
1143+ return sigs [ 0 ]. start != NULL ;
11181144}
11191145
11201146static void handle_signed_tag (struct commit * parent , struct commit_extra_header * * * tail )
11211147{
11221148 struct merge_remote_desc * desc ;
11231149 struct commit_extra_header * mergetag ;
11241150 char * buf ;
1125- unsigned long size , len ;
1151+ unsigned long size ;
11261152 enum object_type type ;
1153+ struct strbuf payload = STRBUF_INIT ;
1154+ struct strbuf signature = STRBUF_INIT ;
11271155
11281156 desc = merge_remote_util (parent );
11291157 if (!desc || !desc -> obj )
11301158 return ;
11311159 buf = read_object_file (& desc -> obj -> oid , & type , & size );
11321160 if (!buf || type != OBJ_TAG )
11331161 goto free_return ;
1134- len = parse_signature (buf , size );
1135- if (size == len )
1162+ if (!parse_signature (buf , size , & payload , & signature ))
11361163 goto free_return ;
11371164 /*
11381165 * We could verify this signature and either omit the tag when
@@ -1151,6 +1178,8 @@ static void handle_signed_tag(struct commit *parent, struct commit_extra_header
11511178
11521179 * * tail = mergetag ;
11531180 * tail = & mergetag -> next ;
1181+ strbuf_release (& payload );
1182+ strbuf_release (& signature );
11541183 return ;
11551184
11561185free_return :
@@ -1165,7 +1194,7 @@ int check_commit_signature(const struct commit *commit, struct signature_check *
11651194
11661195 sigc -> result = 'N' ;
11671196
1168- if (parse_signed_commit (commit , & payload , & signature ) <= 0 )
1197+ if (parse_signed_commit (commit , & payload , & signature , the_hash_algo ) <= 0 )
11691198 goto out ;
11701199 ret = check_signature (payload .buf , payload .len , signature .buf ,
11711200 signature .len , sigc );
@@ -1515,7 +1544,7 @@ int commit_tree_extended(const char *msg, size_t msg_len,
15151544 if (encoding_is_utf8 && !verify_utf8 (& buffer ))
15161545 fprintf (stderr , _ (commit_utf8_warn ));
15171546
1518- if (sign_commit && do_sign_commit (& buffer , sign_commit )) {
1547+ if (sign_commit && sign_with_header (& buffer , sign_commit )) {
15191548 result = -1 ;
15201549 goto out ;
15211550 }
0 commit comments