summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2018-07-26 15:25:44 +0200
committerGitHub <noreply@github.com>2018-07-26 15:25:44 +0200
commit42f8384045ca325c6885be21a89c3d8027995e03 (patch)
treee6c40a543edeb3a48635386b2703168c9774446b
parent7d3930a15e4b4eb292c0e24debdf1b39a6d7d63b (diff)
parent328103482aceca6789e2e8644c28637aadc4c2c2 (diff)
downloadlibgit2-42f8384045ca325c6885be21a89c3d8027995e03.tar.gz
Merge pull request #4721 from nelhage/max-objects
Add a configurable limit to the max pack size that will be indexed
-rw-r--r--include/git2/common.h16
-rw-r--r--src/indexer.c12
-rw-r--r--src/settings.c10
3 files changed, 31 insertions, 7 deletions
diff --git a/include/git2/common.h b/include/git2/common.h
index 8c9347413..a14e0961e 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -195,7 +195,9 @@ typedef enum {
GIT_OPT_SET_WINDOWS_SHAREMODE,
GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION,
GIT_OPT_SET_ALLOCATOR,
- GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY
+ GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY,
+ GIT_OPT_GET_PACK_MAX_OBJECTS,
+ GIT_OPT_SET_PACK_MAX_OBJECTS
} git_libgit2_opt_t;
/**
@@ -372,6 +374,18 @@ typedef enum {
* > fail. (Using the FORCE flag to checkout will still overwrite
* > these changes.)
*
+ * opts(GIT_OPT_GET_PACK_MAX_OBJECTS, size_t *out)
+ *
+ * > Get the maximum number of objects libgit2 will allow in a pack
+ * > file when downloading a pack file from a remote. This can be
+ * > used to limit maximum memory usage when fetching from an untrusted
+ * > remote.
+ *
+ * opts(GIT_OPT_SET_PACK_MAX_OBJECTS, size_t objects)
+ *
+ * > Set the maximum number of objects libgit2 will allow in a pack
+ * > file when downloading a pack file from a remote.
+ *
* @param option Option key
* @param ... value to set the option
* @return 0 on success, <0 on failure
diff --git a/src/indexer.c b/src/indexer.c
index 744a03cf0..4f0c5ca5b 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -22,6 +22,8 @@
extern git_mutex git__mwindow_mutex;
+size_t git_indexer__max_objects = UINT32_MAX;
+
#define UINT31_MAX (0x7FFFFFFF)
struct entry {
@@ -557,12 +559,12 @@ int git_indexer_append(git_indexer *idx, const void *data, size_t size, git_tran
idx->nr_objects = ntohl(hdr->hdr_entries);
idx->off = sizeof(struct git_pack_header);
- /* for now, limit to 2^32 objects */
- assert(idx->nr_objects == (size_t)((unsigned int)idx->nr_objects));
- if (idx->nr_objects == (size_t)((unsigned int)idx->nr_objects))
+ if (idx->nr_objects <= git_indexer__max_objects) {
total_objects = (unsigned int)idx->nr_objects;
- else
- total_objects = UINT_MAX;
+ } else {
+ giterr_set(GITERR_INDEXER, "too many objects");
+ return -1;
+ }
idx->pack->idx_cache = git_oidmap_alloc();
GITERR_CHECK_ALLOC(idx->pack->idx_cache);
diff --git a/src/settings.c b/src/settings.c
index ba2f7158c..4565507dd 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -56,6 +56,7 @@ int git_libgit2_features(void)
/* Declarations for tuneable settings */
extern size_t git_mwindow__window_size;
extern size_t git_mwindow__mapped_limit;
+extern size_t git_indexer__max_objects;
static int config_level_to_sysdir(int config_level)
{
@@ -270,6 +271,14 @@ int git_libgit2_opts(int key, ...)
git_index__enforce_unsaved_safety = (va_arg(ap, int) != 0);
break;
+ case GIT_OPT_SET_PACK_MAX_OBJECTS:
+ git_indexer__max_objects = va_arg(ap, size_t);
+ break;
+
+ case GIT_OPT_GET_PACK_MAX_OBJECTS:
+ *(va_arg(ap, size_t *)) = git_indexer__max_objects;
+ break;
+
default:
giterr_set(GITERR_INVALID, "invalid option key");
error = -1;
@@ -279,4 +288,3 @@ int git_libgit2_opts(int key, ...)
return error;
}
-