Merge pull request #4179 from libgit2/ethomson/expand_tilde
Introduce home directory expansion function for config files, attribute files
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0ae75e1..bcf8160 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,10 @@
### API additions
+* You can now set the default share mode on Windows for opening files using
+ `GIT_OPT_SET_WINDOWS_SHAREMODE` option with `git_libgit2_opts()`.
+ You can query the current share mode with `GIT_OPT_GET_WINDOWS_SHAREMODE`.
+
### API removals
### Breaking API changes
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d5bf21f..ca52db7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -238,6 +238,7 @@
IF (WIN32 AND WINHTTP)
ADD_DEFINITIONS(-DGIT_WINHTTP)
+ ADD_DEFINITIONS(-DGIT_HTTPS)
# Since MinGW does not come with headers or an import library for winhttp,
# we have to include a private header and generate our own import library
@@ -546,11 +547,13 @@
IF (SECURITY_FOUND)
ADD_DEFINITIONS(-DGIT_SECURE_TRANSPORT)
+ ADD_DEFINITIONS(-DGIT_HTTPS)
INCLUDE_DIRECTORIES(${SECURITY_INCLUDE_DIR})
ENDIF ()
IF (OPENSSL_FOUND)
ADD_DEFINITIONS(-DGIT_OPENSSL)
+ ADD_DEFINITIONS(-DGIT_HTTPS)
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES})
ENDIF()
diff --git a/README.md b/README.md
index c3fb27c..1bbd371 100644
--- a/README.md
+++ b/README.md
@@ -43,10 +43,9 @@
What It Can Do
==============
-The goal of this library is to allow its users the ability to handle Git data in
-their applications from their programming language of choice, as is used in
-production for many applications including the GitHub.com site, in Plastic SCM
-and also powering Microsoft's Visual Studio tools for Git.
+libgit2 provides you with the ability to manage Git repositories in the
+programming language of your choice. It's used in production to power many
+applications including GitHub.com, Plastic SCM and Visual Studio Team Services.
It does not aim to replace the git tool or its user-facing commands. Some APIs
resemble the plumbing commands as those align closely with the concepts of the
@@ -68,6 +67,16 @@
* descriptive and detailed error messages
* ...and more (over 175 different API calls)
+As libgit2 is purely a consumer of the Git system, we have to
+adjust to changes made upstream. This has two major consequences:
+
+* Some changes may require us to change provided interfaces. While we try to
+ implement functions in a generic way so that no future changes are required,
+ we cannot promise a completely stable API.
+* As we have to keep up with changes in behavior made upstream, we may lag
+ behind in some areas. We usually to document these incompatibilities in our
+ issue tracker with the label "git change".
+
Optional dependencies
=====================
diff --git a/examples/network/common.c b/examples/network/common.c
index d123eed..1a81a10 100644
--- a/examples/network/common.c
+++ b/examples/network/common.c
@@ -1,5 +1,7 @@
#include "common.h"
#include <stdio.h>
+#include <string.h>
+#include <errno.h>
/* Shamelessly borrowed from http://stackoverflow.com/questions/3417837/
* with permission of the original author, Martin Pool.
@@ -20,15 +22,27 @@
unsigned int UNUSED(allowed_types),
void * UNUSED(payload))
{
- char username[128] = {0};
- char password[128] = {0};
+ char *username = NULL, *password = NULL;
+ int error;
printf("Username: ");
- scanf("%s", username);
+ if (getline(&username, NULL, stdin) < 0) {
+ fprintf(stderr, "Unable to read username: %s", strerror(errno));
+ return -1;
+ }
/* Yup. Right there on your terminal. Careful where you copy/paste output. */
printf("Password: ");
- scanf("%s", password);
+ if (getline(&password, NULL, stdin) < 0) {
+ fprintf(stderr, "Unable to read password: %s", strerror(errno));
+ free(username);
+ return -1;
+ }
- return git_cred_userpass_plaintext_new(out, username, password);
+ error = git_cred_userpass_plaintext_new(out, username, password);
+
+ free(username);
+ free(password);
+
+ return error;
}
diff --git a/include/git2/common.h b/include/git2/common.h
index c909f86..d83e8c3 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -180,6 +180,9 @@
GIT_OPT_GET_USER_AGENT,
GIT_OPT_ENABLE_OFS_DELTA,
GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION,
+ GIT_OPT_GET_WINDOWS_SHAREMODE,
+ GIT_OPT_SET_WINDOWS_SHAREMODE,
+ GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION,
} git_libgit2_opt_t;
/**
@@ -284,6 +287,17 @@
* > - `user_agent` is the value that will be delivered as the
* > User-Agent header on HTTP requests.
*
+ * * opts(GIT_OPT_SET_WINDOWS_SHAREMODE, unsigned long value)
+ *
+ * > Set the share mode used when opening files on Windows.
+ * > For more information, see the documentation for CreateFile.
+ * > The default is: FILE_SHARE_READ | FILE_SHARE_WRITE. This is
+ * > ignored and unused on non-Windows platforms.
+ *
+ * * opts(GIT_OPT_GET_WINDOWS_SHAREMODE, unsigned long *value)
+ *
+ * > Get the share mode used when opening files on Windows.
+ *
* * opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, int enabled)
*
* > Enable strict input validation when creating new objects
@@ -324,6 +338,13 @@
* > is written to permanent storage, not simply cached. This
* > defaults to disabled.
*
+ * opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, int enabled)
+ *
+ * > Enable strict verification of object hashsums when reading
+ * > objects from disk. This may impact performance due to an
+ * > additional checksum calculation on each object. This defaults
+ * > to enabled.
+ *
* @param option Option key
* @param ... value to set the option
* @return 0 on success, <0 on failure
diff --git a/include/git2/errors.h b/include/git2/errors.h
index 3b746b7..6f55802 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -53,6 +53,8 @@
GIT_PASSTHROUGH = -30, /**< Internal only */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
+ GIT_RETRY = -32, /**< Internal only */
+ GIT_EMISMATCH = -33, /**< Hashsum mismatch in object */
} git_error_code;
/**
diff --git a/include/git2/global.h b/include/git2/global.h
index ce5bdf4..2a87e10 100644
--- a/include/git2/global.h
+++ b/include/git2/global.h
@@ -14,7 +14,7 @@
/**
* Init the global state
*
- * This function must the called before any other libgit2 function in
+ * This function must be called before any other libgit2 function in
* order to set up global state and threading.
*
* This function may be called multiple times - it will return the number
diff --git a/include/git2/odb.h b/include/git2/odb.h
index b3ed270..b7dc0c5 100644
--- a/include/git2/odb.h
+++ b/include/git2/odb.h
@@ -488,7 +488,7 @@
* The backends are checked in relative ordering, based on the
* value of the `priority` parameter.
*
- * Read <odb_backends.h> for more information.
+ * Read <sys/odb_backend.h> for more information.
*
* @param odb database to add the backend to
* @param backend pointer to a git_odb_backend instance
@@ -509,7 +509,7 @@
*
* Writing is disabled on alternate backends.
*
- * Read <odb_backends.h> for more information.
+ * Read <sys/odb_backend.h> for more information.
*
* @param odb database to add the backend to
* @param backend pointer to a git_odb_backend instance
diff --git a/include/git2/remote.h b/include/git2/remote.h
index 244794e..e9e4e5b 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -715,8 +715,8 @@
* Peform all the steps from a push.
*
* @param remote the remote to push to
- * @param refspecs the refspecs to use for pushing. If none are
- * passed, the configured refspecs will be used
+ * @param refspecs the refspecs to use for pushing. If NULL or an empty
+ * array, the configured refspecs will be used
* @param opts options to use for this push
*/
GIT_EXTERN(int) git_remote_push(git_remote *remote,
diff --git a/include/git2/sys/transport.h b/include/git2/sys/transport.h
index 60e38b2..a395de5 100644
--- a/include/git2/sys/transport.h
+++ b/include/git2/sys/transport.h
@@ -241,6 +241,16 @@
*/
GIT_EXTERN(int) git_transport_smart_credentials(git_cred **out, git_transport *transport, const char *user, int methods);
+/**
+ * Get a copy of the proxy options
+ *
+ * The url is copied and must be freed by the caller.
+ *
+ * @param out options struct to fill
+ * @param transport the transport to extract the data from.
+ */
+GIT_EXTERN(int) git_transport_smart_proxy_options(git_proxy_options *out, git_transport *transport);
+
/*
*** End of base transport interface ***
*** Begin interface for subtransports for the smart transport ***
diff --git a/libgit2.pc.in b/libgit2.pc.in
index 329a560..96b9659 100644
--- a/libgit2.pc.in
+++ b/libgit2.pc.in
@@ -1,4 +1,4 @@
-prefix=@PKGCONFIG_PREFIX@
+prefix="@PKGCONFIG_PREFIX@"
libdir=@PKGCONFIG_LIBDIR@
includedir=@PKGCONFIG_INCLUDEDIR@
@@ -6,7 +6,7 @@
Description: The git library, take 2
Version: @LIBGIT2_VERSION_STRING@
-Libs: -L"${libdir}" -lgit2
+Libs: -L${libdir} -lgit2
Libs.private: @LIBGIT2_PC_LIBS@
Requires.private: @LIBGIT2_PC_REQUIRES@
diff --git a/src/blame_git.c b/src/blame_git.c
index 735b62d..13f5cb4 100644
--- a/src/blame_git.c
+++ b/src/blame_git.c
@@ -517,11 +517,12 @@
if (!num_parents) {
git_oid_cpy(&blame->options.oldest_commit, git_commit_id(commit));
goto finish;
- }
- else if (num_parents < (int)ARRAY_SIZE(sg_buf))
+ } else if (num_parents < (int)ARRAY_SIZE(sg_buf))
memset(sg_buf, 0, sizeof(sg_buf));
- else
+ else {
sg_origin = git__calloc(num_parents, sizeof(*sg_origin));
+ GITERR_CHECK_ALLOC(sg_origin);
+ }
for (i=0; i<num_parents; i++) {
git_commit *p;
@@ -547,7 +548,6 @@
if (porigin->blob && origin->blob &&
!git_oid_cmp(git_blob_id(porigin->blob), git_blob_id(origin->blob))) {
error = pass_whole_blame(blame, origin, porigin);
- goto finish;
origin_decref(porigin);
goto finish;
}
diff --git a/src/branch.c b/src/branch.c
index 7d5e9cb..fe4955a 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -127,61 +127,30 @@
repository, branch_name, commit->commit, commit->description, force);
}
-int git_branch_is_checked_out(
- const git_reference *branch)
+static int branch_equals(git_repository *repo, const char *path, void *payload)
{
- git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT;
- git_strarray worktrees;
- git_reference *ref = NULL;
- git_repository *repo;
- const char *worktree;
- int found = false;
- size_t i;
+ git_reference *branch = (git_reference *) payload;
+ git_reference *head = NULL;
+ int equal = 0;
- assert(branch && git_reference_is_branch(branch));
+ if (git_reference__read_head(&head, repo, path) < 0 ||
+ git_reference_type(head) != GIT_REF_SYMBOLIC)
+ goto done;
- repo = git_reference_owner(branch);
+ equal = !git__strcmp(head->target.symbolic, branch->name);
- if (git_worktree_list(&worktrees, repo) < 0)
- return -1;
-
- for (i = 0; i < worktrees.count; i++) {
- worktree = worktrees.strings[i];
-
- if (git_repository_head_for_worktree(&ref, repo, worktree) < 0)
- continue;
-
- if (git__strcmp(ref->name, branch->name) == 0) {
- found = true;
- git_reference_free(ref);
- break;
- }
-
- git_reference_free(ref);
- }
- git_strarray_free(&worktrees);
-
- if (found)
- return found;
-
- /* Check HEAD of parent */
- if (git_buf_joinpath(&path, repo->commondir, GIT_HEAD_FILE) < 0)
- goto out;
- if (git_futils_readbuffer(&buf, path.ptr) < 0)
- goto out;
- if (git__prefixcmp(buf.ptr, "ref: ") == 0)
- git_buf_consume(&buf, buf.ptr + strlen("ref: "));
- git_buf_rtrim(&buf);
-
- found = git__strcmp(buf.ptr, branch->name) == 0;
-
-out:
- git_buf_free(&buf);
- git_buf_free(&path);
-
- return found;
+done:
+ git_reference_free(head);
+ return equal;
}
+int git_branch_is_checked_out(const git_reference *branch)
+{
+ assert(branch && git_reference_is_branch(branch));
+
+ return git_repository_foreach_head(git_reference_owner(branch),
+ branch_equals, (void *) branch) == 1;
+}
int git_branch_delete(git_reference *branch)
{
diff --git a/src/config.c b/src/config.c
index 0893feb..169a628 100644
--- a/src/config.c
+++ b/src/config.c
@@ -576,22 +576,50 @@
* Setters
**************/
-static int config_error_nofiles(const char *name)
+typedef enum {
+ BACKEND_USE_SET,
+ BACKEND_USE_DELETE
+} backend_use;
+
+static const char *uses[] = {
+ "set",
+ "delete"
+};
+
+static int get_backend_for_use(git_config_backend **out,
+ git_config *cfg, const char *name, backend_use use)
{
+ size_t i;
+ file_internal *f;
+
+ *out = NULL;
+
+ if (git_vector_length(&cfg->files) == 0) {
+ giterr_set(GITERR_CONFIG,
+ "cannot %s value for '%s' when no config files exist",
+ uses[use], name);
+ return GIT_ENOTFOUND;
+ }
+
+ git_vector_foreach(&cfg->files, i, f) {
+ if (!f->file->readonly) {
+ *out = f->file;
+ return 0;
+ }
+ }
+
giterr_set(GITERR_CONFIG,
- "cannot set value for '%s' when no config files exist", name);
+ "cannot %s value for '%s' when all config files are readonly",
+ uses[use], name);
return GIT_ENOTFOUND;
}
int git_config_delete_entry(git_config *cfg, const char *name)
{
git_config_backend *file;
- file_internal *internal;
- internal = git_vector_get(&cfg->files, 0);
- if (!internal || !internal->file)
- return config_error_nofiles(name);
- file = internal->file;
+ if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
+ return GIT_ENOTFOUND;
return file->del(file, name);
}
@@ -617,17 +645,14 @@
{
int error;
git_config_backend *file;
- file_internal *internal;
if (!value) {
giterr_set(GITERR_CONFIG, "the value to set cannot be NULL");
return -1;
}
- internal = git_vector_get(&cfg->files, 0);
- if (!internal || !internal->file)
- return config_error_nofiles(name);
- file = internal->file;
+ if (get_backend_for_use(&file, cfg, name, BACKEND_USE_SET) < 0)
+ return GIT_ENOTFOUND;
error = file->set(file, name, value);
@@ -1032,12 +1057,9 @@
int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value)
{
git_config_backend *file;
- file_internal *internal;
- internal = git_vector_get(&cfg->files, 0);
- if (!internal || !internal->file)
- return config_error_nofiles(name);
- file = internal->file;
+ if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
+ return GIT_ENOTFOUND;
return file->set_multivar(file, name, regexp, value);
}
@@ -1045,12 +1067,9 @@
int git_config_delete_multivar(git_config *cfg, const char *name, const char *regexp)
{
git_config_backend *file;
- file_internal *internal;
- internal = git_vector_get(&cfg->files, 0);
- if (!internal || !internal->file)
- return config_error_nofiles(name);
- file = internal->file;
+ if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0)
+ return GIT_ENOTFOUND;
return file->del_multivar(file, name, regexp);
}
diff --git a/src/config_file.c b/src/config_file.c
index 5153f57..2302d33 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -1027,7 +1027,7 @@
first_quote = strchr(line, '"');
if (first_quote == NULL) {
set_parse_error(reader, 0, "Missing quotation marks in section header");
- return -1;
+ goto end_error;
}
last_quote = strrchr(line, '"');
@@ -1035,7 +1035,7 @@
if (quoted_len == 0) {
set_parse_error(reader, 0, "Missing closing quotation mark in section header");
- return -1;
+ goto end_error;
}
GITERR_CHECK_ALLOC_ADD(&alloc_len, base_name_len, quoted_len);
@@ -1043,7 +1043,7 @@
if (git_buf_grow(&buf, alloc_len) < 0 ||
git_buf_printf(&buf, "%s.", base_name) < 0)
- goto end_parse;
+ goto end_error;
rpos = 0;
@@ -1059,8 +1059,7 @@
switch (c) {
case 0:
set_parse_error(reader, 0, "Unexpected end-of-line in section header");
- git_buf_free(&buf);
- return -1;
+ goto end_error;
case '"':
goto end_parse;
@@ -1070,8 +1069,7 @@
if (c == 0) {
set_parse_error(reader, rpos, "Unexpected end-of-line in section header");
- git_buf_free(&buf);
- return -1;
+ goto end_error;
}
default:
@@ -1083,10 +1081,8 @@
} while (line + rpos < last_quote);
end_parse:
- if (git_buf_oom(&buf)) {
- git_buf_free(&buf);
- return -1;
- }
+ if (git_buf_oom(&buf))
+ goto end_error;
if (line[rpos] != '"' || line[rpos + 1] != ']') {
set_parse_error(reader, rpos, "Unexpected text after closing quotes");
@@ -1096,6 +1092,11 @@
*section_name = git_buf_detach(&buf);
return 0;
+
+end_error:
+ git_buf_free(&buf);
+
+ return -1;
}
static int parse_section_header(struct reader *reader, char **section_out)
diff --git a/src/config_file.h b/src/config_file.h
index 1c52892..654e6ca 100644
--- a/src/config_file.h
+++ b/src/config_file.h
@@ -7,6 +7,7 @@
#ifndef INCLUDE_config_file_h__
#define INCLUDE_config_file_h__
+#include "git2/sys/config.h"
#include "git2/config.h"
GIT_INLINE(int) git_config_file_open(git_config_backend *cfg, unsigned int level)
diff --git a/src/diff_parse.c b/src/diff_parse.c
index 24a8a4a..5e3a7a1 100644
--- a/src/diff_parse.c
+++ b/src/diff_parse.c
@@ -45,7 +45,7 @@
diff->base.free_fn = diff_parsed_free;
if (git_diff_init_options(&diff->base.opts, GIT_DIFF_OPTIONS_VERSION) < 0) {
- git__free(&diff);
+ git__free(diff);
return NULL;
}
diff --git a/src/fileops.c b/src/fileops.c
index 28f414f..a0a2795 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -66,8 +66,8 @@
int git_futils_creat_locked(const char *path, const mode_t mode)
{
- int fd = p_open(path, O_WRONLY | O_CREAT | O_TRUNC |
- O_EXCL | O_BINARY | O_CLOEXEC, mode);
+ int fd = p_open(path, O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC,
+ mode);
if (fd < 0) {
int error = errno;
@@ -304,13 +304,19 @@
if (fd < 0)
return fd;
- len = git_futils_filesize(fd);
+ if ((len = git_futils_filesize(fd)) < 0) {
+ result = -1;
+ goto out;
+ }
+
if (!git__is_sizet(len)) {
giterr_set(GITERR_OS, "file `%s` too large to mmap", path);
- return -1;
+ result = -1;
+ goto out;
}
result = git_futils_mmap_ro(out, fd, 0, (size_t)len);
+out:
p_close(fd);
return result;
}
diff --git a/src/filter.c b/src/filter.c
index 0d8831e..e74cc10 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -911,14 +911,19 @@
last_stream);
if (error < 0)
- return error;
+ goto out;
git_vector_insert(streams, filter_stream);
last_stream = filter_stream;
}
- *out = last_stream;
- return 0;
+out:
+ if (error)
+ last_stream->close(last_stream);
+ else
+ *out = last_stream;
+
+ return error;
}
void stream_list_free(git_vector *streams)
@@ -943,12 +948,13 @@
git_vector filter_streams = GIT_VECTOR_INIT;
git_writestream *stream_start;
ssize_t readlen;
- int fd = -1, error;
+ int fd = -1, error, initialized = 0;
if ((error = stream_list_init(
&stream_start, &filter_streams, filters, target)) < 0 ||
(error = git_path_join_unrooted(&abspath, path, base, NULL)) < 0)
goto done;
+ initialized = 1;
if ((fd = git_futils_open_ro(abspath.ptr)) < 0) {
error = fd;
@@ -960,13 +966,13 @@
goto done;
}
- if (!readlen)
- error = stream_start->close(stream_start);
- else if (readlen < 0)
+ if (readlen < 0)
error = readlen;
-
done:
+ if (initialized)
+ error |= stream_start->close(stream_start);
+
if (fd >= 0)
p_close(fd);
stream_list_free(&filter_streams);
@@ -981,20 +987,24 @@
{
git_vector filter_streams = GIT_VECTOR_INIT;
git_writestream *stream_start;
- int error = 0, close_error;
+ int error, initialized = 0;
git_buf_sanitize(data);
if ((error = stream_list_init(&stream_start, &filter_streams, filters, target)) < 0)
goto out;
+ initialized = 1;
- error = stream_start->write(stream_start, data->ptr, data->size);
+ if ((error = stream_start->write(
+ stream_start, data->ptr, data->size)) < 0)
+ goto out;
out:
- close_error = stream_start->close(stream_start);
+ if (initialized)
+ error |= stream_start->close(stream_start);
+
stream_list_free(&filter_streams);
- /* propagate the stream init or write error */
- return error < 0 ? error : close_error;
+ return error;
}
int git_filter_list_stream_blob(
diff --git a/src/global.c b/src/global.c
index e2ad8fe..afa57e1 100644
--- a/src/global.c
+++ b/src/global.c
@@ -22,7 +22,7 @@
git_mutex git__mwindow_mutex;
-#define MAX_SHUTDOWN_CB 8
+#define MAX_SHUTDOWN_CB 9
static git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB];
static git_atomic git__n_shutdown_callbacks;
diff --git a/src/hash/hash_collisiondetect.h b/src/hash/hash_collisiondetect.h
index 2bb27ba..5fdae8d 100644
--- a/src/hash/hash_collisiondetect.h
+++ b/src/hash/hash_collisiondetect.h
@@ -28,18 +28,8 @@
GIT_INLINE(int) git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
{
- const char *p = data;
-
assert(ctx);
-
- /* We expect a size_t, but sha1dc only takes an int */
- while (len > INT_MAX) {
- SHA1DCUpdate(&ctx->c, p, INT_MAX);
- p += INT_MAX;
- len -= INT_MAX;
- }
-
- SHA1DCUpdate(&ctx->c, p, len);
+ SHA1DCUpdate(&ctx->c, data, len);
return 0;
}
diff --git a/src/hash/sha1dc/sha1.c b/src/hash/sha1dc/sha1.c
index c846a16..8d12b83 100644
--- a/src/hash/sha1dc/sha1.c
+++ b/src/hash/sha1dc/sha1.c
@@ -1,5 +1,5 @@
/***
-* Copyright 2017 Marc Stevens <marc@marc-stevens.nl>, Dan Shumow (danshu@microsoft.com)
+* Copyright 2017 Marc Stevens <marc@marc-stevens.nl>, Dan Shumow (danshu@microsoft.com)
* Distributed under the MIT Software License.
* See accompanying file LICENSE.txt or copy at
* https://opensource.org/licenses/MIT
@@ -8,16 +8,48 @@
#include <string.h>
#include <memory.h>
#include <stdio.h>
+#include <stdlib.h>
#include "sha1.h"
#include "ubc_check.h"
+
+/*
+ Because Little-Endian architectures are most common,
+ we only set BIGENDIAN if one of these conditions is met.
+ Note that all MSFT platforms are little endian,
+ so none of these will be defined under the MSC compiler.
+ 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.
+ */
+#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || \
+ (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__)) || \
+ defined(__BIG_ENDIAN__) || defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
+ defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__)
+
+#define BIGENDIAN (1)
+
+#endif /*ENDIANNESS SELECTION*/
+
#define rotate_right(x,n) (((x)>>(n))|((x)<<(32-(n))))
#define rotate_left(x,n) (((x)<<(n))|((x)>>(32-(n))))
+#define sha1_bswap32(x) \
+ {x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); x = (x << 16) | (x >> 16);}
+
+#define sha1_mix(W, t) (rotate_left(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1))
+
+#if defined(BIGENDIAN)
+ #define sha1_load(m, t, temp) { temp = m[t]; }
+#else
+ #define sha1_load(m, t, temp) { temp = m[t]; sha1_bswap32(temp); }
+#endif /*define(BIGENDIAN)*/
+
+#define sha1_store(W, t, x) *(volatile uint32_t *)&W[t] = x
+
#define sha1_f1(b,c,d) ((d)^((b)&((c)^(d))))
#define sha1_f2(b,c,d) ((b)^(c)^(d))
-#define sha1_f3(b,c,d) (((b) & ((c)|(d))) | ((c)&(d)))
+#define sha1_f3(b,c,d) (((b)&(c))+((d)&((b)^(c))))
#define sha1_f4(b,c,d) ((b)^(c)^(d))
#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, m, t) \
@@ -38,28 +70,129 @@
#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, m, t) \
{ b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6 + m[t]; }
+#define SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, t, temp) \
+ {sha1_load(m, t, temp); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999; b = rotate_left(b, 30);}
+
+#define SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999; b = rotate_left(b, 30); }
+
+#define SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1; b = rotate_left(b, 30); }
+
+#define SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC; b = rotate_left(b, 30); }
+
+#define SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6; b = rotate_left(b, 30); }
+
+
#define SHA1_STORE_STATE(i) states[i][0] = a; states[i][1] = b; states[i][2] = c; states[i][3] = d; states[i][4] = e;
-
-
-void sha1_message_expansion(uint32_t W[80])
-{
- unsigned i;
-
- for (i = 16; i < 80; ++i)
- W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
-}
-
+#ifdef BUILDNOCOLLDETECTSHA1COMPRESSION
void sha1_compression(uint32_t ihv[5], const uint32_t m[16])
{
- uint32_t a, b, c, d, e, W[80];
+ uint32_t W[80];
+ uint32_t a,b,c,d,e;
unsigned i;
memcpy(W, m, 16 * 4);
for (i = 16; i < 80; ++i)
- W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
+ W[i] = sha1_mix(W, i);
- a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4];
+ a = ihv[0]; b = ihv[1]; c = ihv[2]; d = ihv[3]; e = ihv[4];
+
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18);
+ HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19);
+
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39);
+
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58);
+ HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59);
+
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78);
+ HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79);
+
+ ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e;
+}
+#endif /*BUILDNOCOLLDETECTSHA1COMPRESSION*/
+
+
+static void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80])
+{
+ uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4];
HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0);
HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1);
@@ -150,509 +283,417 @@
-void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80])
+void sha1_compression_states(uint32_t ihv[5], const uint32_t m[16], uint32_t W[80], uint32_t states[80][5])
{
uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4];
-
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18);
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19);
-
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39);
-
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58);
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59);
-
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78);
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79);
-
- ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e;
-}
-
-
-
-void sha1_compression_states(uint32_t ihv[5], const uint32_t W[80], uint32_t states[80][5])
-{
- uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4];
+ uint32_t temp;
#ifdef DOSTORESTATE00
SHA1_STORE_STATE(0)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 0, temp);
#ifdef DOSTORESTATE01
SHA1_STORE_STATE(1)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 1, temp);
#ifdef DOSTORESTATE02
SHA1_STORE_STATE(2)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 2, temp);
#ifdef DOSTORESTATE03
SHA1_STORE_STATE(3)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 3, temp);
#ifdef DOSTORESTATE04
SHA1_STORE_STATE(4)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 4, temp);
#ifdef DOSTORESTATE05
SHA1_STORE_STATE(5)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 5, temp);
#ifdef DOSTORESTATE06
SHA1_STORE_STATE(6)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 6, temp);
#ifdef DOSTORESTATE07
SHA1_STORE_STATE(7)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 7, temp);
#ifdef DOSTORESTATE08
SHA1_STORE_STATE(8)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 8, temp);
#ifdef DOSTORESTATE09
SHA1_STORE_STATE(9)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 9, temp);
#ifdef DOSTORESTATE10
SHA1_STORE_STATE(10)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 10, temp);
#ifdef DOSTORESTATE11
SHA1_STORE_STATE(11)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 11, temp);
#ifdef DOSTORESTATE12
SHA1_STORE_STATE(12)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 12, temp);
#ifdef DOSTORESTATE13
SHA1_STORE_STATE(13)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 13, temp);
#ifdef DOSTORESTATE14
SHA1_STORE_STATE(14)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 14, temp);
#ifdef DOSTORESTATE15
SHA1_STORE_STATE(15)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 15, temp);
#ifdef DOSTORESTATE16
SHA1_STORE_STATE(16)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16);
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(e, a, b, c, d, W, 16, temp);
#ifdef DOSTORESTATE17
SHA1_STORE_STATE(17)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17);
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(d, e, a, b, c, W, 17, temp);
#ifdef DOSTORESTATE18
SHA1_STORE_STATE(18)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18);
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(c, d, e, a, b, W, 18, temp);
#ifdef DOSTORESTATE19
SHA1_STORE_STATE(19)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19);
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(b, c, d, e, a, W, 19, temp);
#ifdef DOSTORESTATE20
SHA1_STORE_STATE(20)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20);
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 20, temp);
#ifdef DOSTORESTATE21
SHA1_STORE_STATE(21)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 21, temp);
+
#ifdef DOSTORESTATE22
SHA1_STORE_STATE(22)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 22, temp);
+
#ifdef DOSTORESTATE23
SHA1_STORE_STATE(23)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23);
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 23, temp);
#ifdef DOSTORESTATE24
SHA1_STORE_STATE(24)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24);
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 24, temp);
#ifdef DOSTORESTATE25
SHA1_STORE_STATE(25)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25);
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 25, temp);
#ifdef DOSTORESTATE26
SHA1_STORE_STATE(26)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26);
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 26, temp);
#ifdef DOSTORESTATE27
SHA1_STORE_STATE(27)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 27, temp);
+
#ifdef DOSTORESTATE28
SHA1_STORE_STATE(28)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 28, temp);
+
#ifdef DOSTORESTATE29
SHA1_STORE_STATE(29)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 29, temp);
+
#ifdef DOSTORESTATE30
SHA1_STORE_STATE(30)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 30, temp);
+
#ifdef DOSTORESTATE31
SHA1_STORE_STATE(31)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 31, temp);
+
#ifdef DOSTORESTATE32
SHA1_STORE_STATE(32)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32);
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 32, temp);
#ifdef DOSTORESTATE33
SHA1_STORE_STATE(33)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33);
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 33, temp);
#ifdef DOSTORESTATE34
SHA1_STORE_STATE(34)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34);
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 34, temp);
#ifdef DOSTORESTATE35
SHA1_STORE_STATE(35)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 35, temp);
+
#ifdef DOSTORESTATE36
SHA1_STORE_STATE(36)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 36, temp);
+
#ifdef DOSTORESTATE37
SHA1_STORE_STATE(37)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 37, temp);
+
#ifdef DOSTORESTATE38
SHA1_STORE_STATE(38)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 38, temp);
+
#ifdef DOSTORESTATE39
SHA1_STORE_STATE(39)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39);
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 39, temp);
#ifdef DOSTORESTATE40
SHA1_STORE_STATE(40)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40);
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 40, temp);
#ifdef DOSTORESTATE41
SHA1_STORE_STATE(41)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41);
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 41, temp);
#ifdef DOSTORESTATE42
SHA1_STORE_STATE(42)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42);
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 42, temp);
#ifdef DOSTORESTATE43
SHA1_STORE_STATE(43)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43);
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 43, temp);
#ifdef DOSTORESTATE44
SHA1_STORE_STATE(44)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44);
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 44, temp);
#ifdef DOSTORESTATE45
SHA1_STORE_STATE(45)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45);
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 45, temp);
#ifdef DOSTORESTATE46
SHA1_STORE_STATE(46)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46);
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 46, temp);
#ifdef DOSTORESTATE47
SHA1_STORE_STATE(47)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47);
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 47, temp);
#ifdef DOSTORESTATE48
SHA1_STORE_STATE(48)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48);
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 48, temp);
#ifdef DOSTORESTATE49
SHA1_STORE_STATE(49)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49);
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 49, temp);
#ifdef DOSTORESTATE50
SHA1_STORE_STATE(50)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50);
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 50, temp);
#ifdef DOSTORESTATE51
SHA1_STORE_STATE(51)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51);
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 51, temp);
#ifdef DOSTORESTATE52
SHA1_STORE_STATE(52)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52);
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 52, temp);
#ifdef DOSTORESTATE53
SHA1_STORE_STATE(53)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53);
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 53, temp);
#ifdef DOSTORESTATE54
SHA1_STORE_STATE(54)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54);
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 54, temp);
#ifdef DOSTORESTATE55
SHA1_STORE_STATE(55)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55);
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 55, temp);
#ifdef DOSTORESTATE56
SHA1_STORE_STATE(56)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56);
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 56, temp);
#ifdef DOSTORESTATE57
SHA1_STORE_STATE(57)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57);
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 57, temp);
#ifdef DOSTORESTATE58
SHA1_STORE_STATE(58)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58);
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 58, temp);
#ifdef DOSTORESTATE59
SHA1_STORE_STATE(59)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59);
-
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 59, temp);
+
#ifdef DOSTORESTATE60
SHA1_STORE_STATE(60)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60);
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 60, temp);
#ifdef DOSTORESTATE61
SHA1_STORE_STATE(61)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61);
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 61, temp);
#ifdef DOSTORESTATE62
SHA1_STORE_STATE(62)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62);
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 62, temp);
#ifdef DOSTORESTATE63
SHA1_STORE_STATE(63)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63);
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 63, temp);
#ifdef DOSTORESTATE64
SHA1_STORE_STATE(64)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64);
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 64, temp);
#ifdef DOSTORESTATE65
SHA1_STORE_STATE(65)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65);
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 65, temp);
#ifdef DOSTORESTATE66
SHA1_STORE_STATE(66)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66);
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 66, temp);
#ifdef DOSTORESTATE67
SHA1_STORE_STATE(67)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67);
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 67, temp);
#ifdef DOSTORESTATE68
SHA1_STORE_STATE(68)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68);
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 68, temp);
#ifdef DOSTORESTATE69
SHA1_STORE_STATE(69)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69);
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 69, temp);
#ifdef DOSTORESTATE70
SHA1_STORE_STATE(70)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70);
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 70, temp);
#ifdef DOSTORESTATE71
SHA1_STORE_STATE(71)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71);
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 71, temp);
#ifdef DOSTORESTATE72
SHA1_STORE_STATE(72)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72);
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 72, temp);
#ifdef DOSTORESTATE73
SHA1_STORE_STATE(73)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73);
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 73, temp);
#ifdef DOSTORESTATE74
SHA1_STORE_STATE(74)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74);
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 74, temp);
#ifdef DOSTORESTATE75
SHA1_STORE_STATE(75)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75);
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 75, temp);
#ifdef DOSTORESTATE76
SHA1_STORE_STATE(76)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76);
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 76, temp);
#ifdef DOSTORESTATE77
SHA1_STORE_STATE(77)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77);
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 77, temp);
#ifdef DOSTORESTATE78
SHA1_STORE_STATE(78)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78);
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 78, temp);
#ifdef DOSTORESTATE79
SHA1_STORE_STATE(79)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79);
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 79, temp);
@@ -663,7 +704,7 @@
#define SHA1_RECOMPRESS(t) \
-void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) \
+static void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) \
{ \
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; \
if (t > 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 79); \
@@ -829,180 +870,794 @@
if (t <= 78) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 78); \
if (t <= 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 79); \
ihvout[0] = ihvin[0] + a; ihvout[1] = ihvin[1] + b; ihvout[2] = ihvin[2] + c; ihvout[3] = ihvin[3] + d; ihvout[4] = ihvin[4] + e; \
-}
+}
+#ifdef DOSTORESTATE0
SHA1_RECOMPRESS(0)
+#endif
+
+#ifdef DOSTORESTATE1
SHA1_RECOMPRESS(1)
+#endif
+
+#ifdef DOSTORESTATE2
SHA1_RECOMPRESS(2)
+#endif
+
+#ifdef DOSTORESTATE3
SHA1_RECOMPRESS(3)
+#endif
+
+#ifdef DOSTORESTATE4
SHA1_RECOMPRESS(4)
+#endif
+
+#ifdef DOSTORESTATE5
SHA1_RECOMPRESS(5)
+#endif
+
+#ifdef DOSTORESTATE6
SHA1_RECOMPRESS(6)
+#endif
+
+#ifdef DOSTORESTATE7
SHA1_RECOMPRESS(7)
+#endif
+
+#ifdef DOSTORESTATE8
SHA1_RECOMPRESS(8)
+#endif
+
+#ifdef DOSTORESTATE9
SHA1_RECOMPRESS(9)
+#endif
+#ifdef DOSTORESTATE10
SHA1_RECOMPRESS(10)
+#endif
+
+#ifdef DOSTORESTATE11
SHA1_RECOMPRESS(11)
+#endif
+
+#ifdef DOSTORESTATE12
SHA1_RECOMPRESS(12)
+#endif
+
+#ifdef DOSTORESTATE13
SHA1_RECOMPRESS(13)
+#endif
+
+#ifdef DOSTORESTATE14
SHA1_RECOMPRESS(14)
+#endif
+
+#ifdef DOSTORESTATE15
SHA1_RECOMPRESS(15)
+#endif
+
+#ifdef DOSTORESTATE16
SHA1_RECOMPRESS(16)
+#endif
+
+#ifdef DOSTORESTATE17
SHA1_RECOMPRESS(17)
+#endif
+
+#ifdef DOSTORESTATE18
SHA1_RECOMPRESS(18)
+#endif
+
+#ifdef DOSTORESTATE19
SHA1_RECOMPRESS(19)
+#endif
+#ifdef DOSTORESTATE20
SHA1_RECOMPRESS(20)
+#endif
+
+#ifdef DOSTORESTATE21
SHA1_RECOMPRESS(21)
+#endif
+
+#ifdef DOSTORESTATE22
SHA1_RECOMPRESS(22)
+#endif
+
+#ifdef DOSTORESTATE23
SHA1_RECOMPRESS(23)
+#endif
+
+#ifdef DOSTORESTATE24
SHA1_RECOMPRESS(24)
+#endif
+
+#ifdef DOSTORESTATE25
SHA1_RECOMPRESS(25)
+#endif
+
+#ifdef DOSTORESTATE26
SHA1_RECOMPRESS(26)
+#endif
+
+#ifdef DOSTORESTATE27
SHA1_RECOMPRESS(27)
+#endif
+
+#ifdef DOSTORESTATE28
SHA1_RECOMPRESS(28)
+#endif
+
+#ifdef DOSTORESTATE29
SHA1_RECOMPRESS(29)
+#endif
+#ifdef DOSTORESTATE30
SHA1_RECOMPRESS(30)
+#endif
+
+#ifdef DOSTORESTATE31
SHA1_RECOMPRESS(31)
+#endif
+
+#ifdef DOSTORESTATE32
SHA1_RECOMPRESS(32)
+#endif
+
+#ifdef DOSTORESTATE33
SHA1_RECOMPRESS(33)
+#endif
+
+#ifdef DOSTORESTATE34
SHA1_RECOMPRESS(34)
+#endif
+
+#ifdef DOSTORESTATE35
SHA1_RECOMPRESS(35)
+#endif
+
+#ifdef DOSTORESTATE36
SHA1_RECOMPRESS(36)
+#endif
+
+#ifdef DOSTORESTATE37
SHA1_RECOMPRESS(37)
+#endif
+
+#ifdef DOSTORESTATE38
SHA1_RECOMPRESS(38)
+#endif
+
+#ifdef DOSTORESTATE39
SHA1_RECOMPRESS(39)
+#endif
+#ifdef DOSTORESTATE40
SHA1_RECOMPRESS(40)
+#endif
+
+#ifdef DOSTORESTATE41
SHA1_RECOMPRESS(41)
+#endif
+
+#ifdef DOSTORESTATE42
SHA1_RECOMPRESS(42)
+#endif
+
+#ifdef DOSTORESTATE43
SHA1_RECOMPRESS(43)
+#endif
+
+#ifdef DOSTORESTATE44
SHA1_RECOMPRESS(44)
+#endif
+
+#ifdef DOSTORESTATE45
SHA1_RECOMPRESS(45)
+#endif
+
+#ifdef DOSTORESTATE46
SHA1_RECOMPRESS(46)
+#endif
+
+#ifdef DOSTORESTATE47
SHA1_RECOMPRESS(47)
+#endif
+
+#ifdef DOSTORESTATE48
SHA1_RECOMPRESS(48)
+#endif
+
+#ifdef DOSTORESTATE49
SHA1_RECOMPRESS(49)
+#endif
+#ifdef DOSTORESTATE50
SHA1_RECOMPRESS(50)
+#endif
+
+#ifdef DOSTORESTATE51
SHA1_RECOMPRESS(51)
+#endif
+
+#ifdef DOSTORESTATE52
SHA1_RECOMPRESS(52)
+#endif
+
+#ifdef DOSTORESTATE53
SHA1_RECOMPRESS(53)
+#endif
+
+#ifdef DOSTORESTATE54
SHA1_RECOMPRESS(54)
+#endif
+
+#ifdef DOSTORESTATE55
SHA1_RECOMPRESS(55)
+#endif
+
+#ifdef DOSTORESTATE56
SHA1_RECOMPRESS(56)
+#endif
+
+#ifdef DOSTORESTATE57
SHA1_RECOMPRESS(57)
+#endif
+
+#ifdef DOSTORESTATE58
SHA1_RECOMPRESS(58)
+#endif
+
+#ifdef DOSTORESTATE59
SHA1_RECOMPRESS(59)
+#endif
+#ifdef DOSTORESTATE60
SHA1_RECOMPRESS(60)
+#endif
+
+#ifdef DOSTORESTATE61
SHA1_RECOMPRESS(61)
+#endif
+
+#ifdef DOSTORESTATE62
SHA1_RECOMPRESS(62)
+#endif
+
+#ifdef DOSTORESTATE63
SHA1_RECOMPRESS(63)
+#endif
+
+#ifdef DOSTORESTATE64
SHA1_RECOMPRESS(64)
+#endif
+
+#ifdef DOSTORESTATE65
SHA1_RECOMPRESS(65)
+#endif
+
+#ifdef DOSTORESTATE66
SHA1_RECOMPRESS(66)
+#endif
+
+#ifdef DOSTORESTATE67
SHA1_RECOMPRESS(67)
+#endif
+
+#ifdef DOSTORESTATE68
SHA1_RECOMPRESS(68)
+#endif
+
+#ifdef DOSTORESTATE69
SHA1_RECOMPRESS(69)
+#endif
+#ifdef DOSTORESTATE70
SHA1_RECOMPRESS(70)
+#endif
+
+#ifdef DOSTORESTATE71
SHA1_RECOMPRESS(71)
+#endif
+
+#ifdef DOSTORESTATE72
SHA1_RECOMPRESS(72)
+#endif
+
+#ifdef DOSTORESTATE73
SHA1_RECOMPRESS(73)
+#endif
+
+#ifdef DOSTORESTATE74
SHA1_RECOMPRESS(74)
+#endif
+
+#ifdef DOSTORESTATE75
SHA1_RECOMPRESS(75)
+#endif
+
+#ifdef DOSTORESTATE76
SHA1_RECOMPRESS(76)
+#endif
+
+#ifdef DOSTORESTATE77
SHA1_RECOMPRESS(77)
+#endif
+
+#ifdef DOSTORESTATE78
SHA1_RECOMPRESS(78)
+#endif
+
+#ifdef DOSTORESTATE79
SHA1_RECOMPRESS(79)
+#endif
-sha1_recompression_type sha1_recompression_step[80] =
+static void sha1_recompression_step(uint32_t step, uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5])
{
- sha1recompress_fast_0, sha1recompress_fast_1, sha1recompress_fast_2, sha1recompress_fast_3, sha1recompress_fast_4, sha1recompress_fast_5, sha1recompress_fast_6, sha1recompress_fast_7, sha1recompress_fast_8, sha1recompress_fast_9,
- sha1recompress_fast_10, sha1recompress_fast_11, sha1recompress_fast_12, sha1recompress_fast_13, sha1recompress_fast_14, sha1recompress_fast_15, sha1recompress_fast_16, sha1recompress_fast_17, sha1recompress_fast_18, sha1recompress_fast_19,
- sha1recompress_fast_20, sha1recompress_fast_21, sha1recompress_fast_22, sha1recompress_fast_23, sha1recompress_fast_24, sha1recompress_fast_25, sha1recompress_fast_26, sha1recompress_fast_27, sha1recompress_fast_28, sha1recompress_fast_29,
- sha1recompress_fast_30, sha1recompress_fast_31, sha1recompress_fast_32, sha1recompress_fast_33, sha1recompress_fast_34, sha1recompress_fast_35, sha1recompress_fast_36, sha1recompress_fast_37, sha1recompress_fast_38, sha1recompress_fast_39,
- sha1recompress_fast_40, sha1recompress_fast_41, sha1recompress_fast_42, sha1recompress_fast_43, sha1recompress_fast_44, sha1recompress_fast_45, sha1recompress_fast_46, sha1recompress_fast_47, sha1recompress_fast_48, sha1recompress_fast_49,
- sha1recompress_fast_50, sha1recompress_fast_51, sha1recompress_fast_52, sha1recompress_fast_53, sha1recompress_fast_54, sha1recompress_fast_55, sha1recompress_fast_56, sha1recompress_fast_57, sha1recompress_fast_58, sha1recompress_fast_59,
- sha1recompress_fast_60, sha1recompress_fast_61, sha1recompress_fast_62, sha1recompress_fast_63, sha1recompress_fast_64, sha1recompress_fast_65, sha1recompress_fast_66, sha1recompress_fast_67, sha1recompress_fast_68, sha1recompress_fast_69,
- sha1recompress_fast_70, sha1recompress_fast_71, sha1recompress_fast_72, sha1recompress_fast_73, sha1recompress_fast_74, sha1recompress_fast_75, sha1recompress_fast_76, sha1recompress_fast_77, sha1recompress_fast_78, sha1recompress_fast_79,
-};
+ switch (step)
+ {
+#ifdef DOSTORESTATE0
+ case 0:
+ sha1recompress_fast_0(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE1
+ case 1:
+ sha1recompress_fast_1(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE2
+ case 2:
+ sha1recompress_fast_2(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE3
+ case 3:
+ sha1recompress_fast_3(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE4
+ case 4:
+ sha1recompress_fast_4(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE5
+ case 5:
+ sha1recompress_fast_5(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE6
+ case 6:
+ sha1recompress_fast_6(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE7
+ case 7:
+ sha1recompress_fast_7(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE8
+ case 8:
+ sha1recompress_fast_8(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE9
+ case 9:
+ sha1recompress_fast_9(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE10
+ case 10:
+ sha1recompress_fast_10(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE11
+ case 11:
+ sha1recompress_fast_11(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE12
+ case 12:
+ sha1recompress_fast_12(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE13
+ case 13:
+ sha1recompress_fast_13(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE14
+ case 14:
+ sha1recompress_fast_14(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE15
+ case 15:
+ sha1recompress_fast_15(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE16
+ case 16:
+ sha1recompress_fast_16(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE17
+ case 17:
+ sha1recompress_fast_17(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE18
+ case 18:
+ sha1recompress_fast_18(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE19
+ case 19:
+ sha1recompress_fast_19(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE20
+ case 20:
+ sha1recompress_fast_20(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE21
+ case 21:
+ sha1recompress_fast_21(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE22
+ case 22:
+ sha1recompress_fast_22(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE23
+ case 23:
+ sha1recompress_fast_23(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE24
+ case 24:
+ sha1recompress_fast_24(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE25
+ case 25:
+ sha1recompress_fast_25(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE26
+ case 26:
+ sha1recompress_fast_26(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE27
+ case 27:
+ sha1recompress_fast_27(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE28
+ case 28:
+ sha1recompress_fast_28(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE29
+ case 29:
+ sha1recompress_fast_29(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE30
+ case 30:
+ sha1recompress_fast_30(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE31
+ case 31:
+ sha1recompress_fast_31(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE32
+ case 32:
+ sha1recompress_fast_32(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE33
+ case 33:
+ sha1recompress_fast_33(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE34
+ case 34:
+ sha1recompress_fast_34(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE35
+ case 35:
+ sha1recompress_fast_35(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE36
+ case 36:
+ sha1recompress_fast_36(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE37
+ case 37:
+ sha1recompress_fast_37(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE38
+ case 38:
+ sha1recompress_fast_38(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE39
+ case 39:
+ sha1recompress_fast_39(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE40
+ case 40:
+ sha1recompress_fast_40(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE41
+ case 41:
+ sha1recompress_fast_41(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE42
+ case 42:
+ sha1recompress_fast_42(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE43
+ case 43:
+ sha1recompress_fast_43(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE44
+ case 44:
+ sha1recompress_fast_44(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE45
+ case 45:
+ sha1recompress_fast_45(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE46
+ case 46:
+ sha1recompress_fast_46(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE47
+ case 47:
+ sha1recompress_fast_47(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE48
+ case 48:
+ sha1recompress_fast_48(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE49
+ case 49:
+ sha1recompress_fast_49(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE50
+ case 50:
+ sha1recompress_fast_50(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE51
+ case 51:
+ sha1recompress_fast_51(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE52
+ case 52:
+ sha1recompress_fast_52(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE53
+ case 53:
+ sha1recompress_fast_53(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE54
+ case 54:
+ sha1recompress_fast_54(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE55
+ case 55:
+ sha1recompress_fast_55(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE56
+ case 56:
+ sha1recompress_fast_56(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE57
+ case 57:
+ sha1recompress_fast_57(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE58
+ case 58:
+ sha1recompress_fast_58(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE59
+ case 59:
+ sha1recompress_fast_59(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE60
+ case 60:
+ sha1recompress_fast_60(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE61
+ case 61:
+ sha1recompress_fast_61(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE62
+ case 62:
+ sha1recompress_fast_62(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE63
+ case 63:
+ sha1recompress_fast_63(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE64
+ case 64:
+ sha1recompress_fast_64(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE65
+ case 65:
+ sha1recompress_fast_65(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE66
+ case 66:
+ sha1recompress_fast_66(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE67
+ case 67:
+ sha1recompress_fast_67(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE68
+ case 68:
+ sha1recompress_fast_68(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE69
+ case 69:
+ sha1recompress_fast_69(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE70
+ case 70:
+ sha1recompress_fast_70(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE71
+ case 71:
+ sha1recompress_fast_71(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE72
+ case 72:
+ sha1recompress_fast_72(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE73
+ case 73:
+ sha1recompress_fast_73(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE74
+ case 74:
+ sha1recompress_fast_74(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE75
+ case 75:
+ sha1recompress_fast_75(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE76
+ case 76:
+ sha1recompress_fast_76(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE77
+ case 77:
+ sha1recompress_fast_77(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE78
+ case 78:
+ sha1recompress_fast_78(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE79
+ case 79:
+ sha1recompress_fast_79(ihvin, ihvout, me2, state);
+ break;
+#endif
+ default:
+ abort();
+ }
+
+}
-
-
-void sha1_process(SHA1_CTX* ctx, const uint32_t block[16])
+static void sha1_process(SHA1_CTX* ctx, const uint32_t block[16])
{
unsigned i, j;
- uint32_t ubc_dv_mask[DVMASKSIZE];
+ uint32_t ubc_dv_mask[DVMASKSIZE] = { 0xFFFFFFFF };
uint32_t ihvtmp[5];
- for (i=0; i < DVMASKSIZE; ++i)
- ubc_dv_mask[i]=0;
+
ctx->ihv1[0] = ctx->ihv[0];
ctx->ihv1[1] = ctx->ihv[1];
ctx->ihv1[2] = ctx->ihv[2];
ctx->ihv1[3] = ctx->ihv[3];
ctx->ihv1[4] = ctx->ihv[4];
- memcpy(ctx->m1, block, 64);
- sha1_message_expansion(ctx->m1);
- if (ctx->detect_coll && ctx->ubc_check)
- {
- ubc_check(ctx->m1, ubc_dv_mask);
- }
- sha1_compression_states(ctx->ihv, ctx->m1, ctx->states);
+
+ sha1_compression_states(ctx->ihv, block, ctx->m1, ctx->states);
+
if (ctx->detect_coll)
{
- for (i = 0; sha1_dvs[i].dvType != 0; ++i)
+ if (ctx->ubc_check)
{
- if ((0 == ctx->ubc_check) || (((uint32_t)(1) << sha1_dvs[i].maskb) & ubc_dv_mask[sha1_dvs[i].maski]))
+ ubc_check(ctx->m1, ubc_dv_mask);
+ }
+
+ if (ubc_dv_mask[0] != 0)
+ {
+ for (i = 0; sha1_dvs[i].dvType != 0; ++i)
{
- for (j = 0; j < 80; ++j)
- ctx->m2[j] = ctx->m1[j] ^ sha1_dvs[i].dm[j];
- (sha1_recompression_step[sha1_dvs[i].testt])(ctx->ihv2, ihvtmp, ctx->m2, ctx->states[sha1_dvs[i].testt]);
- // to verify SHA-1 collision detection code with collisions for reduced-step SHA-1
- if ((ihvtmp[0] == ctx->ihv[0] && ihvtmp[1] == ctx->ihv[1] && ihvtmp[2] == ctx->ihv[2] && ihvtmp[3] == ctx->ihv[3] && ihvtmp[4] == ctx->ihv[4])
- || (ctx->reduced_round_coll && ctx->ihv1[0] == ctx->ihv2[0] && ctx->ihv1[1] == ctx->ihv2[1] && ctx->ihv1[2] == ctx->ihv2[2] && ctx->ihv1[3] == ctx->ihv2[3] && ctx->ihv1[4] == ctx->ihv2[4]))
+ if (ubc_dv_mask[0] & ((uint32_t)(1) << sha1_dvs[i].maskb))
{
- ctx->found_collision = 1;
- // TODO: call callback
- if (ctx->callback != NULL)
- ctx->callback(ctx->total - 64, ctx->ihv1, ctx->ihv2, ctx->m1, ctx->m2);
+ for (j = 0; j < 80; ++j)
+ ctx->m2[j] = ctx->m1[j] ^ sha1_dvs[i].dm[j];
- if (ctx->safe_hash)
+ sha1_recompression_step(sha1_dvs[i].testt, ctx->ihv2, ihvtmp, ctx->m2, ctx->states[sha1_dvs[i].testt]);
+
+ /* to verify SHA-1 collision detection code with collisions for reduced-step SHA-1 */
+ if ((0 == ((ihvtmp[0] ^ ctx->ihv[0]) | (ihvtmp[1] ^ ctx->ihv[1]) | (ihvtmp[2] ^ ctx->ihv[2]) | (ihvtmp[3] ^ ctx->ihv[3]) | (ihvtmp[4] ^ ctx->ihv[4])))
+ || (ctx->reduced_round_coll && 0==((ctx->ihv1[0] ^ ctx->ihv2[0]) | (ctx->ihv1[1] ^ ctx->ihv2[1]) | (ctx->ihv1[2] ^ ctx->ihv2[2]) | (ctx->ihv1[3] ^ ctx->ihv2[3]) | (ctx->ihv1[4] ^ ctx->ihv2[4]))))
{
- sha1_compression_W(ctx->ihv, ctx->m1);
- sha1_compression_W(ctx->ihv, ctx->m1);
- }
+ ctx->found_collision = 1;
- break;
+ if (ctx->safe_hash)
+ {
+ sha1_compression_W(ctx->ihv, ctx->m1);
+ sha1_compression_W(ctx->ihv, ctx->m1);
+ }
+
+ break;
+ }
}
}
}
}
}
-
-
-
-
-void swap_bytes(uint32_t val[16])
+void SHA1DCInit(SHA1_CTX* ctx)
{
- unsigned i;
- for (i = 0; i < 16; ++i)
- {
- val[i] = ((val[i] << 8) & 0xFF00FF00) | ((val[i] >> 8) & 0xFF00FF);
- val[i] = (val[i] << 16) | (val[i] >> 16);
- }
-}
-
-void SHA1DCInit(SHA1_CTX* ctx)
-{
- static const union { unsigned char bytes[4]; uint32_t value; } endianness = { { 0, 1, 2, 3 } };
- static const uint32_t littleendian = 0x03020100;
ctx->total = 0;
ctx->ihv[0] = 0x67452301;
ctx->ihv[1] = 0xEFCDAB89;
@@ -1014,7 +1669,6 @@
ctx->ubc_check = 1;
ctx->detect_coll = 1;
ctx->reduced_round_coll = 0;
- ctx->bigendian = (endianness.value != littleendian);
ctx->callback = NULL;
}
@@ -1056,41 +1710,32 @@
ctx->callback = callback;
}
-void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, unsigned len)
+void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, size_t len)
{
unsigned left, fill;
- if (len == 0)
+ if (len == 0)
return;
left = ctx->total & 63;
fill = 64 - left;
- if (left && len >= fill)
+ if (left && len >= fill)
{
ctx->total += fill;
memcpy(ctx->buffer + left, buf, fill);
- if (!ctx->bigendian)
- swap_bytes((uint32_t*)(ctx->buffer));
sha1_process(ctx, (uint32_t*)(ctx->buffer));
buf += fill;
len -= fill;
left = 0;
}
- while (len >= 64)
+ while (len >= 64)
{
ctx->total += 64;
- if (!ctx->bigendian)
- {
- memcpy(ctx->buffer, buf, 64);
- swap_bytes((uint32_t*)(ctx->buffer));
- sha1_process(ctx, (uint32_t*)(ctx->buffer));
- }
- else
- sha1_process(ctx, (uint32_t*)(buf));
+ sha1_process(ctx, (uint32_t*)(buf));
buf += 64;
len -= 64;
}
- if (len > 0)
+ if (len > 0)
{
ctx->total += len;
memcpy(ctx->buffer + left, buf, len);
@@ -1111,7 +1756,7 @@
uint32_t padn = (last < 56) ? (56 - last) : (120 - last);
uint64_t total;
SHA1DCUpdate(ctx, (const char*)(sha1_padding), padn);
-
+
total = ctx->total - padn;
total <<= 3;
ctx->buffer[56] = (unsigned char)(total >> 56);
@@ -1122,8 +1767,6 @@
ctx->buffer[61] = (unsigned char)(total >> 16);
ctx->buffer[62] = (unsigned char)(total >> 8);
ctx->buffer[63] = (unsigned char)(total);
- if (!ctx->bigendian)
- swap_bytes((uint32_t*)(ctx->buffer));
sha1_process(ctx, (uint32_t*)(ctx->buffer));
output[0] = (unsigned char)(ctx->ihv[0] >> 24);
output[1] = (unsigned char)(ctx->ihv[0] >> 16);
diff --git a/src/hash/sha1dc/sha1.h b/src/hash/sha1dc/sha1.h
index 8b522f9..e867724 100644
--- a/src/hash/sha1dc/sha1.h
+++ b/src/hash/sha1dc/sha1.h
@@ -5,19 +5,24 @@
* https://opensource.org/licenses/MIT
***/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#include <stdint.h>
-// uses SHA-1 message expansion to expand the first 16 words of W[] to 80 words
-void sha1_message_expansion(uint32_t W[80]);
+/* uses SHA-1 message expansion to expand the first 16 words of W[] to 80 words */
+/* void sha1_message_expansion(uint32_t W[80]); */
-// sha-1 compression function; first version takes a message block pre-parsed as 16 32-bit integers, second version takes an already expanded message)
-void sha1_compression(uint32_t ihv[5], const uint32_t m[16]);
-void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80]);
+/* sha-1 compression function; first version takes a message block pre-parsed as 16 32-bit integers, second version takes an already expanded message) */
+/* void sha1_compression(uint32_t ihv[5], const uint32_t m[16]);
+void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80]); */
-// same as sha1_compression_W, but additionally store intermediate states
-// only stores states ii (the state between step ii-1 and step ii) when DOSTORESTATEii is defined in ubc_check.h
-void sha1_compression_states(uint32_t ihv[5], const uint32_t W[80], uint32_t states[80][5]);
+/* same as sha1_compression_W, but additionally store intermediate states */
+/* only stores states ii (the state between step ii-1 and step ii) when DOSTORESTATEii is defined in ubc_check.h */
+void sha1_compression_states(uint32_t[5], const uint32_t[16], uint32_t[80], uint32_t[80][5]);
+/*
// function type for sha1_recompression_step_T (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5])
// where 0 <= T < 80
// me2 is an expanded message (the expansion of an original message block XOR'ed with a disturbance vector's message block difference)
@@ -25,21 +30,21 @@
// the function will return:
// ihvin: the reconstructed input chaining value
// ihvout: the reconstructed output chaining value
+*/
typedef void(*sha1_recompression_type)(uint32_t*, uint32_t*, const uint32_t*, const uint32_t*);
-// table of sha1_recompression_step_0, ... , sha1_recompression_step_79
-extern sha1_recompression_type sha1_recompression_step[80];
+/* table of sha1_recompression_step_0, ... , sha1_recompression_step_79 */
+/* extern sha1_recompression_type sha1_recompression_step[80];*/
-// a callback function type that can be set to be called when a collision block has been found:
-// void collision_block_callback(uint64_t byteoffset, const uint32_t ihvin1[5], const uint32_t ihvin2[5], const uint32_t m1[80], const uint32_t m2[80])
+/* a callback function type that can be set to be called when a collision block has been found: */
+/* void collision_block_callback(uint64_t byteoffset, const uint32_t ihvin1[5], const uint32_t ihvin2[5], const uint32_t m1[80], const uint32_t m2[80]) */
typedef void(*collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*);
-// the SHA-1 context
+/* the SHA-1 context */
typedef struct {
uint64_t total;
uint32_t ihv[5];
unsigned char buffer[64];
- int bigendian;
int found_collision;
int safe_hash;
int detect_coll;
@@ -54,41 +59,47 @@
uint32_t states[80][5];
} SHA1_CTX;
-// initialize SHA-1 context
-void SHA1DCInit(SHA1_CTX*);
+/* initialize SHA-1 context */
+void SHA1DCInit(SHA1_CTX*);
+/*
// function to enable safe SHA-1 hashing:
// collision attacks are thwarted by hashing a detected near-collision block 3 times
// think of it as extending SHA-1 from 80-steps to 240-steps for such blocks:
-// the best collision attacks against SHA-1 have complexity about 2^60,
+// the best collision attacks against SHA-1 have complexity about 2^60,
// thus for 240-steps an immediate lower-bound for the best cryptanalytic attacks would 2^180
// an attacker would be better off using a generic birthday search of complexity 2^80
//
// enabling safe SHA-1 hashing will result in the correct SHA-1 hash for messages where no collision attack was detected
-// but it will result in a different SHA-1 hash for messages where a collision attack was detected
+// but it will result in a different SHA-1 hash for messages where a collision attack was detected
// this will automatically invalidate SHA-1 based digital signature forgeries
// enabled by default
+*/
void SHA1DCSetSafeHash(SHA1_CTX*, int);
-// function to disable or enable the use of Unavoidable Bitconditions (provides a significant speed up)
-// enabled by default
+/* function to disable or enable the use of Unavoidable Bitconditions (provides a significant speed up) */
+/* enabled by default */
void SHA1DCSetUseUBC(SHA1_CTX*, int);
-// function to disable or enable the use of Collision Detection
-// enabled by default
-void SHA1DCSetUseDetectColl(SHA1_CTX* ctx, int detect_coll);
+/* function to disable or enable the use of Collision Detection */
+/* enabled by default */
+void SHA1DCSetUseDetectColl(SHA1_CTX*, int);
-// function to disable or enable the detection of reduced-round SHA-1 collisions
-// disabled by default
+/* function to disable or enable the detection of reduced-round SHA-1 collisions */
+/* disabled by default */
void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX*, int);
-// function to set a callback function, pass NULL to disable
-// by default no callback set
+/* function to set a callback function, pass NULL to disable */
+/* by default no callback set */
void SHA1DCSetCallback(SHA1_CTX*, collision_block_callback);
-// update SHA-1 context with buffer contents
-void SHA1DCUpdate(SHA1_CTX*, const char*, unsigned);
+/* update SHA-1 context with buffer contents */
+void SHA1DCUpdate(SHA1_CTX*, const char*, size_t);
-// obtain SHA-1 hash from SHA-1 context
-// returns: 0 = no collision detected, otherwise = collision found => warn user for active attack
+/* obtain SHA-1 hash from SHA-1 context */
+/* returns: 0 = no collision detected, otherwise = collision found => warn user for active attack */
int SHA1DCFinal(unsigned char[20], SHA1_CTX*);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/src/hash/sha1dc/ubc_check.c b/src/hash/sha1dc/ubc_check.c
index 556aaf3..27d0976 100644
--- a/src/hash/sha1dc/ubc_check.c
+++ b/src/hash/sha1dc/ubc_check.c
@@ -5,6 +5,7 @@
* https://opensource.org/licenses/MIT
***/
+/*
// this file was generated by the 'parse_bitrel' program in the tools section
// using the data files from directory 'tools/data/3565'
//
@@ -17,10 +18,11 @@
// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs
// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met
// thus one needs to do the recompression check for each DV that has its bit set
-//
+//
// ubc_check is programmatically generated and the unavoidable bitconditions have been hardcoded
// a directly verifiable version named ubc_check_verify can be found in ubc_check_verify.c
// ubc_check has been verified against ubc_check_verify using the 'ubc_check_test' program in the tools section
+*/
#include <stdint.h>
#include "ubc_check.h"
@@ -58,7 +60,7 @@
static const uint32_t DV_II_55_0_bit = (uint32_t)(1) << 30;
static const uint32_t DV_II_56_0_bit = (uint32_t)(1) << 31;
-dv_info_t sha1_dvs[] =
+dv_info_t sha1_dvs[] =
{
{1,43,0,58,0,0, { 0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161,0x80000599 } }
, {1,44,0,58,0,1, { 0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161 } }
diff --git a/src/hash/sha1dc/ubc_check.h b/src/hash/sha1dc/ubc_check.h
index 27285bd..b349bed 100644
--- a/src/hash/sha1dc/ubc_check.h
+++ b/src/hash/sha1dc/ubc_check.h
@@ -5,6 +5,7 @@
* https://opensource.org/licenses/MIT
***/
+/*
// this file was generated by the 'parse_bitrel' program in the tools section
// using the data files from directory 'tools/data/3565'
//
@@ -17,10 +18,15 @@
// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs
// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met
// thus one needs to do the recompression check for each DV that has its bit set
+*/
#ifndef UBC_CHECK_H
#define UBC_CHECK_H
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#include <stdint.h>
#define DVMASKSIZE 1
@@ -31,5 +37,10 @@
#define DOSTORESTATE58
#define DOSTORESTATE65
+#define CHECK_DVMASK(_DVMASK) (0 != _DVMASK[0])
-#endif // UBC_CHECK_H
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* UBC_CHECK_H */
diff --git a/src/odb.c b/src/odb.c
index cf321f5..b66324f 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -31,6 +31,8 @@
#define GIT_ALTERNATES_MAX_DEPTH 5
+bool git_odb__strict_hash_verification = true;
+
typedef struct
{
git_odb_backend *backend;
@@ -998,7 +1000,9 @@
size_t i;
git_rawobj raw;
git_odb_object *object;
+ git_oid hashed;
bool found = false;
+ int error = 0;
if (!only_refreshed && odb_read_hardcoded(&raw, id) == 0)
found = true;
@@ -1011,7 +1015,7 @@
continue;
if (b->read != NULL) {
- int error = b->read(&raw.data, &raw.len, &raw.type, b, id);
+ error = b->read(&raw.data, &raw.len, &raw.type, b, id);
if (error == GIT_PASSTHROUGH || error == GIT_ENOTFOUND)
continue;
@@ -1025,12 +1029,26 @@
if (!found)
return GIT_ENOTFOUND;
+ if (git_odb__strict_hash_verification) {
+ if ((error = git_odb_hash(&hashed, raw.data, raw.len, raw.type)) < 0)
+ goto out;
+
+ if (!git_oid_equal(id, &hashed)) {
+ error = git_odb__error_mismatch(id, &hashed);
+ goto out;
+ }
+ }
+
giterr_clear();
if ((object = odb_object__alloc(id, &raw)) == NULL)
- return -1;
+ goto out;
*out = git_cache_store_raw(odb_cache(db), object);
- return 0;
+
+out:
+ if (error)
+ git__free(raw.data);
+ return error;
}
int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
@@ -1081,9 +1099,9 @@
const git_oid *key, size_t len, bool only_refreshed)
{
size_t i;
- int error = GIT_ENOTFOUND;
+ int error = 0;
git_oid found_full_oid = {{0}};
- git_rawobj raw;
+ git_rawobj raw = {0};
void *data = NULL;
bool found = false;
git_odb_object *object;
@@ -1102,14 +1120,22 @@
continue;
if (error)
- return error;
+ goto out;
git__free(data);
data = raw.data;
if (found && git_oid__cmp(&full_oid, &found_full_oid)) {
- git__free(raw.data);
- return git_odb__error_ambiguous("multiple matches for prefix");
+ git_buf buf = GIT_BUF_INIT;
+
+ git_buf_printf(&buf, "multiple matches for prefix: %s",
+ git_oid_tostr_s(&full_oid));
+ git_buf_printf(&buf, " %s",
+ git_oid_tostr_s(&found_full_oid));
+
+ error = git_odb__error_ambiguous(buf.ptr);
+ git_buf_free(&buf);
+ goto out;
}
found_full_oid = full_oid;
@@ -1120,11 +1146,28 @@
if (!found)
return GIT_ENOTFOUND;
+ if (git_odb__strict_hash_verification) {
+ git_oid hash;
+
+ if ((error = git_odb_hash(&hash, raw.data, raw.len, raw.type)) < 0)
+ goto out;
+
+ if (!git_oid_equal(&found_full_oid, &hash)) {
+ error = git_odb__error_mismatch(&found_full_oid, &hash);
+ goto out;
+ }
+ }
+
if ((object = odb_object__alloc(&found_full_oid, &raw)) == NULL)
- return -1;
+ goto out;
*out = git_cache_store_raw(odb_cache(db), object);
- return 0;
+
+out:
+ if (error)
+ git__free(raw.data);
+
+ return error;
}
int git_odb_read_prefix(
@@ -1283,9 +1326,9 @@
{
giterr_set(GITERR_ODB,
"cannot %s - "
- "Invalid length. %"PRIuZ" was expected. The "
- "total size of the received chunks amounts to %"PRIuZ".",
- action, stream->declared_size, stream->received_bytes);
+ "Invalid length. %"PRIdZ" was expected. The "
+ "total size of the received chunks amounts to %"PRIdZ".",
+ action, stream->declared_size, stream->received_bytes);
return -1;
}
@@ -1411,6 +1454,19 @@
return 0;
}
+int git_odb__error_mismatch(const git_oid *expected, const git_oid *actual)
+{
+ char expected_oid[GIT_OID_HEXSZ + 1], actual_oid[GIT_OID_HEXSZ + 1];
+
+ git_oid_tostr(expected_oid, sizeof(expected_oid), expected);
+ git_oid_tostr(actual_oid, sizeof(actual_oid), actual);
+
+ giterr_set(GITERR_ODB, "object hash mismatch - expected %s but got %s",
+ expected_oid, actual_oid);
+
+ return GIT_EMISMATCH;
+}
+
int git_odb__error_notfound(
const char *message, const git_oid *oid, size_t oid_len)
{
diff --git a/src/odb.h b/src/odb.h
index 4f548bb..61d687a 100644
--- a/src/odb.h
+++ b/src/odb.h
@@ -20,6 +20,8 @@
#define GIT_OBJECT_DIR_MODE 0777
#define GIT_OBJECT_FILE_MODE 0444
+extern bool git_odb__strict_hash_verification;
+
/* DO NOT EXPORT */
typedef struct {
void *data; /**< Raw, decompressed object data. */
@@ -96,6 +98,12 @@
*/
int git_odb__hashlink(git_oid *out, const char *path);
+/**
+ * Generate a GIT_EMISMATCH error for the ODB.
+ */
+int git_odb__error_mismatch(
+ const git_oid *expected, const git_oid *actual);
+
/*
* Generate a GIT_ENOTFOUND error for the ODB.
*/
diff --git a/src/odb_loose.c b/src/odb_loose.c
index e14af4f..a97ac25 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -205,6 +205,11 @@
return inflate(s, 0);
}
+static void abort_inflate(z_stream *s)
+{
+ inflateEnd(s);
+}
+
static int finish_inflate(z_stream *s)
{
int status = Z_OK;
@@ -367,6 +372,7 @@
(used = get_object_header(&hdr, head)) == 0 ||
!git_object_typeisloose(hdr.type))
{
+ abort_inflate(&zs);
giterr_set(GITERR_ODB, "failed to inflate disk object");
return -1;
}
diff --git a/src/openssl_stream.c b/src/openssl_stream.c
index c0a9c3c..841dcce 100644
--- a/src/openssl_stream.c
+++ b/src/openssl_stream.c
@@ -37,7 +37,7 @@
#define GIT_SSL_DEFAULT_CIPHERS "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
-#ifdef GIT_THREADS
+#if defined(GIT_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
static git_mutex *openssl_locks;
@@ -70,7 +70,7 @@
git__free(openssl_locks);
}
-#endif /* GIT_THREADS */
+#endif /* GIT_THREADS && OPENSSL_VERSION_NUMBER < 0x10100000L */
static BIO_METHOD *git_stream_bio_method;
static int init_bio_method(void);
@@ -103,8 +103,13 @@
ssl_opts |= SSL_OP_NO_COMPRESSION;
#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
+#else
+ OPENSSL_init_ssl(0, NULL);
+#endif
+
/*
* Load SSLv{2,3} and TLSv1 so that we can talk with servers
* which use the SSL hellos, which are often used for
@@ -146,7 +151,7 @@
int git_openssl_set_locking(void)
{
-#ifdef GIT_THREADS
+#if defined(GIT_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
int num_locks, i;
num_locks = CRYPTO_num_locks();
@@ -163,6 +168,8 @@
CRYPTO_set_locking_callback(openssl_locking_function);
git__on_shutdown(shutdown_ssl_locking);
return 0;
+#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
+ return 0;
#else
giterr_set(GITERR_THREAD, "libgit2 was not built with threads");
return -1;
diff --git a/src/path.c b/src/path.c
index c3d3eb1..b7205a6 100644
--- a/src/path.c
+++ b/src/path.c
@@ -700,7 +700,8 @@
return false;
/* save excursion */
- git_buf_joinpath(dir, dir->ptr, sub);
+ if (git_buf_joinpath(dir, dir->ptr, sub) < 0)
+ return false;
result = predicate(dir->ptr);
@@ -825,8 +826,8 @@
int git_path_apply_relative(git_buf *target, const char *relpath)
{
- git_buf_joinpath(target, git_buf_cstr(target), relpath);
- return git_path_resolve_relative(target, 0);
+ return git_buf_joinpath(target, git_buf_cstr(target), relpath) ||
+ git_path_resolve_relative(target, 0);
}
int git_path_cmp(
diff --git a/src/posix.h b/src/posix.h
index bd5a98e..d26371b 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -24,6 +24,10 @@
#define _S_IFLNK S_IFLNK
#endif
+#ifndef S_IWUSR
+#define S_IWUSR 00200
+#endif
+
#ifndef S_IXUSR
#define S_IXUSR 00100
#endif
diff --git a/src/refs.c b/src/refs.c
index 0837dc4..632a529 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -249,6 +249,40 @@
return 0;
}
+int git_reference__read_head(
+ git_reference **out,
+ git_repository *repo,
+ const char *path)
+{
+ git_buf reference = GIT_BUF_INIT;
+ char *name = NULL;
+ int error;
+
+ if ((error = git_futils_readbuffer(&reference, path)) < 0)
+ goto out;
+ git_buf_rtrim(&reference);
+
+ if (git__strncmp(reference.ptr, GIT_SYMREF, strlen(GIT_SYMREF)) == 0) {
+ git_buf_consume(&reference, reference.ptr + strlen(GIT_SYMREF));
+
+ name = git_path_basename(path);
+
+ if ((*out = git_reference__alloc_symbolic(name, reference.ptr)) == NULL) {
+ error = -1;
+ goto out;
+ }
+ } else {
+ if ((error = git_reference_lookup(out, repo, reference.ptr)) < 0)
+ goto out;
+ }
+
+out:
+ git__free(name);
+ git_buf_free(&reference);
+
+ return error;
+}
+
int git_reference_dwim(git_reference **out, git_repository *repo, const char *refname)
{
int error = 0, i;
@@ -580,19 +614,52 @@
out, ref->db->repo, ref->name, target, 1, ref->target.symbolic, log_message);
}
+typedef struct {
+ const char *old_name;
+ git_refname_t new_name;
+} rename_cb_data;
+
+static int update_wt_heads(git_repository *repo, const char *path, void *payload)
+{
+ rename_cb_data *data = (rename_cb_data *) payload;
+ git_reference *head;
+ char *gitdir = NULL;
+ int error = 0;
+
+ if (git_reference__read_head(&head, repo, path) < 0 ||
+ git_reference_type(head) != GIT_REF_SYMBOLIC ||
+ git__strcmp(head->target.symbolic, data->old_name) != 0 ||
+ (gitdir = git_path_dirname(path)) == NULL)
+ goto out;
+
+ /* Update HEAD it was pointing to the reference being renamed */
+ if ((error = git_repository_create_head(gitdir, data->new_name)) < 0) {
+ giterr_set(GITERR_REFERENCE, "failed to update HEAD after renaming reference");
+ goto out;
+ }
+
+out:
+ git_reference_free(head);
+ git__free(gitdir);
+
+ return error;
+}
+
static int reference__rename(git_reference **out, git_reference *ref, const char *new_name, int force,
const git_signature *signature, const char *message)
{
+ git_repository *repo;
git_refname_t normalized;
bool should_head_be_updated = false;
int error = 0;
assert(ref && new_name && signature);
- if ((error = reference_normalize_for_repo(
- normalized, git_reference_owner(ref), new_name, true)) < 0)
- return error;
+ repo = git_reference_owner(ref);
+ if ((error = reference_normalize_for_repo(
+ normalized, repo, new_name, true)) < 0)
+ return error;
/* Check if we have to update HEAD. */
if ((error = git_branch_is_head(ref)) < 0)
@@ -603,14 +670,18 @@
if ((error = git_refdb_rename(out, ref->db, ref->name, normalized, force, signature, message)) < 0)
return error;
- /* Update HEAD it was pointing to the reference being renamed */
- if (should_head_be_updated &&
- (error = git_repository_set_head(ref->db->repo, normalized)) < 0) {
- giterr_set(GITERR_REFERENCE, "failed to update HEAD after renaming reference");
- return error;
+ /* Update HEAD if it was pointing to the reference being renamed */
+ if (should_head_be_updated) {
+ error = git_repository_set_head(ref->db->repo, normalized);
+ } else {
+ rename_cb_data payload;
+ payload.old_name = ref->name;
+ memcpy(&payload.new_name, &normalized, sizeof(normalized));
+
+ error = git_repository_foreach_head(repo, update_wt_heads, &payload);
}
- return 0;
+ return error;
}
diff --git a/src/refs.h b/src/refs.h
index 80e655a..0c90db3 100644
--- a/src/refs.h
+++ b/src/refs.h
@@ -107,6 +107,20 @@
const char *name,
int max_deref);
+/**
+ * Read reference from a file.
+ *
+ * This function will read in the file at `path`. If it is a
+ * symref, it will return a new unresolved symbolic reference
+ * 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.
+ */
+int git_reference__read_head(
+ git_reference **out,
+ git_repository *repo,
+ const char *path);
+
int git_reference__log_signature(git_signature **out, git_repository *repo);
/** Update a reference after a commit. */
diff --git a/src/remote.c b/src/remote.c
index d3132f7..bd8b3cf 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -192,7 +192,7 @@
static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
{
git_remote *remote;
- git_config *config = NULL;
+ git_config *config_ro = NULL, *config_rw;
git_buf canonical_url = GIT_BUF_INIT;
git_buf var = GIT_BUF_INIT;
int error = -1;
@@ -200,7 +200,7 @@
/* name is optional */
assert(out && repo && url);
- if ((error = git_repository_config__weakptr(&config, repo)) < 0)
+ if ((error = git_repository_config_snapshot(&config_ro, repo)) < 0)
return error;
remote = git__calloc(1, sizeof(git_remote));
@@ -212,7 +212,8 @@
(error = canonicalize_url(&canonical_url, url)) < 0)
goto on_error;
- remote->url = apply_insteadof(repo->_config, canonical_url.ptr, GIT_DIRECTION_FETCH);
+ remote->url = apply_insteadof(config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH);
+ GITERR_CHECK_ALLOC(remote->url);
if (name != NULL) {
remote->name = git__strdup(name);
@@ -221,7 +222,8 @@
if ((error = git_buf_printf(&var, CONFIG_URL_FMT, name)) < 0)
goto on_error;
- if ((error = git_config_set_string(config, var.ptr, canonical_url.ptr)) < 0)
+ if ((error = git_repository_config__weakptr(&config_rw, repo)) < 0 ||
+ (error = git_config_set_string(config_rw, var.ptr, canonical_url.ptr)) < 0)
goto on_error;
}
@@ -233,10 +235,7 @@
if (name && (error = write_add_refspec(repo, name, fetch, true)) < 0)
goto on_error;
- if ((error = git_repository_config_snapshot(&config, repo)) < 0)
- goto on_error;
-
- if ((error = lookup_remote_prune_config(remote, config, name)) < 0)
+ if ((error = lookup_remote_prune_config(remote, config_ro, name)) < 0)
goto on_error;
/* Move the data over to where the matching functions can find them */
@@ -260,7 +259,7 @@
if (error)
git_remote_free(remote);
- git_config_free(config);
+ git_config_free(config_ro);
git_buf_free(&canonical_url);
git_buf_free(&var);
return error;
@@ -2412,7 +2411,7 @@
proxy = &opts->proxy_opts;
}
- assert(remote && refspecs);
+ assert(remote);
if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, proxy, custom_headers)) < 0)
return error;
diff --git a/src/repository.c b/src/repository.c
index 425ef79..48e2706 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -2063,47 +2063,27 @@
return exists;
}
-static int read_worktree_head(git_buf *out, git_repository *repo, const char *name)
+static int get_worktree_file_path(git_buf *out, git_repository *repo, const char *worktree, const char *file)
{
- git_buf path = GIT_BUF_INIT;
- int err;
-
- assert(out && repo && name);
-
git_buf_clear(out);
-
- if ((err = git_buf_printf(&path, "%s/worktrees/%s/HEAD", repo->commondir, name)) < 0)
- goto out;
- if (!git_path_exists(path.ptr))
- {
- err = -1;
- goto out;
- }
-
- if ((err = git_futils_readbuffer(out, path.ptr)) < 0)
- goto out;
- git_buf_rtrim(out);
-
-out:
- git_buf_free(&path);
-
- return err;
+ return git_buf_printf(out, "%s/worktrees/%s/%s", repo->commondir, worktree, file);
}
int git_repository_head_detached_for_worktree(git_repository *repo, const char *name)
{
- git_buf buf = GIT_BUF_INIT;
- int ret;
+ git_reference *ref = NULL;
+ int error;
assert(repo && name);
- if (read_worktree_head(&buf, repo, name) < 0)
- return -1;
+ if ((error = git_repository_head_for_worktree(&ref, repo, name)) < 0)
+ goto out;
- ret = git__strncmp(buf.ptr, GIT_SYMREF, strlen(GIT_SYMREF)) != 0;
- git_buf_free(&buf);
+ error = (git_reference_type(ref) != GIT_REF_SYMBOLIC);
+out:
+ git_reference_free(ref);
- return ret;
+ return error;
}
int git_repository_head(git_reference **head_out, git_repository *repo)
@@ -2127,44 +2107,67 @@
int git_repository_head_for_worktree(git_reference **out, git_repository *repo, const char *name)
{
- git_buf buf = GIT_BUF_INIT;
- git_reference *head;
- int err;
+ git_buf path = GIT_BUF_INIT;
+ git_reference *head = NULL;
+ int error;
assert(out && repo && name);
*out = NULL;
- if (git_repository_head_detached_for_worktree(repo, name))
- return -1;
- if ((err = read_worktree_head(&buf, repo, name)) < 0)
+ if ((error = get_worktree_file_path(&path, repo, name, GIT_HEAD_FILE)) < 0 ||
+ (error = git_reference__read_head(&head, repo, path.ptr)) < 0)
goto out;
- /* We can only resolve symbolic references */
- if (git__strncmp(buf.ptr, GIT_SYMREF, strlen(GIT_SYMREF)))
- {
- err = -1;
- goto out;
- }
- git_buf_consume(&buf, buf.ptr + strlen(GIT_SYMREF));
+ if (git_reference_type(head) != GIT_REF_OID) {
+ git_reference *resolved;
- if ((err = git_reference_lookup(&head, repo, buf.ptr)) < 0)
- goto out;
- if (git_reference_type(head) == GIT_REF_OID)
- {
- *out = head;
- err = 0;
- goto out;
+ error = git_reference_lookup_resolved(&resolved, repo, git_reference_symbolic_target(head), -1);
+ git_reference_free(head);
+ head = resolved;
}
- err = git_reference_lookup_resolved(
- out, repo, git_reference_symbolic_target(head), -1);
- git_reference_free(head);
+ *out = head;
out:
- git_buf_free(&buf);
+ if (error)
+ git_reference_free(head);
- return err;
+ git_buf_free(&path);
+
+ return error;
+}
+
+int git_repository_foreach_head(git_repository *repo, git_repository_foreach_head_cb cb, void *payload)
+{
+ git_strarray worktrees = GIT_VECTOR_INIT;
+ git_buf path = GIT_BUF_INIT;
+ int error;
+ size_t i;
+
+ /* Execute callback for HEAD of commondir */
+ if ((error = git_buf_joinpath(&path, repo->commondir, GIT_HEAD_FILE)) < 0 ||
+ (error = cb(repo, path.ptr, payload) != 0))
+ goto out;
+
+ if ((error = git_worktree_list(&worktrees, repo)) < 0) {
+ error = 0;
+ goto out;
+ }
+
+ /* Execute callback for all worktree HEADs */
+ for (i = 0; i < worktrees.count; i++) {
+ if (get_worktree_file_path(&path, repo, worktrees.strings[i], GIT_HEAD_FILE) < 0)
+ continue;
+
+ if ((error = cb(repo, path.ptr, payload)) != 0)
+ goto out;
+ }
+
+out:
+ git_buf_free(&path);
+ git_strarray_free(&worktrees);
+ return error;
}
int git_repository_head_unborn(git_repository *repo)
@@ -2529,7 +2532,9 @@
git_buf_puts(out, " to ");
- if (git_reference__is_branch(new))
+ if (git_reference__is_branch(new) ||
+ git_reference__is_tag(new) ||
+ git_reference__is_remote(new))
git_buf_puts(out, git_reference__shorthand(new));
else
git_buf_puts(out, new);
@@ -2540,6 +2545,41 @@
return 0;
}
+static int detach(git_repository *repo, const git_oid *id, const char *new)
+{
+ int error;
+ git_buf log_message = GIT_BUF_INIT;
+ git_object *object = NULL, *peeled = NULL;
+ git_reference *new_head = NULL, *current = NULL;
+
+ assert(repo && id);
+
+ if ((error = git_reference_lookup(¤t, repo, GIT_HEAD_FILE)) < 0)
+ return error;
+
+ if ((error = git_object_lookup(&object, repo, id, GIT_OBJ_ANY)) < 0)
+ goto cleanup;
+
+ if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0)
+ goto cleanup;
+
+ if (new == NULL)
+ new = git_oid_tostr_s(git_object_id(peeled));
+
+ if ((error = checkout_message(&log_message, current, new)) < 0)
+ goto cleanup;
+
+ error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, git_buf_cstr(&log_message));
+
+cleanup:
+ git_buf_free(&log_message);
+ git_object_free(object);
+ git_object_free(peeled);
+ git_reference_free(current);
+ git_reference_free(new_head);
+ return error;
+}
+
int git_repository_set_head(
git_repository* repo,
const char* refname)
@@ -2562,6 +2602,8 @@
if (ref && current->type == GIT_REF_SYMBOLIC && git__strcmp(current->target.symbolic, ref->name) &&
git_reference_is_branch(ref) && git_branch_is_checked_out(ref)) {
+ giterr_set(GITERR_REPOSITORY, "cannot set HEAD to reference '%s' as it is the current HEAD "
+ "of a linked repository.", git_reference_name(ref));
error = -1;
goto cleanup;
}
@@ -2571,7 +2613,8 @@
error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE,
git_reference_name(ref), true, git_buf_cstr(&log_message));
} else {
- error = git_repository_set_head_detached(repo, git_reference_target(ref));
+ error = detach(repo, git_reference_target(ref),
+ git_reference_is_tag(ref) || git_reference_is_remote(ref) ? refname : NULL);
}
} else if (git_reference__is_branch(refname)) {
error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, refname,
@@ -2586,41 +2629,6 @@
return error;
}
-static int detach(git_repository *repo, const git_oid *id, const char *from)
-{
- int error;
- git_buf log_message = GIT_BUF_INIT;
- git_object *object = NULL, *peeled = NULL;
- git_reference *new_head = NULL, *current = NULL;
-
- assert(repo && id);
-
- if ((error = git_reference_lookup(¤t, repo, GIT_HEAD_FILE)) < 0)
- return error;
-
- if ((error = git_object_lookup(&object, repo, id, GIT_OBJ_ANY)) < 0)
- goto cleanup;
-
- if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0)
- goto cleanup;
-
- if (from == NULL)
- from = git_oid_tostr_s(git_object_id(peeled));
-
- if ((error = checkout_message(&log_message, current, from)) < 0)
- goto cleanup;
-
- error = git_reference_create(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), true, git_buf_cstr(&log_message));
-
-cleanup:
- git_buf_free(&log_message);
- git_object_free(object);
- git_object_free(peeled);
- git_reference_free(current);
- git_reference_free(new_head);
- return error;
-}
-
int git_repository_set_head_detached(
git_repository* repo,
const git_oid* commitish)
diff --git a/src/repository.h b/src/repository.h
index 33adfa6..f922d00 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -160,6 +160,26 @@
int git_repository_create_head(const char *git_dir, const char *ref_name);
/*
+ * Called for each HEAD.
+ *
+ * Can return either 0, causing the iteration over HEADs to
+ * continue, or a non-0 value causing the iteration to abort. The
+ * return value is passed back to the caller of
+ * `git_repository_foreach_head`
+ */
+typedef int (*git_repository_foreach_head_cb)(git_repository *repo, const char *path, void *payload);
+
+/*
+ * Iterate over repository and all worktree HEADs.
+ *
+ * This function will be called for the repository HEAD and for
+ * all HEADS of linked worktrees. For each HEAD, the callback is
+ * executed with the given payload. The return value equals the
+ * return value of the last executed callback function.
+ */
+int git_repository_foreach_head(git_repository *repo, git_repository_foreach_head_cb cb, void *payload);
+
+/*
* Weak pointers to repository internals.
*
* The returned pointers do not need to be freed. Do not keep
diff --git a/src/revparse.c b/src/revparse.c
index d5511b4..fd6bd1e 100644
--- a/src/revparse.c
+++ b/src/revparse.c
@@ -892,6 +892,17 @@
const char *rstr;
revspec->flags = GIT_REVPARSE_RANGE;
+ /*
+ * Following git.git, don't allow '..' because it makes command line
+ * arguments which can be either paths or revisions ambiguous when the
+ * path is almost certainly intended. The empty range '...' is still
+ * allowed.
+ */
+ if (!git__strcmp(spec, "..")) {
+ giterr_set(GITERR_INVALID, "Invalid pattern '..'");
+ return GIT_EINVALIDSPEC;
+ }
+
lstr = git__substrdup(spec, dotdot - spec);
rstr = dotdot + 2;
if (dotdot[2] == '.') {
@@ -899,9 +910,17 @@
rstr++;
}
- error = git_revparse_single(&revspec->from, repo, lstr);
- if (!error)
- error = git_revparse_single(&revspec->to, repo, rstr);
+ error = git_revparse_single(
+ &revspec->from,
+ repo,
+ *lstr == '\0' ? "HEAD" : lstr);
+
+ if (!error) {
+ error = git_revparse_single(
+ &revspec->to,
+ repo,
+ *rstr == '\0' ? "HEAD" : rstr);
+ }
git__free((void*)lstr);
} else {
diff --git a/src/settings.c b/src/settings.c
index 24e549e..25c5aae 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -15,6 +15,7 @@
#include "cache.h"
#include "global.h"
#include "object.h"
+#include "odb.h"
#include "refs.h"
#include "transports/smart.h"
@@ -31,7 +32,7 @@
#ifdef GIT_THREADS
| GIT_FEATURE_THREADS
#endif
-#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT)
+#ifdef GIT_HTTPS
| GIT_FEATURE_HTTPS
#endif
#if defined(GIT_SSH)
@@ -231,6 +232,22 @@
git_object__synchronous_writing = (va_arg(ap, int) != 0);
break;
+ case GIT_OPT_GET_WINDOWS_SHAREMODE:
+#ifdef GIT_WIN32
+ *(va_arg(ap, unsigned long *)) = git_win32__createfile_sharemode;
+#endif
+ break;
+
+ case GIT_OPT_SET_WINDOWS_SHAREMODE:
+#ifdef GIT_WIN32
+ git_win32__createfile_sharemode = va_arg(ap, unsigned long);
+#endif
+ break;
+
+ case GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION:
+ git_odb__strict_hash_verification = (va_arg(ap, int) != 0);
+ break;
+
default:
giterr_set(GITERR_INVALID, "invalid option key");
error = -1;
diff --git a/src/signature.c b/src/signature.c
index e792a52..a56b8a2 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -228,8 +228,11 @@
const char *time_start = email_end + 2;
const char *time_end;
- if (git__strtol64(&sig->when.time, time_start, &time_end, 10) < 0)
+ if (git__strtol64(&sig->when.time, time_start, &time_end, 10) < 0) {
+ git__free(sig->name);
+ git__free(sig->email);
return signature_error("invalid Unix timestamp");
+ }
/* do we have a timezone? */
if (time_end + 1 < buffer_end) {
diff --git a/src/socket_stream.c b/src/socket_stream.c
index fca4117..c0a1684 100644
--- a/src/socket_stream.c
+++ b/src/socket_stream.c
@@ -106,10 +106,8 @@
for (p = info; p != NULL; p = p->ai_next) {
s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
- if (s == INVALID_SOCKET) {
- net_set_error("error creating socket");
- break;
- }
+ if (s == INVALID_SOCKET)
+ continue;
if (connect(s, p->ai_addr, (socklen_t)p->ai_addrlen) == 0)
break;
diff --git a/src/transports/http.c b/src/transports/http.c
index 949e857..cb4a6d0 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -575,6 +575,9 @@
if ((error = git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &url)) < 0)
return error;
+ opts.credentials = t->owner->proxy.credentials;
+ opts.certificate_check = t->owner->proxy.certificate_check;
+ opts.payload = t->owner->proxy.payload;
opts.type = GIT_PROXY_SPECIFIED;
opts.url = url;
error = git_stream_set_proxy(t->io, &opts);
diff --git a/src/transports/smart.c b/src/transports/smart.c
index e4aa26d..a96fdf6 100644
--- a/src/transports/smart.c
+++ b/src/transports/smart.c
@@ -472,6 +472,12 @@
return t->cred_acquire_cb(out, t->url, user, methods, t->cred_acquire_payload);
}
+int git_transport_smart_proxy_options(git_proxy_options *out, git_transport *transport)
+{
+ transport_smart *t = (transport_smart *) transport;
+ return git_proxy_options_dup(out, &t->proxy);
+}
+
int git_transport_smart(git_transport **out, git_remote *owner, void *param)
{
transport_smart *t;
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index 44d02e5..4c55e3f 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -9,6 +9,7 @@
#include <libssh2.h>
#endif
+#include "global.h"
#include "git2.h"
#include "buffer.h"
#include "netops.h"
@@ -893,11 +894,22 @@
#endif
}
+#ifdef GIT_SSH
+static void shutdown_ssh(void)
+{
+ libssh2_exit();
+}
+#endif
+
int git_transport_ssh_global_init(void)
{
#ifdef GIT_SSH
+ if (libssh2_init(0) < 0) {
+ giterr_set(GITERR_SSH, "unable to initialize libssh2");
+ return -1;
+ }
- libssh2_init(0);
+ git__on_shutdown(shutdown_ssh);
return 0;
#else
diff --git a/src/tree.c b/src/tree.c
index dba2060..6b1d1b2 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -818,7 +818,7 @@
size_t i, entrycount;
git_odb *odb;
git_tree_entry *entry;
- git_vector entries;
+ git_vector entries = GIT_VECTOR_INIT;
assert(bld);
assert(tree);
@@ -826,35 +826,37 @@
git_buf_clear(tree);
entrycount = git_strmap_num_entries(bld->map);
- if (git_vector_init(&entries, entrycount, entry_sort_cmp) < 0)
- return -1;
+ if ((error = git_vector_init(&entries, entrycount, entry_sort_cmp)) < 0)
+ goto out;
if (tree->asize == 0 &&
- (error = git_buf_grow(tree, entrycount * 72)) < 0)
- return error;
+ (error = git_buf_grow(tree, entrycount * 72)) < 0)
+ goto out;
git_strmap_foreach_value(bld->map, entry, {
- if (git_vector_insert(&entries, entry) < 0)
- return -1;
+ if ((error = git_vector_insert(&entries, entry)) < 0)
+ goto out;
});
git_vector_sort(&entries);
for (i = 0; i < entries.length && !error; ++i) {
- git_tree_entry *entry = git_vector_get(&entries, i);
+ entry = git_vector_get(&entries, i);
git_buf_printf(tree, "%o ", entry->attr);
git_buf_put(tree, entry->filename, entry->filename_len + 1);
git_buf_put(tree, (char *)entry->oid->id, GIT_OID_RAWSZ);
- if (git_buf_oom(tree))
+ if (git_buf_oom(tree)) {
error = -1;
+ goto out;
+ }
}
- if (!error &&
- !(error = git_repository_odb__weakptr(&odb, bld->repo)))
+ if ((error = git_repository_odb__weakptr(&odb, bld->repo)) == 0)
error = git_odb_write(oid, odb, tree->ptr, tree->size, GIT_OBJ_TREE);
+out:
git_vector_free(&entries);
return error;
diff --git a/src/win32/posix.h b/src/win32/posix.h
index 73705fb..64769ec 100644
--- a/src/win32/posix.h
+++ b/src/win32/posix.h
@@ -14,6 +14,9 @@
#include "utf-conv.h"
#include "dir.h"
+extern unsigned long git_win32__createfile_sharemode;
+extern int git_win32__retries;
+
typedef SOCKET GIT_SOCKET;
#define p_lseek(f,n,w) _lseeki64(f, n, w)
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index 5172627..e4fe414 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -26,15 +26,6 @@
#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
#endif
-/* Options which we always provide to _wopen.
- *
- * _O_BINARY - Raw access; no translation of CR or LF characters
- * _O_NOINHERIT - Do not mark the created handle as inheritable by child processes.
- * The Windows default is 'not inheritable', but the CRT's default (following
- * POSIX convention) is 'inheritable'. We have no desire for our handles to be
- * inheritable on Windows, so specify the flag to get default behavior back. */
-#define STANDARD_OPEN_FLAGS (_O_BINARY | _O_NOINHERIT)
-
/* Allowable mode bits on Win32. Using mode bits that are not supported on
* Win32 (eg S_IRWXU) is generally ignored, but Wine warns loudly about it
* so we simply remove them.
@@ -44,6 +35,164 @@
/* GetFinalPathNameByHandleW signature */
typedef DWORD(WINAPI *PFGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD);
+unsigned long git_win32__createfile_sharemode =
+ FILE_SHARE_READ | FILE_SHARE_WRITE;
+int git_win32__retries = 10;
+
+GIT_INLINE(void) set_errno(void)
+{
+ switch (GetLastError()) {
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_DRIVE:
+ case ERROR_NO_MORE_FILES:
+ case ERROR_BAD_NETPATH:
+ case ERROR_BAD_NET_NAME:
+ case ERROR_BAD_PATHNAME:
+ case ERROR_FILENAME_EXCED_RANGE:
+ errno = ENOENT;
+ break;
+ case ERROR_BAD_ENVIRONMENT:
+ errno = E2BIG;
+ break;
+ case ERROR_BAD_FORMAT:
+ case ERROR_INVALID_STARTING_CODESEG:
+ case ERROR_INVALID_STACKSEG:
+ case ERROR_INVALID_MODULETYPE:
+ case ERROR_INVALID_EXE_SIGNATURE:
+ case ERROR_EXE_MARKED_INVALID:
+ case ERROR_BAD_EXE_FORMAT:
+ case ERROR_ITERATED_DATA_EXCEEDS_64k:
+ case ERROR_INVALID_MINALLOCSIZE:
+ case ERROR_DYNLINK_FROM_INVALID_RING:
+ case ERROR_IOPL_NOT_ENABLED:
+ case ERROR_INVALID_SEGDPL:
+ case ERROR_AUTODATASEG_EXCEEDS_64k:
+ case ERROR_RING2SEG_MUST_BE_MOVABLE:
+ case ERROR_RELOC_CHAIN_XEEDS_SEGLIM:
+ case ERROR_INFLOOP_IN_RELOC_CHAIN:
+ errno = ENOEXEC;
+ break;
+ case ERROR_INVALID_HANDLE:
+ case ERROR_INVALID_TARGET_HANDLE:
+ case ERROR_DIRECT_ACCESS_HANDLE:
+ errno = EBADF;
+ break;
+ case ERROR_WAIT_NO_CHILDREN:
+ case ERROR_CHILD_NOT_COMPLETE:
+ errno = ECHILD;
+ break;
+ case ERROR_NO_PROC_SLOTS:
+ case ERROR_MAX_THRDS_REACHED:
+ case ERROR_NESTING_NOT_ALLOWED:
+ errno = EAGAIN;
+ break;
+ case ERROR_ARENA_TRASHED:
+ case ERROR_NOT_ENOUGH_MEMORY:
+ case ERROR_INVALID_BLOCK:
+ case ERROR_NOT_ENOUGH_QUOTA:
+ errno = ENOMEM;
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_CURRENT_DIRECTORY:
+ case ERROR_WRITE_PROTECT:
+ case ERROR_BAD_UNIT:
+ case ERROR_NOT_READY:
+ case ERROR_BAD_COMMAND:
+ case ERROR_CRC:
+ case ERROR_BAD_LENGTH:
+ case ERROR_SEEK:
+ case ERROR_NOT_DOS_DISK:
+ case ERROR_SECTOR_NOT_FOUND:
+ case ERROR_OUT_OF_PAPER:
+ case ERROR_WRITE_FAULT:
+ case ERROR_READ_FAULT:
+ case ERROR_GEN_FAILURE:
+ case ERROR_SHARING_VIOLATION:
+ case ERROR_LOCK_VIOLATION:
+ case ERROR_WRONG_DISK:
+ case ERROR_SHARING_BUFFER_EXCEEDED:
+ case ERROR_NETWORK_ACCESS_DENIED:
+ case ERROR_CANNOT_MAKE:
+ case ERROR_FAIL_I24:
+ case ERROR_DRIVE_LOCKED:
+ case ERROR_SEEK_ON_DEVICE:
+ case ERROR_NOT_LOCKED:
+ case ERROR_LOCK_FAILED:
+ errno = EACCES;
+ break;
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
+ errno = EEXIST;
+ break;
+ case ERROR_NOT_SAME_DEVICE:
+ errno = EXDEV;
+ break;
+ case ERROR_INVALID_FUNCTION:
+ case ERROR_INVALID_ACCESS:
+ case ERROR_INVALID_DATA:
+ case ERROR_INVALID_PARAMETER:
+ case ERROR_NEGATIVE_SEEK:
+ errno = EINVAL;
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ errno = EMFILE;
+ break;
+ case ERROR_DISK_FULL:
+ errno = ENOSPC;
+ break;
+ case ERROR_BROKEN_PIPE:
+ errno = EPIPE;
+ break;
+ case ERROR_DIR_NOT_EMPTY:
+ errno = ENOTEMPTY;
+ break;
+ default:
+ errno = EINVAL;
+ }
+}
+
+GIT_INLINE(bool) last_error_retryable(void)
+{
+ int os_error = GetLastError();
+
+ return (os_error == ERROR_SHARING_VIOLATION ||
+ os_error == ERROR_ACCESS_DENIED);
+}
+
+#define do_with_retries(fn, remediation) \
+ do { \
+ int __tries, __ret; \
+ for (__tries = 0; __tries < git_win32__retries; __tries++) { \
+ if (__tries && (__ret = (remediation)) != 0) \
+ return __ret; \
+ if ((__ret = (fn)) != GIT_RETRY) \
+ return __ret; \
+ Sleep(5); \
+ } \
+ return -1; \
+ } while (0) \
+
+static int ensure_writable(wchar_t *path)
+{
+ DWORD attrs;
+
+ if ((attrs = GetFileAttributesW(path)) == INVALID_FILE_ATTRIBUTES)
+ goto on_error;
+
+ if ((attrs & FILE_ATTRIBUTE_READONLY) == 0)
+ return 0;
+
+ if (!SetFileAttributesW(path, (attrs & ~FILE_ATTRIBUTE_READONLY)))
+ goto on_error;
+
+ return 0;
+
+on_error:
+ set_errno();
+ return -1;
+}
+
/**
* Truncate or extend file.
*
@@ -89,24 +238,26 @@
return -1;
}
+GIT_INLINE(int) unlink_once(const wchar_t *path)
+{
+ if (DeleteFileW(path))
+ return 0;
+
+ if (last_error_retryable())
+ return GIT_RETRY;
+
+ set_errno();
+ return -1;
+}
+
int p_unlink(const char *path)
{
- git_win32_path buf;
- int error;
+ git_win32_path wpath;
- if (git_win32_path_from_utf8(buf, path) < 0)
+ if (git_win32_path_from_utf8(wpath, path) < 0)
return -1;
- error = _wunlink(buf);
-
- /* If the file could not be deleted because it was
- * read-only, clear the bit and try again */
- if (error == -1 && errno == EACCES) {
- _wchmod(buf, 0666);
- error = _wunlink(buf);
- }
-
- return error;
+ do_with_retries(unlink_once(wpath), ensure_writable(wpath));
}
int p_fsync(int fd)
@@ -212,44 +363,6 @@
return do_lstat(filename, buf, true);
}
-int p_utimes(const char *filename, const struct p_timeval times[2])
-{
- int fd, error;
-
- if ((fd = p_open(filename, O_RDWR)) < 0)
- return fd;
-
- error = p_futimes(fd, times);
-
- close(fd);
- return error;
-}
-
-int p_futimes(int fd, const struct p_timeval times[2])
-{
- HANDLE handle;
- FILETIME atime = {0}, mtime = {0};
-
- if (times == NULL) {
- SYSTEMTIME st;
-
- GetSystemTime(&st);
- SystemTimeToFileTime(&st, &atime);
- SystemTimeToFileTime(&st, &mtime);
- } else {
- git_win32__timeval_to_filetime(&atime, times[0]);
- git_win32__timeval_to_filetime(&mtime, times[1]);
- }
-
- if ((handle = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE)
- return -1;
-
- if (SetFileTime(handle, NULL, &atime, &mtime) == 0)
- return -1;
-
- return 0;
-}
-
int p_readlink(const char *path, char *buf, size_t bufsiz)
{
git_win32_path path_w, target_w;
@@ -282,12 +395,91 @@
return git_futils_fake_symlink(old, new);
}
+struct open_opts {
+ DWORD access;
+ DWORD sharing;
+ SECURITY_ATTRIBUTES security;
+ DWORD creation_disposition;
+ DWORD attributes;
+ int osf_flags;
+};
+
+GIT_INLINE(void) open_opts_from_posix(struct open_opts *opts, int flags, mode_t mode)
+{
+ memset(opts, 0, sizeof(struct open_opts));
+
+ switch (flags & (O_WRONLY | O_RDWR)) {
+ case O_WRONLY:
+ opts->access = GENERIC_WRITE;
+ break;
+ case O_RDWR:
+ opts->access = GENERIC_READ | GENERIC_WRITE;
+ break;
+ default:
+ opts->access = GENERIC_READ;
+ break;
+ }
+
+ opts->sharing = (DWORD)git_win32__createfile_sharemode;
+
+ switch (flags & (O_CREAT | O_TRUNC | O_EXCL)) {
+ case O_CREAT | O_EXCL:
+ case O_CREAT | O_TRUNC | O_EXCL:
+ opts->creation_disposition = CREATE_NEW;
+ break;
+ case O_CREAT | O_TRUNC:
+ opts->creation_disposition = CREATE_ALWAYS;
+ break;
+ case O_TRUNC:
+ opts->creation_disposition = TRUNCATE_EXISTING;
+ break;
+ case O_CREAT:
+ opts->creation_disposition = OPEN_ALWAYS;
+ break;
+ default:
+ opts->creation_disposition = OPEN_EXISTING;
+ break;
+ }
+
+ opts->attributes = ((flags & O_CREAT) && !(mode & S_IWRITE)) ?
+ FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL;
+ opts->osf_flags = flags & (O_RDONLY | O_APPEND);
+
+ opts->security.nLength = sizeof(SECURITY_ATTRIBUTES);
+ opts->security.lpSecurityDescriptor = NULL;
+ opts->security.bInheritHandle = 0;
+}
+
+GIT_INLINE(int) open_once(
+ const wchar_t *path,
+ struct open_opts *opts)
+{
+ int fd;
+
+ HANDLE handle = CreateFileW(path, opts->access, opts->sharing,
+ &opts->security, opts->creation_disposition, opts->attributes, 0);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ if (last_error_retryable())
+ return GIT_RETRY;
+
+ set_errno();
+ return -1;
+ }
+
+ if ((fd = _open_osfhandle((intptr_t)handle, opts->osf_flags)) < 0)
+ CloseHandle(handle);
+
+ return fd;
+}
+
int p_open(const char *path, int flags, ...)
{
- git_win32_path buf;
+ git_win32_path wpath;
mode_t mode = 0;
+ struct open_opts opts = {0};
- if (git_win32_path_from_utf8(buf, path) < 0)
+ if (git_win32_path_from_utf8(wpath, path) < 0)
return -1;
if (flags & O_CREAT) {
@@ -298,19 +490,83 @@
va_end(arg_list);
}
- return _wopen(buf, flags | STANDARD_OPEN_FLAGS, mode & WIN32_MODE_MASK);
+ open_opts_from_posix(&opts, flags, mode);
+
+ do_with_retries(
+ open_once(wpath, &opts),
+ 0);
}
int p_creat(const char *path, mode_t mode)
{
- git_win32_path buf;
+ return p_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
+}
- if (git_win32_path_from_utf8(buf, path) < 0)
+int p_utimes(const char *path, const struct p_timeval times[2])
+{
+ git_win32_path wpath;
+ int fd, error;
+ DWORD attrs_orig, attrs_new = 0;
+ struct open_opts opts = { 0 };
+
+ if (git_win32_path_from_utf8(wpath, path) < 0)
return -1;
- return _wopen(buf,
- _O_WRONLY | _O_CREAT | _O_TRUNC | STANDARD_OPEN_FLAGS,
- mode & WIN32_MODE_MASK);
+ attrs_orig = GetFileAttributesW(wpath);
+
+ if (attrs_orig & FILE_ATTRIBUTE_READONLY) {
+ attrs_new = attrs_orig & ~FILE_ATTRIBUTE_READONLY;
+
+ if (!SetFileAttributesW(wpath, attrs_new)) {
+ giterr_set(GITERR_OS, "failed to set attributes");
+ return -1;
+ }
+ }
+
+ open_opts_from_posix(&opts, O_RDWR, 0);
+
+ if ((fd = open_once(wpath, &opts)) < 0) {
+ error = -1;
+ goto done;
+ }
+
+ error = p_futimes(fd, times);
+ close(fd);
+
+done:
+ if (attrs_orig != attrs_new) {
+ DWORD os_error = GetLastError();
+ SetFileAttributesW(wpath, attrs_orig);
+ SetLastError(os_error);
+ }
+
+ return error;
+}
+
+int p_futimes(int fd, const struct p_timeval times[2])
+{
+ HANDLE handle;
+ FILETIME atime = { 0 }, mtime = { 0 };
+
+ if (times == NULL) {
+ SYSTEMTIME st;
+
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &atime);
+ SystemTimeToFileTime(&st, &mtime);
+ }
+ else {
+ git_win32__timeval_to_filetime(&atime, times[0]);
+ git_win32__timeval_to_filetime(&mtime, times[1]);
+ }
+
+ if ((handle = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE)
+ return -1;
+
+ if (SetFileTime(handle, NULL, &atime, &mtime) == 0)
+ return -1;
+
+ return 0;
}
int p_getcwd(char *buffer_out, size_t size)
@@ -583,62 +839,27 @@
return _waccess(buf, mode & WIN32_MODE_MASK);
}
-static int ensure_writable(wchar_t *fpath)
+GIT_INLINE(int) rename_once(const wchar_t *from, const wchar_t *to)
{
- DWORD attrs;
-
- attrs = GetFileAttributesW(fpath);
- if (attrs == INVALID_FILE_ATTRIBUTES) {
- if (GetLastError() == ERROR_FILE_NOT_FOUND)
- return 0;
-
- giterr_set(GITERR_OS, "failed to get attributes");
- return -1;
- }
-
- if (!(attrs & FILE_ATTRIBUTE_READONLY))
+ if (MoveFileExW(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
return 0;
- attrs &= ~FILE_ATTRIBUTE_READONLY;
- if (!SetFileAttributesW(fpath, attrs)) {
- giterr_set(GITERR_OS, "failed to set attributes");
- return -1;
- }
+ if (last_error_retryable())
+ return GIT_RETRY;
- return 0;
+ set_errno();
+ return -1;
}
int p_rename(const char *from, const char *to)
{
- git_win32_path wfrom;
- git_win32_path wto;
- int rename_tries;
- int rename_succeeded;
- int error;
+ git_win32_path wfrom, wto;
if (git_win32_path_from_utf8(wfrom, from) < 0 ||
git_win32_path_from_utf8(wto, to) < 0)
return -1;
- /* wait up to 50ms if file is locked by another thread or process */
- rename_tries = 0;
- rename_succeeded = 0;
- while (rename_tries < 10) {
- if (ensure_writable(wto) == 0 &&
- MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != 0) {
- rename_succeeded = 1;
- break;
- }
-
- error = GetLastError();
- if (error == ERROR_SHARING_VIOLATION || error == ERROR_ACCESS_DENIED) {
- Sleep(5);
- rename_tries++;
- } else
- break;
- }
-
- return rename_succeeded ? 0 : -1;
+ do_with_retries(rename_once(wfrom, wto), ensure_writable(wto));
}
int p_recv(GIT_SOCKET socket, void *buffer, size_t length, int flags)
diff --git a/src/worktree.c b/src/worktree.c
index 393a088..55fbf52 100644
--- a/src/worktree.c
+++ b/src/worktree.c
@@ -212,8 +212,7 @@
goto out;
out:
- if (error)
- free(name);
+ free(name);
git_buf_free(&parent);
return error;
diff --git a/tests/clone/local.c b/tests/clone/local.c
index 91a0a1c..7f54d05 100644
--- a/tests/clone/local.c
+++ b/tests/clone/local.c
@@ -16,6 +16,7 @@
return git_buf_printf(buf, "file://%s/%s", host, path);
}
+#ifdef GIT_WIN32
static int git_style_unc_path(git_buf *buf, const char *host, const char *path)
{
git_buf_clear(buf);
@@ -49,6 +50,7 @@
return 0;
}
+#endif
void test_clone_local__should_clone_local(void)
{
diff --git a/tests/config/readonly.c b/tests/config/readonly.c
new file mode 100644
index 0000000..f45abdd
--- /dev/null
+++ b/tests/config/readonly.c
@@ -0,0 +1,64 @@
+#include "clar_libgit2.h"
+#include "config_file.h"
+#include "config.h"
+
+static git_config *cfg;
+
+void test_config_readonly__initialize(void)
+{
+ cl_git_pass(git_config_new(&cfg));
+}
+
+void test_config_readonly__cleanup(void)
+{
+ git_config_free(cfg);
+ cfg = NULL;
+}
+
+void test_config_readonly__writing_to_readonly_fails(void)
+{
+ git_config_backend *backend;
+
+ cl_git_pass(git_config_file__ondisk(&backend, "global"));
+ backend->readonly = 1;
+ cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, 0));
+
+ cl_git_fail_with(GIT_ENOTFOUND, git_config_set_string(cfg, "foo.bar", "baz"));
+ cl_assert(!git_path_exists("global"));
+}
+
+void test_config_readonly__writing_to_cfg_with_rw_precedence_succeeds(void)
+{
+ git_config_backend *backend;
+
+ cl_git_pass(git_config_file__ondisk(&backend, "global"));
+ backend->readonly = 1;
+ cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, 0));
+
+ cl_git_pass(git_config_file__ondisk(&backend, "local"));
+ cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_LOCAL, 0));
+
+ cl_git_pass(git_config_set_string(cfg, "foo.bar", "baz"));
+
+ cl_assert(git_path_exists("local"));
+ cl_assert(!git_path_exists("global"));
+ cl_git_pass(p_unlink("local"));
+}
+
+void test_config_readonly__writing_to_cfg_with_ro_precedence_succeeds(void)
+{
+ git_config_backend *backend;
+
+ cl_git_pass(git_config_file__ondisk(&backend, "local"));
+ backend->readonly = 1;
+ cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_LOCAL, 0));
+
+ cl_git_pass(git_config_file__ondisk(&backend, "global"));
+ cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, 0));
+
+ cl_git_pass(git_config_set_string(cfg, "foo.bar", "baz"));
+
+ cl_assert(!git_path_exists("local"));
+ cl_assert(git_path_exists("global"));
+ cl_git_pass(p_unlink("global"));
+}
diff --git a/tests/core/features.c b/tests/core/features.c
index cf5e190..7b28cc0 100644
--- a/tests/core/features.c
+++ b/tests/core/features.c
@@ -17,7 +17,9 @@
cl_assert((caps & GIT_FEATURE_THREADS) == 0);
#endif
+#ifdef GIT_HTTPS
cl_assert((caps & GIT_FEATURE_HTTPS) != 0);
+#endif
#if defined(GIT_SSH)
cl_assert((caps & GIT_FEATURE_SSH) != 0);
diff --git a/tests/filter/custom.c b/tests/filter/custom.c
index fd1cd27..799beef 100644
--- a/tests/filter/custom.c
+++ b/tests/filter/custom.c
@@ -55,6 +55,7 @@
"hero* bitflip reverse\n"
"herofile text\n"
"heroflip -reverse binary\n"
+ "villain erroneous\n"
"*.bin binary\n");
}
@@ -82,6 +83,11 @@
create_reverse_filter("+prereverse"),
GIT_FILTER_DRIVER_PRIORITY));
+ cl_git_pass(git_filter_register(
+ "erroneous",
+ create_erroneous_filter("+erroneous"),
+ GIT_FILTER_DRIVER_PRIORITY));
+
filters_registered = 1;
}
}
@@ -235,3 +241,18 @@
cl_git_fail(git_filter_unregister(GIT_FILTER_IDENT));
cl_assert_equal_i(GIT_ENOTFOUND, git_filter_unregister("not-a-filter"));
}
+
+void test_filter_custom__erroneous_filter_fails(void)
+{
+ git_filter_list *filters;
+ git_buf out = GIT_BUF_INIT;
+ git_buf in = GIT_BUF_INIT_CONST(workdir_data, strlen(workdir_data));
+
+ cl_git_pass(git_filter_list_load(
+ &filters, g_repo, NULL, "villain", GIT_FILTER_TO_WORKTREE, 0));
+
+ cl_git_fail(git_filter_list_apply_to_data(&out, filters, &in));
+
+ git_filter_list_free(filters);
+ git_buf_free(&out);
+}
diff --git a/tests/filter/custom_helpers.c b/tests/filter/custom_helpers.c
index 2c80212..d7f2afe 100644
--- a/tests/filter/custom_helpers.c
+++ b/tests/filter/custom_helpers.c
@@ -106,3 +106,36 @@
return filter;
}
+
+int erroneous_filter_stream(
+ git_writestream **out,
+ git_filter *self,
+ void **payload,
+ const git_filter_source *src,
+ git_writestream *next)
+{
+ GIT_UNUSED(out);
+ GIT_UNUSED(self);
+ GIT_UNUSED(payload);
+ GIT_UNUSED(src);
+ GIT_UNUSED(next);
+ return -1;
+}
+
+static void erroneous_filter_free(git_filter *f)
+{
+ git__free(f);
+}
+
+git_filter *create_erroneous_filter(const char *attrs)
+{
+ git_filter *filter = git__calloc(1, sizeof(git_filter));
+ cl_assert(filter);
+
+ filter->version = GIT_FILTER_VERSION;
+ filter->attributes = attrs;
+ filter->stream = erroneous_filter_stream;
+ filter->shutdown = erroneous_filter_free;
+
+ return filter;
+}
diff --git a/tests/filter/custom_helpers.h b/tests/filter/custom_helpers.h
index 13cfb23..537a51d 100644
--- a/tests/filter/custom_helpers.h
+++ b/tests/filter/custom_helpers.h
@@ -2,6 +2,7 @@
extern git_filter *create_bitflip_filter(void);
extern git_filter *create_reverse_filter(const char *attr);
+extern git_filter *create_erroneous_filter(const char *attr);
extern int bitflip_filter_apply(
git_filter *self,
diff --git a/tests/object/lookup.c b/tests/object/lookup.c
index cfa6d46..544f32b 100644
--- a/tests/object/lookup.c
+++ b/tests/object/lookup.c
@@ -6,13 +6,12 @@
void test_object_lookup__initialize(void)
{
- cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git")));
+ g_repo = cl_git_sandbox_init("testrepo.git");
}
void test_object_lookup__cleanup(void)
{
- git_repository_free(g_repo);
- g_repo = NULL;
+ cl_git_sandbox_cleanup();
}
void test_object_lookup__lookup_wrong_type_returns_enotfound(void)
@@ -63,3 +62,61 @@
GIT_ENOTFOUND, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_TAG));
}
+void test_object_lookup__lookup_corrupt_object_returns_error(void)
+{
+ const char *commit = "8e73b769e97678d684b809b163bebdae2911720f",
+ *file = "objects/8e/73b769e97678d684b809b163bebdae2911720f";
+ git_buf path = GIT_BUF_INIT, contents = GIT_BUF_INIT;
+ git_oid oid;
+ git_object *object;
+ size_t i;
+
+ cl_git_pass(git_oid_fromstr(&oid, commit));
+ cl_git_pass(git_buf_joinpath(&path, git_repository_path(g_repo), file));
+ cl_git_pass(git_futils_readbuffer(&contents, path.ptr));
+
+ /* Corrupt and try to read the object */
+ for (i = 0; i < contents.size; i++) {
+ contents.ptr[i] ^= 0x1;
+ cl_git_pass(git_futils_writebuffer(&contents, path.ptr, O_RDWR, 0644));
+ cl_git_fail(git_object_lookup(&object, g_repo, &oid, GIT_OBJ_COMMIT));
+ contents.ptr[i] ^= 0x1;
+ }
+
+ /* Restore original content and assert we can read the object */
+ cl_git_pass(git_futils_writebuffer(&contents, path.ptr, O_RDWR, 0644));
+ cl_git_pass(git_object_lookup(&object, g_repo, &oid, GIT_OBJ_COMMIT));
+
+ git_object_free(object);
+ git_buf_free(&path);
+ git_buf_free(&contents);
+}
+
+void test_object_lookup__lookup_object_with_wrong_hash_returns_error(void)
+{
+ const char *oldloose = "objects/8e/73b769e97678d684b809b163bebdae2911720f",
+ *newloose = "objects/8e/73b769e97678d684b809b163bebdae2911720e",
+ *commit = "8e73b769e97678d684b809b163bebdae2911720e";
+ git_buf oldpath = GIT_BUF_INIT, newpath = GIT_BUF_INIT;
+ git_object *object;
+ git_oid oid;
+
+ cl_git_pass(git_oid_fromstr(&oid, commit));
+
+ /* Copy object to another location with wrong hash */
+ cl_git_pass(git_buf_joinpath(&oldpath, git_repository_path(g_repo), oldloose));
+ cl_git_pass(git_buf_joinpath(&newpath, git_repository_path(g_repo), newloose));
+ cl_git_pass(git_futils_cp(oldpath.ptr, newpath.ptr, 0644));
+
+ /* Verify that lookup fails due to a hashsum mismatch */
+ cl_git_fail_with(GIT_EMISMATCH, git_object_lookup(&object, g_repo, &oid, GIT_OBJ_COMMIT));
+
+ /* Disable verification and try again */
+ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 0));
+ cl_git_pass(git_object_lookup(&object, g_repo, &oid, GIT_OBJ_COMMIT));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 1));
+
+ git_object_free(object);
+ git_buf_free(&oldpath);
+ git_buf_free(&newpath);
+}
diff --git a/tests/odb/backend/nonrefreshing.c b/tests/odb/backend/nonrefreshing.c
index b435294..f12ac74 100644
--- a/tests/odb/backend/nonrefreshing.c
+++ b/tests/odb/backend/nonrefreshing.c
@@ -17,6 +17,9 @@
static fake_backend *_fake;
static git_oid _oid;
+#define HASH "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
+#define EMPTY_HASH "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"
+
static int fake_backend__exists(git_odb_backend *backend, const git_oid *oid)
{
fake_backend *fake;
@@ -78,7 +81,6 @@
{
fake_backend *fake;
- GIT_UNUSED(out_oid);
GIT_UNUSED(buffer_p);
GIT_UNUSED(len_p);
GIT_UNUSED(type_p);
@@ -89,6 +91,7 @@
fake->read_prefix_calls++;
+ git_oid_cpy(out_oid, &_oid);
*len_p = 0;
*buffer_p = NULL;
*type_p = GIT_OBJ_BLOB;
@@ -130,7 +133,7 @@
return 0;
}
-static void setup_repository_and_backend(git_error_code error_code)
+static void setup_repository_and_backend(git_error_code error_code, const char *hash)
{
git_odb *odb = NULL;
git_odb_backend *backend = NULL;
@@ -144,7 +147,7 @@
_fake = (fake_backend *)backend;
- cl_git_pass(git_oid_fromstr(&_oid, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
+ cl_git_pass(git_oid_fromstr(&_oid, hash));
}
void test_odb_backend_nonrefreshing__cleanup(void)
@@ -156,7 +159,7 @@
{
git_odb *odb;
- setup_repository_and_backend(GIT_ENOTFOUND);
+ setup_repository_and_backend(GIT_ENOTFOUND, HASH);
cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
cl_assert_equal_b(false, git_odb_exists(odb, &_oid));
@@ -168,7 +171,7 @@
{
git_object *obj;
- setup_repository_and_backend(GIT_ENOTFOUND);
+ setup_repository_and_backend(GIT_ENOTFOUND, HASH);
cl_git_fail_with(
git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY),
@@ -181,7 +184,7 @@
{
git_object *obj;
- setup_repository_and_backend(GIT_ENOTFOUND);
+ setup_repository_and_backend(GIT_ENOTFOUND, HASH);
cl_git_fail_with(
git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY),
@@ -196,7 +199,7 @@
size_t len;
git_otype type;
- setup_repository_and_backend(GIT_ENOTFOUND);
+ setup_repository_and_backend(GIT_ENOTFOUND, HASH);
cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
@@ -211,7 +214,7 @@
{
git_odb *odb;
- setup_repository_and_backend(GIT_OK);
+ setup_repository_and_backend(GIT_OK, HASH);
cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
cl_assert_equal_b(true, git_odb_exists(odb, &_oid));
@@ -223,7 +226,7 @@
{
git_object *obj;
- setup_repository_and_backend(GIT_OK);
+ setup_repository_and_backend(GIT_OK, EMPTY_HASH);
cl_git_pass(git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY));
@@ -236,7 +239,7 @@
{
git_object *obj;
- setup_repository_and_backend(GIT_OK);
+ setup_repository_and_backend(GIT_OK, EMPTY_HASH);
cl_git_pass(git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY));
@@ -251,7 +254,7 @@
size_t len;
git_otype type;
- setup_repository_and_backend(GIT_OK);
+ setup_repository_and_backend(GIT_OK, HASH);
cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
@@ -264,7 +267,7 @@
{
git_object *obj;
- setup_repository_and_backend(GIT_ENOTFOUND);
+ setup_repository_and_backend(GIT_ENOTFOUND, HASH);
cl_git_fail_with(
git_revparse_single(&obj, _repo, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
diff --git a/tests/odb/freshen.c b/tests/odb/freshen.c
index f41e436..9d3cf51 100644
--- a/tests/odb/freshen.c
+++ b/tests/odb/freshen.c
@@ -55,6 +55,31 @@
cl_assert(before.st_mtime < after.st_mtime);
}
+#define UNIQUE_STR "doesnt exist in the odb yet\n"
+#define UNIQUE_BLOB_ID "78a87d0b8878c5953b9a63015ff4e22a3d898826"
+#define UNIQUE_BLOB_FN "78/a87d0b8878c5953b9a63015ff4e22a3d898826"
+
+void test_odb_freshen__readonly_object(void)
+{
+ git_oid expected_id, id;
+ struct stat before, after;
+
+ cl_git_pass(git_oid_fromstr(&expected_id, UNIQUE_BLOB_ID));
+
+ cl_git_pass(git_blob_create_frombuffer(&id, repo, UNIQUE_STR, CONST_STRLEN(UNIQUE_STR)));
+ cl_assert_equal_oid(&expected_id, &id);
+
+ set_time_wayback(&before, UNIQUE_BLOB_FN);
+ cl_assert((before.st_mode & S_IWUSR) == 0);
+
+ cl_git_pass(git_blob_create_frombuffer(&id, repo, UNIQUE_STR, CONST_STRLEN(UNIQUE_STR)));
+ cl_assert_equal_oid(&expected_id, &id);
+ cl_must_pass(p_lstat("testrepo.git/objects/" UNIQUE_BLOB_FN, &after));
+
+ cl_assert(before.st_atime < after.st_atime);
+ cl_assert(before.st_mtime < after.st_mtime);
+}
+
#define LOOSE_TREE_ID "944c0f6e4dfa41595e6eb3ceecdb14f50fe18162"
#define LOOSE_TREE_FN "94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162"
diff --git a/tests/online/badssl.c b/tests/online/badssl.c
index aa4c24d..6524fcd 100644
--- a/tests/online/badssl.c
+++ b/tests/online/badssl.c
@@ -4,7 +4,7 @@
static git_repository *g_repo;
-#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT)
+#ifdef GIT_HTTPS
static bool g_has_ssl = true;
#else
static bool g_has_ssl = false;
diff --git a/tests/refs/revparse.c b/tests/refs/revparse.c
index c22c304..459188c 100644
--- a/tests/refs/revparse.c
+++ b/tests/refs/revparse.c
@@ -122,6 +122,14 @@
test_id_inrepo(spec, expected_left, expected_right, expected_flags, g_repo);
}
+static void test_invalid_revspec(const char* invalid_spec)
+{
+ git_revspec revspec;
+
+ cl_assert_equal_i(
+ GIT_EINVALIDSPEC, git_revparse(&revspec, g_repo, invalid_spec));
+}
+
void test_refs_revparse__initialize(void)
{
cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git")));
@@ -749,6 +757,33 @@
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
+
+ test_id("HEAD~3..",
+ "4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
+ "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+ GIT_REVPARSE_RANGE);
+
+ test_id("HEAD~3...",
+ "4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
+ "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+ GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
+
+ test_id("..HEAD~3",
+ "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+ "4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
+ GIT_REVPARSE_RANGE);
+
+ test_id("...HEAD~3",
+ "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+ "4a202b346bb0fb0db7eff3cffeb3c70babbd2045",
+ GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
+
+ test_id("...",
+ "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+ "a65fedf39aefe402d3bb6e24df4d4f5fe4547750",
+ GIT_REVPARSE_RANGE | GIT_REVPARSE_MERGE_BASE);
+
+ test_invalid_revspec("..");
}
void test_refs_revparse__ext_retrieves_both_the_reference_and_its_target(void)
diff --git a/tests/repo/discover.c b/tests/repo/discover.c
index abb7bd1..eadd055 100644
--- a/tests/repo/discover.c
+++ b/tests/repo/discover.c
@@ -33,7 +33,7 @@
git_buf_attach(&resolved, p_realpath(expected_path, NULL), 0);
cl_assert(resolved.size > 0);
cl_git_pass(git_path_to_dir(&resolved));
- cl_git_pass(git_repository_discover(&found_path, start_path, 0, ceiling_dirs));
+ cl_git_pass(git_repository_discover(&found_path, start_path, 1, ceiling_dirs));
cl_assert_equal_s(found_path.ptr, resolved.ptr);
diff --git a/tests/repo/head.c b/tests/repo/head.c
index 31c2287..d021160 100644
--- a/tests/repo/head.c
+++ b/tests/repo/head.c
@@ -261,15 +261,19 @@
cl_git_pass(git_revparse_single(&tag, repo, "tags/test"));
cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag)));
cl_git_pass(git_repository_set_head(repo, "refs/heads/haacked"));
+ cl_git_pass(git_repository_set_head(repo, "refs/tags/test"));
+ cl_git_pass(git_repository_set_head(repo, "refs/remotes/test/master"));
- test_reflog(repo, 2, NULL, "refs/heads/haacked", "foo@example.com", "checkout: moving from master to haacked");
- test_reflog(repo, 1, NULL, "tags/test^{commit}", "foo@example.com", "checkout: moving from unborn to e90810b8df3e80c413d903f631643c716887138d");
- test_reflog(repo, 0, "tags/test^{commit}", "refs/heads/haacked", "foo@example.com", "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked");
+ test_reflog(repo, 4, NULL, "refs/heads/haacked", "foo@example.com", "checkout: moving from master to haacked");
+ test_reflog(repo, 3, NULL, "tags/test^{commit}", "foo@example.com", "checkout: moving from unborn to e90810b8df3e80c413d903f631643c716887138d");
+ test_reflog(repo, 2, "tags/test^{commit}", "refs/heads/haacked", "foo@example.com", "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to haacked");
+ test_reflog(repo, 1, "refs/heads/haacked", "tags/test^{commit}", "foo@example.com", "checkout: moving from haacked to test");
+ test_reflog(repo, 0, "tags/test^{commit}", "refs/remotes/test/master", "foo@example.com", "checkout: moving from e90810b8df3e80c413d903f631643c716887138d to test/master");
cl_git_pass(git_annotated_commit_from_revspec(&annotated, repo, "haacked~0"));
cl_git_pass(git_repository_set_head_detached_from_annotated(repo, annotated));
- test_reflog(repo, 0, NULL, "refs/heads/haacked", "foo@example.com", "checkout: moving from haacked to haacked~0");
+ test_reflog(repo, 0, NULL, "refs/heads/haacked", "foo@example.com", "checkout: moving from be3563ae3f795b2b4353bcce3a527ad0a4f7f644 to haacked~0");
git_annotated_commit_free(annotated);
git_object_free(tag);
diff --git a/tests/repo/open.c b/tests/repo/open.c
index 6114ad2..3239b6f 100644
--- a/tests/repo/open.c
+++ b/tests/repo/open.c
@@ -398,7 +398,8 @@
cl_git_fail(git_repository_open_bare(&barerepo, "alternate/subdir/sub2"));
cl_git_pass(git_repository_open_ext(
- &barerepo, "alternate/subdir/sub2", GIT_REPOSITORY_OPEN_BARE, NULL));
+ &barerepo, "alternate/subdir/sub2",
+ GIT_REPOSITORY_OPEN_BARE|GIT_REPOSITORY_OPEN_CROSS_FS, NULL));
cl_assert(git_repository_is_bare(barerepo));
git_repository_free(barerepo);
}
diff --git a/tests/threads/basic.c b/tests/threads/basic.c
index a9310bb..af60490 100644
--- a/tests/threads/basic.c
+++ b/tests/threads/basic.c
@@ -54,12 +54,6 @@
{
return param;
}
-
-static void *exit_abruptly(void *param)
-{
- git_thread_exit(param);
- return NULL;
-}
#endif
void test_threads_basic__exit(void)
diff --git a/tests/threads/diff.c b/tests/threads/diff.c
index c328114..2560402 100644
--- a/tests/threads/diff.c
+++ b/tests/threads/diff.c
@@ -19,12 +19,27 @@
static git_tree *_a, *_b;
static git_atomic _counts[4];
static int _check_counts;
+#ifdef GIT_WIN32
+static int _retries;
+#endif
#define THREADS 20
+void test_threads_diff__initialize(void)
+{
+#ifdef GIT_WIN32
+ _retries = git_win32__retries;
+ git_win32__retries = 1;
+#endif
+}
+
void test_threads_diff__cleanup(void)
{
cl_git_sandbox_cleanup();
+
+#ifdef GIT_WIN32
+ git_win32__retries = _retries;
+#endif
}
static void setup_trees(void)
diff --git a/tests/worktree/refs.c b/tests/worktree/refs.c
index b9a0560..95b173e 100644
--- a/tests/worktree/refs.c
+++ b/tests/worktree/refs.c
@@ -107,28 +107,42 @@
void test_worktree_refs__delete_fails_for_checked_out_branch(void)
{
- git_reference *branch;
+ git_reference *branch;
- cl_git_pass(git_branch_lookup(&branch, fixture.repo,
- "testrepo-worktree", GIT_BRANCH_LOCAL));
- cl_git_fail(git_branch_delete(branch));
+ cl_git_pass(git_branch_lookup(&branch, fixture.repo,
+ "testrepo-worktree", GIT_BRANCH_LOCAL));
+ cl_git_fail(git_branch_delete(branch));
- git_reference_free(branch);
+ git_reference_free(branch);
}
void test_worktree_refs__delete_succeeds_after_pruning_worktree(void)
{
- git_reference *branch;
- git_worktree *worktree;
+ git_reference *branch;
+ git_worktree *worktree;
- cl_git_pass(git_worktree_lookup(&worktree, fixture.repo, fixture.worktreename));
- cl_git_pass(git_worktree_prune(worktree, GIT_WORKTREE_PRUNE_VALID));
- git_worktree_free(worktree);
+ cl_git_pass(git_worktree_lookup(&worktree, fixture.repo, fixture.worktreename));
+ cl_git_pass(git_worktree_prune(worktree, GIT_WORKTREE_PRUNE_VALID));
+ git_worktree_free(worktree);
- cl_git_pass(git_branch_lookup(&branch, fixture.repo,
- "testrepo-worktree", GIT_BRANCH_LOCAL));
- cl_git_pass(git_branch_delete(branch));
- git_reference_free(branch);
+ cl_git_pass(git_branch_lookup(&branch, fixture.repo,
+ "testrepo-worktree", GIT_BRANCH_LOCAL));
+ cl_git_pass(git_branch_delete(branch));
+ git_reference_free(branch);
+}
+
+void test_worktree_refs__renaming_reference_updates_worktree_heads(void)
+{
+ git_reference *head, *branch, *renamed;
+
+ cl_git_pass(git_branch_lookup(&branch, fixture.repo,
+ "testrepo-worktree", GIT_BRANCH_LOCAL));
+ cl_git_pass(git_reference_rename(&renamed, branch, "refs/heads/renamed", 0, NULL));
+ cl_git_pass(git_repository_head(&head, fixture.worktree));
+
+ git_reference_free(head);
+ git_reference_free(branch);
+ git_reference_free(renamed);
}
void test_worktree_refs__creating_refs_uses_commondir(void)
diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c
index 6e90e6a..73991bf 100644
--- a/tests/worktree/worktree.c
+++ b/tests/worktree/worktree.c
@@ -486,3 +486,46 @@
git_worktree_free(wt);
}
+
+static int read_head_ref(git_repository *repo, const char *path, void *payload)
+{
+ git_vector *refs = (git_vector *) payload;
+ git_reference *head;
+
+ GIT_UNUSED(repo);
+
+ cl_git_pass(git_reference__read_head(&head, repo, path));
+
+ git_vector_insert(refs, head);
+
+ return 0;
+}
+
+void test_worktree_worktree__foreach_head_gives_same_results_in_wt_and_repo(void)
+{
+ git_vector repo_refs = GIT_VECTOR_INIT, worktree_refs = GIT_VECTOR_INIT;
+ git_reference *heads[2];
+ size_t i;
+
+ cl_git_pass(git_reference_lookup(&heads[0], fixture.repo, GIT_HEAD_FILE));
+ cl_git_pass(git_reference_lookup(&heads[1], fixture.worktree, GIT_HEAD_FILE));
+
+ cl_git_pass(git_repository_foreach_head(fixture.repo, read_head_ref, &repo_refs));
+ cl_git_pass(git_repository_foreach_head(fixture.worktree, read_head_ref, &worktree_refs));
+
+ cl_assert_equal_i(repo_refs.length, ARRAY_SIZE(heads));
+ cl_assert_equal_i(worktree_refs.length, ARRAY_SIZE(heads));
+
+ for (i = 0; i < ARRAY_SIZE(heads); i++) {
+ cl_assert_equal_s(heads[i]->name, ((git_reference *) repo_refs.contents[i])->name);
+ cl_assert_equal_s(heads[i]->name, ((git_reference *) repo_refs.contents[i])->name);
+ cl_assert_equal_s(heads[i]->name, ((git_reference *) worktree_refs.contents[i])->name);
+
+ git_reference_free(heads[i]);
+ git_reference_free(repo_refs.contents[i]);
+ git_reference_free(worktree_refs.contents[i]);
+ }
+
+ git_vector_free(&repo_refs);
+ git_vector_free(&worktree_refs);
+}