3 #include "delta-apply.h"
6 * This file was heavily cribbed from BinaryDelta.java in JGit, which
7 * itself was heavily cribbed from <code>patch-delta.c</code> in the
8 * GIT project. The original delta patching code was written by
9 * Nicolas Pitre <nico@cam.org>.
14 const unsigned char **delta
,
15 const unsigned char *end
)
17 const unsigned char *d
= *delta
;
19 unsigned int c
, shift
= 0;
25 r
|= (c
& 0x7f) << shift
;
35 const unsigned char *base
,
37 const unsigned char *delta
,
40 const unsigned char *delta_end
= delta
+ delta_len
;
41 size_t base_sz
, res_sz
;
42 unsigned char *res_dp
;
44 /* Check that the base size matches the data we were given;
45 * if not we would underflow while accessing data from the
46 * base object, resulting in data corruption or segfault.
48 if ((hdr_sz(&base_sz
, &delta
, delta_end
) < 0) || (base_sz
!= base_len
))
51 if (hdr_sz(&res_sz
, &delta
, delta_end
) < 0)
54 if ((res_dp
= git__malloc(res_sz
+ 1)) == NULL
)
56 res_dp
[res_sz
] = '\0';
60 while (delta
< delta_end
) {
61 unsigned char cmd
= *delta
++;
63 /* cmd is a copy instruction; copy from the base.
65 size_t off
= 0, len
= 0;
67 if (cmd
& 0x01) off
= *delta
++;
68 if (cmd
& 0x02) off
|= *delta
++ << 8;
69 if (cmd
& 0x04) off
|= *delta
++ << 16;
70 if (cmd
& 0x08) off
|= *delta
++ << 24;
72 if (cmd
& 0x10) len
= *delta
++;
73 if (cmd
& 0x20) len
|= *delta
++ << 8;
74 if (cmd
& 0x40) len
|= *delta
++ << 16;
75 if (!len
) len
= 0x10000;
77 if (base_len
< off
+ len
|| res_sz
< len
)
79 memcpy(res_dp
, base
+ off
, len
);
84 /* cmd is a literal insert instruction; copy from
85 * the delta stream itself.
87 if (delta_end
- delta
< cmd
|| res_sz
< cmd
)
89 memcpy(res_dp
, delta
, cmd
);
95 /* cmd == 0 is reserved for future encodings.
101 if (delta
!= delta_end
|| res_sz
)