New upstream version 0.27.4+dfsg.1

This commit is contained in:
Ximin Luo 2018-08-10 19:43:40 -07:00
parent eae0bfdcd8
commit 4b3ec53c78
63 changed files with 1251 additions and 359 deletions

View File

@ -21,6 +21,7 @@ env:
- OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON -DENABLE_WERROR=ON"
dist: trusty
osx_image: xcode8.3
sudo: false
addons:

View File

@ -1,13 +1,88 @@
v0.27 + 1
v0.27.4
-------
This is a security release fixing out-of-bounds reads when
processing smart-protocol "ng" packets.
When parsing an "ng" packet, we keep track of both the current position
as well as the remaining length of the packet itself. But instead of
taking care not to exceed the length, we pass the current pointer's
position to `strchr`, which will search for a certain character until
hitting NUL. It is thus possible to create a crafted packet which
doesn't contain a NUL byte to trigger an out-of-bounds read.
The issue was discovered by the oss-fuzz project, issue 9406.
v0.27.3
-------
This is a security release fixing out-of-bounds reads when
reading objects from a packfile. This corresponds to
CVE-2018-10887 and CVE-2018-10888, which were both reported by
Riccardo Schirone.
When packing objects into a single so-called packfile, objects
may not get stored as complete copies but instead as deltas
against another object "base". A specially crafted delta object
could trigger an integer overflow and thus bypass our input
validation, which may result in copying memory before or after
the base object into the final deflated object. This may lead to
objects containing copies of system memory being written into the
object database. As the hash of those objects cannot be easily
controlled by the attacker, it is unlikely that any of those
objects will be valid and referenced by the commit graph.
Note that the error could also be triggered by the function
`git_apply__patch`. But as this function is not in use outside of
our test suite, it is not a possible attack vector.
v0.27.2
---------
### Changes or improvements
### API additions
* Fix builds with LibreSSL 2.7.
### API removals
* Fix for `git_diff_status_char()` not returning the correct mapping for
`GIT_DELTA_TYPECHANGE`.
### Breaking API changes
* Fix for the submodules API not reporting errors when parsing the ".gitmodules"
file.
* Fix for accepting a ".gitmodules" file where two submodules have the same
path.
* Fix for hiding references in a graph walk not always limiting the graph
correctly.
* Fix for directory patterns with trailing spaces in attribute files not being
handled correctly.
* Fix SSH transports not properly disconnecting from the server.
* Fix reading HEAD reflog in worktrees.
* Update our copy of SHA1DC to fix errors with endianess on some platforms.
v0.27.1
---------
This is a security release fixing insufficient validation of submodule names
(CVE-2018-11235, reported by Etienne Stalmans) and disallows `.gitmodules` files
as symlinks.
While submodule names come from the untrusted ".gitmodules" file, we blindly
append the name to "$GIT_DIR/modules" to construct the final path of the
submodule repository. In case the name contains e.g. "../", an adversary would
be able to escape your repository and write data at arbitrary paths. In
accordance with git, we now enforce some rules for submodule names which will
cause libgit2 to ignore these malicious names.
Adding a symlink as `.gitmodules` into the index from the workdir or checking
out such files is not allowed as this can make a Git implementation write
outside of the repository and bypass the `fsck` checks for CVE-2018-11235.
libgit2 is not susceptible to CVE-2018-11233.
v0.27
---------

View File

@ -29,7 +29,7 @@ INCLUDE(CheckFunctionExists)
INCLUDE(CheckSymbolExists)
INCLUDE(CheckStructHasMember)
INCLUDE(AddCFlagIfSupported)
INCLUDE(FindPkgConfig)
INCLUDE(FindPkgLibraries)
INCLUDE(FindThreads)
INCLUDE(FindStatNsec)
INCLUDE(IdeSplitSources)

View File

@ -43,6 +43,11 @@ build_script:
if "%GENERATOR%"=="MSYS Makefiles" (C:\MinGW\msys\1.0\bin\sh --login /c/projects/libgit2/script/appveyor-mingw.sh)
test_script:
- ps: |
# Disable DHE key exchange to fix intermittent build failures ("A buffer
# provided was too small") due to SChannel bug. See e.g.
# - https://github.com/aws/aws-sdk-cpp/issues/671
# - https://github.com/dotnet/corefx/issues/7812
New-Item HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman -Force | New-ItemProperty -Name Enabled -Value 0 -Force
$ErrorActionPreference="Stop"
Start-FileDownload https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar -FileName poxyproxy.jar
# Run this early so we know it's ready by the time we need it

View File

@ -0,0 +1,28 @@
INCLUDE(FindPkgConfig)
# This function will find and set up a pkg-config based module.
# If a pc-file was found, it will resolve library paths to
# absolute paths. Furthermore, the function will automatically
# fall back to use static libraries in case no dynamic libraries
# were found.
FUNCTION(FIND_PKGLIBRARIES prefix package)
PKG_CHECK_MODULES(${prefix} ${package})
IF(NOT ${prefix}_FOUND)
RETURN()
ENDIF()
FOREACH(LIBRARY ${${prefix}_LIBRARIES})
FIND_LIBRARY(${LIBRARY}_RESOLVED ${LIBRARY} PATHS ${${prefix}_LIBRARY_DIRS})
IF(${${LIBRARY}_RESOLVED} STREQUAL "${LIBRARY}_RESOLVED-NOTFOUND")
MESSAGE(FATAL_ERROR "could not resolve ${LIBRARY}")
ENDIF()
LIST(APPEND RESOLVED_LIBRARIES ${${LIBRARY}_RESOLVED})
ENDFOREACH(LIBRARY)
SET(${prefix}_FOUND 1 PARENT_SCOPE)
SET(${prefix}_LIBRARIES ${RESOLVED_LIBRARIES} PARENT_SCOPE)
SET(${prefix}_INCLUDE_DIRS ${${prefix}_INCLUDE_DIRS} PARENT_SCOPE)
SET(${prefix}_LDFLAGS ${${prefix}_LDFLAGS} PARENT_SCOPE)
MESSAGE(STATUS " Resolved libraries: ${RESOLVED_LIBRARIES}")
ENDFUNCTION()

View File

