libgit2/libgit2 — pull request #922 by pwkelley (2012-09-09 17:14:51+00:00)
Title: Fix a hang in git_odb__hashfd

If the size of a file that is being hashed by `git_odb__hashfd` decreases after the size of the file is fetched by a stat call, but before the file is opened for read by the caller, then `git_odb__hashfd` will spin forever.

`read()` starts returning zero for the number of bytes read once EOF is reached, but size is still > 0, so the loop never terminates.

With this patch, we treat a 0 byte read as EOF and complete the hash even though we know it must be wrong (because the object header has the wrong size in it).

For the purposes of computing status, having a "wrong" hash is just fine -- that just means the object ID comparison will fail and the item will count as modified. The code path for blob creation, where we want stronger guarantees, doesn't (and won't ever) go through `git_odb__hashfd`.

I would be interested to know whether people think doing it this way is better or worse than changing the signature to not take in a size, and having `git_odb__hashfd` call fstat on the file descriptor to get the size. That would prevent the problem by giving no ability to the caller to pass in a file size captured before the fd was opened for read. There would presumably be a perf penalty from the extra stat.