summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/git2/common.h8
-rw-r--r--src/odb.c14
-rw-r--r--src/odb.h2
-rw-r--r--src/settings.c5
-rw-r--r--tests/object/lookup.c5
5 files changed, 29 insertions, 5 deletions
diff --git a/include/git2/common.h b/include/git2/common.h
index 6d2092028..d83e8c3a0 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -182,6 +182,7 @@ typedef enum {
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;
/**
@@ -337,6 +338,13 @@ typedef enum {
* > 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/src/odb.c b/src/odb.c
index 0efa23417..157a3808e 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;
@@ -1027,12 +1029,14 @@ static int odb_read_1(git_odb_object **out, git_odb *db, const git_oid *id,
if (!found)
return GIT_ENOTFOUND;
- if ((error = git_odb_hash(&hashed, raw.data, raw.len, raw.type)) < 0)
- goto out;
+ 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;
+ if (!git_oid_equal(id, &hashed)) {
+ error = git_odb__error_mismatch(id, &hashed);
+ goto out;
+ }
}
giterr_clear();
diff --git a/src/odb.h b/src/odb.h
index 78c7b0339..61d687abf 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. */
diff --git a/src/settings.c b/src/settings.c
index 07ac16a8f..169fcd51c 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"
@@ -243,6 +244,10 @@ int git_libgit2_opts(int key, ...)
#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/tests/object/lookup.c b/tests/object/lookup.c
index ed12f917a..277e2e0c0 100644
--- a/tests/object/lookup.c
+++ b/tests/object/lookup.c
@@ -111,6 +111,11 @@ void test_object_lookup__lookup_object_with_wrong_hash_returns_error(void)
/* 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_buf_free(&oldpath);
git_buf_free(&newpath);
}