Skip to content

Commit 6853a25

Browse files
committed
Merge branch 'pks/stream-truncated-writes'
2 parents 2f1d6ef + 0ceac0d commit 6853a25

File tree

7 files changed

+73
-70
lines changed

7 files changed

+73
-70
lines changed

src/stream.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,21 @@ GIT_INLINE(ssize_t) git_stream_write(git_stream *st, const char *data, size_t le
5555
return st->write(st, data, len, flags);
5656
}
5757

58+
GIT_INLINE(int) git_stream__write_full(git_stream *st, const char *data, size_t len, int flags)
59+
{
60+
size_t total_written = 0;
61+
62+
while (total_written < len) {
63+
ssize_t written = git_stream_write(st, data + total_written, len - total_written, flags);
64+
if (written <= 0)
65+
return -1;
66+
67+
total_written += written;
68+
}
69+
70+
return 0;
71+
}
72+
5873
GIT_INLINE(int) git_stream_close(git_stream *st)
5974
{
6075
return st->close(st);

src/streams/mbedtls.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@
4242
#define GIT_SSL_DEFAULT_CIPHERS "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-DSS-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-DSS-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA:TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-DSS-WITH-AES-128-CBC-SHA256:TLS-DHE-DSS-WITH-AES-256-CBC-SHA256:TLS-DHE-DSS-WITH-AES-128-CBC-SHA:TLS-DHE-DSS-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-AES-128-GCM-SHA256:TLS-RSA-WITH-AES-256-GCM-SHA384:TLS-RSA-WITH-AES-128-CBC-SHA256:TLS-RSA-WITH-AES-256-CBC-SHA256:TLS-RSA-WITH-AES-128-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA"
4343
#define GIT_SSL_DEFAULT_CIPHERS_COUNT 30
4444

45-
mbedtls_ssl_config *git__ssl_conf;
45+
static mbedtls_ssl_config *git__ssl_conf;
4646
static int ciphers_list[GIT_SSL_DEFAULT_CIPHERS_COUNT];
47-
mbedtls_entropy_context *mbedtls_entropy;
47+
static mbedtls_entropy_context *mbedtls_entropy;
4848

4949
/**
5050
* This function aims to clean-up the SSL context which
@@ -166,18 +166,16 @@ int git_mbedtls_stream_global_init(void)
166166
return -1;
167167
}
168168

169-
mbedtls_ssl_config *git__ssl_conf;
170-
171169
static int bio_read(void *b, unsigned char *buf, size_t len)
172170
{
173171
git_stream *io = (git_stream *) b;
174-
return (int) git_stream_read(io, buf, len);
172+
return (int) git_stream_read(io, buf, min(len, INT_MAX));
175173
}
176174

177175
static int bio_write(void *b, const unsigned char *buf, size_t len)
178176
{
179177
git_stream *io = (git_stream *) b;
180-
return (int) git_stream_write(io, (const char *)buf, len, 0);
178+
return (int) git_stream_write(io, (const char *)buf, min(len, INT_MAX), 0);
181179
}
182180

183181
static int ssl_set_error(mbedtls_ssl_context *ssl, int error)
@@ -246,7 +244,7 @@ typedef struct {
246244
} mbedtls_stream;
247245

248246

249-
int mbedtls_connect(git_stream *stream)
247+
static int mbedtls_connect(git_stream *stream)
250248
{
251249
int ret;
252250
mbedtls_stream *st = (mbedtls_stream *) stream;
@@ -266,7 +264,7 @@ int mbedtls_connect(git_stream *stream)
266264
return verify_server_cert(st->ssl);
267265
}
268266

269-
int mbedtls_certificate(git_cert **out, git_stream *stream)
267+
static int mbedtls_certificate(git_cert **out, git_stream *stream)
270268
{
271269
unsigned char *encoded_cert;
272270
mbedtls_stream *st = (mbedtls_stream *) stream;
@@ -303,25 +301,27 @@ static int mbedtls_set_proxy(git_stream *stream, const git_proxy_options *proxy_
303301
return git_stream_set_proxy(st->io, proxy_options);
304302
}
305303

306-
ssize_t mbedtls_stream_write(git_stream *stream, const char *data, size_t data_len, int flags)
304+
static ssize_t mbedtls_stream_write(git_stream *stream, const char *data, size_t len, int flags)
307305
{
308-
ssize_t written = 0, len = min(data_len, SSIZE_MAX);
309306
mbedtls_stream *st = (mbedtls_stream *) stream;
307+
int written;
310308

311309
GIT_UNUSED(flags);
312310

313-
do {
314-
int error = mbedtls_ssl_write(st->ssl, (const unsigned char *)data + written, len - written);
315-
if (error <= 0) {
316-
return ssl_set_error(st->ssl, error);
317-
}
318-
written += error;
319-
} while (written < len);
311+
/*
312+
* `mbedtls_ssl_write` can only represent INT_MAX bytes
313+
* written via its return value. We thus need to clamp
314+
* the maximum number of bytes written.
315+
*/
316+
len = min(len, INT_MAX);
317+
318+
if ((written = mbedtls_ssl_write(st->ssl, (const unsigned char *)data, len)) <= 0)
319+
return ssl_set_error(st->ssl, written);
320320

321321
return written;
322322
}
323323

