@@ -1272,6 +1272,58 @@ static int peel_onion(struct repository *r, const char *name, int len,
1272
1272
return 0 ;
1273
1273
}
1274
1274
1275
+ /*
1276
+ * Documentation/revisions.txt says:
1277
+ * '<describeOutput>', e.g. 'v1.7.4.2-679-g3bee7fb'::
1278
+ * Output from `git describe`; i.e. a closest tag, optionally
1279
+ * followed by a dash and a number of commits, followed by a dash, a
1280
+ * 'g', and an abbreviated object name.
1281
+ *
1282
+ * which means that the stuff before '-g${HASH}' needs to be a valid
1283
+ * refname, a dash, and a non-negative integer. This function verifies
1284
+ * that.
1285
+ *
1286
+ * In particular, we do not want to treat
1287
+ * branchname:path/to/file/named/i-gaffed
1288
+ * as a request for commit affed.
1289
+ *
1290
+ * More generally, we should probably not treat
1291
+ * 'refs/heads/./../.../ ~^:/?*[////\\\&}/busted.lock-g050e0ef6ead'
1292
+ * as a request for object 050e0ef6ead either.
1293
+ *
1294
+ * We are called with name[len] == '-' and name[len+1] == 'g', i.e.
1295
+ * we are verifying ${REFNAME}-{INTEGER} part of the name.
1296
+ */
1297
+ static int ref_and_count_parts_valid (const char * name , int len )
1298
+ {
1299
+ struct strbuf sb ;
1300
+ const char * cp ;
1301
+ int flags = REFNAME_ALLOW_ONELEVEL ;
1302
+ int ret = 1 ;
1303
+
1304
+ /* Ensure we have at least one digit */
1305
+ if (!isxdigit (name [len - 1 ]))
1306
+ return 0 ;
1307
+
1308
+ /* Skip over digits backwards until we get to the dash */
1309
+ for (cp = name + len - 2 ; name < cp ; cp -- ) {
1310
+ if (* cp == '-' )
1311
+ break ;
1312
+ if (!isxdigit (* cp ))
1313
+ return 0 ;
1314
+ }
1315
+ /* Ensure we found the leading dash */
1316
+ if (* cp != '-' )
1317
+ return 0 ;
1318
+
1319
+ len = cp - name ;
1320
+ strbuf_init (& sb , len );
1321
+ strbuf_add (& sb , name , len );
1322
+ ret = !check_refname_format (sb .buf , flags );
1323
+ strbuf_release (& sb );
1324
+ return ret ;
1325
+ }
1326
+
1275
1327
static int get_describe_name (struct repository * r ,
1276
1328
const char * name , int len ,
1277
1329
struct object_id * oid )
@@ -1285,7 +1337,8 @@ static int get_describe_name(struct repository *r,
1285
1337
/* We must be looking at g in "SOMETHING-g"
1286
1338
* for it to be describe output.
1287
1339
*/
1288
- if (ch == 'g' && cp [-1 ] == '-' ) {
1340
+ if (ch == 'g' && cp [-1 ] == '-' &&
1341
+ ref_and_count_parts_valid (name , cp - 1 - name )) {
1289
1342
cp ++ ;
1290
1343
len -= cp - name ;
1291
1344
return get_short_oid (r ,
@@ -2052,12 +2105,14 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo,
2052
2105
return -1 ;
2053
2106
}
2054
2107
for (cp = name , bracket_depth = 0 ; * cp ; cp ++ ) {
2055
- if (* cp == '{' )
2108
+ if (strchr ("@^" , * cp ) && cp [1 ] == '{' ) {
2109
+ cp ++ ;
2056
2110
bracket_depth ++ ;
2057
- else if (bracket_depth && * cp == '}' )
2111
+ } else if (bracket_depth && * cp == '}' ) {
2058
2112
bracket_depth -- ;
2059
- else if (!bracket_depth && * cp == ':' )
2113
+ } else if (!bracket_depth && * cp == ':' ) {
2060
2114
break ;
2115
+ }
2061
2116
}
2062
2117
if (* cp == ':' ) {
2063
2118
struct object_id tree_oid ;
0 commit comments