1/*
2 * diff-delta.c: generate a delta between two buffers
3 *
4 * This code was greatly inspired by parts of LibXDiff from Davide Libenzi
5 * http://www.xmailserver.org/xdiff-lib.html
6 *
7 * Rewritten for GIT by Nicolas Pitre <nico@fluxnic.net>, (C) 2005-2007
8 *
9 * This code is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include "git-compat-util.h"
15#include "delta.h"
16
17/* maximum hash entry list for the same hash bucket */
18#define HASH_LIMIT 64
19
20#define RABIN_SHIFT 23
21#define RABIN_WINDOW 16
22
23static const unsigned int T[256] = {
24 0x00000000, 0xab59b4d1, 0x56b369a2, 0xfdeadd73, 0x063f6795, 0xad66d344,
25 0x508c0e37, 0xfbd5bae6, 0x0c7ecf2a, 0xa7277bfb, 0x5acda688, 0xf1941259,
26 0x0a41a8bf, 0xa1181c6e, 0x5cf2c11d, 0xf7ab75cc, 0x18fd9e54, 0xb3a42a85,
27 0x4e4ef7f6, 0xe5174327, 0x1ec2f9c1, 0xb59b4d10, 0x48719063, 0xe32824b2,
28 0x1483517e, 0xbfdae5af, 0x423038dc, 0xe9698c0d, 0x12bc36eb, 0xb9e5823a,
29 0x440f5f49, 0xef56eb98, 0x31fb3ca8, 0x9aa28879, 0x6748550a, 0xcc11e1db,
30 0x37c45b3d, 0x9c9defec, 0x6177329f, 0xca2e864e, 0x3d85f382, 0x96dc4753,
31 0x6b369a20, 0xc06f2ef1, 0x3bba9417, 0x90e320c6, 0x6d09fdb5, 0xc6504964,
32 0x2906a2fc, 0x825f162d, 0x7fb5cb5e, 0xd4ec7f8f, 0x2f39c569, 0x846071b8,
33 0x798aaccb, 0xd2d3181a, 0x25786dd6, 0x8e21d907, 0x73cb0474, 0xd892b0a5,
34 0x23470a43, 0x881ebe92, 0x75f463e1, 0xdeadd730, 0x63f67950, 0xc8afcd81,
35 0x354510f2, 0x9e1ca423, 0x65c91ec5, 0xce90aa14, 0x337a7767, 0x9823c3b6,
36 0x6f88b67a, 0xc4d102ab, 0x393bdfd8, 0x92626b09, 0x69b7d1ef, 0xc2ee653e,
37 0x3f04b84d, 0x945d0c9c, 0x7b0be704, 0xd05253d5, 0x2db88ea6, 0x86e13a77,
38 0x7d348091, 0xd66d3440, 0x2b87e933, 0x80de5de2, 0x7775282e, 0xdc2c9cff,
39 0x21c6418c, 0x8a9ff55d, 0x714a4fbb, 0xda13fb6a, 0x27f92619, 0x8ca092c8,
40 0x520d45f8, 0xf954f129, 0x04be2c5a, 0xafe7988b, 0x5432226d, 0xff6b96bc,
41 0x02814bcf, 0xa9d8ff1e, 0x5e738ad2, 0xf52a3e03, 0x08c0e370, 0xa39957a1,
42 0x584ced47, 0xf3155996, 0x0eff84e5, 0xa5a63034, 0x4af0dbac, 0xe1a96f7d,
43 0x1c43b20e, 0xb71a06df, 0x4ccfbc39, 0xe79608e8, 0x1a7cd59b, 0xb125614a,
44 0x468e1486, 0xedd7a057, 0x103d7d24, 0xbb64c9f5, 0x40b17313, 0xebe8c7c2,
45 0x16021ab1, 0xbd5bae60, 0x6cb54671, 0xc7ecf2a0, 0x3a062fd3, 0x915f9b02,
46 0x6a8a21e4, 0xc1d39535, 0x3c394846, 0x9760fc97, 0x60cb895b, 0xcb923d8a,
47 0x3678e0f9, 0x9d215428, 0x66f4eece, 0xcdad5a1f, 0x3047876c, 0x9b1e33bd,
48 0x7448d825, 0xdf116cf4, 0x22fbb187, 0x89a20556, 0x7277bfb0, 0xd92e0b61,
49 0x24c4d612, 0x8f9d62c3, 0x7836170f, 0xd36fa3de, 0x2e857ead, 0x85dcca7c,
50 0x7e09709a, 0xd550c44b, 0x28ba1938, 0x83e3ade9, 0x5d4e7ad9, 0xf617ce08,
51 0x0bfd137b, 0xa0a4a7aa, 0x5b711d4c, 0xf028a99d, 0x0dc274ee, 0xa69bc03f,
52 0x5130b5f3, 0xfa690122, 0x0783dc51, 0xacda6880, 0x570fd266, 0xfc5666b7,
53 0x01bcbbc4, 0xaae50f15, 0x45b3e48d, 0xeeea505c, 0x13008d2f, 0xb85939fe,
54 0x438c8318, 0xe8d537c9, 0x153feaba, 0xbe665e6b, 0x49cd2ba7, 0xe2949f76,
55 0x1f7e4205, 0xb427f6d4, 0x4ff24c32, 0xe4abf8e3, 0x19412590, 0xb2189141,
56 0x0f433f21, 0xa41a8bf0, 0x59f05683, 0xf2a9e252, 0x097c58b4, 0xa225ec65,
57 0x5fcf3116, 0xf49685c7, 0x033df00b, 0xa86444da, 0x558e99a9, 0xfed72d78,
58 0x0502979e, 0xae5b234f, 0x53b1fe3c, 0xf8e84aed, 0x17bea175, 0xbce715a4,
59 0x410dc8d7, 0xea547c06, 0x1181c6e0, 0xbad87231, 0x4732af42, 0xec6b1b93,
60 0x1bc06e5f, 0xb099da8e, 0x4d7307fd, 0xe62ab32c, 0x1dff09ca, 0xb6a6bd1b,
61 0x4b4c6068, 0xe015d4b9, 0x3eb80389, 0x95e1b758, 0x680b6a2b, 0xc352defa,
62 0x3887641c, 0x93ded0cd, 0x6e340dbe, 0xc56db96f, 0x32c6cca3, 0x999f7872,
63 0x6475a501, 0xcf2c11d0, 0x34f9ab36, 0x9fa01fe7, 0x624ac294, 0xc9137645,
64 0x26459ddd, 0x8d1c290c, 0x70f6f47f, 0xdbaf40ae, 0x207afa48, 0x8b234e99,
65 0x76c993ea, 0xdd90273b, 0x2a3b52f7, 0x8162e626, 0x7c883b55, 0xd7d18f84,
66 0x2c043562, 0x875d81b3, 0x7ab75cc0, 0xd1eee811
67};
68
69static const unsigned int U[256] = {
70 0x00000000, 0x7eb5200d, 0x5633f4cb, 0x2886d4c6, 0x073e5d47, 0x798b7d4a,
71 0x510da98c, 0x2fb88981, 0x0e7cba8e, 0x70c99a83, 0x584f4e45, 0x26fa6e48,
72 0x0942e7c9, 0x77f7c7c4, 0x5f711302, 0x21c4330f, 0x1cf9751c, 0x624c5511,
73 0x4aca81d7, 0x347fa1da, 0x1bc7285b, 0x65720856, 0x4df4dc90, 0x3341fc9d,
74 0x1285cf92, 0x6c30ef9f, 0x44b63b59, 0x3a031b54, 0x15bb92d5, 0x6b0eb2d8,
75 0x4388661e, 0x3d3d4613, 0x39f2ea38, 0x4747ca35, 0x6fc11ef3, 0x11743efe,
76 0x3eccb77f, 0x40799772, 0x68ff43b4, 0x164a63b9, 0x378e50b6, 0x493b70bb,
77 0x61bda47d, 0x1f088470, 0x30b00df1, 0x4e052dfc, 0x6683f93a, 0x1836d937,
78 0x250b9f24, 0x5bbebf29, 0x73386bef, 0x0d8d4be2, 0x2235c263, 0x5c80e26e,
79 0x740636a8, 0x0ab316a5, 0x2b7725aa, 0x55c205a7, 0x7d44d161, 0x03f1f16c,
80 0x2c4978ed, 0x52fc58e0, 0x7a7a8c26, 0x04cfac2b, 0x73e5d470, 0x0d50f47d,
81 0x25d620bb, 0x5b6300b6, 0x74db8937, 0x0a6ea93a, 0x22e87dfc, 0x5c5d5df1,
82 0x7d996efe, 0x032c4ef3, 0x2baa9a35, 0x551fba38, 0x7aa733b9, 0x041213b4,
83 0x2c94c772, 0x5221e77f, 0x6f1ca16c, 0x11a98161, 0x392f55a7, 0x479a75aa,
84 0x6822fc2b, 0x1697dc26, 0x3e1108e0, 0x40a428ed, 0x61601be2, 0x1fd53bef,
85 0x3753ef29, 0x49e6cf24, 0x665e46a5, 0x18eb66a8, 0x306db26e, 0x4ed89263,
86 0x4a173e48, 0x34a21e45, 0x1c24ca83, 0x6291ea8e, 0x4d29630f, 0x339c4302,
87 0x1b1a97c4, 0x65afb7c9, 0x446b84c6, 0x3adea4cb, 0x1258700d, 0x6ced5000,
88 0x4355d981, 0x3de0f98c, 0x15662d4a, 0x6bd30d47, 0x56ee4b54, 0x285b6b59,
89 0x00ddbf9f, 0x7e689f92, 0x51d01613, 0x2f65361e, 0x07e3e2d8, 0x7956c2d5,
90 0x5892f1da, 0x2627d1d7, 0x0ea10511, 0x7014251c, 0x5facac9d, 0x21198c90,
91 0x099f5856, 0x772a785b, 0x4c921c31, 0x32273c3c, 0x1aa1e8fa, 0x6414c8f7,
92 0x4bac4176, 0x3519617b, 0x1d9fb5bd, 0x632a95b0, 0x42eea6bf, 0x3c5b86b2,
93 0x14dd5274, 0x6a687279, 0x45d0fbf8, 0x3b65dbf5, 0x13e30f33, 0x6d562f3e,
94 0x506b692d, 0x2ede4920, 0x06589de6, 0x78edbdeb, 0x5755346a, 0x29e01467,
95 0x0166c0a1, 0x7fd3e0ac, 0x5e17d3a3, 0x20a2f3ae, 0x08242768, 0x76910765,
96 0x59298ee4, 0x279caee9, 0x0f1a7a2f, 0x71af5a22, 0x7560f609, 0x0bd5d604,
97 0x235302c2, 0x5de622cf, 0x725eab4e, 0x0ceb8b43, 0x246d5f85, 0x5ad87f88,
98 0x7b1c4c87, 0x05a96c8a, 0x2d2fb84c, 0x539a9841, 0x7c2211c0, 0x029731cd,
99 0x2a11e50b, 0x54a4c506, 0x69998315, 0x172ca318, 0x3faa77de, 0x411f57d3,
100 0x6ea7de52, 0x1012fe5f, 0x38942a99, 0x46210a94, 0x67e5399b, 0x19501996,
101 0x31d6cd50, 0x4f63ed5d, 0x60db64dc, 0x1e6e44d1, 0x36e89017, 0x485db01a,
102 0x3f77c841, 0x41c2e84c, 0x69443c8a, 0x17f11c87, 0x38499506, 0x46fcb50b,
103 0x6e7a61cd, 0x10cf41c0, 0x310b72cf, 0x4fbe52c2, 0x67388604, 0x198da609,
104 0x36352f88, 0x48800f85, 0x6006db43, 0x1eb3fb4e, 0x238ebd5d, 0x5d3b9d50,
105 0x75bd4996, 0x0b08699b, 0x24b0e01a, 0x5a05c017, 0x728314d1, 0x0c3634dc,
106 0x2df207d3, 0x534727de, 0x7bc1f318, 0x0574d315, 0x2acc5a94, 0x54797a99,
107 0x7cffae5f, 0x024a8e52, 0x06852279, 0x78300274, 0x50b6d6b2, 0x2e03f6bf,
108 0x01bb7f3e, 0x7f0e5f33, 0x57888bf5, 0x293dabf8, 0x08f998f7, 0x764cb8fa,
109 0x5eca6c3c, 0x207f4c31, 0x0fc7c5b0, 0x7172e5bd, 0x59f4317b, 0x27411176,
110 0x1a7c5765, 0x64c97768, 0x4c4fa3ae, 0x32fa83a3, 0x1d420a22, 0x63f72a2f,
111 0x4b71fee9, 0x35c4dee4, 0x1400edeb, 0x6ab5cde6, 0x42331920, 0x3c86392d,
112 0x133eb0ac, 0x6d8b90a1, 0x450d4467, 0x3bb8646a
113};
114
115struct index_entry {
116 const unsigned char *ptr;
117 unsigned int val;
118};
119
120struct unpacked_index_entry {
121 struct index_entry entry;
122 struct unpacked_index_entry *next;
123};
124
125struct delta_index {
126 unsigned long memsize;
127 const void *src_buf;
128 unsigned long src_size;
129 unsigned int hash_mask;
130 struct index_entry *hash[FLEX_ARRAY];
131};
132
133struct delta_index * create_delta_index(const void *buf, unsigned long bufsize)
134{
135 unsigned int i, hsize, hmask, entries, prev_val, *hash_count;
136 const unsigned char *data, *buffer = buf;
137 struct delta_index *index;
138 struct unpacked_index_entry *entry, **hash;
139 struct index_entry *packed_entry, **packed_hash;
140 void *mem;
141 unsigned long memsize;
142
143 if (!buf || !bufsize)
144 return NULL;
145
146 /* Determine index hash size. Note that indexing skips the
147 first byte to allow for optimizing the Rabin's polynomial
148 initialization in create_delta(). */
149 entries = (bufsize - 1) / RABIN_WINDOW;
150 if (bufsize >= 0xffffffffUL) {
151 /*
152 * Current delta format can't encode offsets into
153 * reference buffer with more than 32 bits.
154 */
155 entries = 0xfffffffeU / RABIN_WINDOW;
156 }
157 hsize = entries / 4;
158 for (i = 4; (1u << i) < hsize; i++);
159 hsize = 1 << i;
160 hmask = hsize - 1;
161
162 /* allocate lookup index */
163 memsize = sizeof(*hash) * hsize +
164 sizeof(*entry) * entries;
165 mem = malloc(memsize);
166 if (!mem)
167 return NULL;
168 hash = mem;
169 mem = hash + hsize;
170 entry = mem;
171
172 memset(hash, 0, hsize * sizeof(*hash));
173
174 /* allocate an array to count hash entries */
175 hash_count = calloc(hsize, sizeof(*hash_count));
176 if (!hash_count) {
177 free(hash);
178 return NULL;
179 }
180
181 /* then populate the index */
182 prev_val = ~0;
183 for (data = buffer + entries * RABIN_WINDOW - RABIN_WINDOW;
184 data >= buffer;
185 data -= RABIN_WINDOW) {
186 unsigned int val = 0;
187 for (i = 1; i <= RABIN_WINDOW; i++)
188 val = ((val << 8) | data[i]) ^ T[val >> RABIN_SHIFT];
189 if (val == prev_val) {
190 /* keep the lowest of consecutive identical blocks */
191 entry[-1].entry.ptr = data + RABIN_WINDOW;
192 --entries;
193 } else {
194 prev_val = val;
195 i = val & hmask;
196 entry->entry.ptr = data + RABIN_WINDOW;
197 entry->entry.val = val;
198 entry->next = hash[i];
199 hash[i] = entry++;
200 hash_count[i]++;
201 }
202 }
203
204 /*
205 * Determine a limit on the number of entries in the same hash
206 * bucket. This guards us against pathological data sets causing
207 * really bad hash distribution with most entries in the same hash
208 * bucket that would bring us to O(m*n) computing costs (m and n
209 * corresponding to reference and target buffer sizes).
210 *
211 * Make sure none of the hash buckets has more entries than
212 * we're willing to test. Otherwise we cull the entry list
213 * uniformly to still preserve a good repartition across
214 * the reference buffer.
215 */
216 for (i = 0; i < hsize; i++) {
217 int acc;
218
219 if (hash_count[i] <= HASH_LIMIT)
220 continue;
221
222 /* We leave exactly HASH_LIMIT entries in the bucket */
223 entries -= hash_count[i] - HASH_LIMIT;
224
225 entry = hash[i];
226 acc = 0;
227
228 /*
229 * Assume that this loop is gone through exactly
230 * HASH_LIMIT times and is entered and left with
231 * acc==0. So the first statement in the loop
232 * contributes (hash_count[i]-HASH_LIMIT)*HASH_LIMIT
233 * to the accumulator, and the inner loop consequently
234 * is run (hash_count[i]-HASH_LIMIT) times, removing
235 * one element from the list each time. Since acc
236 * balances out to 0 at the final run, the inner loop
237 * body can't be left with entry==NULL. So we indeed
238 * encounter entry==NULL in the outer loop only.
239 */
240 do {
241 acc += hash_count[i] - HASH_LIMIT;
242 if (acc > 0) {
243 struct unpacked_index_entry *keep = entry;
244 do {
245 entry = entry->next;
246 acc -= HASH_LIMIT;
247 } while (acc > 0);
248 keep->next = entry->next;
249 }
250 entry = entry->next;
251 } while (entry);
252 }
253 free(hash_count);
254
255 /*
256 * Now create the packed index in array form
257 * rather than linked lists.
258 */
259 memsize = sizeof(*index)
260 + sizeof(*packed_hash) * (hsize+1)
261 + sizeof(*packed_entry) * entries;
262 mem = malloc(memsize);
263 if (!mem) {
264 free(hash);
265 return NULL;
266 }
267
268 index = mem;
269 index->memsize = memsize;
270 index->src_buf = buf;
271 index->src_size = bufsize;
272 index->hash_mask = hmask;
273
274 mem = index->hash;
275 packed_hash = mem;
276 mem = packed_hash + (hsize+1);
277 packed_entry = mem;
278
279 for (i = 0; i < hsize; i++) {
280 /*
281 * Coalesce all entries belonging to one linked list
282 * into consecutive array entries.
283 */
284 packed_hash[i] = packed_entry;
285 for (entry = hash[i]; entry; entry = entry->next)
286 *packed_entry++ = entry->entry;
287 }
288
289 /* Sentinel value to indicate the length of the last hash bucket */
290 packed_hash[hsize] = packed_entry;
291
292 assert(packed_entry - (struct index_entry *)mem == entries);
293 free(hash);
294
295 return index;
296}
297
298void free_delta_index(struct delta_index *index)
299{
300 free(index);
301}
302
303unsigned long sizeof_delta_index(struct delta_index *index)
304{
305 if (index)
306 return index->memsize;
307 else
308 return 0;
309}
310
311/*
312 * The maximum size for any opcode sequence, including the initial header
313 * plus Rabin window plus biggest copy.
314 */
315#define MAX_OP_SIZE (5 + 5 + 1 + RABIN_WINDOW + 7)
316
317void *
318create_delta(const struct delta_index *index,
319 const void *trg_buf, unsigned long trg_size,
320 unsigned long *delta_size, unsigned long max_size)
321{
322 unsigned int i, val;
323 off_t outpos, moff;
324 size_t l, outsize, msize;
325 int inscnt;
326 const unsigned char *ref_data, *ref_top, *data, *top;
327 unsigned char *out;
328
329 *delta_size = 0;
330
331 if (!trg_buf || !trg_size)
332 return NULL;
333
334 outpos = 0;
335 outsize = 8192;
336 if (max_size && outsize >= max_size)
337 outsize = max_size + MAX_OP_SIZE + 1;
338 out = malloc(outsize);
339 if (!out)
340 return NULL;
341
342 /* store reference buffer size */
343 l = index->src_size;
344 while (l >= 0x80) {
345 out[outpos++] = l | 0x80;
346 l >>= 7;
347 }
348 out[outpos++] = l;
349
350 /* store target buffer size */
351 l = trg_size;
352 while (l >= 0x80) {
353 out[outpos++] = l | 0x80;
354 l >>= 7;
355 }
356 out[outpos++] = l;
357
358 ref_data = index->src_buf;
359 ref_top = ref_data + index->src_size;
360 data = trg_buf;
361 top = (const unsigned char *) trg_buf + trg_size;
362
363 outpos++;
364 val = 0;
365 for (i = 0; i < RABIN_WINDOW && data < top; i++, data++) {
366 out[outpos++] = *data;
367 val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT];
368 }
369 inscnt = i;
370
371 moff = 0;
372 msize = 0;
373 while (data < top) {
374 if (msize < 4096) {
375 struct index_entry *entry;
376 val ^= U[data[-RABIN_WINDOW]];
377 val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT];
378 i = val & index->hash_mask;
379 for (entry = index->hash[i]; entry < index->hash[i+1]; entry++) {
380 const unsigned char *ref = entry->ptr;
381 const unsigned char *src = data;
382 unsigned int ref_size = ref_top - ref;
383 if (entry->val != val)
384 continue;
385 if (ref_size > top - src)
386 ref_size = top - src;
387 if (ref_size <= msize)
388 break;
389 while (ref_size-- && *src++ == *ref)
390 ref++;
391 if (msize < ref - entry->ptr) {
392 /* this is our best match so far */
393 msize = ref - entry->ptr;
394 moff = entry->ptr - ref_data;
395 if (msize >= 4096) /* good enough */
396 break;
397 }
398 }
399 }
400
401 if (msize < 4) {
402 if (!inscnt)
403 outpos++;
404 out[outpos++] = *data++;
405 inscnt++;
406 if (inscnt == 0x7f) {
407 out[outpos - inscnt - 1] = inscnt;
408 inscnt = 0;
409 }
410 msize = 0;
411 } else {
412 unsigned int left;
413 unsigned char *op;
414
415 if (inscnt) {
416 while (moff && ref_data[moff-1] == data[-1]) {
417 /* we can match one byte back */
418 msize++;
419 moff--;
420 data--;
421 outpos--;
422 if (--inscnt)
423 continue;
424 outpos--; /* remove count slot */
425 inscnt--; /* make it -1 */
426 break;
427 }
428 out[outpos - inscnt - 1] = inscnt;
429 inscnt = 0;
430 }
431
432 /* A copy op is currently limited to 64KB (pack v2) */
433 left = (msize < 0x10000) ? 0 : (msize - 0x10000);
434 msize -= left;
435
436 op = out + outpos++;
437 i = 0x80;
438
439 if (moff & 0x000000ff)
440 out[outpos++] = moff >> 0, i |= 0x01;
441 if (moff & 0x0000ff00)
442 out[outpos++] = moff >> 8, i |= 0x02;
443 if (moff & 0x00ff0000)
444 out[outpos++] = moff >> 16, i |= 0x04;
445 if (moff & 0xff000000)
446 out[outpos++] = moff >> 24, i |= 0x08;
447
448 if (msize & 0x00ff)
449 out[outpos++] = msize >> 0, i |= 0x10;
450 if (msize & 0xff00)
451 out[outpos++] = msize >> 8, i |= 0x20;
452
453 *op = i;
454
455 data += msize;
456 moff += msize;
457 msize = left;
458
459 if (moff > 0xffffffff)
460 msize = 0;
461
462 if (msize < 4096) {
463 int j;
464 val = 0;
465 for (j = -RABIN_WINDOW; j < 0; j++)
466 val = ((val << 8) | data[j])
467 ^ T[val >> RABIN_SHIFT];
468 }
469 }
470
471 if (outpos >= outsize - MAX_OP_SIZE) {
472 void *tmp = out;
473 outsize = outsize * 3 / 2;
474 if (max_size && outsize >= max_size)
475 outsize = max_size + MAX_OP_SIZE + 1;
476 if (max_size && outpos > max_size)
477 break;
478 out = realloc(out, outsize);
479 if (!out) {
480 free(tmp);
481 return NULL;
482 }
483 }
484 }
485
486 if (inscnt)
487 out[outpos - inscnt - 1] = inscnt;
488
489 if (max_size && outpos > max_size) {
490 free(out);
491 return NULL;
492 }
493
494 *delta_size = outpos;
495 return out;
496}