commit - 246e1c78b7c0d1b05a03e5801ffd25d90014f4a4
commit + 34fca9c35c1a35f6e163edd53f5cf674b30c1799
blob - 1893ac395efc26967299e737c552d73fe606efc2
blob + 9959137774da2dd00f419381147d0952d0d20785
--- lib/delta.c
+++ lib/delta.c
}
const struct got_error *
-got_delta_apply_in_mem(uint8_t *base_buf, const uint8_t *delta_buf,
- size_t delta_len, uint8_t *outbuf, size_t *outsize)
+got_delta_apply_in_mem(uint8_t *base_buf, size_t base_bufsz,
+ const uint8_t *delta_buf, size_t delta_len, uint8_t *outbuf,
+ size_t *outsize, size_t maxoutsize)
{
const struct got_error *err = NULL;
uint64_t base_size, result_size;
err = parse_opcode(&offset, &len, &p, &remain);
if (err)
break;
+ if (base_bufsz < offset + len ||
+ *outsize + len > maxoutsize)
+ return got_error(GOT_ERR_BAD_DELTA);
memcpy(outbuf + *outsize, base_buf + offset, len);
if (err == NULL) {
*outsize += len;
err = next_delta_byte(&p, &remain);
if (err)
break;
- if (remain < len)
+ if (remain < len || *outsize + len > maxoutsize)
return got_error(GOT_ERR_BAD_DELTA);
memcpy(outbuf + *outsize, p, len);
p += len;
blob - 6f61627e302246e2daad1fa4ffdf095067b082ca
blob + a2cb4a3ab0d26620028ba99100ba2d73563520c9
--- lib/got_lib_delta.h
+++ lib/got_lib_delta.h
struct got_delta_chain *);
const struct got_error *got_delta_get_sizes(uint64_t *, uint64_t *,
const uint8_t *, size_t);
-const struct got_error *got_delta_apply_in_mem(uint8_t *, const uint8_t *,
- size_t, uint8_t *, size_t *);
+const struct got_error *got_delta_apply_in_mem(uint8_t *, size_t,
+ const uint8_t *, size_t, uint8_t *, size_t *, size_t);
const struct got_error *got_delta_apply(FILE *, const uint8_t *, size_t,
FILE *, size_t *);
blob - fd18041fae8a7d318c0d9a6a115419cf8cd82e18
blob + b16b4be257ce68d10cdae28713c204ef2a8862dc
--- lib/pack.c
+++ lib/pack.c
const struct got_error *err = NULL;
struct got_delta *delta;
uint8_t *base_buf = NULL, *accum_buf = NULL;
- size_t accum_size = 0;
+ size_t base_bufsz = 0, accum_size = 0;
uint64_t max_size;
int n = 0;
/* Deltas are ordered in ascending order. */
SIMPLEQ_FOREACH(delta, &deltas->entries, entry) {
if (n == 0) {
- size_t base_len, mapoff;
+ size_t mapoff;
off_t delta_data_offset;
/* Plain object types are the delta base. */
if (pack->map) {
mapoff = (size_t)delta_data_offset;
err = got_inflate_to_file_mmap(
- &base_len, pack->map, mapoff,
+ &base_bufsz, pack->map, mapoff,
pack->filesize - mapoff, base_file);
} else
- err = got_inflate_to_file_fd(&base_len,
- pack->fd, base_file);
+ err = got_inflate_to_file_fd(
+ &base_bufsz, pack->fd, base_file);
} else {
if (pack->map) {
mapoff = (size_t)delta_data_offset;
err = got_inflate_to_mem_mmap(&base_buf,
- &base_len, pack->map, mapoff,
+ &base_bufsz, pack->map, mapoff,
pack->filesize - mapoff);
} else
err = got_inflate_to_mem_fd(&base_buf,
- &base_len, pack->fd);
- if (base_len < max_size) {
- uint8_t *p;
- p = reallocarray(base_buf, 1, max_size);
- if (p == NULL) {
- err = got_error_from_errno();
- goto done;
- }
- base_buf = p;
- }
+ &base_bufsz, pack->fd);
}
if (err)
goto done;
}
if (base_buf) {
- err = got_delta_apply_in_mem(base_buf, delta->delta_buf,
- delta->delta_len, accum_buf, &accum_size);
+ err = got_delta_apply_in_mem(base_buf, base_bufsz,
+ delta->delta_buf, delta->delta_len, accum_buf,
+ &accum_size, max_size);
n++;
} else {
err = got_delta_apply(base_file, delta->delta_buf,
/* Accumulated delta becomes the new base. */
if (base_buf) {
uint8_t *tmp = accum_buf;
+ /*
+ * Base buffer switches roles with accumulation
+ * buffer. Ensure it can hold the largest
+ * result in the delta chain. The initial
+ * allocation might have been smaller.
+ */
+ if (base_bufsz < max_size) {
+ uint8_t *p;
+ p = reallocarray(base_buf, 1, max_size);
+ if (p == NULL) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ base_buf = p;
+ base_bufsz = max_size;
+ }
accum_buf = base_buf;
base_buf = tmp;
} else {
const struct got_error *err = NULL;
struct got_delta *delta;
uint8_t *base_buf = NULL, *accum_buf = NULL;
- size_t accum_size;
+ size_t base_bufsz = 0, accum_size = 0;
uint64_t max_size;
int n = 0;
/* Deltas are ordered in ascending order. */
SIMPLEQ_FOREACH(delta, &deltas->entries, entry) {
if (n == 0) {
- size_t base_len;
size_t delta_data_offset;
/* Plain object types are the delta base. */
if (pack->map) {
size_t mapoff = (size_t)delta_data_offset;
err = got_inflate_to_mem_mmap(&base_buf,
- &base_len, pack->map, mapoff,
+ &base_bufsz, pack->map, mapoff,
pack->filesize - mapoff);
} else {
if (lseek(pack->fd, delta_data_offset, SEEK_SET)
goto done;
}
err = got_inflate_to_mem_fd(&base_buf,
- &base_len, pack->fd);
+ &base_bufsz, pack->fd);
}
if (err)
goto done;
- if (base_len < max_size) {
- uint8_t *p;
- p = reallocarray(base_buf, 1, max_size);
- if (p == NULL) {
- err = got_error_from_errno();
- goto done;
- }
- base_buf = p;
- }
n++;
continue;
}
- err = got_delta_apply_in_mem(base_buf, delta->delta_buf,
- delta->delta_len, accum_buf, &accum_size);
+ err = got_delta_apply_in_mem(base_buf, base_bufsz,
+ delta->delta_buf, delta->delta_len, accum_buf,
+ &accum_size, max_size);
n++;
if (err)
goto done;
if (n < deltas->nentries) {
/* Accumulated delta becomes the new base. */
uint8_t *tmp = accum_buf;
+ /*
+ * Base buffer switches roles with accumulation buffer.
+ * Ensure it can hold the largest result in the delta
+ * chain. Initial allocation might have been smaller.
+ */
+ if (base_bufsz < max_size) {
+ uint8_t *p;
+ p = reallocarray(base_buf, 1, max_size);
+ if (p == NULL) {
+ err = got_error_from_errno();
+ goto done;
+ }
+ base_buf = p;
+ base_bufsz = max_size;
+ }
accum_buf = base_buf;
base_buf = tmp;
}