commit - b419fc475bafd6efb01d324f86b462e1a24eda93
commit + 0c048b1581c5801a4fd5bf5b68d120bf8ed430a0
blob - 8706e35fba0b89f57c66633608d8653ef595eba2
blob + 2ee49f4dea4dc0411630a0f1a58de71caf718ba2
--- include/got_error.h
+++ include/got_error.h
#define GOT_ERR_PRIVSEP_MSG 39
#define GOT_ERR_PRIVSEP_DIED 40
#define GOT_ERR_PRIVSEP_EXIT 41
+#define GOT_ERR_PACK_OFFSET 42
static const struct got_error {
int code;
{ GOT_ERR_PRIVSEP_MSG,"unexpected message from unprivileged process" },
{ GOT_ERR_PRIVSEP_DIED,"unprivileged process died unexpectedly" },
{ GOT_ERR_PRIVSEP_EXIT,"bad exit code from unprivileged process" },
+ { GOT_ERR_PACK_OFFSET,"bad offset in pack file" },
};
/*
blob - 79459d949b01708f338b76794511f6ac966bd6cd
blob + 5ae9420580cc4f8445c55cd7f6fdc5d834dacb2f
--- lib/pack.c
+++ lib/pack.c
static const struct got_error *
resolve_delta_chain(struct got_delta_chain *, struct got_repository *,
- int, const char *, off_t, size_t, int, size_t, unsigned int);
+ int, size_t, 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,
static const struct got_error *
resolve_offset_delta(struct got_delta_chain *deltas,
- struct got_repository *repo, int fd, const char *path_packfile,
- off_t delta_offset,size_t tslen, int delta_type, size_t delta_size,
- unsigned int recursion)
+ struct got_repository *repo, int fd, size_t packfile_size,
+ const char *path_packfile, off_t delta_offset, size_t tslen,
+ int delta_type, size_t delta_size, unsigned int recursion)
{
const struct got_error *err;
return err;
/* An offset delta must be in the same packfile. */
+ if (base_offset >= packfile_size)
+ return got_error(GOT_ERR_PACK_OFFSET);
if (lseek(fd, base_offset, SEEK_SET) == -1)
return got_error_from_errno();
if (err)
return err;
- return resolve_delta_chain(deltas, repo, fd, path_packfile,
- base_offset, base_tslen, base_type, base_size, recursion - 1);
+ return resolve_delta_chain(deltas, repo, fd, packfile_size,
+ path_packfile, base_offset, base_tslen, base_type, base_size,
+ recursion - 1);
}
static const struct got_error *
goto done;
}
+ if (base_offset >= base_pack->filesize) {
+ err = got_error(GOT_ERR_PACK_OFFSET);
+ goto done;
+ }
if (lseek(base_pack->fd, base_offset, SEEK_SET) == -1) {
err = got_error_from_errno();
goto done;
goto done;
err = resolve_delta_chain(deltas, repo, base_pack->fd,
- path_base_packfile, base_offset, base_tslen, base_type,
- base_size, recursion - 1);
+ base_pack->filesize, path_base_packfile, base_offset,
+ base_tslen, base_type, base_size, recursion - 1);
done:
free(path_base_packfile);
return err;
static const struct got_error *
resolve_delta_chain(struct got_delta_chain *deltas, struct got_repository *repo,
- int fd, const char *path_packfile, off_t delta_offset, size_t tslen,
- int delta_type, size_t delta_size, unsigned int recursion)
+ int fd, size_t packfile_size, const char *path_packfile, off_t delta_offset,
+ size_t tslen, int delta_type, size_t delta_size, unsigned int recursion)
{
const struct got_error *err = NULL;
delta_type, delta_size, 0, NULL, 0);
break;
case GOT_OBJ_TYPE_OFFSET_DELTA:
- err = resolve_offset_delta(deltas, repo, fd, path_packfile,
- delta_offset, tslen, delta_type, delta_size, recursion - 1);
+ err = resolve_offset_delta(deltas, repo, fd, packfile_size,
+ path_packfile, delta_offset, tslen, delta_type, delta_size,
+ recursion - 1);
break;
case GOT_OBJ_TYPE_REF_DELTA:
err = resolve_ref_delta(deltas, repo, fd, path_packfile,
static const struct got_error *
open_delta_object(struct got_object **obj, struct got_repository *repo,
struct got_packidx_v2_hdr *packidx, const char *path_packfile,
- int fd, struct got_object_id *id, off_t offset, size_t tslen,
- int delta_type, size_t delta_size)
+ int fd, size_t packfile_size, struct got_object_id *id, off_t offset,
+ size_t tslen, int delta_type, size_t delta_size)
{
const struct got_error *err = NULL;
int resolved_type;
SIMPLEQ_INIT(&(*obj)->deltas.entries);
(*obj)->flags |= GOT_OBJ_FLAG_DELTIFIED;
- err = resolve_delta_chain(&(*obj)->deltas, repo, fd,
+ err = resolve_delta_chain(&(*obj)->deltas, repo, fd, packfile_size,
path_packfile, offset, tslen, delta_type, delta_size,
GOT_DELTA_CHAIN_RECURSION_MAX);
if (err)
goto done;
}
+ if (offset >= pack->filesize) {
+ err = got_error(GOT_ERR_PACK_OFFSET);
+ goto done;
+ }
if (lseek(pack->fd, offset, SEEK_SET) == -1) {
err = got_error_from_errno();
goto done;
case GOT_OBJ_TYPE_OFFSET_DELTA:
case GOT_OBJ_TYPE_REF_DELTA:
err = open_delta_object(obj, repo, packidx, path_packfile,
- pack->fd, id, offset, tslen, type, size);
+ pack->fd, pack->filesize, id, offset, tslen, type, size);
break;
default:
if (n == 0) {
struct got_pack *pack;
size_t base_len;
+ off_t delta_data_offset;
/* Plain object types are the delta base. */
if (delta->type != GOT_OBJ_TYPE_COMMIT &&
goto done;
}
- if (lseek(pack->fd, delta->offset + delta->tslen,
- SEEK_SET) == -1) {
+ delta_data_offset = delta->offset + delta->tslen;
+ if (delta_data_offset >= pack->filesize) {
+ err = got_error(GOT_ERR_PACK_OFFSET);
+ goto done;
+ }
+ if (lseek(pack->fd, delta_data_offset, SEEK_SET) == -1) {
err = got_error_from_errno();
goto done;
}
if (n == 0) {
struct got_pack *pack;
size_t base_len;
+ size_t delta_data_offset;
/* Plain object types are the delta base. */
if (delta->type != GOT_OBJ_TYPE_COMMIT &&
goto done;
}
- if (lseek(pack->fd, delta->offset + delta->tslen,
- SEEK_SET) == -1) {
+ delta_data_offset = delta->offset + delta->tslen;
+ if (delta_data_offset >= pack->filesize) {
+ err = got_error(GOT_ERR_PACK_OFFSET);
+ goto done;
+ }
+ if (lseek(pack->fd, delta_data_offset, SEEK_SET) == -1) {
err = got_error_from_errno();
goto done;
}
goto done;
}
+ if (obj->pack_offset >= pack->filesize) {
+ err = got_error(GOT_ERR_PACK_OFFSET);
+ goto done;
+ }
if (lseek(pack->fd, obj->pack_offset, SEEK_SET) == -1) {
err = got_error_from_errno();
goto done;
goto done;
}
+ if (obj->pack_offset >= pack->filesize) {
+ err = got_error(GOT_ERR_PACK_OFFSET);
+ goto done;
+ }
if (lseek(pack->fd, obj->pack_offset, SEEK_SET) == -1) {
err = got_error_from_errno();
goto done;