]>
git.proxmox.com Git - libgit2.git/blob - src/delta-apply.c
2 * Copyright (C) 2009-2011 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
;
41 const unsigned char *base
,
43 const unsigned char *delta
,
46 const unsigned char *delta_end
= delta
+ delta_len
;
47 size_t base_sz
, res_sz
;
48 unsigned char *res_dp
;
50 /* Check that the base size matches the data we were given;
51 * if not we would underflow while accessing data from the
52 * base object, resulting in data corruption or segfault.
54 if ((hdr_sz(&base_sz
, &delta
, delta_end
) < 0) || (base_sz
!= base_len
))
55 return git__throw(GIT_ERROR
, "Failed to apply delta. Base size does not match given data");
57 if (hdr_sz(&res_sz
, &delta
, delta_end
) < 0)
58 return git__throw(GIT_ERROR
, "Failed to apply delta. Base size does not match given data");
60 if ((res_dp
= git__malloc(res_sz
+ 1)) == NULL
)
62 res_dp
[res_sz
] = '\0';
66 while (delta
< delta_end
) {
67 unsigned char cmd
= *delta
++;
69 /* cmd is a copy instruction; copy from the base.
71 size_t off
= 0, len
= 0;
73 if (cmd
& 0x01) off
= *delta
++;
74 if (cmd
& 0x02) off
|= *delta
++ << 8;
75 if (cmd
& 0x04) off
|= *delta
++ << 16;
76 if (cmd
& 0x08) off
|= *delta
++ << 24;
78 if (cmd
& 0x10) len
= *delta
++;
79 if (cmd
& 0x20) len
|= *delta
++ << 8;
80 if (cmd
& 0x40) len
|= *delta
++ << 16;
81 if (!len
) len
= 0x10000;
83 if (base_len
< off
+ len
|| res_sz
< len
)
85 memcpy(res_dp
, base
+ off
, len
);
90 /* cmd is a literal insert instruction; copy from
91 * the delta stream itself.
93 if (delta_end
- delta
< cmd
|| res_sz
< cmd
)
95 memcpy(res_dp
, delta
, cmd
);
101 /* cmd == 0 is reserved for future encodings.
107 if (delta
!= delta_end
|| res_sz
)
112 git__free(out
->data
);
114 return git__throw(GIT_ERROR
, "Failed to apply delta");