Thread (45 messages) flat view 45 messages, 4 authors, 2017-09-15

Re: [PATCH 1/7] config: avoid "write_in_full(fd, buf, len) < len" pattern

From: Jeff King <hidden>
Date: 2017-09-13 17:53:45

On Wed, Sep 13, 2017 at 10:47:28AM -0700, Jonathan Nieder wrote:
Jeff King wrote:
quoted
I scoured the code base for cases of this, but it turns out
that these two in git_config_set_multivar_in_file_gently()
are the only ones. This case is actually quite interesting:
we don't have a size_t, but rather use the subtraction of
two pointers. Which you might think would be a signed
ptrdiff_t, but clearly both gcc and clang treat it as
unsigned (possibly because the conditional just above
guarantees that the result is greater than zero).
Do you have more detail about this?  I get worried when I read
something like this that sounds like a compiler bug.

C99 sayeth:

	When two pointers are subtracted, both shall point to elements
	of the same array object, or one past the last element of the
	array object; the result is the difference of the subscripts
	of the two array elements. The size of the result is
	implementation-defined, and its type (a signed integer type)
	is ptrdiff_t defined in the <stddef.h> header.
I'm not sure if it's a compiler bug or not. I read the bits about
ptrdiff_t, and it wasn't entirely clear to me if a pointer difference
_is_ an actual ptrdiff_t, or if it can generally be stored in one. Right
below that text it also says:

  If the result is not representable in an object of that type, the
  behavior is undefined.

That said, I might be wrong that unsigned promotion is the culprit. I
didn't look at the generated assembly. But I also can't see what else
would be causing the problem here. We're clearly returning "-1" and the
condition doesn't trigger.
How can I reproduce the problem?
I gave a recipe in the commit message, which is the best I came up with.
You could probably use a fault-injection library to convince write() to
fail. Or just tweak the source code to have write_in_full() return -1.
quoted
There's no addition to the test suite here, since you need
to convince write() to fail in order to see the problem. The
simplest reproduction recipe I came up with is to trigger
ENOSPC (this only works on Linux, obviously):
Does /dev/full make it simpler to reproduce?
I don't think so, because the write() failure is to the lockfile, which
is created with O_EXCL. So even if you could convince "config.lock" to
be the right device type, the open() would fail.

-Peff
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help