@@ -1095,15 +1095,23 @@ static int gitdiff_unrecognized(const char *line, struct patch *patch)
1095
1095
return -1 ;
1096
1096
}
1097
1097
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 )
1099
1103
{
1100
- int nslash = p_value ;
1104
+ int nslash ;
1101
1105
int i ;
1102
1106
1107
+ if (!p_value )
1108
+ return (llen && line [0 ] == '/' ) ? NULL : line ;
1109
+
1110
+ nslash = p_value ;
1103
1111
for (i = 0 ; i < llen ; i ++ ) {
1104
1112
int ch = line [i ];
1105
1113
if (ch == '/' && -- nslash <= 0 )
1106
- return & line [i ];
1114
+ return ( i == 0 ) ? NULL : & line [i + 1 ];
1107
1115
}
1108
1116
return NULL ;
1109
1117
}
@@ -1133,12 +1141,11 @@ static char *git_header_name(const char *line, int llen)
1133
1141
if (unquote_c_style (& first , line , & second ))
1134
1142
goto free_and_fail1 ;
1135
1143
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 )
1140
1147
goto free_and_fail1 ;
1141
- strbuf_remove (& first , 0 , cp + 1 - first .buf );
1148
+ strbuf_remove (& first , 0 , cp - first .buf );
1142
1149
1143
1150
/*
1144
1151
* second points at one past closing dq of name.
@@ -1152,22 +1159,21 @@ static char *git_header_name(const char *line, int llen)
1152
1159
if (* second == '"' ) {
1153
1160
if (unquote_c_style (& sp , second , NULL ))
1154
1161
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 )
1157
1164
goto free_and_fail1 ;
1158
1165
/* They must match, otherwise ignore */
1159
- if (strcmp (cp + 1 , first .buf ))
1166
+ if (strcmp (cp , first .buf ))
1160
1167
goto free_and_fail1 ;
1161
1168
strbuf_release (& sp );
1162
1169
return strbuf_detach (& first , NULL );
1163
1170
}
1164
1171
1165
1172
/* 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 )
1168
1175
goto free_and_fail1 ;
1169
- cp ++ ;
1170
- if (line + llen - cp != first .len + 1 ||
1176
+ if (line + llen - cp != first .len ||
1171
1177
memcmp (first .buf , cp , first .len ))
1172
1178
goto free_and_fail1 ;
1173
1179
return strbuf_detach (& first , NULL );
@@ -1179,10 +1185,9 @@ static char *git_header_name(const char *line, int llen)
1179
1185
}
1180
1186
1181
1187
/* 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 )
1184
1190
return NULL ;
1185
- name ++ ;
1186
1191
1187
1192
/*
1188
1193
* 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)
1196
1201
if (unquote_c_style (& sp , second , NULL ))
1197
1202
goto free_and_fail2 ;
1198
1203
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 )
1201
1206
goto free_and_fail2 ;
1202
- np ++ ;
1203
1207
1204
1208
len = sp .buf + sp .len - np ;
1205
1209
if (len < second - name &&
@@ -1231,13 +1235,27 @@ static char *git_header_name(const char *line, int llen)
1231
1235
case '\n' :
1232
1236
return NULL ;
1233
1237
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 ));
1235
1250
if (!second )
1236
1251
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 ))
1239
1258
return xmemdupz (name , len );
1240
- }
1241
1259
}
1242
1260
}
1243
1261
}
0 commit comments