@@ -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 )
@@ -931,17 +931,20 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
931
931
* Parse @{-N} syntax, return the number of characters parsed
932
932
* if successful; otherwise signal an error with negative value.
933
933
*/
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 )
935
936
{
936
937
long nth ;
937
938
int retval ;
938
939
struct grab_nth_branch_switch_cbdata cb ;
939
940
const char * brace ;
940
941
char * num_end ;
941
942
943
+ if (namelen < 4 )
944
+ return -1 ;
942
945
if (name [0 ] != '@' || name [1 ] != '{' || name [2 ] != '-' )
943
946
return -1 ;
944
- brace = strchr (name , '}' );
947
+ brace = memchr (name , '}' , namelen );
945
948
if (!brace )
946
949
return -1 ;
947
950
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
1014
1017
return -1 ;
1015
1018
1016
1019
/* make sure it's a single @, or @@{.*}, not @foo */
1017
- next = strchr (name + len + 1 , '@' );
1020
+ next = memchr (name + len + 1 , '@' , namelen - len - 1 );
1018
1021
if (next && next [1 ] != '{' )
1019
1022
return -1 ;
1020
1023
if (!next )
@@ -1048,6 +1051,57 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu
1048
1051
return ret - used + len ;
1049
1052
}
1050
1053
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
+
1051
1105
/*
1052
1106
* This reads short-hand syntax that not only evaluates to a commit
1053
1107
* 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
1071
1125
*/
1072
1126
int interpret_branch_name (const char * name , int namelen , struct strbuf * buf )
1073
1127
{
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 );
1078
1131
1079
1132
if (!namelen )
1080
1133
namelen = strlen (name );
@@ -1088,44 +1141,20 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
1088
1141
return reinterpret (name , namelen , len , buf );
1089
1142
}
1090
1143
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 ) {
1098
1147
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 ) ;
1102
1151
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 ;
1122
1155
}
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 ;
1129
1158
}
1130
1159
1131
1160
int strbuf_branchname (struct strbuf * sb , const char * name )
0 commit comments