v0 protocol: use size_t for capability length/offset

When parsing server capabilities, we use "int" to store lengths and offsets. At first glance this seems like a spot where our parser may be confused by integer overflow if somebody sent us a malicious response. In practice these strings are all bounded by the 64k limit of a pkt-line, so using "int" is OK. However, it makes the code simpler to audit if they just use size_t everywhere. Note that because we take these parameters as pointers, this also forces many callers to update their declared types. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Apr 14, 2023 at 17:25 UTC 7ce4c8f752bc0da682acbda6457d6543ad5d0069
7 files changed +19 -19
builtin/receive-pack.c
+1 -1
@@ -2093,7 +2093,7 @@ static struct command *read_head_info(struct packet_reader *reader,
2093 const char *feature_list = reader->line + linelen + 1;
2094 const char *hash = NULL;
2095 const char *client_sid;
2096 - int len = 0;
2096 + size_t len = 0;
2097 if (parse_feature_request(feature_list, "report-status"))
2098 report_status = 1;
2099 if (parse_feature_request(feature_list, "report-status-v2"))
connect.c
+11 -11
@@ -22,7 +22,7 @@
22
23 static char *server_capabilities_v1;
24 static struct strvec server_capabilities_v2 = STRVEC_INIT;
25 -static const char *next_server_feature_value(const char *feature, int *len, int *offset);
25 +static const char *next_server_feature_value(const char *feature, size_t *len, size_t *offset);
26
27 static int check_ref(const char *name, unsigned int flags)
28 {
@@ -205,10 +205,10 @@ reject:
205 static void annotate_refs_with_symref_info(struct ref *ref)
206 {
207 struct string_list symref = STRING_LIST_INIT_DUP;
208 - int offset = 0;
208 + size_t offset = 0;
209
210 while (1) {
211 - int len;
211 + size_t len;
212 const char *val;
213
214 val = next_server_feature_value("symref", &len, &offset);
@@ -231,7 +231,7 @@ static void annotate_refs_with_symref_info(struct ref *ref)
231 static void process_capabilities(struct packet_reader *reader, int *linelen)
232 {
233 const char *feat_val;
234 - int feat_len;
234 + size_t feat_len;
235 const char *line = reader->line;
236 int nul_location = strlen(line);
237 if (nul_location == *linelen)
@@ -596,10 +596,10 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
596 return list;
597 }
598
599 -const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset)
599 +const char *parse_feature_value(const char *feature_list, const char *feature, size_t *lenp, size_t *offset)
600 {
601 const char *orig_start = feature_list;
602 - int len;
602 + size_t len;
603
604 if (!feature_list)
605 return NULL;
@@ -623,7 +623,7 @@ const char *parse_feature_value(const char *feature_list, const char *feature, i
623 }
624 /* feature with a value (e.g., "agent=git/1.2.3") */
625 else if (*value == '=') {
626 - int end;
626 + size_t end;
627
628 value++;
629 end = strcspn(value, " \t\n");
@@ -645,8 +645,8 @@ const char *parse_feature_value(const char *feature_list, const char *feature, i
645
646 int server_supports_hash(const char *desired, int *feature_supported)
647 {
648 - int offset = 0;
649 - int len;
648 + size_t offset = 0;
649 + size_t len;
650 const char *hash;
651
652 hash = next_server_feature_value("object-format", &len, &offset);
@@ -670,12 +670,12 @@ int parse_feature_request(const char *feature_list, const char *feature)
670 return !!parse_feature_value(feature_list, feature, NULL, NULL);
671 }
672
673 -static const char *next_server_feature_value(const char *feature, int *len, int *offset)
673 +static const char *next_server_feature_value(const char *feature, size_t *len, size_t *offset)
674 {
675 return parse_feature_value(server_capabilities_v1, feature, len, offset);
676 }
677
678 -const char *server_feature_value(const char *feature, int *len)
678 +const char *server_feature_value(const char *feature, size_t *len)
679 {
680 return parse_feature_value(server_capabilities_v1, feature, len, NULL);
681 }
connect.h
+2 -2
@@ -12,14 +12,14 @@ int finish_connect(struct child_process *conn);
12 int git_connection_is_socket(struct child_process *conn);
13 int server_supports(const char *feature);
14 int parse_feature_request(const char *features, const char *feature);
15 -const char *server_feature_value(const char *feature, int *len_ret);
15 +const char *server_feature_value(const char *feature, size_t *len_ret);
16 int url_is_local_not_ssh(const char *url);
17
18 struct packet_reader;
19 enum protocol_version discover_version(struct packet_reader *reader);
20
21 int server_supports_hash(const char *desired, int *feature_supported);
22 -const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp, int *offset);
22 +const char *parse_feature_value(const char *feature_list, const char *feature, size_t *lenp, size_t *offset);
23 int server_supports_v2(const char *c);
24 void ensure_server_supports_v2(const char *c);
25 int server_feature_v2(const char *c, const char **v);
fetch-pack.c
+2 -2
@@ -1099,7 +1099,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
1099 struct ref *ref = copy_ref_list(orig_ref);
1100 struct object_id oid;
1101 const char *agent_feature;
1102 - int agent_len;
1102 + size_t agent_len;
1103 struct fetch_negotiator negotiator_alloc;
1104 struct fetch_negotiator *negotiator;
1105
@@ -1117,7 +1117,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
1117 agent_supported = 1;
1118 if (agent_len)
1119 print_verbose(args, _("Server version is %.*s"),
1120 - agent_len, agent_feature);
1120 + (int)agent_len, agent_feature);
1121 }
1122
1123 if (!server_supports("session-id"))
send-pack.c
+1 -1
@@ -538,7 +538,7 @@ int send_pack(struct send_pack_args *args,
538 die(_("the receiving end does not support this repository's hash algorithm"));
539
540 if (args->push_cert != SEND_PACK_PUSH_CERT_NEVER) {
541 - int len;
541 + size_t len;
542 push_cert_nonce = server_feature_value("push-cert", &len);
543 if (push_cert_nonce) {
544 reject_invalid_nonce(push_cert_nonce, len);
transport.c
+1 -1
@@ -317,7 +317,7 @@ static struct ref *handshake(struct transport *transport, int for_push,
317 struct git_transport_data *data = transport->data;
318 struct ref *refs = NULL;
319 struct packet_reader reader;
320 - int sid_len;
320 + size_t sid_len;
321 const char *server_sid;
322
323 connect_setup(transport, for_push);
upload-pack.c
+1 -1
@@ -1067,7 +1067,7 @@ static void receive_needs(struct upload_pack_data *data,
1067 const char *features;
1068 struct object_id oid_buf;
1069 const char *arg;
1070 - int feature_len;
1070 + size_t feature_len;
1071
1072 reset_timeout(data->timeout);
1073 if (packet_reader_read(reader) != PACKET_READ_NORMAL)