* [PATCH] stream_to_pack: xread does not guarantee to read all requested bytes
@ 2013-08-20 9:15 Johannes Sixt
2013-08-20 15:00 ` Junio C Hamano
0 siblings, 1 reply; 8+ messages in thread
From: Johannes Sixt @ 2013-08-20 9:15 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
The deflate loop in bulk-checkin::stream_to_pack expects to get all bytes
from a file that it requests to read in a single function call. But it
used xread(), which does not give that guarantee. Replace it by
read_in_full().
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
The size is limited to sizeof(ibuf) == 16384 bytes, so that there
should not be a problem with the unpatched code on any OS in practice.
Nevertheless, this change seems reasonable from a code hygiene POV.
bulk-checkin.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 6b0b6d4..118c625 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -114,7 +114,7 @@ static int stream_to_pack(struct bulk_checkin_state *state,
if (size && !s.avail_in) {
ssize_t rsize = size < sizeof(ibuf) ? size : sizeof(ibuf);
- if (xread(fd, ibuf, rsize) != rsize)
+ if (read_in_full(fd, ibuf, rsize) != rsize)
die("failed to read %d bytes from '%s'",
(int)rsize, path);
offset += rsize;
--
1.8.4.rc3.1241.gcbfd92d.dirty
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] stream_to_pack: xread does not guarantee to read all requested bytes
2013-08-20 9:15 [PATCH] stream_to_pack: xread does not guarantee to read all requested bytes Johannes Sixt
@ 2013-08-20 15:00 ` Junio C Hamano
2013-08-20 15:16 ` Antoine Pelisse
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Junio C Hamano @ 2013-08-20 15:00 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Git Mailing List
Johannes Sixt <j6t@kdbg.org> writes:
> The deflate loop in bulk-checkin::stream_to_pack expects to get all bytes
> from a file that it requests to read in a single function call. But it
> used xread(), which does not give that guarantee. Replace it by
> read_in_full().
>
> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
> ---
> The size is limited to sizeof(ibuf) == 16384 bytes, so that there
> should not be a problem with the unpatched code on any OS in practice.
> Nevertheless, this change seems reasonable from a code hygiene POV.
>
> bulk-checkin.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/bulk-checkin.c b/bulk-checkin.c
> index 6b0b6d4..118c625 100644
> --- a/bulk-checkin.c
> +++ b/bulk-checkin.c
> @@ -114,7 +114,7 @@ static int stream_to_pack(struct bulk_checkin_state *state,
>
> if (size && !s.avail_in) {
> ssize_t rsize = size < sizeof(ibuf) ? size : sizeof(ibuf);
> - if (xread(fd, ibuf, rsize) != rsize)
> + if (read_in_full(fd, ibuf, rsize) != rsize)
This is the kind of thing i was wondering and worried about with the
other "clipped xread/xwrite" patch. The original of this caller is
obviously wrong. Thanks for spotting and fixing.
I wonder if there are more like this broken caller or xread and/or
xwrite.
> die("failed to read %d bytes from '%s'",
> (int)rsize, path);
> offset += rsize;
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] stream_to_pack: xread does not guarantee to read all requested bytes
2013-08-20 15:00 ` Junio C Hamano
@ 2013-08-20 15:16 ` Antoine Pelisse
2013-08-20 18:27 ` Junio C Hamano
2013-08-20 18:27 ` Johannes Sixt
2013-08-20 18:23 ` Johannes Sixt
2013-08-20 18:52 ` Junio C Hamano
2 siblings, 2 replies; 8+ messages in thread
From: Antoine Pelisse @ 2013-08-20 15:16 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Sixt, Git Mailing List
On Tue, Aug 20, 2013 at 5:00 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Johannes Sixt <j6t@kdbg.org> writes:
>
>> The deflate loop in bulk-checkin::stream_to_pack expects to get all bytes
>> from a file that it requests to read in a single function call. But it
>> used xread(), which does not give that guarantee. Replace it by
>> read_in_full().
>>
>> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
>> ---
>> The size is limited to sizeof(ibuf) == 16384 bytes, so that there
>> should not be a problem with the unpatched code on any OS in practice.
>> Nevertheless, this change seems reasonable from a code hygiene POV.
>>
>> bulk-checkin.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/bulk-checkin.c b/bulk-checkin.c
>> index 6b0b6d4..118c625 100644
>> --- a/bulk-checkin.c
>> +++ b/bulk-checkin.c
>> @@ -114,7 +114,7 @@ static int stream_to_pack(struct bulk_checkin_state *state,
>>
>> if (size && !s.avail_in) {
>> ssize_t rsize = size < sizeof(ibuf) ? size : sizeof(ibuf);
>> - if (xread(fd, ibuf, rsize) != rsize)
>> + if (read_in_full(fd, ibuf, rsize) != rsize)
>
> This is the kind of thing i was wondering and worried about with the
> other "clipped xread/xwrite" patch. The original of this caller is
> obviously wrong. Thanks for spotting and fixing.
>
> I wonder if there are more like this broken caller or xread and/or
> xwrite.
I was actually wondering when it's better to use xread() over
read_in_full() ? Considering that we don't know if xread() will read
the whole buffer or not, would it not be better to always use
read_in_full() ? I guess there is a drawback to this, but I'm not
exactly sure what it is.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] stream_to_pack: xread does not guarantee to read all requested bytes
2013-08-20 15:00 ` Junio C Hamano
2013-08-20 15:16 ` Antoine Pelisse
@ 2013-08-20 18:23 ` Johannes Sixt
2013-08-20 18:52 ` Junio C Hamano
2 siblings, 0 replies; 8+ messages in thread
From: Johannes Sixt @ 2013-08-20 18:23 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
Am 20.08.2013 17:00, schrieb Junio C Hamano:
> I wonder if there are more like this broken caller or xread and/or
> xwrite.
Looking at the grep -C1 output, there are no others.
The only one that looked suspicious was xread in remote-curl.c, but it is
fine (it just eats all data from the input).
-- Hannes
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] stream_to_pack: xread does not guarantee to read all requested bytes
2013-08-20 15:16 ` Antoine Pelisse
@ 2013-08-20 18:27 ` Junio C Hamano
2013-08-20 18:27 ` Johannes Sixt
1 sibling, 0 replies; 8+ messages in thread
From: Junio C Hamano @ 2013-08-20 18:27 UTC (permalink / raw)
To: Antoine Pelisse; +Cc: Johannes Sixt, Git Mailing List
Antoine Pelisse <apelisse@gmail.com> writes:
> I was actually wondering when it's better to use xread() over
> read_in_full()?
When the caller wants to do more control over a read that may have
to loop. For example, this loop in builtin/index-pack.c::fill()
do {
ssize_t ret = xread(input_fd, input_buffer + input_len,
sizeof(input_buffer) - input_len);
if (ret <= 0) {
if (!ret)
die(_("early EOF"));
die_errno(_("read error on input"));
}
input_len += ret;
if (from_stdin)
display_throughput(progress, consumed_bytes + input_len);
} while (input_len < min);
cannot be replaced blindly with read_in_full() because (1) the
caller wants to do the "display_throughput()" part in the loop, and
(2) the caller wants to fill at least "min" bytes but can happily
accept to read more up to the size of the input_buffer.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] stream_to_pack: xread does not guarantee to read all requested bytes
2013-08-20 15:16 ` Antoine Pelisse
2013-08-20 18:27 ` Junio C Hamano
@ 2013-08-20 18:27 ` Johannes Sixt
1 sibling, 0 replies; 8+ messages in thread
From: Johannes Sixt @ 2013-08-20 18:27 UTC (permalink / raw)
To: Antoine Pelisse; +Cc: Junio C Hamano, Git Mailing List
Am 20.08.2013 17:16, schrieb Antoine Pelisse:
> I was actually wondering when it's better to use xread() over
> read_in_full() ? Considering that we don't know if xread() will read
> the whole buffer or not, would it not be better to always use
> read_in_full() ?
Of course, you know whether the whole buffer was filled: xread() returns
the number of bytes read. Same for xwrite().
> I guess there is a drawback to this, but I'm not
> exactly sure what it is.
The disadvantage of read_in_full() is that it can happen that it reads
data from the stream successfully, but then reports an error. In this
case, the data read is lost.
Analogously, when write_in_full() writes (some) data successfully, but
ultimately fails, you don't know how much was written successfully.
-- Hannes
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] stream_to_pack: xread does not guarantee to read all requested bytes
2013-08-20 15:00 ` Junio C Hamano
2013-08-20 15:16 ` Antoine Pelisse
2013-08-20 18:23 ` Johannes Sixt
@ 2013-08-20 18:52 ` Junio C Hamano
2013-08-20 19:37 ` Johannes Sixt
2 siblings, 1 reply; 8+ messages in thread
From: Junio C Hamano @ 2013-08-20 18:52 UTC (permalink / raw)
To: Git Mailing List; +Cc: Johannes Sixt
Junio C Hamano <gitster@pobox.com> writes:
> I wonder if there are more like this broken caller or xread and/or
> xwrite.
Here is a result of a quick audit (of 1.8.0.x codebase).
As xwrite() will not be splitting a single-byte request, the patch
to cat-file is more or less a theoretical fix, but if writing the
date string can fail in I/O error, writing a terminating LF after it
can fail the same way, so we should be consistent.
Everybody supports the side-band tranfer these days, so the patches
to receive-pack and upload-pack are also theoretical fixes, I
think. Note that in the more recent codebase, safe_write() is gone
and we use write_or_die() instead in upload-pack.
builtin/cat-file.c | 2 +-
builtin/receive-pack.c | 2 +-
upload-pack.c | 5 -----
3 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 00528dd..4beb4d8 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -63,7 +63,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
tz = strtol(ep, NULL, 10);
sp = show_date(date, tz, 0);
write_or_die(1, sp, strlen(sp));
- xwrite(1, "\n", 1);
+ write_or_die(1, "\n", 1);
break;
}
}
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index ff781fe..a41740d 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -202,7 +202,7 @@ static void report_message(const char *prefix, const char *err, va_list params)
if (use_sideband)
send_sideband(1, 2, msg, sz, use_sideband);
else
- xwrite(2, msg, sz);
+ write_in_full(2, msg, sz);
}
static void rp_warning(const char *err, ...)
diff --git a/upload-pack.c b/upload-pack.c
index 2e90ccb..7a3e4fd 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -64,11 +64,6 @@ static ssize_t send_client_data(int fd, const char *data, ssize_t sz)
if (fd == 3)
/* emergency quit */
fd = 2;
- if (fd == 2) {
- /* XXX: are we happy to lose stuff here? */
- xwrite(fd, data, sz);
- return sz;
- }
return safe_write(fd, data, sz);
}
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] stream_to_pack: xread does not guarantee to read all requested bytes
2013-08-20 18:52 ` Junio C Hamano
@ 2013-08-20 19:37 ` Johannes Sixt
0 siblings, 0 replies; 8+ messages in thread
From: Johannes Sixt @ 2013-08-20 19:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
Am 20.08.2013 20:52, schrieb Junio C Hamano:
> Junio C Hamano <gitster@pobox.com> writes:
>
>> I wonder if there are more like this broken caller or xread and/or
>> xwrite.
>
> Here is a result of a quick audit (of 1.8.0.x codebase).
>
> As xwrite() will not be splitting a single-byte request, the patch
> to cat-file is more or less a theoretical fix, but if writing the
> date string can fail in I/O error, writing a terminating LF after it
> can fail the same way, so we should be consistent.
>
> Everybody supports the side-band tranfer these days, so the patches
> to receive-pack and upload-pack are also theoretical fixes, I
> think. Note that in the more recent codebase, safe_write() is gone
> and we use write_or_die() instead in upload-pack.
These changes look reasonable. Thank you!
>
> builtin/cat-file.c | 2 +-
> builtin/receive-pack.c | 2 +-
> upload-pack.c | 5 -----
> 3 files changed, 2 insertions(+), 7 deletions(-)
>
> diff --git a/builtin/cat-file.c b/builtin/cat-file.c
> index 00528dd..4beb4d8 100644
> --- a/builtin/cat-file.c
> +++ b/builtin/cat-file.c
> @@ -63,7 +63,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
> tz = strtol(ep, NULL, 10);
> sp = show_date(date, tz, 0);
> write_or_die(1, sp, strlen(sp));
> - xwrite(1, "\n", 1);
> + write_or_die(1, "\n", 1);
> break;
> }
> }
> diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
> index ff781fe..a41740d 100644
> --- a/builtin/receive-pack.c
> +++ b/builtin/receive-pack.c
> @@ -202,7 +202,7 @@ static void report_message(const char *prefix, const char *err, va_list params)
> if (use_sideband)
> send_sideband(1, 2, msg, sz, use_sideband);
> else
> - xwrite(2, msg, sz);
> + write_in_full(2, msg, sz);
> }
>
> static void rp_warning(const char *err, ...)
> diff --git a/upload-pack.c b/upload-pack.c
> index 2e90ccb..7a3e4fd 100644
> --- a/upload-pack.c
> +++ b/upload-pack.c
> @@ -64,11 +64,6 @@ static ssize_t send_client_data(int fd, const char *data, ssize_t sz)
> if (fd == 3)
> /* emergency quit */
> fd = 2;
> - if (fd == 2) {
> - /* XXX: are we happy to lose stuff here? */
> - xwrite(fd, data, sz);
> - return sz;
> - }
> return safe_write(fd, data, sz);
> }
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2013-08-20 19:37 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-20 9:15 [PATCH] stream_to_pack: xread does not guarantee to read all requested bytes Johannes Sixt
2013-08-20 15:00 ` Junio C Hamano
2013-08-20 15:16 ` Antoine Pelisse
2013-08-20 18:27 ` Junio C Hamano
2013-08-20 18:27 ` Johannes Sixt
2013-08-20 18:23 ` Johannes Sixt
2013-08-20 18:52 ` Junio C Hamano
2013-08-20 19:37 ` Johannes Sixt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).