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 
23 static 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 
69 static 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 
115 struct index_entry {
116 	const unsigned char *ptr;
117 	unsigned int val;
118 };
119 
120 struct unpacked_index_entry {
121 	struct index_entry entry;
122 	struct unpacked_index_entry *next;
123 };
124 
125 struct 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 
create_delta_index(const void * buf,unsigned long bufsize)133 struct 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 
free_delta_index(struct delta_index * index)298 void free_delta_index(struct delta_index *index)
299 {
300 	free(index);
301 }
302 
sizeof_delta_index(struct delta_index * index)303 unsigned 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 
317 void *
create_delta(const struct delta_index * index,const void * trg_buf,unsigned long trg_size,unsigned long * delta_size,unsigned long max_size)318 create_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 }
497