324-
ssize_t mbedtls_stream_read(git_stream *stream, void *data, size_t len)
324+
static ssize_t mbedtls_stream_read(git_stream *stream, void *data, size_t len)
325325
{
326326
mbedtls_stream *st = (mbedtls_stream *) stream;
327327
int ret;
@@ -332,7 +332,7 @@ ssize_t mbedtls_stream_read(git_stream *stream, void *data, size_t len)
332332
return ret;
333333
}
334334

335-
int mbedtls_stream_close(git_stream *stream)
335+
static int mbedtls_stream_close(git_stream *stream)
336336
{
337337
mbedtls_stream *st = (mbedtls_stream *) stream;
338338
int ret = 0;
@@ -345,7 +345,7 @@ int mbedtls_stream_close(git_stream *stream)
345345
return st->owned ? git_stream_close(st->io) : 0;
346346
}
347347

348-
void mbedtls_stream_free(git_stream *stream)
348+
static void mbedtls_stream_free(git_stream *stream)
349349
{
350350
mbedtls_stream *st = (mbedtls_stream *) stream;
351351

src/streams/openssl.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -572,9 +572,7 @@ typedef struct {
572572
git_cert_x509 cert_info;
573573
} openssl_stream;
574574

575-
int openssl_close(git_stream *stream);
576-
577-
int openssl_connect(git_stream *stream)
575+
static int openssl_connect(git_stream *stream)
578576
{
579577
int ret;
580578
BIO *bio;
@@ -602,7 +600,7 @@ int openssl_connect(git_stream *stream)
602600
return verify_server_cert(st->ssl, st->host);
603601
}
604602

605-
int openssl_certificate(git_cert **out, git_stream *stream)
603+
static int openssl_certificate(git_cert **out, git_stream *stream)
606604
{
607605
openssl_stream *st = (openssl_stream *) stream;
608606
int len;
@@ -644,21 +642,20 @@ static int openssl_set_proxy(git_stream *stream, const git_proxy_options *proxy_
644642
return git_stream_set_proxy(st->io, proxy_opts);
645643
}
646644

647-
ssize_t openssl_write(git_stream *stream, const char *data, size_t data_len, int flags)
645+
static ssize_t openssl_write(git_stream *stream, const char *data, size_t data_len, int flags)
648646
{
649647
openssl_stream *st = (openssl_stream *) stream;
650648
int ret, len = min(data_len, INT_MAX);
651649

652650
GIT_UNUSED(flags);
653651

654-
if ((ret = SSL_write(st->ssl, data, len)) <= 0) {
652+
if ((ret = SSL_write(st->ssl, data, len)) <= 0)
655653
return ssl_set_error(st->ssl, ret);
656-
}
657654

658655
return ret;
659656
}
660657

661-
ssize_t openssl_read(git_stream *stream, void *data, size_t len)
658+
static ssize_t openssl_read(git_stream *stream, void *data, size_t len)
662659
{
663660
openssl_stream *st = (openssl_stream *) stream;
664661
int ret;
@@ -669,7 +666,7 @@ ssize_t openssl_read(git_stream *stream, void *data, size_t len)
669666
return ret;
670667
}
671668

672-
int openssl_close(git_stream *stream)
669+
static int openssl_close(git_stream *stream)
673670
{
674671
openssl_stream *st = (openssl_stream *) stream;
675672
int ret;
@@ -682,7 +679,7 @@ int openssl_close(git_stream *stream)
682679
return st->owned ? git_stream_close(st->io) : 0;
683680
}
684681

685-
void openssl_free(git_stream *stream)
682+
static void openssl_free(git_stream *stream)
686683
{
687684
openssl_stream *st = (openssl_stream *) stream;
688685

src/streams/socket.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static int close_socket(GIT_SOCKET s)
6969

7070
}
7171

72-
int socket_connect(git_stream *stream)
72+
static int socket_connect(git_stream *stream)
7373
{
7474
struct addrinfo *info = NULL, *p;
7575
struct addrinfo hints;
@@ -130,26 +130,22 @@ int socket_connect(git_stream *stream)
130130
return 0;
131131
}
132132

133-
ssize_t socket_write(git_stream *stream, const char *data, size_t data_len, int flags)
133+
static ssize_t socket_write(git_stream *stream, const char *data, size_t len, int flags)
134134
{
135-
ssize_t ret, off = 0, len = min(data_len, SSIZE_MAX);
136135
git_socket_stream *st = (git_socket_stream *) stream;
136+
ssize_t written;
137137

138-
while (off < len) {
139-
errno = 0;
140-
ret = p_send(st->s, data + off, len - off, flags);
141-
if (ret < 0) {
142-
net_set_error("Error sending data");
143-
return -1;
144-
}
138+
errno = 0;
145139

146-
off += ret;
140+
if ((written = p_send(st->s, data, len, flags)) < 0) {
141+
net_set_error("Error sending data");
142+
return -1;
147143
}
148144

149-
return off;
145+
return written;
150146
}
151147

152-
ssize_t socket_read(git_stream *stream, void *data, size_t len)
148+
static ssize_t socket_read(git_stream *stream, void *data, size_t len)
153149
{
154150
ssize_t ret;
155151
git_socket_stream *st = (git_socket_stream *) stream;
@@ -160,7 +156,7 @@ ssize_t socket_read(git_stream *stream, void *data, size_t len)
160156
return ret;
161157
}
162158

163-
int socket_close(git_stream *stream)
159+
static int socket_close(git_stream *stream)
164160
{
165161
git_socket_stream *st = (git_socket_stream *) stream;
166162
int error;
@@ -171,7 +167,7 @@ int socket_close(git_stream *stream)
171167
return error;
172168
}
173169

174-
void socket_free(git_stream *stream)
170+
static void socket_free(git_stream *stream)
175171
{
176172
git_socket_stream *st = (git_socket_stream *) stream;
177173

src/streams/stransport.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,8 @@ static OSStatus write_cb(SSLConnectionRef conn, const void *data, size_t *len)
149149
{
150150
git_stream *io = (git_stream *) conn;
151151

152-
if (git_stream_write(io, data, *len, 0) < 0) {
152+
if (git_stream__write_full(io, data, *len, 0) < 0)
153153
return -36; /* "ioErr" from MacErrors.h which is not available on iOS */
154-
}
155154

156155
return noErr;
157156
}

src/transports/git.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,15 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
7676
static int send_command(git_proto_stream *s)
7777
{
7878
git_buf request = GIT_BUF_INIT;
79-
size_t write_size;
8079
int error;
8180

82-
error = gen_proto(&request, s->cmd, s->url);
83-
if (error < 0)
81+
if ((error = gen_proto(&request, s->cmd, s->url)) < 0)
8482
goto cleanup;
8583

86-
write_size = min(request.size, INT_MAX);
87-
error = (int)git_stream_write(s->io, request.ptr, write_size, 0);
84+
if ((error = git_stream__write_full(s->io, request.ptr, request.size, 0)) < 0)
85+
goto cleanup;
8886

89-
if (error >= 0)
90-
s->sent_command = 1;
87+
s->sent_command = 1;
9188

9289
cleanup:
9390
git_buf_dispose(&request);
@@ -122,16 +119,15 @@ static int git_proto_stream_read(
122119
static int git_proto_stream_write(
123120
git_smart_subtransport_stream *stream,
124121
const char *buffer,
125-
size_t buffer_len)
122+
size_t len)
126123
{
127124
git_proto_stream *s = (git_proto_stream *)stream;
128-
size_t len = min(buffer_len, INT_MAX);
129125
int error;
130126

131127
if (!s->sent_command && (error = send_command(s)) < 0)
132128
return error;
133129

134-
return (int)git_stream_write(s->io, buffer, len, 0);
130+
return git_stream__write_full(s->io, buffer, len, 0);
135131
}
136132

137133
static void git_proto_stream_free(git_smart_subtransport_stream *stream)

src/transports/http.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -643,19 +643,19 @@ static int write_chunk(git_stream *io, const char *buffer, size_t len)
643643
if (git_buf_oom(&buf))
644644
return -1;
645645

646-
if (git_stream_write(io, buf.ptr, buf.size, 0) < 0) {
646+
if (git_stream__write_full(io, buf.ptr, buf.size, 0) < 0) {
647647
git_buf_dispose(&buf);
648648
return -1;
649649
}
650650

651651
git_buf_dispose(&buf);
652652

653653
/* Chunk body */
654-
if (len > 0 && git_stream_write(io, buffer, len, 0) < 0)
654+
if (len > 0 && git_stream__write_full(io, buffer, len, 0) < 0)
655655
return -1;
656656

657657
/* Chunk footer */
658-
if (git_stream_write(io, "\r\n", 2, 0) < 0)
658+
if (git_stream__write_full(io, "\r\n", 2, 0) < 0)
659659
return -1;
660660

661661
return 0;
@@ -853,8 +853,8 @@ static int proxy_connect(
853853
if ((error = gen_connect_req(&request, t)) < 0)
854854
goto done;
855855

856-
if ((error = git_stream_write(proxy_stream,
857-
request.ptr, request.size, 0)) < 0)
856+
if ((error = git_stream__write_full(proxy_stream, request.ptr,
857+
request.size, 0)) < 0)
858858
goto done;
859859

860860
git_buf_dispose(&request);
@@ -1034,8 +1034,8 @@ static int http_stream_read(
10341034
if (gen_request(&request, s, 0) < 0)
10351035
return -1;
10361036

1037-
if (git_stream_write(t->server.stream,
1038-
request.ptr, request.size, 0) < 0) {
1037+
if (git_stream__write_full(t->server.stream, request.ptr,
1038+
request.size, 0) < 0) {
10391039
git_buf_dispose(&request);
10401040
return -1;
10411041
}
@@ -1058,7 +1058,8 @@ static int http_stream_read(
10581058
s->chunk_buffer_len = 0;
10591059

10601060
/* Write the final chunk. */
1061-
if (git_stream_write(t->server.stream, "0\r\n\r\n", 5, 0) < 0)
1061+
if (git_stream__write_full(t->server.stream,
1062+
"0\r\n\r\n", 5, 0) < 0)
10621063
return -1;
10631064
}
10641065

@@ -1157,8 +1158,8 @@ static int http_stream_write_chunked(
11571158
if (gen_request(&request, s, 0) < 0)
11581159
return -1;
11591160

1160-
if (git_stream_write(t->server.stream,
1161-
request.ptr, request.size, 0) < 0) {
1161+
if (git_stream__write_full(t->server.stream, request.ptr,
1162+
request.size, 0) < 0) {
11621163
git_buf_dispose(&request);
11631164
return -1;
11641165
}
@@ -1233,11 +1234,10 @@ static int http_stream_write_single(
12331234
if (gen_request(&request, s, len) < 0)
12341235
return -1;
12351236

1236-
if (git_stream_write(t->server.stream,
1237-
request.ptr, request.size, 0) < 0)
1237+
if (git_stream__write_full(t->server.stream, request.ptr, request.size, 0) < 0)
12381238
goto on_error;
12391239

1240-
if (len && git_stream_write(t->server.stream, buffer, len, 0) < 0)
1240+
if (len && git_stream__write_full(t->server.stream, buffer, len, 0) < 0)
12411241
goto on_error;
12421242

12431243
git_buf_dispose(&request);

0 commit comments

Comments
 (0)