@@ -430,7 +430,7 @@ static inline int upstream_mark(const char *string, int len)
430430}
431431
432432static int get_sha1_1 (const char * name , int len , unsigned char * sha1 , unsigned lookup_flags );
433- static int interpret_nth_prior_checkout (const char * name , struct strbuf * buf );
433+ static int interpret_nth_prior_checkout (const char * name , int namelen , struct strbuf * buf );
434434
435435static int get_sha1_basic (const char * str , int len , unsigned char * sha1 )
436436{
@@ -492,7 +492,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
492492 struct strbuf buf = STRBUF_INIT ;
493493 int detached ;
494494
495- if (interpret_nth_prior_checkout (str , & buf ) > 0 ) {
495+ if (interpret_nth_prior_checkout (str , len , & buf ) > 0 ) {
496496 detached = (buf .len == 40 && !get_sha1_hex (buf .buf , sha1 ));
497497 strbuf_release (& buf );
498498 if (detached )
@@ -931,17 +931,20 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
931931 * Parse @{-N} syntax, return the number of characters parsed
932932 * if successful; otherwise signal an error with negative value.
933933 */
934- static int interpret_nth_prior_checkout (const char * name , struct strbuf * buf )
934+ static int interpret_nth_prior_checkout (const char * name , int namelen ,
935+ struct strbuf * buf )
935936{
936937 long nth ;
937938 int retval ;
938939 struct grab_nth_branch_switch_cbdata cb ;
939940 const char * brace ;
940941 char * num_end ;
941942
943+ if (namelen < 4 )
944+ return -1 ;
942945 if (name [0 ] != '@' || name [1 ] != '{' || name [2 ] != '-' )
943946 return -1 ;
944- brace = strchr (name , '}' );
947+ brace = memchr (name , '}' , namelen );
945948 if (!brace )
946949 return -1 ;
947950 nth = strtol (name + 3 , & num_end , 10 );
@@ -1014,7 +1017,7 @@ static int interpret_empty_at(const char *name, int namelen, int len, struct str
10141017 return -1 ;
10151018
10161019 /* make sure it's a single @, or @@{.*}, not @foo */
1017- next = strchr (name + len + 1 , '@' );
1020+ next = memchr (name + len + 1 , '@' , namelen - len - 1 );
10181021 if (next && next [1 ] != '{' )
10191022 return -1 ;
10201023 if (!next )
@@ -1048,6 +1051,57 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu
10481051 return ret - used + len ;
10491052}
10501053
1054+ static void set_shortened_ref (struct strbuf * buf , const char * ref )
1055+ {
1056+ char * s = shorten_unambiguous_ref (ref , 0 );
1057+ strbuf_reset (buf );
1058+ strbuf_addstr (buf , s );
1059+ free (s );
1060+ }
1061+
1062+ static const char * get_upstream_branch (const char * branch_buf , int len )
1063+ {
1064+ char * branch = xstrndup (branch_buf , len );
1065+ struct branch * upstream = branch_get (* branch ? branch : NULL );
1066+
1067+ /*
1068+ * Upstream can be NULL only if branch refers to HEAD and HEAD
1069+ * points to something different than a branch.
1070+ */
1071+ if (!upstream )
1072+ die (_ ("HEAD does not point to a branch" ));
1073+ if (!upstream -> merge || !upstream -> merge [0 ]-> dst ) {
1074+ if (!ref_exists (upstream -> refname ))
1075+ die (_ ("No such branch: '%s'" ), branch );
1076+ if (!upstream -> merge ) {
1077+ die (_ ("No upstream configured for branch '%s'" ),
1078+ upstream -> name );
1079+ }
1080+ die (
1081+ _ ("Upstream branch '%s' not stored as a remote-tracking branch" ),
1082+ upstream -> merge [0 ]-> src );
1083+ }
1084+ free (branch );
1085+
1086+ return upstream -> merge [0 ]-> dst ;
1087+ }
1088+
1089+ static int interpret_upstream_mark (const char * name , int namelen ,
1090+ int at , struct strbuf * buf )
1091+ {
1092+ int len ;
1093+
1094+ len = upstream_mark (name + at , namelen - at );
1095+ if (!len )
1096+ return -1 ;
1097+
1098+ if (memchr (name , ':' , at ))
1099+ return -1 ;
1100+
1101+ set_shortened_ref (buf , get_upstream_branch (name , at ));
1102+ return len + at ;
1103+ }
1104+
10511105/*
10521106 * This reads short-hand syntax that not only evaluates to a commit
10531107 * object name, but also can act as if the end user spelled the name
@@ -1071,10 +1125,9 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu
10711125 */
10721126int interpret_branch_name (const char * name , int namelen , struct strbuf * buf )
10731127{
1074- char * cp ;
1075- struct branch * upstream ;
1076- int len = interpret_nth_prior_checkout (name , buf );
1077- int tmp_len ;
1128+ char * at ;
1129+ const char * start ;
1130+ int len = interpret_nth_prior_checkout (name , namelen , buf );
10781131
10791132 if (!namelen )
10801133 namelen = strlen (name );
@@ -1088,44 +1141,20 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
10881141 return reinterpret (name , namelen , len , buf );
10891142 }
10901143
1091- cp = strchr (name , '@' );
1092- if (!cp )
1093- return -1 ;
1094-
1095- len = interpret_empty_at (name , namelen , cp - name , buf );
1096- if (len > 0 )
1097- return reinterpret (name , namelen , len , buf );
1144+ for (start = name ;
1145+ (at = memchr (start , '@' , namelen - (start - name )));
1146+ start = at + 1 ) {
10981147
1099- tmp_len = upstream_mark ( cp , namelen - ( cp - name ) );
1100- if (! tmp_len )
1101- return -1 ;
1148+ len = interpret_empty_at ( name , namelen , at - name , buf );
1149+ if (len > 0 )
1150+ return reinterpret ( name , namelen , len , buf ) ;
11021151
1103- len = cp + tmp_len - name ;
1104- cp = xstrndup (name , cp - name );
1105- upstream = branch_get (* cp ? cp : NULL );
1106- /*
1107- * Upstream can be NULL only if cp refers to HEAD and HEAD
1108- * points to something different than a branch.
1109- */
1110- if (!upstream )
1111- die (_ ("HEAD does not point to a branch" ));
1112- if (!upstream -> merge || !upstream -> merge [0 ]-> dst ) {
1113- if (!ref_exists (upstream -> refname ))
1114- die (_ ("No such branch: '%s'" ), cp );
1115- if (!upstream -> merge ) {
1116- die (_ ("No upstream configured for branch '%s'" ),
1117- upstream -> name );
1118- }
1119- die (
1120- _ ("Upstream branch '%s' not stored as a remote-tracking branch" ),
1121- upstream -> merge [0 ]-> src );
1152+ len = interpret_upstream_mark (name , namelen , at - name , buf );
1153+ if (len > 0 )
1154+ return len ;
11221155 }
1123- free (cp );
1124- cp = shorten_unambiguous_ref (upstream -> merge [0 ]-> dst , 0 );
1125- strbuf_reset (buf );
1126- strbuf_addstr (buf , cp );
1127- free (cp );
1128- return len ;
1156+
1157+ return -1 ;
11291158}
11301159
11311160int strbuf_branchname (struct strbuf * sb , const char * name )
0 commit comments