@ -1,4 +1,3 @@
LINK_DIRECTORIES(${LIBGIT2_LIBDIRS})
INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES})
FILE(GLOB_RECURSE SRC_EXAMPLE_GIT2 network/*.c network/*.h common.?)

View File

@ -7,10 +7,10 @@
#ifndef INCLUDE_git_version_h__
#define INCLUDE_git_version_h__
#define LIBGIT2_VERSION "0.27.0"
#define LIBGIT2_VERSION "0.27.4"
#define LIBGIT2_VER_MAJOR 0
#define LIBGIT2_VER_MINOR 27
#define LIBGIT2_VER_REVISION 0
#define LIBGIT2_VER_REVISION 4
#define LIBGIT2_VER_PATCH 0
#define LIBGIT2_SOVERSION 27

View File

@ -17,7 +17,6 @@ SET(LIBGIT2_INCLUDES
"${libgit2_SOURCE_DIR}/src"
"${libgit2_SOURCE_DIR}/include")
SET(LIBGIT2_LIBS "")
SET(LIBGIT2_LIBDIRS "")
# Installation paths
#
@ -109,7 +108,6 @@ IF (WIN32 AND WINHTTP)
ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/winhttp" "${libgit2_BINARY_DIR}/deps/winhttp")
LIST(APPEND LIBGIT2_LIBS winhttp)
LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/winhttp")
LIST(APPEND LIBGIT2_LIBDIRS ${LIBWINHTTP_PATH})
ELSE()
LIST(APPEND LIBGIT2_LIBS "winhttp")
LIST(APPEND LIBGIT2_PC_LIBS "-lwinhttp")
@ -119,13 +117,11 @@ IF (WIN32 AND WINHTTP)
LIST(APPEND LIBGIT2_PC_LIBS "-lrpcrt4" "-lcrypt32" "-lole32")
ELSE ()
IF (CURL)
PKG_CHECK_MODULES(CURL libcurl)
FIND_PKGLIBRARIES(CURL libcurl)
ENDIF ()
IF (CURL_FOUND)
SET(GIT_CURL 1)
LIST(APPEND LIBGIT2_INCLUDES ${CURL_INCLUDE_DIRS})
LIST(APPEND LIBGIT2_LIBDIRS ${CURL_LIBRARY_DIRS})
LIST(APPEND LIBGIT2_LIBS ${CURL_LIBRARIES})
LIST(APPEND LIBGIT2_PC_LIBS ${CURL_LDFLAGS})
ENDIF()
@ -282,15 +278,13 @@ ENDIF()
# Optional external dependency: libssh2
IF (USE_SSH)
PKG_CHECK_MODULES(LIBSSH2 libssh2)
FIND_PKGLIBRARIES(LIBSSH2 libssh2)
ENDIF()
IF (LIBSSH2_FOUND)
SET(GIT_SSH 1)
LIST(APPEND LIBGIT2_INCLUDES ${LIBSSH2_INCLUDE_DIRS})
LIST(APPEND LIBGIT2_LIBS ${LIBSSH2_LIBRARIES})
LIST(APPEND LIBGIT2_LIBDIRS ${LIBSSH2_LIBRARY_DIRS})
LIST(APPEND LIBGIT2_PC_LIBS ${LIBSSH2_LDFLAGS})
#SET(LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS} ${LIBSSH2_LDFLAGS}")
CHECK_LIBRARY_EXISTS("${LIBSSH2_LIBRARIES}" libssh2_userauth_publickey_frommemory "${LIBSSH2_LIBRARY_DIRS}" HAVE_LIBSSH2_MEMORY_CREDENTIALS)
IF (HAVE_LIBSSH2_MEMORY_CREDENTIALS)
@ -404,7 +398,6 @@ ENDIF()
SET(LIBGIT2_OBJECTS ${LIBGIT2_OBJECTS} PARENT_SCOPE)
SET(LIBGIT2_INCLUDES ${LIBGIT2_INCLUDES} PARENT_SCOPE)
SET(LIBGIT2_LIBS ${LIBGIT2_LIBS} PARENT_SCOPE)
SET(LIBGIT2_LIBDIRS ${LIBGIT2_LIBDIRS} PARENT_SCOPE)
IF(XCODE_VERSION)
# This is required for Xcode to actually link the libgit2 library
@ -414,7 +407,6 @@ IF(XCODE_VERSION)
ENDIF()
# Compile and link libgit2
LINK_DIRECTORIES(${LIBGIT2_LIBDIRS})
ADD_LIBRARY(git2 ${WIN_RC} ${LIBGIT2_OBJECTS})
TARGET_LINK_LIBRARIES(git2 ${LIBGIT2_LIBS})

View File

@ -633,6 +633,11 @@ int git_attr_fnmatch__parse(
if (--spec->length == 0)
return GIT_ENOTFOUND;
/* Remove trailing spaces. */
while (pattern[spec->length - 1] == ' ' || pattern[spec->length - 1] == '\t')
if (--spec->length == 0)
return GIT_ENOTFOUND;
if (pattern[spec->length - 1] == '/') {
spec->length--;
spec->flags = spec->flags | GIT_ATTR_FNMATCH_DIRECTORY;

View File

@ -1276,14 +1276,14 @@ static int checkout_verify_paths(
unsigned int flags = GIT_PATH_REJECT_WORKDIR_DEFAULTS;
if (action & CHECKOUT_ACTION__REMOVE) {
if (!git_path_isvalid(repo, delta->old_file.path, flags)) {
if (!git_path_isvalid(repo, delta->old_file.path, delta->old_file.mode, flags)) {
giterr_set(GITERR_CHECKOUT, "cannot remove invalid path '%s'", delta->old_file.path);
return -1;
}
}
if (action & ~CHECKOUT_ACTION__REMOVE) {
if (!git_path_isvalid(repo, delta->new_file.path, flags)) {
if (!git_path_isvalid(repo, delta->new_file.path, delta->new_file.mode, flags)) {
giterr_set(GITERR_CHECKOUT, "cannot checkout to invalid path '%s'", delta->new_file.path);
return -1;
}

View File

@ -539,10 +539,11 @@ int git_delta_apply(
*out = NULL;
*out_len = 0;
/* Check that the base size matches the data we were given;
* if not we would underflow while accessing data from the
* base object, resulting in data corruption or segfault.
*/
/*
* Check that the base size matches the data we were given;
* if not we would underflow while accessing data from the
* base object, resulting in data corruption or segfault.
*/
if ((hdr_sz(&base_sz, &delta, delta_end) < 0) || (base_sz != base_len)) {
giterr_set(GITERR_INVALID, "failed to apply delta: base size does not match given data");
return -1;
@ -564,31 +565,34 @@ int git_delta_apply(
while (delta < delta_end) {
unsigned char cmd = *delta++;
if (cmd & 0x80) {
/* cmd is a copy instruction; copy from the base.
*/
size_t off = 0, len = 0;
/* cmd is a copy instruction; copy from the base. */
size_t off = 0, len = 0, end;
if (cmd & 0x01) off = *delta++;
if (cmd & 0x02) off |= *delta++ << 8UL;
if (cmd & 0x04) off |= *delta++ << 16UL;
if (cmd & 0x08) off |= *delta++ << 24UL;
#define ADD_DELTA(o, shift) { if (delta < delta_end) (o) |= ((unsigned) *delta++ << shift); else goto fail; }
if (cmd & 0x01) ADD_DELTA(off, 0UL);
if (cmd & 0x02) ADD_DELTA(off, 8UL);
if (cmd & 0x04) ADD_DELTA(off, 16UL);
if (cmd & 0x08) ADD_DELTA(off, 24UL);
if (cmd & 0x10) len = *delta++;
if (cmd & 0x20) len |= *delta++ << 8UL;
if (cmd & 0x40) len |= *delta++ << 16UL;
if (!len) len = 0x10000;
if (cmd & 0x10) ADD_DELTA(len, 0UL);
if (cmd & 0x20) ADD_DELTA(len, 8UL);
if (cmd & 0x40) ADD_DELTA(len, 16UL);
if (!len) len = 0x10000;
#undef ADD_DELTA
if (base_len < off + len || res_sz < len)
if (GIT_ADD_SIZET_OVERFLOW(&end, off, len) ||
base_len < end || res_sz < len)
goto fail;
memcpy(res_dp, base + off, len);
res_dp += len;
res_sz -= len;
}
else if (cmd) {
/* cmd is a literal insert instruction; copy from
* the delta stream itself.
*/
} else if (cmd) {
/*
* cmd is a literal insert instruction; copy from
* the delta stream itself.
*/
if (delta_end - delta < cmd || res_sz < cmd)
goto fail;
memcpy(res_dp, delta, cmd);
@ -596,10 +600,8 @@ int git_delta_apply(
res_dp += cmd;
res_sz -= cmd;
}
else {
/* cmd == 0 is reserved for future encodings.
*/
} else {
/* cmd == 0 is reserved for future encodings. */
goto fail;
}
}

View File

@ -130,6 +130,7 @@ char git_diff_status_char(git_delta_t status)
case GIT_DELTA_COPIED: code = 'C'; break;
case GIT_DELTA_IGNORED: code = 'I'; break;
case GIT_DELTA_UNTRACKED: code = '?'; break;
case GIT_DELTA_TYPECHANGE: code = 'T'; break;
case GIT_DELTA_UNREADABLE: code = 'X'; break;
default: code = ' '; break;
}

View File

@ -10,6 +10,9 @@
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __unix__
#include <sys/types.h> /* make sure macros like _BIG_ENDIAN visible */
#endif
#endif
#ifdef SHA1DC_CUSTOM_INCLUDE_SHA1_C
@ -23,6 +26,13 @@
#include "sha1.h"
#include "ubc_check.h"
#if (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \
defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || \
defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || \
defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) || \
defined(__386) || defined(_M_X64) || defined(_M_AMD64))
#define SHA1DC_ON_INTEL_LIKE_PROCESSOR
#endif
/*
Because Little-Endian architectures are most common,
@ -32,29 +42,70 @@
If you are compiling on a big endian platform and your compiler does not define one of these,
you will have to add whatever macros your tool chain defines to indicate Big-Endianness.
*/
#ifdef SHA1DC_BIGENDIAN
#undef SHA1DC_BIGENDIAN
#endif
#if (defined(_BYTE_ORDER) || defined(__BYTE_ORDER) || defined(__BYTE_ORDER__))
#if ((defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN)) || \
(defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || \
(defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__)) )
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
/*
* Should detect Big Endian under GCC since at least 4.6.0 (gcc svn
* rev #165881). See
* https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
*
* This also works under clang since 3.2, it copied the GCC-ism. See
* clang.git's 3b198a97d2 ("Preprocessor: add __BYTE_ORDER__
* predefined macro", 2012-07-27)
*/
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define SHA1DC_BIGENDIAN
#endif
#else
#if (defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN) || defined(__BIG_ENDIAN__) || \
defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || \
defined(__sparc))
/* Not under GCC-alike */
#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN)
/*
* Should detect Big Endian under glibc.git since 14245eb70e ("entered
* into RCS", 1992-11-25). Defined in <endian.h> which will have been
* brought in by standard headers. See glibc.git and
* https://sourceforge.net/p/predef/wiki/Endianness/
*/
#if __BYTE_ORDER == __BIG_ENDIAN
#define SHA1DC_BIGENDIAN
#endif
/* Not under GCC-alike or glibc */
#elif defined(_BYTE_ORDER) && defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN)
/*
* *BSD and newlib (embeded linux, cygwin, etc).
* the defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN) part prevents
* this condition from matching with Solaris/sparc.
* (Solaris defines only one endian macro)
*/
#if _BYTE_ORDER == _BIG_ENDIAN
#define SHA1DC_BIGENDIAN
#endif
/* Not under GCC-alike or glibc or *BSD or newlib */
#elif (defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || \
defined(__sparc))
/*
* Should define Big Endian for a whitelist of known processors. See
* https://sourceforge.net/p/predef/wiki/Endianness/ and
* http://www.oracle.com/technetwork/server-storage/solaris/portingtosolaris-138514.html
*/
#define SHA1DC_BIGENDIAN
/* Not under GCC-alike or glibc or *BSD or newlib or <processor whitelist> */
#elif defined(SHA1DC_ON_INTEL_LIKE_PROCESSOR)
/*
* As a last resort before we do anything else we're not 100% sure
* about below, we blacklist specific processors here. We could add
* more, see e.g. https://wiki.debian.org/ArchitectureSpecificsMemo
*/
#else /* Not under GCC-alike or glibc or *BSD or newlib or <processor whitelist> or <processor blacklist> */
/* We do nothing more here for now */
/*#error "Uncomment this to see if you fall through all the detection"*/
#endif /* Big Endian detection */
#if (defined(SHA1DC_FORCE_LITTLEENDIAN) && defined(SHA1DC_BIGENDIAN))
#undef SHA1DC_BIGENDIAN
#endif
@ -63,15 +114,8 @@
#endif
/*ENDIANNESS SELECTION*/
#if (defined SHA1DC_FORCE_UNALIGNED_ACCESS || \
defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \
defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || \
defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || \
defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) || \
defined(__386) || defined(_M_X64) || defined(_M_AMD64))
#if defined(SHA1DC_FORCE_UNALIGNED_ACCESS) || defined(SHA1DC_ON_INTEL_LIKE_PROCESSOR)
#define SHA1DC_ALLOW_UNALIGNED_ACCESS
#endif /*UNALIGNMENT DETECTION*/
@ -918,7 +962,7 @@ static void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], co
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4127) /* Complier complains about the checks in the above macro being constant. */
#pragma warning(disable: 4127) /* Compiler complains about the checks in the above macro being constant. */
#endif
#ifdef DOSTORESTATE0

