The thread local storage is used to hold some global state that
is dynamically allocated and should be freed upon exit. On
Windows, we clean up the C run-time right after execution of
registered shutdown callbacks and before cleaning up the TLS.
When we clean up the CRT, we also cause it to analyze for memory
leaks. As we did not free the TLS yet this will lead to false
positives.
Fix the issue by first freeing the TLS and cleaning up the CRT
only afterwards.
When removing an entry from the index by its position, we first
retrieve the position from the index's entries and then try to
remove the retrieved value from the index map with
`DELETE_IN_MAP`. When `index_remove_entry` returns `NULL` we try
to feed it into the `DELETE_IN_MAP` macro, which will
unconditionally call `idxentry_hash` and then happily dereference
the `NULL` entry pointer.
Fix the issue by not passing a `NULL` entry into `DELETE_IN_MAP`.
When we receive a packet of exactly four bytes encoding its
length as those four bytes it can be treated as an empty line.
While it is not really specified how those empty lines should be
treated, we currently ignore them and do not return an error when
trying to parse it but simply advance the data pointer.
Callers invoking `git_pkt_parse_line` are currently not prepared
to handle this case as they do not explicitly check this case.
While they could always reset the passed out-pointer to `NULL`
before calling `git_pkt_parse_line` and determine if the pointer
has been set afterwards, it makes more sense to update
`git_pkt_parse_line` to set the out-pointer to `NULL` itself when
it encounters such an empty packet. Like this it is guaranteed
that there will be no invalid memory references to free'd
pointers.
As such, the issue has been fixed such that `git_pkt_parse_line`
always sets the packet out pointer to `NULL` when an empty packet
has been received and callers check for this condition, skipping
such packets.
When adding a new entry to an existing index via `git_index_read_index`,
be sure to remove the tree cache entry for that new path. This will
mark all parent trees as dirty.
Clear any error state upon each iteration. If one of the iterations
ends (with an error of `GIT_ITEROVER`) we need to reset that error to 0,
lest we stop the whole process prematurely.
Read a tree into an index using `git_index_read_index` (by reading
a tree into a new index, then reading that index into the current
index), then write the index back out, ensuring that our new index
is treesame to the tree that we read.
We compute offsets by executing `off |= (*delta++ << 24)` for
multiple constants, where `off` is of type `size_t` and `delta`
is of type `unsigned char`. The usual arithmetic conversions (see
ISO C89 §3.2.1.5 "Usual arithmetic conversions") kick in here,
causing us to promote both operands to `int` and then extending
the result to an `unsigned long` when OR'ing it with `off`.
The integer promotion to `int` may result in wrong size
calculations for big values.
Fix the issue by making the constants `unsigned long`, causing both
operands to be promoted to `unsigned long`.
An object's size is computed by reading the object header's size
field until the most significant bit is not set anymore. To get
the total size, we increase the shift on each iteration and add
the shifted value to the total size.
We read the current value into a variable of type `unsigned
char`, from which we then take all bits except the most
significant bit and shift the result. We will end up with a
maximum shift of 60, but this exceeds the width of the value's
type, resulting in undefined behavior.
Fix the issue by instead reading the values into a variable of
type `unsigned long`, which matches the required width. This is
equivalent to git.git, which uses an `unsigned long` as well.
When `git_repository__cvar` fails we may end up with a
`ignorecase` value of `-1`. As we subsequently check if
`ignorecase` is non-zero, we may end up reporting that data
should be removed when in fact it should not.
Err on the safer side and set `ignorecase = 0` when
`git_repository__cvar` fails.
When we read the header, we want to know the size and type of the
object. We're currently inflating the full delta in order to read the
first few bytes. This can mean hundreds of kB needlessly inflated for
large objects.
Instead use a packfile stream to read just enough so we can read the two
varints in the header and avoid inflating most of the delta.
openssl_read should return -1 in case of error.
SSL_read returns values <= 0 in case of error.
A return value of 0 can lead to an infinite loop, so the return value
of ssl_set_error will be returned if SSL_read is not successful (analog
to openssl_write).
While no extra header fields are defined for tags, git accepts them by
ignoring them and continuing the search for the message. There are a few
tags like this in the wild which git parses just fine, so we should do
the same.
When trying to determine if we can safely overwrite an existing workdir
item, we may need to calculate the oid for the workdir item to determine
if its identical to the old side (and eligible for removal).
We previously did this regardless of the type of entry in the workdir;
if it was a directory, we would open(2) it and then try to read(2).
The read(2) of a directory fails on many platforms, so we would treat it
as if it were unmodified and continue to perform the checkout.
On FreeBSD, you _can_ read(2) a directory, so this pattern failed. We
would calculate an oid from the data read and determine that the
directory was modified and would therefore generate a checkout conflict.
This reliance on read(2) is silly (and was most likely accidentally
giving us the behavior we wanted), we should be explicit about the
directory test.
When creating and printing diffs, deal with binary deltas that have
binary data specially, versus diffs that have a binary file but lack the
actual binary data.
The `PKG_CHECK_MODULES` function searches a pkg-config module and
then proceeds to set various variables containing information on
how to link to the library. In contrast to the `FIND_PACKAGE`
function, the library path set by `PKG_CHECK_MODULES` will not
necessarily contain linking instructions with a complete path to
the library, though. So when a library is not installed in a
standard location, the linker might later fail due to being
unable to locate it.
While we already honor this when configuring libssh2 by adding
`LIBSSH2_LIBRARY_DIRS` to the link directories, we fail to do so
for libcurl, preventing us to build libgit2 on e.g. FreeBSD. Fix
the issue by adding the curl library directory to the linker
search path.
Instead of skipping printing a binary diff when there is no data, skip
printing when we have a status of `UNMODIFIED`. This is more in-line
with our internal data model and allows us to expand the notion of
binary data.
In the future, there may have no data because the files were unmodified
(there was no data to produce) or it may have no data because there was
no data given to us in a patch. We want to treat these cases
separately.
When generating diffs for binary files, we load and decompress
the blobs in order to generate the actual diff, which can be very
costly. While we cannot avoid this for the case when we are
called with the `GIT_DIFF_SHOW_BINARY` flag, we do not have to
load the blobs in the case where this flag is not set, as the
caller is expected to have no interest in the actual content of
binary files.
Fix the issue by only generating a binary diff when the caller is
actually interested in the diff. As libgit2 uses heuristics to
determine that a blob contains binary data by inspecting its size
without loading from the ODB, this saves us quite some time when
diffing in a repository with binary files.
According to the reference the git_checkout_tree and git_checkout_head
functions should accept NULL in the opts field
This was broken since the opts field was dereferenced and thus lead to a
crash.
Introduce GIT_OPT_ENABLE_SYMBOLIC_REF_TARGET_VALIDATION option.
Setting this option to 0 allows
validation of a symbolic ref's target to be bypassed.
This option is enabled by default.
This mechanism is added primarily to address a discrepancy between git
behaviour and libgit2 behaviour, whereby the former allows the symbolic
ref target to carry an arbitrary string and the latter does not, so:
$ git symbolic-ref refs/heads/foo bar
$ cat .git/refs/heads/foo
ref: bar
where as attempting the same via libgit2 raises an error:
The given reference name 'bar' is not valid
this mechanism also allows those that might want to make use of
git's more lenient treatment of symbolic ref targets to do so.