git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).