View File

@ -213,16 +213,6 @@ static int parse_ignore_file(
if (ignore_case)
match->flags |= GIT_ATTR_FNMATCH_ICASE;
while (match->length > 0) {
if (match->pattern[match->length - 1] == ' ' ||
match->pattern[match->length - 1] == '\t') {
match->pattern[match->length - 1] = 0;
match->length --;
} else {
break;
}
}
scan = git__next_line(scan);
/*

View File

@ -884,11 +884,13 @@ static int index_entry_create(
git_index_entry **out,
git_repository *repo,
const char *path,
struct stat *st,
bool from_workdir)
{
size_t pathlen = strlen(path), alloclen;
struct entry_internal *entry;
unsigned int path_valid_flags = GIT_PATH_REJECT_INDEX_DEFAULTS;
uint16_t mode = 0;
/* always reject placing `.git` in the index and directory traversal.
* when requested, disallow platform-specific filenames and upgrade to
@ -896,8 +898,10 @@ static int index_entry_create(
*/
if (from_workdir)
path_valid_flags |= GIT_PATH_REJECT_WORKDIR_DEFAULTS;
if (st)
mode = st->st_mode;
if (!git_path_isvalid(repo, path, path_valid_flags)) {
if (!git_path_isvalid(repo, path, mode, path_valid_flags)) {
giterr_set(GITERR_INDEX, "invalid path: '%s'", path);
return -1;
}
@ -922,15 +926,35 @@ static int index_entry_init(
{
int error = 0;
git_index_entry *entry = NULL;
git_buf path = GIT_BUF_INIT;
struct stat st;
git_oid oid;
git_repository *repo;
if (INDEX_OWNER(index) == NULL)
return create_index_error(-1,
"could not initialize index entry. "
"Index is not backed up by an existing repository.");
if (index_entry_create(&entry, INDEX_OWNER(index), rel_path, true) < 0)
/*
* FIXME: this is duplicated with the work in
* git_blob__create_from_paths. It should accept an optional stat
* structure so we can pass in the one we have to do here.
*/
repo = INDEX_OWNER(index);
if (git_repository__ensure_not_bare(repo, "create blob from file") < 0)
return GIT_EBAREREPO;
if (git_buf_joinpath(&path, git_repository_workdir(repo), rel_path) < 0)
return -1;
error = git_path_lstat(path.ptr, &st);
git_buf_free(&path);
if (error < 0)
return error;
if (index_entry_create(&entry, INDEX_OWNER(index), rel_path, &st, true) < 0)
return -1;
/* write the blob to disk and get the oid and stat info */
@ -1016,7 +1040,7 @@ static int index_entry_dup(
git_index *index,
const git_index_entry *src)
{
if (index_entry_create(out, INDEX_OWNER(index), src->path, false) < 0)
if (index_entry_create(out, INDEX_OWNER(index), src->path, NULL, false) < 0)
return -1;
index_entry_cpy(*out, src);
@ -1038,7 +1062,7 @@ static int index_entry_dup_nocache(
git_index *index,
const git_index_entry *src)
{
if (index_entry_create(out, INDEX_OWNER(index), src->path, false) < 0)
if (index_entry_create(out, INDEX_OWNER(index), src->path, NULL, false) < 0)
return -1;
index_entry_cpy_nocache(*out, src);
@ -1461,9 +1485,6 @@ static int add_repo_as_submodule(git_index_entry **out, git_index *index, const
struct stat st;
int error;
if (index_entry_create(&entry, INDEX_OWNER(index), path, true) < 0)
return -1;
if ((error = git_buf_joinpath(&abspath, git_repository_workdir(repo), path)) < 0)
return error;
@ -1472,6 +1493,9 @@ static int add_repo_as_submodule(git_index_entry **out, git_index *index, const
return -1;
}
if (index_entry_create(&entry, INDEX_OWNER(index), path, &st, true) < 0)
return -1;
git_index_entry__init_from_stat(entry, &st, !index->distrust_filemode);
if ((error = git_repository_open(&sub, abspath.ptr)) < 0)
@ -2965,7 +2989,7 @@ static int read_tree_cb(
if (git_buf_joinpath(&path, root, tentry->filename) < 0)
return -1;
if (index_entry_create(&entry, INDEX_OWNER(data->index), path.ptr, false) < 0)
if (index_entry_create(&entry, INDEX_OWNER(data->index), path.ptr, NULL, false) < 0)
return -1;
entry->mode = tentry->attr;

View File

@ -157,6 +157,7 @@ static void impl__free(git_odb_backend *_backend)
{
struct memory_packer_db *db = (struct memory_packer_db *)_backend;
git_mempack_reset(_backend);
git_oidmap_free(db->objects);
git__free(db);
}

View File

@ -1561,18 +1561,31 @@ static int32_t next_hfs_char(const char **in, size_t *len)
return 0; /* NULL byte -- end of string */
}
static bool verify_dotgit_hfs(const char *path, size_t len)
static bool verify_dotgit_hfs_generic(const char *path, size_t len, const char *needle, size_t needle_len)
{
if (next_hfs_char(&path, &len) != '.' ||
next_hfs_char(&path, &len) != 'g' ||
next_hfs_char(&path, &len) != 'i' ||
next_hfs_char(&path, &len) != 't' ||
next_hfs_char(&path, &len) != 0)
size_t i;
char c;
if (next_hfs_char(&path, &len) != '.')
return true;
for (i = 0; i < needle_len; i++) {
c = next_hfs_char(&path, &len);
if (c != needle[i])
return true;
}
if (next_hfs_char(&path, &len) != '\0')
return true;
return false;
}
static bool verify_dotgit_hfs(const char *path, size_t len)
{
return verify_dotgit_hfs_generic(path, len, "git", CONST_STRLEN("git"));
}
GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size_t len)
{
git_buf *reserved = git_repository__reserved_names_win32;
@ -1608,6 +1621,57 @@ GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size
return false;
}
GIT_INLINE(bool) only_spaces_and_dots(const char *path)
{
const char *c = path;
for (;; c++) {
if (*c == '\0')
return true;
if (*c != ' ' && *c != '.')
return false;
}
return true;
}
GIT_INLINE(bool) verify_dotgit_ntfs_generic(const char *name, size_t len, const char *dotgit_name, size_t dotgit_len, const char *shortname_pfix)
{
int i, saw_tilde;
if (name[0] == '.' && len >= dotgit_len &&
!strncasecmp(name + 1, dotgit_name, dotgit_len)) {
return !only_spaces_and_dots(name + dotgit_len + 1);
}
/* Detect the basic NTFS shortname with the first six chars */
if (!strncasecmp(name, dotgit_name, 6) && name[6] == '~' &&
name[7] >= '1' && name[7] <= '4')
return !only_spaces_and_dots(name + 8);
/* Catch fallback names */
for (i = 0, saw_tilde = 0; i < 8; i++) {
if (name[i] == '\0') {
return true;
} else if (saw_tilde) {
if (name[i] < '0' || name[i] > '9')
return true;
} else if (name[i] == '~') {
if (name[i+1] < '1' || name[i+1] > '9')
return true;
saw_tilde = 1;
} else if (i >= 6) {
return true;
} else if (name[i] < 0) {
return true;
} else if (git__tolower(name[i]) != shortname_pfix[i]) {
return true;
}
}
return !only_spaces_and_dots(name + i);
}
GIT_INLINE(bool) verify_char(unsigned char c, unsigned int flags)
{
if ((flags & GIT_PATH_REJECT_BACKSLASH) && c == '\\')
@ -1635,6 +1699,24 @@ GIT_INLINE(bool) verify_char(unsigned char c, unsigned int flags)
return true;
}
/*
* Return the length of the common prefix between str and prefix, comparing them
* case-insensitively (must be ASCII to match).
*/
GIT_INLINE(size_t) common_prefix_icase(const char *str, size_t len, const char *prefix)
{
size_t count = 0;
while (len >0 && tolower(*str) == tolower(*prefix)) {
count++;
str++;
prefix++;
len--;
}
return count;
}
/*
* We fundamentally don't like some paths when dealing with user-inputted
* strings (in checkout or ref names): we don't want dot or dot-dot
@ -1648,6 +1730,7 @@ static bool verify_component(
git_repository *repo,
const char *component,
size_t len,
uint16_t mode,
unsigned int flags)
{
if (len == 0)
@ -1680,26 +1763,38 @@ static bool verify_component(
return false;
}
if (flags & GIT_PATH_REJECT_DOT_GIT_HFS &&
!verify_dotgit_hfs(component, len))
return false;
if (flags & GIT_PATH_REJECT_DOT_GIT_HFS) {
if (!verify_dotgit_hfs(component, len))
return false;
if (S_ISLNK(mode) && git_path_is_hfs_dotgit_modules(component, len))
return false;
}
if (flags & GIT_PATH_REJECT_DOT_GIT_NTFS &&
!verify_dotgit_ntfs(repo, component, len))
return false;
if (flags & GIT_PATH_REJECT_DOT_GIT_NTFS) {
if (!verify_dotgit_ntfs(repo, component, len))
return false;
if (S_ISLNK(mode) && git_path_is_ntfs_dotgit_modules(component, len))
return false;
}
/* don't bother rerunning the `.git` test if we ran the HFS or NTFS
* specific tests, they would have already rejected `.git`.
*/
if ((flags & GIT_PATH_REJECT_DOT_GIT_HFS) == 0 &&
(flags & GIT_PATH_REJECT_DOT_GIT_NTFS) == 0 &&
(flags & GIT_PATH_REJECT_DOT_GIT_LITERAL) &&
len == 4 &&
component[0] == '.' &&
(component[1] == 'g' || component[1] == 'G') &&
(component[2] == 'i' || component[2] == 'I') &&
(component[3] == 't' || component[3] == 'T'))
return false;
(flags & GIT_PATH_REJECT_DOT_GIT_NTFS) == 0 &&
(flags & GIT_PATH_REJECT_DOT_GIT_LITERAL)) {
if (len >= 4 &&
component[0] == '.' &&
(component[1] == 'g' || component[1] == 'G') &&
(component[2] == 'i' || component[2] == 'I') &&
(component[3] == 't' || component[3] == 'T')) {
if (len == 4)
return false;
if (S_ISLNK(mode) && common_prefix_icase(component, len, ".gitmodules") == len)
return false;
}
}
return true;
}
@ -1737,6 +1832,7 @@ GIT_INLINE(unsigned int) dotgit_flags(
bool git_path_isvalid(
git_repository *repo,
const char *path,
uint16_t mode,
unsigned int flags)
{
const char *start, *c;
@ -1750,14 +1846,14 @@ bool git_path_isvalid(
return false;
if (*c == '/') {
if (!verify_component(repo, start, (c - start), flags))
if (!verify_component(repo, start, (c - start), mode, flags))
return false;
start = c+1;
}
}
return verify_component(repo, start, (c - start), flags);
return verify_component(repo, start, (c - start), mode, flags);
}
int git_path_normalize_slashes(git_buf *out, const char *path)
@ -1775,3 +1871,65 @@ int git_path_normalize_slashes(git_buf *out, const char *path)
return 0;
}
static int verify_dotgit_generic(const char *name, size_t len, const char *dotgit_name, size_t dotgit_len, const char *shortname_pfix)
{
if (!verify_dotgit_ntfs_generic(name, len, dotgit_name, dotgit_len, shortname_pfix))
return false;
return verify_dotgit_hfs_generic(name, len, dotgit_name, dotgit_len);
}
int git_path_is_ntfs_dotgit_modules(const char *name, size_t len)
{
return !verify_dotgit_ntfs_generic(name, len, "gitmodules", CONST_STRLEN("gitmodules"), "gi7eba");
}
int git_path_is_hfs_dotgit_modules(const char *name, size_t len)
{
return !verify_dotgit_hfs_generic(name, len, "gitmodules", CONST_STRLEN("gitmodules"));
}
int git_path_is_dotgit_modules(const char *name, size_t len)
{
if (git_path_is_hfs_dotgit_modules(name, len))
return 1;
return git_path_is_ntfs_dotgit_modules(name, len);
}
int git_path_is_ntfs_dotgit_ignore(const char *name, size_t len)
{
return !verify_dotgit_ntfs_generic(name, len, "gitignore", CONST_STRLEN("gitignore"), "gi250a");
}
int git_path_is_hfs_dotgit_ignore(const char *name, size_t len)
{
return !verify_dotgit_hfs_generic(name, len, "gitignore", CONST_STRLEN("gitignore"));
}
int git_path_is_dotgit_ignore(const char *name, size_t len)
{
if (git_path_is_hfs_dotgit_ignore(name, len))
return 1;
return git_path_is_ntfs_dotgit_ignore(name, len);
}
int git_path_is_hfs_dotgit_attributes(const char *name, size_t len)
{
return !verify_dotgit_hfs_generic(name, len, "gitattributes", CONST_STRLEN("gitattributes"));
}
int git_path_is_ntfs_dotgit_attributes(const char *name, size_t len)
{
return !verify_dotgit_ntfs_generic(name, len, "gitattributes", CONST_STRLEN("gitattributes"), "gi7d29");
}
int git_path_is_dotgit_attributes(const char *name, size_t len)
{
if (git_path_is_hfs_dotgit_attributes(name, len))
return 1;
return git_path_is_ntfs_dotgit_attributes(name, len);
}

View File

@ -637,6 +637,7 @@ extern int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or
extern bool git_path_isvalid(
git_repository *repo,
const char *path,
uint16_t mode,
unsigned int flags);
/**
@ -644,4 +645,76 @@ extern bool git_path_isvalid(
*/
int git_path_normalize_slashes(git_buf *out, const char *path);
/**
* Check whether a path component corresponds to a .gitmodules file
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_dotgit_modules(const char *name, size_t len);
/**
* Check whether a path component corresponds to a .gitmodules file in NTFS
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_ntfs_dotgit_modules(const char *name, size_t len);
/**
* Check whether a path component corresponds to a .gitmodules file in HFS+
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_hfs_dotgit_modules(const char *name, size_t len);
/**
* Check whether a path component corresponds to a .gitignore file
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_dotgit_ignore(const char *name, size_t len);
/**
* Check whether a path component corresponds to a .gitignore file in NTFS
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_ntfs_dotgit_ignore(const char *name, size_t len);
/**
* Check whether a path component corresponds to a .gitignore file in HFS+
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_hfs_dotgit_ignore(const char *name, size_t len);
/**
* Check whether a path component corresponds to a .gitignore file
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_dotgit_attributes(const char *name, size_t len);
/**
* Check whether a path component corresponds to a .gitattributes file in NTFS
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_ntfs_dotgit_attributes(const char *name, size_t len);
/**
* Check whether a path component corresponds to a .gitattributes file in HFS+
*
* @param name the path component to check
* @param len the length of `name`
*/
extern int git_path_is_hfs_dotgit_attributes(const char *name, size_t len);
#endif

View File

@ -744,7 +744,7 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *
assert(file && backend && name);
if (!git_path_isvalid(backend->repo, name, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
if (!git_path_isvalid(backend->repo, name, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
giterr_set(GITERR_INVALID, "invalid reference name '%s'", name);
return GIT_EINVALIDSPEC;
}
@ -1603,6 +1603,8 @@ static int create_new_reflog_file(const char *filepath)
GIT_INLINE(int) retrieve_reflog_path(git_buf *path, git_repository *repo, const char *name)
{
if (strcmp(name, GIT_HEAD_FILE) == 0)
return git_buf_join3(path, '/', repo->gitdir, GIT_REFLOG_DIR, name);
return git_buf_join3(path, '/', repo->commondir, GIT_REFLOG_DIR, name);
}
@ -1740,7 +1742,7 @@ static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char
repo = backend->repo;
if (!git_path_isvalid(backend->repo, refname, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
if (!git_path_isvalid(backend->repo, refname, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
giterr_set(GITERR_INVALID, "invalid reference name '%s'", refname);
return GIT_EINVALIDSPEC;
}

View File

@ -115,6 +115,9 @@ int git_reference_dup(git_reference **dest, git_reference *source)
GITERR_CHECK_ALLOC(*dest);
(*dest)->db = source->db;
GIT_REFCOUNT_INC((*dest)->db);
return 0;
}

View File

@ -116,6 +116,10 @@ int git_reference_lookup_resolved(
* with the given name pointing to the reference pointed to by
* the file. If it is not a symbolic reference, it will return
* the resolved reference.
*
* Note that because the refdb is not involved for symbolic references, they
* won't be owned, hence you should either not make the returned reference
* 'externally visible', or perform the lookup before returning it to the user.
*/
int git_reference__read_head(
git_reference **out,

View File

@ -304,6 +304,7 @@ int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs)
git_buf buf = GIT_BUF_INIT;
size_t j, pos;
git_remote_head key;
git_refspec *cur;
const char* formatters[] = {
GIT_REFS_DIR "%s",
@ -312,7 +313,9 @@ int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs)
NULL
};
git_refspec *cur = git__calloc(1, sizeof(git_refspec));
assert(out && spec && refs);
cur = git__calloc(1, sizeof(git_refspec));
GITERR_CHECK_ALLOC(cur);
cur->force = spec->force;

View File

@ -237,7 +237,7 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
goto on_error;
/* only write for non-anonymous remotes */
if (name && (error = write_add_refspec(repo, name, fetch, true)) < 0)
if (repo && name && (error = write_add_refspec(repo, name, fetch, true)) < 0)
goto on_error;
if (repo && (error = lookup_remote_prune_config(remote, config_ro, name)) < 0)

View File

@ -375,20 +375,6 @@ static int add_parents_to_list(git_revwalk *walk, git_commit_list_node *commit,
return 0;
}
static int everybody_uninteresting(git_commit_list *orig)
{
git_commit_list *list = orig;
while (list) {
git_commit_list_node *commit = list->item;
list = list->next;
if (!commit->uninteresting)
return 0;
}
return 1;
}
/* How many unintersting commits we want to look at after we run out of interesting ones */
#define SLOP 5
@ -398,16 +384,15 @@ static int still_interesting(git_commit_list *list, int64_t time, int slop)
if (!list)
return 0;
/*
* If the destination list has commits with an earlier date
* than our source we want to continue looking.
*/
if (time <= list->item->time)
return SLOP;
/* If we find interesting commits, we reset the slop count */
if (!everybody_uninteresting(list))
return SLOP;
for (; list; list = list->next) {
/*
* If the destination list has commits with an earlier date than
* our source or if it still contains interesting commits we
* want to continue looking.
*/
if (!list->item->uninteresting || list->item->time > time)
return SLOP;
}
/* Everything's uninteresting, reduce the count */
return slop - 1;

View File

@ -104,7 +104,8 @@ int git_openssl_stream_global_init(void)
ssl_opts |= SSL_OP_NO_COMPRESSION;
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
#else

View File

@ -31,7 +31,8 @@ extern int git_openssl__set_cert_location(const char *file, const char *path);
# if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
# if OPENSSL_VERSION_NUMBER < 0x10100000L || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
GIT_INLINE(BIO_METHOD*) BIO_meth_new(int type, const char *name)
{

View File

@ -91,7 +91,7 @@ __KHASH_IMPL(
static int submodule_alloc(git_submodule **out, git_repository *repo, const char *name);
static git_config_backend *open_gitmodules(git_repository *repo, int gitmod);
static git_config *gitmodules_snapshot(git_repository *repo);
static int gitmodules_snapshot(git_config **snap, git_repository *repo);
static int get_url_base(git_buf *url, git_repository *repo);
static int lookup_head_remote_key(git_buf *remote_key, git_repository *repo);
static int lookup_default_remote(git_remote **remote, git_repository *repo);
@ -169,13 +169,13 @@ static void free_submodule_names(git_strmap *names)
* TODO: for some use-cases, this might need case-folding on a
* case-insensitive filesystem
*/
static int load_submodule_names(git_strmap *out, git_config *cfg)
static int load_submodule_names(git_strmap *out, git_repository *repo, git_config *cfg)
{
const char *key = "submodule\\..*\\.path";
git_config_iterator *iter;
git_config_entry *entry;
git_buf buf = GIT_BUF_INIT;
int rval;
int rval, isvalid;
int error = 0;
if ((error = git_config_iterator_glob_new(&iter, cfg, key)) < 0)
@ -186,16 +186,36 @@ static int load_submodule_names(git_strmap *out, git_config *cfg)
fdot = strchr(entry->name, '.');
ldot = strrchr(entry->name, '.');
if (git_strmap_exists(out, entry->value)) {
giterr_set(GITERR_SUBMODULE,
"duplicated submodule path '%s'", entry->value);
error = -1;
goto out;
}
git_buf_clear(&buf);
git_buf_put(&buf, fdot + 1, ldot - fdot - 1);
isvalid = git_submodule_name_is_valid(repo, buf.ptr, 0);
if (isvalid < 0) {
error = isvalid;
goto out;
}
if (!isvalid)
continue;
git_strmap_insert(out, entry->value, git_buf_detach(&buf), &rval);
if (rval < 0) {
giterr_set(GITERR_NOMEMORY, "error inserting submodule into hash table");
return -1;
}
}
if (error == GIT_ITEROVER)
error = 0;
out:
git_buf_free(&buf);
git_config_iterator_free(iter);
return 0;
return error;
}
int git_submodule_lookup(
@ -314,6 +334,28 @@ int git_submodule_lookup(
return 0;
}
int git_submodule_name_is_valid(git_repository *repo, const char *name, int flags)
{
git_buf buf = GIT_BUF_INIT;
int error, isvalid;
if (flags == 0)
flags = GIT_PATH_REJECT_FILESYSTEM_DEFAULTS;
/* Avoid allocating a new string if we can avoid it */
if (strchr(name, '\\') != NULL) {
if ((error = git_path_normalize_slashes(&buf, name)) < 0)
return error;
} else {
git_buf_attach_notowned(&buf, name, strlen(name));
}
isvalid = git_path_isvalid(repo, buf.ptr, 0, flags);
git_buf_free(&buf);
return isvalid;
}
static void submodule_free_dup(void *sm)
{
git_submodule_free(sm);
@ -359,7 +401,7 @@ static int submodules_from_index(git_strmap *map, git_index *idx, git_config *cf
git_strmap *names = 0;
git_strmap_alloc(&names);
if ((error = load_submodule_names(names, cfg)))
if ((error = load_submodule_names(names, git_index_owner(idx), cfg)))
goto done;
if ((error = git_iterator_for_index(&i, git_index_owner(idx), idx, NULL)) < 0)
@ -411,7 +453,7 @@ static int submodules_from_head(git_strmap *map, git_tree *head, git_config *cfg
const git_index_entry *entry;
git_strmap *names = 0;
git_strmap_alloc(&names);
if ((error = load_submodule_names(names, cfg)))
if ((error = load_submodule_names(names, git_tree_owner(head), cfg)))
goto done;
if ((error = git_iterator_for_tree(&i, head, NULL)) < 0)
@ -509,8 +551,11 @@ int git_submodule__map(git_repository *repo, git_strmap *map)
data.map = map;
data.repo = repo;
if ((mods = gitmodules_snapshot(repo)) == NULL)
if ((error = gitmodules_snapshot(&mods, repo)) < 0) {
if (error == GIT_ENOTFOUND)
error = 0;
goto cleanup;
}
data.mods = mods;
if ((error = git_config_foreach(
@ -1502,16 +1547,23 @@ static int submodule_update_head(git_submodule *submodule)
int git_submodule_reload(git_submodule *sm, int force)
{
int error = 0;
int error = 0, isvalid;
git_config *mods;
GIT_UNUSED(force);
assert(sm);
isvalid = git_submodule_name_is_valid(sm->repo, sm->name, 0);
if (isvalid <= 0) {
/* This should come with a warning, but we've no API for that */
return isvalid;
}
if (!git_repository_is_bare(sm->repo)) {
/* refresh config data */
mods = gitmodules_snapshot(sm->repo);
if ((error = gitmodules_snapshot(&mods, sm->repo)) < 0 && error != GIT_ENOTFOUND)
return error;
if (mods != NULL) {
error = submodule_read_config(sm, mods);
git_config_free(mods);
@ -1849,7 +1901,7 @@ static int submodule_load_each(const git_config_entry *entry, void *payload)
git_strmap *map = data->map;
git_buf name = GIT_BUF_INIT;
git_submodule *sm;
int error;
int error, isvalid;
if (git__prefixcmp(entry->name, "submodule.") != 0)
return 0;
@ -1865,6 +1917,12 @@ static int submodule_load_each(const git_config_entry *entry, void *payload)
if ((error = git_buf_set(&name, namestart, property - namestart -1)) < 0)
return error;
isvalid = git_submodule_name_is_valid(data->repo, name.ptr, 0);
if (isvalid <= 0) {
error = isvalid;
goto done;
}
/*
* Now that we have the submodule's name, we can use that to
* figure out whether it's in the map. If it's not, we create
@ -1915,32 +1973,37 @@ static int submodule_load_from_wd_lite(git_submodule *sm)
}
/**
* Returns a snapshot of $WORK_TREE/.gitmodules.
* Requests a snapshot of $WORK_TREE/.gitmodules.
*
* We ignore any errors and just pretend the file isn't there.
* Returns GIT_ENOTFOUND in case no .gitmodules file exist
*/
static git_config *gitmodules_snapshot(git_repository *repo)
static int gitmodules_snapshot(git_config **snap, git_repository *repo)
{
const char *workdir = git_repository_workdir(repo);
git_config *mods = NULL, *snap = NULL;
git_config *mods = NULL;
git_buf path = GIT_BUF_INIT;
int error;
if (workdir != NULL) {
if (git_buf_joinpath(&path, workdir, GIT_MODULES_FILE) != 0)
return NULL;
if (!workdir)
return GIT_ENOTFOUND;
if (git_config_open_ondisk(&mods, path.ptr) < 0)
mods = NULL;
}
if ((error = git_buf_joinpath(&path, workdir, GIT_MODULES_FILE)) < 0)
return error;
if ((error = git_config_open_ondisk(&mods, path.ptr)) < 0)
goto cleanup;
if ((error = git_config_snapshot(snap, mods)) < 0)
goto cleanup;
error = 0;
cleanup:
if (mods)
git_config_free(mods);
git_buf_free(&path);
if (mods) {
git_config_snapshot(&snap, mods);
git_config_free(mods);
}
return snap;
return error;
}
static git_config_backend *open_gitmodules(

View File

@ -148,4 +148,17 @@ extern int git_submodule_parse_update(
extern int git_submodule__map(
git_repository *repo,
git_strmap *map);
/**
* Check whether a submodule's name is valid.
*
* Check the path against the path validity rules, either the filesystem
* defaults (like checkout does) or whichever you want to compare against.
*
* @param repo the repository which contains the submodule
* @param name the name to check
* @param flags the `GIT_PATH` flags to use for the check (0 to use filesystem defaults)
*/
extern int git_submodule_name_is_valid(git_repository *repo, const char *name, int flags);
#endif

View File

@ -510,8 +510,14 @@ static int local_counting(int stage, unsigned int current, unsigned int total, v
static int foreach_reference_cb(git_reference *reference, void *payload)
{
git_revwalk *walk = (git_revwalk *)payload;
int error;
int error = git_revwalk_hide(walk, git_reference_target(reference));
if (git_reference_type(reference) != GIT_REF_OID) {
git_reference_free(reference);
return 0;
}
error = git_revwalk_hide(walk, git_reference_target(reference));
/* The reference is in the local repository, so the target may not
* exist on the remote. It also may not be a commit. */
if (error == GIT_ENOTFOUND || error == GITERR_INVALID) {

View File

@ -299,8 +299,11 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len)
pkt->ref = NULL;
pkt->type = GIT_PKT_NG;
if (len < 3)
goto out_err;
line += 3; /* skip "ng " */
if (!(ptr = strchr(line, ' ')))
len -= 3;
if (!(ptr = memchr(line, ' ', len)))
goto out_err;
len = ptr - line;
@ -311,8 +314,11 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len)
memcpy(pkt->ref, line, len);
pkt->ref[len] = '\0';
if (len < 1)
goto out_err;
line = ptr + 1;
if (!(ptr = strchr(line, '\n')))
len -= 1;
if (!(ptr = memchr(line, '\n', len)))
goto out_err;
len = ptr - line;

View File

@ -212,6 +212,7 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream)
}
if (s->session) {
libssh2_session_disconnect(s->session, "closing transport");
libssh2_session_free(s->session);
s->session = NULL;
}
@ -489,7 +490,7 @@ static int _git_ssh_session_create(
}
do {
rc = libssh2_session_startup(s, socket->s);
rc = libssh2_session_handshake(s, socket->s);
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
if (rc != LIBSSH2_ERROR_NONE) {

View File

@ -54,7 +54,7 @@ GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
static int valid_entry_name(git_repository *repo, const char *filename)
{
return *filename != '\0' &&
git_path_isvalid(repo, filename,
git_path_isvalid(repo, filename, 0,
GIT_PATH_REJECT_TRAVERSAL | GIT_PATH_REJECT_DOT_GIT | GIT_PATH_REJECT_SLASH);
}

View File

@ -10,7 +10,12 @@
#include "common.h"
#ifdef GIT_WIN32
# include "win32/utf-conv.h"
# include "win32/w32_buffer.h"
# ifdef HAVE_QSORT_S
# include <search.h>
# endif
#endif
#ifdef _MSC_VER

View File

@ -131,7 +131,7 @@ static int open_worktree_dir(git_worktree **out, const char *parent, const char
goto out;
}
if ((wt = git__calloc(1, sizeof(struct git_repository))) == NULL) {
if ((wt = git__calloc(1, sizeof(*wt))) == NULL) {
error = -1;
goto out;
}

View File

@ -9,6 +9,7 @@ SET(CLAR_FIXTURES "${CMAKE_CURRENT_SOURCE_DIR}/resources/")
SET(CLAR_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
ADD_DEFINITIONS(-DCLAR_FIXTURE_PATH=\"${CLAR_FIXTURES}\")
ADD_DEFINITIONS(-DCLAR_TMPDIR=\"libgit2_tests\")
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
INCLUDE_DIRECTORIES(${CLAR_PATH} ${libgit2_BINARY_DIR}/src)
FILE(GLOB_RECURSE SRC_TEST ${CLAR_PATH}/*/*.c ${CLAR_PATH}/*/*.h)
@ -30,7 +31,6 @@ SET_SOURCE_FILES_PROPERTIES(
${CLAR_PATH}/clar.c
PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clar.suite)
LINK_DIRECTORIES(${LIBGIT2_LIBDIRS})
INCLUDE_DIRECTORIES(${LIBGIT2_INCLUDES})
ADD_EXECUTABLE(libgit2_clar ${SRC_CLAR} ${SRC_TEST} ${LIBGIT2_OBJECTS})

View File

@ -61,6 +61,22 @@ void test_attr_ignore__ignore_space(void)
assert_is_ignored(true, "NewFolder/NewFolder/File.txt");
}
void test_attr_ignore__ignore_dir(void)
{
cl_git_rewritefile("attr/.gitignore", "dir/\n");
assert_is_ignored(true, "dir");
assert_is_ignored(true, "dir/file");
}
void test_attr_ignore__ignore_dir_with_trailing_space(void)
{
cl_git_rewritefile("attr/.gitignore", "dir/ \n");
assert_is_ignored(true, "dir");
assert_is_ignored(true, "dir/file");
}
void test_attr_ignore__ignore_root(void)
{
cl_git_rewritefile("attr/.gitignore", "/\n\n/NewFolder\n/NewFolder/NewFolder");

View File

@ -364,3 +364,15 @@ void test_checkout_nasty__symlink3(void)
test_checkout_passes("refs/heads/symlink3", ".git/foobar");
}
void test_checkout_nasty__gitmodules_symlink(void)
{
cl_repo_set_bool(repo, "core.protectHFS", true);
test_checkout_fails("refs/heads/gitmodules-symlink", ".gitmodules");
cl_repo_set_bool(repo, "core.protectHFS", false);
cl_repo_set_bool(repo, "core.protectNTFS", true);
test_checkout_fails("refs/heads/gitmodules-symlink", ".gitmodules");
cl_repo_set_bool(repo, "core.protectNTFS", false);
test_checkout_fails("refs/heads/gitmodules-symlink", ".gitmodules");
}

View File

@ -1,4 +1,5 @@
#include "clar_libgit2.h"
#include "diff_generate.h"
#include "git2/checkout.h"
#include "path.h"
#include "posix.h"
@ -307,3 +308,28 @@ void test_checkout_typechange__checkout_with_conflicts(void)
git_object_free(obj);
}
}
void test_checkout_typechange__status_char(void)
{
size_t i;
git_oid oid;
git_commit *commit;
git_diff *diff;
const git_diff_delta *delta;
git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
char expected[8] = {'M', 'M', 'R', 'T', 'D', 'R', 'A', 'R'};
git_oid_fromstr(&oid, "9b19edf33a03a0c59cdfc113bfa5c06179bf9b1a");
cl_git_pass(git_commit_lookup(&commit, g_repo, &oid));
diffopts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE;
cl_git_pass(git_diff__commit(&diff, g_repo, commit, &diffopts));
cl_git_pass(git_diff_find_similar(diff, NULL));
for (i = 0; i < git_diff_num_deltas(diff); i++) {
delta = git_diff_get_delta(diff, i);
cl_assert_equal_i(expected[i], git_diff_status_char(delta->status));
}
git_diff_free(diff);
git_commit_free(commit);
}

21
tests/delta/apply.c Normal file
View File

@ -0,0 +1,21 @@
#include "clar_libgit2.h"
#include "delta.h"
void test_delta_apply__read_at_off(void)
{
unsigned char base[16] = { 0 }, delta[] = { 0x10, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00 };
void *out;
size_t outlen;
cl_git_fail(git_delta_apply(&out, &outlen, base, sizeof(base), delta, sizeof(delta)));
}
void test_delta_apply__read_after_limit(void)
{
unsigned char base[16] = { 0 }, delta[] = { 0x10, 0x70, 0xff };
void *out;
size_t outlen;
cl_git_fail(git_delta_apply(&out, &outlen, base, sizeof(base), delta, sizeof(delta)));
}

View File

@ -3,6 +3,7 @@
#include "git2/sys/diff.h"
#include "buffer.h"
#include "delta.h"
#include "filebuf.h"
#include "repository.h"

View File

@ -254,7 +254,7 @@ void test_diff_stats__rename_nochanges_no_find(void)
git_buf_free(&buf);
}
void test_diff_stats__rename_and_modifiy_no_find(void)
void test_diff_stats__rename_and_modify_no_find(void)
{
git_buf buf = GIT_BUF_INIT;
const char *stat =

View File

@ -343,6 +343,29 @@ void test_fetchhead_nonetwork__unborn_with_upstream(void)
cl_fixture_cleanup("./repowithunborn");
}
void test_fetchhead_nonetwork__fetch_into_repo_with_symrefs(void)
{
git_repository *repo;
git_remote *remote;
git_reference *symref;
repo = cl_git_sandbox_init("empty_standard_repo");
/*
* Testing for a specific constellation where the repository has at
* least one symbolic reference in its refdb.
*/
cl_git_pass(git_reference_symbolic_create(&symref, repo, "refs/heads/symref", "refs/heads/master", 0, NULL));
cl_git_pass(git_remote_set_url(repo, "origin", cl_fixture("testrepo.git")));
cl_git_pass(git_remote_lookup(&remote, repo, "origin"));
cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL));
git_remote_free(remote);
git_reference_free(symref);
cl_git_sandbox_cleanup();
}
void test_fetchhead_nonetwork__quote_in_branch_name(void)
{
cl_set_cleanup(&cleanup_repository, "./test1");

View File

@ -54,256 +54,256 @@ void test_path_core__make_relative(void)
void test_path_core__isvalid_standard(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar/file.txt", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar/.file", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar/file.txt", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar/.file", 0, 0));
}
void test_path_core__isvalid_empty_dir_component(void)
{
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo//bar", 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo//bar", 0, 0));
/* leading slash */
cl_assert_equal_b(false, git_path_isvalid(NULL, "/", 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "/foo", 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "/foo/bar", 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "/", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "/foo", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "/foo/bar", 0, 0));
/* trailing slash */
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/", 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar/", 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar/", 0, 0));
}
void test_path_core__isvalid_dot_and_dotdot(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, ".", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "./foo", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "./foo", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "./foo", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "./foo", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "..", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "../foo", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/..", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "../foo", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "..", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "../foo", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/..", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "../foo", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".", GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "./foo", GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.", GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "./foo", GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".", 0, GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "./foo", 0, GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.", 0, GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "./foo", 0, GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "..", GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "../foo", GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/..", GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "../foo", GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "..", 0, GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "../foo", 0, GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/..", 0, GIT_PATH_REJECT_TRAVERSAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "../foo", 0, GIT_PATH_REJECT_TRAVERSAL));
}
void test_path_core__isvalid_dot_git(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git/foo", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.git", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.git/bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.GIT/bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar/.Git", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git/foo", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.git", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.git/bar", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.GIT/bar", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar/.Git", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git", GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git/foo", GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.git", GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.git/bar", GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.GIT/bar", GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar/.Git", GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git/foo", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.git/bar", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/.GIT/bar", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar/.Git", 0, GIT_PATH_REJECT_DOT_GIT_LITERAL));
cl_assert_equal_b(true, git_path_isvalid(NULL, "!git", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/!git", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "!git/bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".tig", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.tig", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".tig/bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "!git", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/!git", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "!git/bar", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".tig", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/.tig", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".tig/bar", 0, 0));
}
void test_path_core__isvalid_backslash(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo\\file.txt", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar\\file.txt", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar\\", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo\\file.txt", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar\\file.txt", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar\\", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo\\file.txt", GIT_PATH_REJECT_BACKSLASH));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar\\file.txt", GIT_PATH_REJECT_BACKSLASH));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar\\", GIT_PATH_REJECT_BACKSLASH));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo\\file.txt", 0, GIT_PATH_REJECT_BACKSLASH));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar\\file.txt", 0, GIT_PATH_REJECT_BACKSLASH));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar\\", 0, GIT_PATH_REJECT_BACKSLASH));
}
void test_path_core__isvalid_trailing_dot(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo.", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo...", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar.", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo./bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo.", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo...", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar.", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo./bar", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo.", GIT_PATH_REJECT_TRAILING_DOT));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo...", GIT_PATH_REJECT_TRAILING_DOT));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar.", GIT_PATH_REJECT_TRAILING_DOT));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo./bar", GIT_PATH_REJECT_TRAILING_DOT));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo.", 0, GIT_PATH_REJECT_TRAILING_DOT));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo...", 0, GIT_PATH_REJECT_TRAILING_DOT));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar.", 0, GIT_PATH_REJECT_TRAILING_DOT));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo./bar", 0, GIT_PATH_REJECT_TRAILING_DOT));
}
void test_path_core__isvalid_trailing_space(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo ", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo ", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar ", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, " ", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo /bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo ", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo ", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar ", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, " ", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo /bar", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo ", GIT_PATH_REJECT_TRAILING_SPACE));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo ", GIT_PATH_REJECT_TRAILING_SPACE));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar ", GIT_PATH_REJECT_TRAILING_SPACE));
cl_assert_equal_b(false, git_path_isvalid(NULL, " ", GIT_PATH_REJECT_TRAILING_SPACE));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo /bar", GIT_PATH_REJECT_TRAILING_SPACE));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
cl_assert_equal_b(false, git_path_isvalid(NULL, " ", 0, GIT_PATH_REJECT_TRAILING_SPACE));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo /bar", 0, GIT_PATH_REJECT_TRAILING_SPACE));
}
void test_path_core__isvalid_trailing_colon(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo:", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar:", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ":", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo:/bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo:", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo/bar:", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ":", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "foo:/bar", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo:", GIT_PATH_REJECT_TRAILING_COLON));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar:", GIT_PATH_REJECT_TRAILING_COLON));
cl_assert_equal_b(false, git_path_isvalid(NULL, ":", GIT_PATH_REJECT_TRAILING_COLON));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo:/bar", GIT_PATH_REJECT_TRAILING_COLON));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo:", 0, GIT_PATH_REJECT_TRAILING_COLON));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo/bar:", 0, GIT_PATH_REJECT_TRAILING_COLON));
cl_assert_equal_b(false, git_path_isvalid(NULL, ":", 0, GIT_PATH_REJECT_TRAILING_COLON));
cl_assert_equal_b(false, git_path_isvalid(NULL, "foo:/bar", 0, GIT_PATH_REJECT_TRAILING_COLON));
}
void test_path_core__isvalid_dotgit_ntfs(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git ", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git.", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git.. .", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git ", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git.", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git.. .", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1 ", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1.", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1.. .", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1 ", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1.", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "git~1.. .", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git", GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git ", GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git.", GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git.. .", GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git ", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git.", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git.. .", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1", GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1 ", GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1.", GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1.. .", GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1 ", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1.", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "git~1.. .", 0, GIT_PATH_REJECT_DOT_GIT_NTFS));
}
void test_path_core__isvalid_dos_paths(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux.", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux:", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux.asdf", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux.asdf\\zippy", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux:asdf\\foobar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "con", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "prn", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "nul", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux.", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux:", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux.asdf", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux.asdf\\zippy", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux:asdf\\foobar", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "con", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "prn", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "nul", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux.", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux:", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux.asdf", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux.asdf\\zippy", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux:asdf\\foobar", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "con", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "prn", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "nul", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux.", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux:", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux.asdf", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux.asdf\\zippy", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "aux:asdf\\foobar", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "con", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "prn", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "nul", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux1", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux1", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "auxn", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux\\foo", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux1", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux1", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "auxn", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "aux\\foo", 0, GIT_PATH_REJECT_DOS_PATHS));
}
void test_path_core__isvalid_dos_paths_withnum(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1.", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1:", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1.asdf", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1.asdf\\zippy", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1:asdf\\foobar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1\\foo", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "lpt1", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1.", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1:", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1.asdf", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1.asdf\\zippy", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1:asdf\\foobar", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1\\foo", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "lpt1", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1.", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1:", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1.asdf", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1.asdf\\zippy", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1:asdf\\foobar", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1/foo", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "lpt1", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1.", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1:", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1.asdf", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1.asdf\\zippy", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1:asdf\\foobar", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "com1/foo", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "lpt1", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com0", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com0", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com10", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com10", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "comn", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1\\foo", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "lpt0", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "lpt10", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "lptn", GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com0", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com0", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com10", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com10", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "comn", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "com1\\foo", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "lpt0", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "lpt10", 0, GIT_PATH_REJECT_DOS_PATHS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "lptn", 0, GIT_PATH_REJECT_DOS_PATHS));
}
void test_path_core__isvalid_nt_chars(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf\001foo", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf\037bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf<bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf>foo", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf:foo", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf\"bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf|foo", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf?bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf*bar", 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf\001foo", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf\037bar", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf<bar", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf>foo", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf:foo", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf\"bar", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf|foo", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf?bar", 0, 0));
cl_assert_equal_b(true, git_path_isvalid(NULL, "asdf*bar", 0, 0));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf\001foo", GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf\037bar", GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf<bar", GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf>foo", GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf:foo", GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf\"bar", GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf|foo", GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf?bar", GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf*bar", GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf\001foo", 0, GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf\037bar", 0, GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf<bar", 0, GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf>foo", 0, GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf:foo", 0, GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf\"bar", 0, GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf|foo", 0, GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf?bar", 0, GIT_PATH_REJECT_NT_CHARS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "asdf*bar", 0, GIT_PATH_REJECT_NT_CHARS));
}
void test_path_core__isvalid_dotgit_with_hfs_ignorables(void)
{
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git\xe2\x80\x8c", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".gi\xe2\x80\x8dT", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".g\xe2\x80\x8eIt", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".\xe2\x80\x8fgIt", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x80\xaa.gIt", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".git\xe2\x80\x8c", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".gi\xe2\x80\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".g\xe2\x80\x8eIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".\xe2\x80\x8fgIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x80\xaa.gIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x80\xab.\xe2\x80\xacG\xe2\x80\xadI\xe2\x80\xaet", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x81\xab.\xe2\x80\xaaG\xe2\x81\xabI\xe2\x80\xact", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x81\xad.\xe2\x80\xaeG\xef\xbb\xbfIT", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x80\xab.\xe2\x80\xacG\xe2\x80\xadI\xe2\x80\xaet", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x81\xab.\xe2\x80\xaaG\xe2\x81\xabI\xe2\x80\xact", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, "\xe2\x81\xad.\xe2\x80\xaeG\xef\xbb\xbfIT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".g", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, " .git", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "..git\xe2\x80\x8c", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi\xe2\x80\x8dT.", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".g\xe2\x80It", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".\xe2gIt", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "\xe2\x80\xaa.gi", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi\x80\x8dT", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi\x8dT", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".g\xe2i\x80T\x8e", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git\xe2\x80\xbf", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git\xe2\xab\x81", GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".g", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, " .git", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "..git\xe2\x80\x8c", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi\xe2\x80\x8dT.", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".g\xe2\x80It", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".\xe2gIt", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, "\xe2\x80\xaa.gi", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi\x80\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".gi\x8dT", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".g\xe2i\x80T\x8e", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git\xe2\x80\xbf", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(true, git_path_isvalid(NULL, ".git\xe2\xab\x81", 0, GIT_PATH_REJECT_DOT_GIT_HFS));
}
static void test_join_unrooted(

119
tests/path/dotgit.c Normal file
View File

@ -0,0 +1,119 @@
#include "clar_libgit2.h"
#include "path.h"
static char *gitmodules_altnames[] = {
".gitmodules",
/*
* Equivalent to the ".git\u200cmodules" string from git but hard-coded
* as a UTF-8 sequence
*/
".git\xe2\x80\x8cmodules",
".Gitmodules",
".gitmoduleS",
".gitmodules ",
".gitmodules.",
".gitmodules ",
".gitmodules. ",
".gitmodules .",
".gitmodules..",
".gitmodules ",
".gitmodules. ",
".gitmodules . ",
".gitmodules .",
".Gitmodules ",
".Gitmodules.",
".Gitmodules ",
".Gitmodules. ",
".Gitmodules .",
".Gitmodules..",
".Gitmodules ",
".Gitmodules. ",
".Gitmodules . ",
".Gitmodules .",
"GITMOD~1",
"gitmod~1",
"GITMOD~2",
"gitmod~3",
"GITMOD~4",
"GITMOD~1 ",
"gitmod~2.",
"GITMOD~3 ",
"gitmod~4. ",
"GITMOD~1 .",
"gitmod~2 ",
"GITMOD~3. ",
"gitmod~4 . ",
"GI7EBA~1",
"gi7eba~9",
"GI7EB~10",
"GI7EB~11",
"GI7EB~99",
"GI7EB~10",
"GI7E~100",
"GI7E~101",
"GI7E~999",
"~1000000",
"~9999999",
};
static char *gitmodules_not_altnames[] = {
".gitmodules x",
".gitmodules .x",
" .gitmodules",
"..gitmodules",
"gitmodules",
".gitmodule",
".gitmodules x ",
".gitmodules .x",
"GI7EBA~",
"GI7EBA~0",
"GI7EBA~~1",
"GI7EBA~X",
"Gx7EBA~1",
"GI7EBX~1",
"GI7EB~1",
"GI7EB~01",
"GI7EB~1",
};
void test_path_dotgit__dotgit_modules(void)
{
size_t i;
cl_assert_equal_i(1, git_path_is_dotgit_modules(".gitmodules", strlen(".gitmodules")));
cl_assert_equal_i(1, git_path_is_dotgit_modules(".git\xe2\x80\x8cmodules", strlen(".git\xe2\x80\x8cmodules")));
for (i = 0; i < ARRAY_SIZE(gitmodules_altnames); i++) {
const char *name = gitmodules_altnames[i];
if (!git_path_is_dotgit_modules(name, strlen(name)))
cl_fail(name);
}
for (i = 0; i < ARRAY_SIZE(gitmodules_not_altnames); i++) {
const char *name = gitmodules_not_altnames[i];
if (git_path_is_dotgit_modules(name, strlen(name)))
cl_fail(name);
}
}
void test_path_dotgit__dotgit_modules_symlink(void)
{
cl_assert_equal_b(true, git_path_isvalid(NULL, ".gitmodules", 0, GIT_PATH_REJECT_DOT_GIT_HFS|GIT_PATH_REJECT_DOT_GIT_NTFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_HFS));
cl_assert_equal_b(false, git_path_isvalid(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_NTFS));
}

View File

@ -21,6 +21,7 @@ void test_refs_dup__direct(void)
cl_git_pass(git_reference_dup(&b, a));
cl_assert(git_reference_cmp(a, b) == 0);
cl_assert(git_reference_owner(b) == g_repo);
git_reference_free(b);
git_reference_free(a);
@ -34,6 +35,7 @@ void test_refs_dup__symbolic(void)
cl_git_pass(git_reference_dup(&b, a));
cl_assert(git_reference_cmp(a, b) == 0);
cl_assert(git_reference_owner(b) == g_repo);
git_reference_free(b);
git_reference_free(a);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -555,3 +555,30 @@ void test_revwalk_basic__old_hidden_commit_two(void)
cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid, _walk));
}
/*
* Ensure that we correctly hide all parent commits of a newer
* commit when first hiding older commits.
*
* % git rev-list D ^B ^A ^E
* 790ba0facf6fd103699a5c40cd19dad277ff49cd
* b82cee5004151ae0c4f82b69fb71b87477664b6f
*/
void test_revwalk_basic__newer_hidden_commit_hides_old_commits(void)
{
git_oid oid;
revwalk_basic_setup_walk("revwalk.git");
cl_git_pass(git_revwalk_push_ref(_walk, "refs/heads/D"));
cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/B"));
cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/A"));
cl_git_pass(git_revwalk_hide_ref(_walk, "refs/heads/E"));
cl_git_pass(git_revwalk_next(&oid, _walk));
cl_assert(git_oid_streq(&oid, "b82cee5004151ae0c4f82b69fb71b87477664b6f"));
cl_git_pass(git_revwalk_next(&oid, _walk));
cl_assert(git_oid_streq(&oid, "790ba0facf6fd103699a5c40cd19dad277ff49cd"));
cl_git_fail_with(GIT_ITEROVER, git_revwalk_next(&oid, _walk));
}

