1. 10 Mar, 2018 40 commits
    • mingw: update TLS option flags · 9bdc00b1
      Include the constants for `WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1` and
      `WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2` so that they can be used by mingw.
      
      This updates both the `deps/winhttp` framework (for classic mingw) and
      adds the defines for mingw64, which does not use that framework.
      Edward Thomson committed
    • checkout test: further ensure workdir perms are updated · 1b853c48
      When both the index _and_ the working directory has changed
      permissions on a file permissions on a file - but only the permissions,
      such that the contents of the file are identical - ensure that
      `git_checkout` updates the permissions to match the checkout target.
      Edward Thomson committed
    • checkout test: ensure workdir perms are updated · 73615900
      When the working directory has changed permissions on a file - but only
      the permissions, such that the contents of the file are identical -
      ensure that `git_checkout` updates the permissions to match the checkout
      target.
      Edward Thomson committed
    • checkout: take mode into account when comparing index to baseline · 3983fc1d
      When checking out a file, we determine whether the baseline (what we
      expect to be in the working directory) actually matches the contents
      of the working directory.  This is safe behavior to prevent us from
      overwriting changes in the working directory.
      
      We look at the index to optimize this test: if we know that the index
      matches the working directory, then we can simply look at the index
      data compared to the baseline.
      
      We have historically compared the baseline to the index entry by oid.
      However, we must also compare the mode of the two items to ensure that
      they are identical.  Otherwise, we will refuse to update the working
      directory for a mode change.
      Edward Thomson committed
    • diff_tform: fix rename detection with rewrite/delete pair · e74e05ed
      A rewritten file can either be classified as a modification of its
      contents or of a delete of the complete file followed by an addition of
      the new content. This distinction becomes important when we want to
      detect renames for rewrites. Given a scenario where a file "a" has been
      deleted and another file "b" has been renamed to "a", this should be
      detected as a deletion of "a" followed by a rename of "a" -> "b". Thus,
      splitting of the original rewrite into a delete/add pair is important
      here.
      
      This splitting is represented by a flag we can set at the current delta.
      While the flag is already being set in case we want to break rewrites,
      we do not do so in case where the `GIT_DIFF_FIND_RENAMES_FROM_REWRITES`
      flag is set. This can trigger an assert when we try to match the source
      and target deltas.
      
      Fix the issue by setting the `GIT_DIFF_FLAG__TO_SPLIT` flag at the delta
      when it is a rename target and `GIT_DIFF_FIND_RENAMES_FROM_REWRITES` is
      set.
      Patrick Steinhardt committed
    • tests: add rename-rewrite scenarios to "renames" repository · e229e90d
      Add two more scenarios to the "renames" repository. The first scenario
      has a major rewrite of a file and a delete of another file, the second
      scenario has a deletion of a file and rename of another file to the
      deleted file. Both scenarios will be used in the following commit.
      Patrick Steinhardt committed
    • tests: diff::rename: use defines for commit OIDs · be205dfa
      While we frequently reuse commit OIDs throughout the file, we do not
      have any constants to refer to these commits. Make this a bit easier to
      read by giving the commit OIDs somewhat descriptive names of what kind
      of commit they refer to.
      Patrick Steinhardt committed
    • merge: virtual commit should be last argument to merge-base · b3c0d43c
      Our virtual commit must be the last argument to merge-base: since our
      algorithm pushes _both_ parents of the virtual commit, it needs to be
      the last argument, since merge-base:
      
      > Given three commits A, B and C, git merge-base A B C will compute the
      > merge base between A and a hypothetical commit M
      
      We want to calculate the merge base between the actual commit ("two")
      and the virtual commit ("one") - since one actually pushes its parents
      to the merge-base calculation, we need to calculate the merge base of
      "two" and the parents of one.
      Tyrie Vella committed
    • merge::trees::recursive: test for virtual base building · dc51d774
      Virtual base building: ensure that the virtual base is created and
      revwalked in the same way as git.
      Edward Thomson committed
    • merge: reverse merge bases for recursive merge · b2b37077
      When the commits being merged have multiple merge bases, reverse the
      order when creating the virtual merge base.  This is for compatibility
      with git's merge-recursive algorithm, and ensures that we build
      identical trees.
      
      Git does this to try to use older merge bases first.  Per 8918b0c:
      
      > It seems to be the only sane way to do it: when a two-head merge is
      > done, and the merge-base and one of the two branches agree, the
      > merge assumes that the other branch has something new.
      >
      > If we start creating virtual commits from newer merge-bases, and go
      > back to older merge-bases, and then merge with newer commits again,
      > chances are that a patch is lost, _because_ the merge-base and the
      > head agree on it. Unlikely, yes, but it happened to me.
      Edward Thomson committed
    • oidarray: introduce git_oidarray__reverse · 457a81bb
      Provide a simple function to reverse an oidarray.
      Edward Thomson committed
    • odb: export mempack backend · 5e97bdaf
      Fixes #4492, #4496.
      Adrián Medraño Calvo committed
    • Fix unpack double free · e83efde4
      If an element has been cached, but then the call to
      packfile_unpack_compressed() fails, the very next thing that happens is
      that its data is freed and then the element is not removed from the
      cache, which frees the data again.
      
      This change sets obj->data to NULL to avoid the double-free. It also
      stops trying to resolve deltas after two continuous failed rounds of
      resolution, and adds a test for this.
      lhchavez committed
    • diff_file: properly refcount blobs when initializing file contents · a521f5b1
      When initializing a `git_diff_file_content` from a source whose data is
      derived from a blob, we simply assign the blob's pointer to the
      resulting struct without incrementing its refcount. Thus, the structure
      can only be used as long as the blob is kept alive by the caller.
      
      Fix the issue by using `git_blob_dup` instead of a direct assignment.
      This function will increment the refcount of the blob without allocating
      new memory, so it does exactly what we want. As
      `git_diff_file_content__unload` already frees the blob when
      `GIT_DIFF_FLAG__FREE_BLOB` is set, we don't need to add new code
      handling the free but only have to set that flag correctly.
      Patrick Steinhardt committed
    • streams: openssl: fix thread-safety for OpenSSL error messages · 7cc80546
      The function `ERR_error_string` can be invoked without providing a
      buffer, in which case OpenSSL will simply return a string printed into a
      static buffer. Obviously and as documented in ERR_error_string(3), this
      is not thread-safe at all. As libgit2 is a library, though, it is easily
      possible that other threads may be using OpenSSL at the same time, which
      might lead to clobbered error strings.
      
      Fix the issue by instead using a stack-allocated buffer. According to
      the documentation, the caller has to provide a buffer of at least 256
      bytes of size. While we do so, make sure that the buffer will never get
      overflown by switching to `ERR_error_string_n` to specify the buffer's
      size.
      Patrick Steinhardt committed
    • hash: openssl: check return values of SHA1_* functions · 7ad0cee6
      The OpenSSL functions `SHA1_Init`, `SHA1_Update` and `SHA1_Final` all
      return 1 for success and 0 otherwise, but we never check their return
      values. Do so.
      Patrick Steinhardt committed
    • Simplified overflow condition · 8f189cbf
      lhchavez committed
    • Using unsigned instead · feb00daf
      lhchavez committed
    • libFuzzer: Prevent a potential shift overflow · a42e11ae
      The type of |base_offset| in get_delta_base() is `git_off_t`, which is a
      signed `long`. That means that we need to make sure that the 8 most
      significant bits are zero (instead of 7) to avoid an overflow when it is
      shifted by 7 bits.
      
      Found using libFuzzer.
      lhchavez committed
    • libFuzzer: Fix missing trailer crash · a3cd5e94
      This change fixes an invalid memory access when the trailer is missing /
      corrupt.
      
      Found using libFuzzer.
      lhchavez committed
    • libFuzzer: Fix a git_packfile_stream leak · 5cc3971a
      This change ensures that the git_packfile_stream object in
      git_indexer_append() does not leak when the stream has errors.
      
      Found using libFuzzer.
      lhchavez committed
    • openssl: fix thread-safety on non-glibc POSIX systems · 049e1de5
      While the OpenSSL library provides all means to work safely in a
      multi-threaded application, we fail to do so correctly. Quoting from
      crypto_lock(3):
      
          OpenSSL can safely be used in multi-threaded applications provided
          that at least two callback functions are set, locking_function and
          threadid_func.
      
      We do in fact provide the means to set up the locking function via
      `git_openssl_set_locking()`, where we initialize a set of locks by using
      the POSIX threads API and set the correct callback function to lock and
      unlock them.
      
      But what we do not do is setting the `threadid_func` callback. This
      function is being used to correctly locate thread-local data of the
      OpenSSL library and should thus return per-thread identifiers. Digging
      deeper into OpenSSL's documentation, the library does provide a fallback
      in case that locking function is not provided by the user. On Windows
      and BeOS we should be safe, as it simply "uses the system's default
      thread identifying API". On other platforms though OpenSSL will fall
      back to using the address of `errno`, assuming it is thread-local.
      
      While this assumption holds true for glibc-based systems, POSIX in fact
      does not specify whether it is thread-local or not. Quoting from
      errno(3p):
      
          It is unspecified whether errno is a macro or an identifier declared
          with external linkage.
      
      And in fact, with musl there is at least one libc implementation which
      simply declares `errno` as a simple `int` without being thread-local. On
      those systems, the fallback threadid function of OpenSSL will not be
      thread-safe.
      
      Fix this by setting up our own callback for this setting. As users of
      libgit2 may want to set it themselves, we obviously cannot always set
      that function on initialization. But as we already set up primitives for
      threading in `git_openssl_set_locking()`, this function becomes the
      obvious choice where to implement the additional setup.
      Patrick Steinhardt committed
    • diff_generate: fix unsetting diff flags · 3c4e0cee
      The macro `DIFF_FLAG_SET` can be used to set or unset a flag by
      modifying the diff's bitmask. While the case of setting the flag is
      handled correctly, the case of unsetting the flag was not. Instead of
      inverting the flags, we are inverting the value which is used to decide
      whether we want to set or unset the bits.
      
      The value being used here is a simple `bool` which is `false`. As that
      is being uplifted to `int` when getting the bitwise-complement, we will
      end up retaining all bits inside of the bitmask. As that's only ever
      used to set `GIT_DIFF_IGNORE_CASE`, we were actually always ignoring
      case for generated diffs.
      
      Fix that by instead getting the bitwise-complement of `FLAG`, not `VAL`.
      Patrick Steinhardt committed
    • diff: remove unused macros `DIFF_FLAG_*` · 05a753d4
      In commit 9be638ec (git_diff_generated: abstract generated diffs,
      2016-04-19), the code for generated diffs was moved out of the generic
      "diff.c" and instead into its own module. During that conversion, it was
      forgotten to remove the macros `DIFF_FLAG_IS_SET`, `DIFF_FLAG_ISNT_SET`
      and `DIFF_FLAG_SET`, which are now only used in "diff_generated.c".
      
      Remove those macros now.
      Patrick Steinhardt committed
    • Include git2/worktree.h in git2.h · 5c3a42ad
      I'm not sure if worktree.h was intentionally left out of git2.h. Looks like an oversight since it is in fact documented.
      apnadkarni committed
    • checkout: test force checkout when mode changes · e66bc08c
      Test that we can successfully force checkout a target when the file
      contents are identical, but the mode has changed.
      Edward Thomson committed
    • checkout: do not test file mode on Windows · 8631357e
      On Windows, we do not support file mode changes, so do not test
      for type changes between the disk and tree being checked out.
      
      We could have false positives since the on-disk file can only have
      an (effective) mode of 0100644 since NTFS does not support executable
      files.  If the tree being checked out did have an executable file,
      we would erroneously decide that the file on disk had been changed.
      Edward Thomson committed
    • checkout: treat files as modified if mode differs · 24388179
      When performing a forced checkout, treat files as modified when the
      workdir or the index is identical except for the mode.  This ensures
      that force checkout will update the mode to the target.  (Apply this
      check for regular files only, if one of the items was a file and the
      other was another type of item then this would be a typechange and
      handled independently.)
      Edward Thomson committed
    • transports: smart: fix memory leak when skipping symbolic refs · f41e86d6
      When we setup the revision walk for negotiating references with a
      remote, we iterate over all references, ignoring tags and symbolic
      references. While skipping over symbolic references, we forget to free
      the looked up reference, resulting in a memory leak when the next
      iteration simply overwrites the variable.
      
      Fix that issue by freeing the reference at the beginning of each
      iteration and collapsing return paths for error and success.
      Patrick Steinhardt committed
    • refs: do not use peeled OID if peeling to a tag · cda18f9b
      If a reference stored in a packed-refs file does not directly point to a
      commit, tree or blob, the packed-refs file will also will include a
      fully-peeled OID pointing to the first underlying object of that type.
      If we try to peel a reference to an object, we will use that peeled OID
      to speed up resolving the object.
      
      As a reference for an annotated tag does not directly point to a commit,
      tree or blob but instead to the tag object, the packed-refs file will
      have an accomodating fully-peeled OID pointing to the object referenced
      by that tag. When we use the fully-peeled OID pointing to the referenced
      object when peeling, we obviously cannot peel that to the tag anymore.
      
      Fix this issue by not using the fully-peeled OID whenever we want to
      peel to a tag. Note that this does not include the case where we want to
      resolve to _any_ object type. Existing code may make use from the fact
      that we resolve those to commit objects instead of tag objects, even
      though that behaviour is inconsistent between packed and loose
      references. Furthermore, some tests of ours make the assumption that we
      in fact resolve those references to a commit.
      Patrick Steinhardt committed
    • proxy: add a free function for the options's pointers · e29ab6fe
      When we duplicate a user-provided options struct, we're stuck with freeing the
      url in it. In case we add stuff to the proxy struct, let's add a function in
      which to put the logic.
      Carlos Martín Nieto committed
    • Clear the remote_ref_name buffer in git_push_update_tips() · c3fbf905
      If fetch_spec was a non-pattern, and it is not the first iteration of push_status vector, then git_refspec_transform would result in the new value appended via git_buf_puts to the previous iteration value.
      
      Forcibly clearing the buffer on each iteration to prevent this behavior.
      Slava Karpenko committed