@@ -1095,15 +1095,23 @@ static int gitdiff_unrecognized(const char *line, struct patch *patch)
10951095 return -1 ;
10961096}
10971097
1098- static const char * stop_at_slash (const char * line , int llen )
1098+ /*
1099+ * Skip p_value leading components from "line"; as we do not accept
1100+ * absolute paths, return NULL in that case.
1101+ */
1102+ static const char * skip_tree_prefix (const char * line , int llen )
10991103{
1100- int nslash = p_value ;
1104+ int nslash ;
11011105 int i ;
11021106
1107+ if (!p_value )
1108+ return (llen && line [0 ] == '/' ) ? NULL : line ;
1109+
1110+ nslash = p_value ;
11031111 for (i = 0 ; i < llen ; i ++ ) {
11041112 int ch = line [i ];
11051113 if (ch == '/' && -- nslash <= 0 )
1106- return & line [i ];
1114+ return ( i == 0 ) ? NULL : & line [i + 1 ];
11071115 }
11081116 return NULL ;
11091117}
@@ -1133,12 +1141,11 @@ static char *git_header_name(const char *line, int llen)
11331141 if (unquote_c_style (& first , line , & second ))
11341142 goto free_and_fail1 ;
11351143
1136- /* advance to the first slash */
1137- cp = stop_at_slash (first .buf , first .len );
1138- /* we do not accept absolute paths */
1139- if (!cp || cp == first .buf )
1144+ /* strip the a/b prefix including trailing slash */
1145+ cp = skip_tree_prefix (first .buf , first .len );
1146+ if (!cp )
11401147 goto free_and_fail1 ;
1141- strbuf_remove (& first , 0 , cp + 1 - first .buf );
1148+ strbuf_remove (& first , 0 , cp - first .buf );
11421149
11431150 /*
11441151 * second points at one past closing dq of name.
@@ -1152,22 +1159,21 @@ static char *git_header_name(const char *line, int llen)
11521159 if (* second == '"' ) {
11531160 if (unquote_c_style (& sp , second , NULL ))
11541161 goto free_and_fail1 ;
1155- cp = stop_at_slash (sp .buf , sp .len );
1156- if (!cp || cp == sp . buf )
1162+ cp = skip_tree_prefix (sp .buf , sp .len );
1163+ if (!cp )
11571164 goto free_and_fail1 ;
11581165 /* They must match, otherwise ignore */
1159- if (strcmp (cp + 1 , first .buf ))
1166+ if (strcmp (cp , first .buf ))
11601167 goto free_and_fail1 ;
11611168 strbuf_release (& sp );
11621169 return strbuf_detach (& first , NULL );
11631170 }
11641171
11651172 /* unquoted second */
1166- cp = stop_at_slash (second , line + llen - second );
1167- if (!cp || cp == second )
1173+ cp = skip_tree_prefix (second , line + llen - second );
1174+ if (!cp )
11681175 goto free_and_fail1 ;
1169- cp ++ ;
1170- if (line + llen - cp != first .len + 1 ||
1176+ if (line + llen - cp != first .len ||
11711177 memcmp (first .buf , cp , first .len ))
11721178 goto free_and_fail1 ;
11731179 return strbuf_detach (& first , NULL );
@@ -1179,10 +1185,9 @@ static char *git_header_name(const char *line, int llen)
11791185 }
11801186
11811187 /* unquoted first name */
1182- name = stop_at_slash (line , llen );
1183- if (!name || name == line )
1188+ name = skip_tree_prefix (line , llen );
1189+ if (!name )
11841190 return NULL ;
1185- name ++ ;
11861191
11871192 /*
11881193 * since the first name is unquoted, a dq if exists must be
@@ -1196,10 +1201,9 @@ static char *git_header_name(const char *line, int llen)
11961201 if (unquote_c_style (& sp , second , NULL ))
11971202 goto free_and_fail2 ;
11981203
1199- np = stop_at_slash (sp .buf , sp .len );
1200- if (!np || np == sp . buf )
1204+ np = skip_tree_prefix (sp .buf , sp .len );
1205+ if (!np )
12011206 goto free_and_fail2 ;
1202- np ++ ;
12031207
12041208 len = sp .buf + sp .len - np ;
12051209 if (len < second - name &&
@@ -1231,13 +1235,27 @@ static char *git_header_name(const char *line, int llen)
12311235 case '\n' :
12321236 return NULL ;
12331237 case '\t' : case ' ' :
1234- second = stop_at_slash (name + len , line_len - len );
1238+ /*
1239+ * Is this the separator between the preimage
1240+ * and the postimage pathname? Again, we are
1241+ * only interested in the case where there is
1242+ * no rename, as this is only to set def_name
1243+ * and a rename patch has the names elsewhere
1244+ * in an unambiguous form.
1245+ */
1246+ if (!name [len + 1 ])
1247+ return NULL ; /* no postimage name */
1248+ second = skip_tree_prefix (name + len + 1 ,
1249+ line_len - (len + 1 ));
12351250 if (!second )
12361251 return NULL ;
1237- second ++ ;
1238- if (second [len ] == '\n' && !strncmp (name , second , len )) {
1252+ /*
1253+ * Does len bytes starting at "name" and "second"
1254+ * (that are separated by one HT or SP we just
1255+ * found) exactly match?
1256+ */
1257+ if (second [len ] == '\n' && !strncmp (name , second , len ))
12391258 return xmemdupz (name , len );
1240- }
12411259 }
12421260 }
12431261}
0 commit comments