98
tests/submodule/escape.c Normal file
View File

@ -0,0 +1,98 @@
#include "clar_libgit2.h"
#include "posix.h"
#include "path.h"
#include "submodule_helpers.h"
#include "fileops.h"
#include "repository.h"
static git_repository *g_repo = NULL;
void test_submodule_escape__cleanup(void)
{
cl_git_sandbox_cleanup();
}
#define EVIL_SM_NAME "../../modules/evil"
#define EVIL_SM_NAME_WINDOWS "..\\\\..\\\\modules\\\\evil"
#define EVIL_SM_NAME_WINDOWS_UNESC "..\\..\\modules\\evil"
static int find_evil(git_submodule *sm, const char *name, void *payload)
{
int *foundit = (int *) payload;
GIT_UNUSED(sm);
if (!git__strcmp(EVIL_SM_NAME, name) ||
!git__strcmp(EVIL_SM_NAME_WINDOWS_UNESC, name))
*foundit = true;
return 0;
}
void test_submodule_escape__from_gitdir(void)
{
int foundit;
git_submodule *sm;
git_buf buf = GIT_BUF_INIT;
unsigned int sm_location;
g_repo = setup_fixture_submodule_simple();
cl_git_pass(git_buf_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
cl_git_rewritefile(buf.ptr,
"[submodule \"" EVIL_SM_NAME "\"]\n"
" path = testrepo\n"
" url = ../testrepo.git\n");
git_buf_free(&buf);
/* Find it all the different ways we know about it */
foundit = 0;
cl_git_pass(git_submodule_foreach(g_repo, find_evil, &foundit));
cl_assert_equal_i(0, foundit);
cl_git_fail_with(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, EVIL_SM_NAME));
/*
* We do know about this as it's in the index and HEAD, but the data is
* incomplete as there is no configured data for it (we pretend it
* doesn't exist). This leaves us with an odd situation but it's
* consistent with what we would do if we did add a submodule with no
* configuration.
*/
cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo"));
cl_git_pass(git_submodule_location(&sm_location, sm));
cl_assert_equal_i(GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_HEAD, sm_location);
git_submodule_free(sm);
}
void test_submodule_escape__from_gitdir_windows(void)
{
int foundit;
git_submodule *sm;
git_buf buf = GIT_BUF_INIT;
unsigned int sm_location;
g_repo = setup_fixture_submodule_simple();
cl_git_pass(git_buf_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
cl_git_rewritefile(buf.ptr,
"[submodule \"" EVIL_SM_NAME_WINDOWS "\"]\n"
" path = testrepo\n"
" url = ../testrepo.git\n");
git_buf_free(&buf);
/* Find it all the different ways we know about it */
foundit = 0;
cl_git_pass(git_submodule_foreach(g_repo, find_evil, &foundit));
cl_assert_equal_i(0, foundit);
cl_git_fail_with(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, EVIL_SM_NAME_WINDOWS_UNESC));
/*
* We do know about this as it's in the index and HEAD, but the data is
* incomplete as there is no configured data for it (we pretend it
* doesn't exist). This leaves us with an odd situation but it's
* consistent with what we would do if we did add a submodule with no
* configuration.
*/
cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo"));
cl_git_pass(git_submodule_location(&sm_location, sm));
cl_assert_equal_i(GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_HEAD, sm_location);
git_submodule_free(sm);
}

