commit 5b7e13a71fb6ddb69c2a98e5c8d5192d8805519b from: Stefan Sperling date: Mon Apr 02 10:46:33 2018 UTC put a limit on delta chain recursion commit - dfb54902d34a7b74997a77674e6f8200141ed154 commit + 5b7e13a71fb6ddb69c2a98e5c8d5192d8805519b blob - 4927b6057d86838ccd49bf408dff0712446eec31 blob + 86c785de07fb2604fc83ef040c4eef616c0598ad --- include/got_error.h +++ include/got_error.h @@ -45,6 +45,7 @@ #define GOT_ERR_WORKTREE_BUSY 29 #define GOT_ERR_DIR_OBSTRUCTED 30 #define GOT_ERR_FILE_OBSTRUCTED 31 +#define GOT_ERR_RECURSION 32 static const struct got_error { int code; @@ -78,6 +79,7 @@ static const struct got_error { { GOT_ERR_WORKTREE_META,"bad worktree meta data" }, { GOT_ERR_WORKTREE_VERS,"unsupported worktree format version" }, { GOT_ERR_WORKTREE_BUSY,"worktree already locked" }, + { GOT_ERR_RECURSION, "recursion limit reached" }, }; /* blob - d7b25da90c43d78a330740ca5661a4a9e502595c blob + 710d4edf7f4242a2bde28dbcbfcbdf99c9774b31 --- lib/pack.c +++ lib/pack.c @@ -55,6 +55,8 @@ #define GOT_PACKIDX_NAMELEN (strlen(GOT_PACK_PREFIX) + \ SHA1_DIGEST_STRING_LENGTH - 1 + \ strlen(GOT_PACKIDX_SUFFIX)) + +#define GOT_DELTA_CHAIN_RECURSION_MAX 100 #ifndef MIN #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b)) @@ -734,7 +736,7 @@ parse_offset_delta(off_t *base_offset, FILE *packfile, static const struct got_error * resolve_delta_chain(struct got_delta_chain *, struct got_repository *, - FILE *, const char *, off_t, size_t, int, size_t); + FILE *, const char *, off_t, size_t, int, size_t, unsigned int); static const struct got_error * add_delta(struct got_delta_chain *deltas, const char *path_packfile, @@ -757,7 +759,8 @@ add_delta(struct got_delta_chain *deltas, const char * static const struct got_error * resolve_offset_delta(struct got_delta_chain *deltas, struct got_repository *repo, FILE *packfile, const char *path_packfile, - off_t delta_offset,size_t tslen, int delta_type, size_t delta_size) + off_t delta_offset,size_t tslen, int delta_type, size_t delta_size, + unsigned int recursion) { const struct got_error *err; @@ -796,13 +799,13 @@ resolve_offset_delta(struct got_delta_chain *deltas, return err; return resolve_delta_chain(deltas, repo, packfile, path_packfile, - base_offset, base_tslen, base_type, base_size); + base_offset, base_tslen, base_type, base_size, recursion - 1); } static const struct got_error * resolve_ref_delta(struct got_delta_chain *deltas, struct got_repository *repo, FILE *packfile, const char *path_packfile, off_t delta_offset, - size_t tslen, int delta_type, size_t delta_size) + size_t tslen, int delta_type, size_t delta_size, unsigned int recursion) { const struct got_error *err; struct got_object_id id; @@ -868,7 +871,7 @@ resolve_ref_delta(struct got_delta_chain *deltas, stru err = resolve_delta_chain(deltas, repo, base_pack->packfile, path_base_packfile, base_offset, base_tslen, base_type, - base_size); + base_size, recursion - 1); done: free(path_base_packfile); return err; @@ -877,10 +880,13 @@ done: static const struct got_error * resolve_delta_chain(struct got_delta_chain *deltas, struct got_repository *repo, FILE *packfile, const char *path_packfile, off_t delta_offset, size_t tslen, - int delta_type, size_t delta_size) + int delta_type, size_t delta_size, unsigned int recursion) { const struct got_error *err = NULL; + if (--recursion == 0) + return got_error(GOT_ERR_RECURSION); + switch (delta_type) { case GOT_OBJ_TYPE_COMMIT: case GOT_OBJ_TYPE_TREE: @@ -893,12 +899,12 @@ resolve_delta_chain(struct got_delta_chain *deltas, st case GOT_OBJ_TYPE_OFFSET_DELTA: err = resolve_offset_delta(deltas, repo, packfile, path_packfile, delta_offset, tslen, delta_type, - delta_size); + delta_size, recursion - 1); break; case GOT_OBJ_TYPE_REF_DELTA: err = resolve_ref_delta(deltas, repo, packfile, path_packfile, delta_offset, tslen, delta_type, - delta_size); + delta_size, recursion - 1); break; default: return got_error(GOT_ERR_OBJ_TYPE); @@ -937,7 +943,8 @@ open_delta_object(struct got_object **obj, struct got_ (*obj)->flags |= GOT_OBJ_FLAG_DELTIFIED; err = resolve_delta_chain(&(*obj)->deltas, repo, packfile, - path_packfile, offset, tslen, delta_type, delta_size); + path_packfile, offset, tslen, delta_type, delta_size, + GOT_DELTA_CHAIN_RECURSION_MAX); if (err) goto done;