@@ -1272,6 +1272,58 @@ static int peel_onion(struct repository *r, const char *name, int len,
12721272 return 0 ;
12731273}
12741274
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+
12751327static int get_describe_name (struct repository * r ,
12761328 const char * name , int len ,
12771329 struct object_id * oid )
@@ -1285,7 +1337,8 @@ static int get_describe_name(struct repository *r,
12851337 /* We must be looking at g in "SOMETHING-g"
12861338 * for it to be describe output.
12871339 */
1288- if (ch == 'g' && cp [-1 ] == '-' ) {
1340+ if (ch == 'g' && cp [-1 ] == '-' &&
1341+ ref_and_count_parts_valid (name , cp - 1 - name )) {
12891342 cp ++ ;
12901343 len -= cp - name ;
12911344 return get_short_oid (r ,
@@ -2052,12 +2105,14 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo,
20522105 return -1 ;
20532106 }
20542107 for (cp = name , bracket_depth = 0 ; * cp ; cp ++ ) {
2055- if (* cp == '{' )
2108+ if (strchr ("@^" , * cp ) && cp [1 ] == '{' ) {
2109+ cp ++ ;
20562110 bracket_depth ++ ;
2057- else if (bracket_depth && * cp == '}' )
2111+ } else if (bracket_depth && * cp == '}' ) {
20582112 bracket_depth -- ;
2059- else if (!bracket_depth && * cp == ':' )
2113+ } else if (!bracket_depth && * cp == ':' ) {
20602114 break ;
2115+ }
20612116 }
20622117 if (* cp == ':' ) {
20632118 struct object_id tree_oid ;
0 commit comments