View File

@ -132,6 +132,27 @@ void test_submodule_lookup__foreach(void)
cl_assert_equal_i(8, data.count);
}
static int foreach_cb(git_submodule *sm, const char *name, void *payload)
{
GIT_UNUSED(sm);
GIT_UNUSED(name);
GIT_UNUSED(payload);
return 0;
}
void test_submodule_lookup__duplicated_path(void)
{
cl_git_rewritefile("submod2/.gitmodules",
"[submodule \"sm1\"]\n"
" path = duplicated-path\n"
" url = sm1\n"
"[submodule \"sm2\"]\n"
" path = duplicated-path\n"
" url = sm2\n");
cl_git_fail(git_submodule_foreach(g_repo, foreach_cb, NULL));
}
void test_submodule_lookup__lookup_even_with_unborn_head(void)
{
git_reference *head;
@ -430,14 +451,6 @@ void test_submodule_lookup__lookup_in_bare_repository_fails(void)
cl_git_fail(git_submodule_lookup(&sm, g_repo, "nonexisting"));
}
static int foreach_cb(git_submodule *sm, const char *name, void *payload)
{
GIT_UNUSED(sm);
GIT_UNUSED(name);
GIT_UNUSED(payload);
return 0;
}
void test_submodule_lookup__foreach_in_bare_repository_fails(void)
{
cl_git_sandbox_cleanup();
@ -445,3 +458,19 @@ void test_submodule_lookup__foreach_in_bare_repository_fails(void)
cl_git_fail(git_submodule_foreach(g_repo, foreach_cb, NULL));
}
void test_submodule_lookup__fail_invalid_gitmodules(void)
{
git_submodule *sm;
sm_lookup_data data;
memset(&data, 0, sizeof(data));
cl_git_rewritefile("submod2/.gitmodules",
"[submodule \"Test_App\"\n"
" path = Test_App\n"
" url = ../Test_App\n");
cl_git_fail(git_submodule_lookup(&sm, g_repo, "Test_App"));
cl_git_fail(git_submodule_foreach(g_repo, sm_lookup_cb, &data));
}

