]>
git.proxmox.com Git - libgit2.git/blob - src/delta-apply.c
2 * Copyright (C) 2009-2012 the libgit2 contributors
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
9 #include "delta-apply.h"
12 * This file was heavily cribbed from BinaryDelta.java in JGit, which
13 * itself was heavily cribbed from <code>patch-delta.c</code> in the
14 * GIT project. The original delta patching code was written by
15 * Nicolas Pitre <nico@cam.org>.
20 const unsigned char **delta
,
21 const unsigned char *end
)
23 const unsigned char *d
= *delta
;
25 unsigned int c
, shift
= 0;
31 r
|= (c
& 0x7f) << shift
;
39 int git__delta_read_header(
40 const unsigned char *delta
,
45 const unsigned char *delta_end
= delta
+ delta_len
;
46 if ((hdr_sz(base_sz
, &delta
, delta_end
) < 0) ||
47 (hdr_sz(res_sz
, &delta
, delta_end
) < 0))
54 const unsigned char *base
,
56 const unsigned char *delta
,
59 const unsigned char *delta_end
= delta
+ delta_len
;
60 size_t base_sz
, res_sz
;
61 unsigned char *res_dp
;
63 /* Check that the base size matches the data we were given;
64 * if not we would underflow while accessing data from the
65 * base object, resulting in data corruption or segfault.
67 if ((hdr_sz(&base_sz
, &delta
, delta_end
) < 0) || (base_sz
!= base_len
)) {
68 giterr_set(GITERR_INVALID
, "Failed to apply delta. Base size does not match given data");
72 if (hdr_sz(&res_sz
, &delta
, delta_end
) < 0) {
73 giterr_set(GITERR_INVALID
, "Failed to apply delta. Base size does not match given data");
77 res_dp
= git__malloc(res_sz
+ 1);
78 GITERR_CHECK_ALLOC(res_dp
);
80 res_dp
[res_sz
] = '\0';
84 while (delta
< delta_end
) {
85 unsigned char cmd
= *delta
++;
87 /* cmd is a copy instruction; copy from the base.
89 size_t off
= 0, len
= 0;
91 if (cmd
& 0x01) off
= *delta
++;
92 if (cmd
& 0x02) off
|= *delta
++ << 8;
93 if (cmd
& 0x04) off
|= *delta
++ << 16;
94 if (cmd
& 0x08) off
|= *delta
++ << 24;
96 if (cmd
& 0x10) len
= *delta
++;
97 if (cmd
& 0x20) len
|= *delta
++ << 8;
98 if (cmd
& 0x40) len
|= *delta
++ << 16;
99 if (!len
) len
= 0x10000;
101 if (base_len
< off
+ len
|| res_sz
< len
)
103 memcpy(res_dp
, base
+ off
, len
);
108 /* cmd is a literal insert instruction; copy from
109 * the delta stream itself.
111 if (delta_end
- delta
< cmd
|| res_sz
< cmd
)
113 memcpy(res_dp
, delta
, cmd
);
119 /* cmd == 0 is reserved for future encodings.
125 if (delta
!= delta_end
|| res_sz
)
130 git__free(out
->data
);
132 giterr_set(GITERR_INVALID
, "Failed to apply delta");