@@ -430,7 +430,7 @@ static inline int upstream_mark(const char *string, int len)
430
430
}
431
431
432
432
static 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 );
434
434
435
435
static int get_sha1_basic (const char * str , int len , unsigned char * sha1 )
436
436
{
@@ -492,7 +492,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
492
492
struct strbuf buf = STRBUF_INIT ;
493
493
int detached ;
494
494
495
- if (interpret_nth_prior_checkout (str , & buf ) > 0 ) {
495
+ if (interpret_nth_prior_checkout (str , len , & buf ) > 0 ) {
496
496
detached = (buf .len == 40 && !get_sha1_hex (buf .buf , sha1 ));
497
497
strbuf_release (& buf );
498
498
if (detached )
@@ -929,17 +929,20 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
929
929
* Parse @{-N} syntax, return the number of characters parsed
930
930
* if successful; otherwise signal an error with negative value.
931
931
*/
932
- static int interpret_nth_prior_checkout (const char * name , struct strbuf * buf )
932
+ static int interpret_nth_prior_checkout (const char * name , int namelen ,
933
+ struct strbuf * buf )
933
934
{
934
935
long nth ;
935
936
int retval ;
936
937
struct grab_nth_branch_switch_cbdata cb ;
937
938
const char * brace ;
938
939
char * num_end ;
939
940
941
+ if (namelen < 4 )
942
+ return -1 ;
940
943
if (name [0 ] != '@' || name [1 ] != '{' || name [2 ] != '-' )
941
944
return -1 ;
942
- brace = strchr (name , '}' );
945
+ brace = memchr (name , '}' , namelen );
943
946
if (!brace )
944
947
return -1 ;
945
948
nth = strtol (name + 3 , & num_end , 10 );
@@ -1012,7 +1015,7 @@ static int interpret_empty_at(const char *name, int namelen, int len, struct str
1012
1015
return -1 ;
1013
1016
1014
1017
/* make sure it's a single @, or @@{.*}, not @foo */
1015
- next = strchr (name + len + 1 , '@' );
1018
+ next = memchr (name + len + 1 , '@' , namelen - len - 1 );
1016
1019
if (next && next [1 ] != '{' )
1017
1020
return -1 ;
1018
1021
if (!next )
@@ -1046,6 +1049,57 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu
1046
1049
return ret - used + len ;
1047
1050
}
1048
1051
1052
+ static void set_shortened_ref (struct strbuf * buf , const char * ref )
1053
+ {
1054
+ char * s = shorten_unambiguous_ref (ref , 0 );
1055
+ strbuf_reset (buf );
1056
+ strbuf_addstr (buf , s );
1057
+ free (s );
1058
+ }
1059
+
1060
+ static const char * get_upstream_branch (const char * branch_buf , int len )
1061
+ {
1062
+ char * branch = xstrndup (branch_buf , len );
1063
+ struct branch * upstream = branch_get (* branch ? branch : NULL );
1064
+
1065
+ /*
1066
+ * Upstream can be NULL only if branch refers to HEAD and HEAD
1067
+ * points to something different than a branch.
1068
+ */
1069
+ if (!upstream )
1070
+ die (_ ("HEAD does not point to a branch" ));
1071
+ if (!upstream -> merge || !upstream -> merge [0 ]-> dst ) {
1072
+ if (!ref_exists (upstream -> refname ))
1073
+ die (_ ("No such branch: '%s'" ), branch );
1074
+ if (!upstream -> merge ) {
1075
+ die (_ ("No upstream configured for branch '%s'" ),
1076
+ upstream -> name );
1077
+ }
1078
+ die (
1079
+ _ ("Upstream branch '%s' not stored as a remote-tracking branch" ),
1080
+ upstream -> merge [0 ]-> src );
1081
+ }
1082
+ free (branch );
1083
+
1084
+ return upstream -> merge [0 ]-> dst ;
1085
+ }
1086
+
1087
+ static int interpret_upstream_mark (const char * name , int namelen ,
1088
+ int at , struct strbuf * buf )
1089
+ {
1090
+ int len ;
1091
+
1092
+ len = upstream_mark (name + at , namelen - at );
1093
+ if (!len )
1094
+ return -1 ;
1095
+
1096
+ if (memchr (name , ':' , at ))
1097
+ return -1 ;
1098
+
1099
+ set_shortened_ref (buf , get_upstream_branch (name , at ));
1100
+ return len + at ;
1101
+ }
1102
+
1049
1103
/*
1050
1104
* This reads short-hand syntax that not only evaluates to a commit
1051
1105
* object name, but also can act as if the end user spelled the name
@@ -1069,10 +1123,9 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu
1069
1123
*/
1070
1124
int interpret_branch_name (const char * name , int namelen , struct strbuf * buf )
1071
1125
{
1072
- char * cp ;
1073
- struct branch * upstream ;
1074
- int len = interpret_nth_prior_checkout (name , buf );
1075
- int tmp_len ;
1126
+ char * at ;
1127
+ const char * start ;
1128
+ int len = interpret_nth_prior_checkout (name , namelen , buf );
1076
1129
1077
1130
if (!namelen )
1078
1131
namelen = strlen (name );
@@ -1086,44 +1139,20 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
1086
1139
return reinterpret (name , namelen , len , buf );
1087
1140
}
1088
1141
1089
- cp = strchr (name , '@' );
1090
- if (!cp )
1091
- return -1 ;
1092
-
1093
- len = interpret_empty_at (name , namelen , cp - name , buf );
1094
- if (len > 0 )
1095
- return reinterpret (name , namelen , len , buf );
1142
+ for (start = name ;
1143
+ (at = memchr (start , '@' , namelen - (start - name )));
1144
+ start = at + 1 ) {
1096
1145
1097
- tmp_len = upstream_mark ( cp , namelen - ( cp - name ) );
1098
- if (! tmp_len )
1099
- return -1 ;
1146
+ len = interpret_empty_at ( name , namelen , at - name , buf );
1147
+ if (len > 0 )
1148
+ return reinterpret ( name , namelen , len , buf ) ;
1100
1149
1101
- len = cp + tmp_len - name ;
1102
- cp = xstrndup (name , cp - name );
1103
- upstream = branch_get (* cp ? cp : NULL );
1104
- /*
1105
- * Upstream can be NULL only if cp refers to HEAD and HEAD
1106
- * points to something different than a branch.
1107
- */
1108
- if (!upstream )
1109
- die (_ ("HEAD does not point to a branch" ));
1110
- if (!upstream -> merge || !upstream -> merge [0 ]-> dst ) {
1111
- if (!ref_exists (upstream -> refname ))
1112
- die (_ ("No such branch: '%s'" ), cp );
1113
- if (!upstream -> merge ) {
1114
- die (_ ("No upstream configured for branch '%s'" ),
1115
- upstream -> name );
1116
- }
1117
- die (
1118
- _ ("Upstream branch '%s' not stored as a remote-tracking branch" ),
1119
- upstream -> merge [0 ]-> src );
1150
+ len = interpret_upstream_mark (name , namelen , at - name , buf );
1151
+ if (len > 0 )
1152
+ return len ;
1120
1153
}
1121
- free (cp );
1122
- cp = shorten_unambiguous_ref (upstream -> merge [0 ]-> dst , 0 );
1123
- strbuf_reset (buf );
1124
- strbuf_addstr (buf , cp );
1125
- free (cp );
1126
- return len ;
1154
+
1155
+ return -1 ;
1127
1156
}
1128
1157
1129
1158
int strbuf_branchname (struct strbuf * sb , const char * name )
0 commit comments