View File

@ -22,6 +22,32 @@ void test_worktree_reflog__cleanup(void)
cleanup_fixture_worktree(&fixture);
}
void test_worktree_reflog__read_worktree_HEAD(void)
{
git_reflog *reflog;
const git_reflog_entry *entry;
cl_git_pass(git_reflog_read(&reflog, fixture.worktree, "HEAD"));
cl_assert_equal_i(1, git_reflog_entrycount(reflog));
entry = git_reflog_entry_byindex(reflog, 0);
cl_assert(entry != NULL);
cl_assert_equal_s("checkout: moving from 099fabac3a9ea935598528c27f866e34089c2eff to testrepo-worktree", git_reflog_entry_message(entry));
git_reflog_free(reflog);
}
void test_worktree_reflog__read_parent_HEAD(void)
{
git_reflog *reflog;
cl_git_pass(git_reflog_read(&reflog, fixture.repo, "HEAD"));
/* there is no logs/HEAD in the parent repo */
cl_assert_equal_i(0, git_reflog_entrycount(reflog));
git_reflog_free(reflog);
}
void test_worktree_reflog__read(void)
{
git_reflog *reflog;

View File

@ -27,6 +27,7 @@ void test_worktree_repository__head(void)
cl_git_pass(git_reference_lookup(&ref, fixture.repo, "refs/heads/testrepo-worktree"));
cl_git_pass(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree"));
cl_assert(git_reference_cmp(ref, head) == 0);
cl_assert(git_reference_owner(ref) == fixture.repo);
git_reference_free(ref);
git_reference_free(head);