1 #include "mupdf/fitz.h"
2 
3 #include <string.h>
4 #include <stdarg.h>
5 
6 fz_buffer *
fz_new_buffer(fz_context * ctx,size_t size)7 fz_new_buffer(fz_context *ctx, size_t size)
8 {
9 	fz_buffer *b;
10 
11 	size = size > 1 ? size : 16;
12 
13 	b = fz_malloc_struct(ctx, fz_buffer);
14 	b->refs = 1;
15 	fz_try(ctx)
16 	{
17 		b->data = Memento_label(fz_malloc(ctx, size), "fz_buffer_data");
18 	}
19 	fz_catch(ctx)
20 	{
21 		fz_free(ctx, b);
22 		fz_rethrow(ctx);
23 	}
24 	b->cap = size;
25 	b->len = 0;
26 	b->unused_bits = 0;
27 
28 	return b;
29 }
30 
31 fz_buffer *
fz_new_buffer_from_data(fz_context * ctx,unsigned char * data,size_t size)32 fz_new_buffer_from_data(fz_context *ctx, unsigned char *data, size_t size)
33 {
34 	fz_buffer *b = NULL;
35 
36 	fz_try(ctx)
37 	{
38 		b = fz_malloc_struct(ctx, fz_buffer);
39 		b->refs = 1;
40 		b->data = data;
41 		b->cap = size;
42 		b->len = size;
43 		b->unused_bits = 0;
44 	}
45 	fz_catch(ctx)
46 	{
47 		fz_free(ctx, data);
48 		fz_rethrow(ctx);
49 	}
50 
51 	return b;
52 }
53 
54 fz_buffer *
fz_new_buffer_from_shared_data(fz_context * ctx,const unsigned char * data,size_t size)55 fz_new_buffer_from_shared_data(fz_context *ctx, const unsigned char *data, size_t size)
56 {
57 	fz_buffer *b;
58 
59 	b = fz_malloc_struct(ctx, fz_buffer);
60 	b->refs = 1;
61 	b->data = (unsigned char *)data; /* cast away const */
62 	b->cap = size;
63 	b->len = size;
64 	b->unused_bits = 0;
65 	b->shared = 1;
66 
67 	return b;
68 }
69 
70 fz_buffer *
fz_new_buffer_from_copied_data(fz_context * ctx,const unsigned char * data,size_t size)71 fz_new_buffer_from_copied_data(fz_context *ctx, const unsigned char *data, size_t size)
72 {
73 	fz_buffer *b = fz_new_buffer(ctx, size);
74 	b->len = size;
75 	memcpy(b->data, data, size);
76 	return b;
77 }
78 
79 fz_buffer *
fz_new_buffer_from_base64(fz_context * ctx,const char * data,size_t size)80 fz_new_buffer_from_base64(fz_context *ctx, const char *data, size_t size)
81 {
82 	fz_buffer *buf = fz_new_buffer(ctx, size);
83 	const char *end = data + (size > 0 ? size : strlen(data));
84 	const char *s = data;
85 	fz_try(ctx)
86 	{
87 		while (s < end)
88 		{
89 			int c = *s++;
90 			if (c >= 'A' && c <= 'Z')
91 				fz_append_bits(ctx, buf, c - 'A', 6);
92 			else if (c >= 'a' && c <= 'z')
93 				fz_append_bits(ctx, buf, c - 'a' + 26, 6);
94 			else if (c >= '0' && c <= '9')
95 				fz_append_bits(ctx, buf, c - '0' + 52, 6);
96 			else if (c == '+')
97 				fz_append_bits(ctx, buf, 62, 6);
98 			else if (c == '/')
99 				fz_append_bits(ctx, buf, 63, 6);
100 		}
101 	}
102 	fz_catch(ctx)
103 	{
104 		fz_drop_buffer(ctx, buf);
105 		fz_rethrow(ctx);
106 	}
107 	return buf;
108 }
109 
110 fz_buffer *
fz_keep_buffer(fz_context * ctx,fz_buffer * buf)111 fz_keep_buffer(fz_context *ctx, fz_buffer *buf)
112 {
113 	return fz_keep_imp(ctx, buf, &buf->refs);
114 }
115 
116 void
fz_drop_buffer(fz_context * ctx,fz_buffer * buf)117 fz_drop_buffer(fz_context *ctx, fz_buffer *buf)
118 {
119 	if (fz_drop_imp(ctx, buf, &buf->refs))
120 	{
121 		if (!buf->shared)
122 			fz_free(ctx, buf->data);
123 		fz_free(ctx, buf);
124 	}
125 }
126 
127 void
fz_resize_buffer(fz_context * ctx,fz_buffer * buf,size_t size)128 fz_resize_buffer(fz_context *ctx, fz_buffer *buf, size_t size)
129 {
130 	if (buf->shared)
131 		fz_throw(ctx, FZ_ERROR_GENERIC, "cannot resize a buffer with shared storage");
132 	buf->data = fz_realloc(ctx, buf->data, size);
133 	buf->cap = size;
134 	if (buf->len > buf->cap)
135 		buf->len = buf->cap;
136 }
137 
138 void
fz_grow_buffer(fz_context * ctx,fz_buffer * buf)139 fz_grow_buffer(fz_context *ctx, fz_buffer *buf)
140 {
141 	size_t newsize = (buf->cap * 3) / 2;
142 	if (newsize == 0)
143 		newsize = 256;
144 	fz_resize_buffer(ctx, buf, newsize);
145 }
146 
147 static void
fz_ensure_buffer(fz_context * ctx,fz_buffer * buf,size_t min)148 fz_ensure_buffer(fz_context *ctx, fz_buffer *buf, size_t min)
149 {
150 	size_t newsize = buf->cap;
151 	if (newsize < 16)
152 		newsize = 16;
153 	while (newsize < min)
154 	{
155 		newsize = (newsize * 3) / 2;
156 	}
157 	fz_resize_buffer(ctx, buf, newsize);
158 }
159 
160 void
fz_trim_buffer(fz_context * ctx,fz_buffer * buf)161 fz_trim_buffer(fz_context *ctx, fz_buffer *buf)
162 {
163 	if (buf->cap > buf->len+1)
164 		fz_resize_buffer(ctx, buf, buf->len);
165 }
166 
167 void
fz_clear_buffer(fz_context * ctx,fz_buffer * buf)168 fz_clear_buffer(fz_context *ctx, fz_buffer *buf)
169 {
170 	buf->len = 0;
171 }
172 
173 void
fz_terminate_buffer(fz_context * ctx,fz_buffer * buf)174 fz_terminate_buffer(fz_context *ctx, fz_buffer *buf)
175 {
176 	/* ensure that there is a zero-byte after the end of the data */
177 	if (buf->len + 1 > buf->cap)
178 		fz_grow_buffer(ctx, buf);
179 	buf->data[buf->len] = 0;
180 }
181 
182 size_t
fz_buffer_storage(fz_context * ctx,fz_buffer * buf,unsigned char ** datap)183 fz_buffer_storage(fz_context *ctx, fz_buffer *buf, unsigned char **datap)
184 {
185 	if (datap)
186 		*datap = (buf ? buf->data : NULL);
187 	return (buf ? buf->len : 0);
188 }
189 
190 const char *
fz_string_from_buffer(fz_context * ctx,fz_buffer * buf)191 fz_string_from_buffer(fz_context *ctx, fz_buffer *buf)
192 {
193 	if (!buf)
194 		return "";
195 	fz_terminate_buffer(ctx, buf);
196 	return (const char *)buf->data;
197 }
198 
199 size_t
fz_buffer_extract(fz_context * ctx,fz_buffer * buf,unsigned char ** datap)200 fz_buffer_extract(fz_context *ctx, fz_buffer *buf, unsigned char **datap)
201 {
202 	size_t len = buf ? buf->len : 0;
203 	*datap = (buf ? buf->data : NULL);
204 
205 	if (buf)
206 	{
207 		buf->data = NULL;
208 		buf->len = 0;
209 	}
210 	return len;
211 }
212 
213 void
fz_append_buffer(fz_context * ctx,fz_buffer * buf,fz_buffer * extra)214 fz_append_buffer(fz_context *ctx, fz_buffer *buf, fz_buffer *extra)
215 {
216 	if (buf->cap - buf->len < extra->len)
217 	{
218 		buf->data = fz_realloc(ctx, buf->data, buf->len + extra->len);
219 		buf->cap = buf->len + extra->len;
220 	}
221 
222 	memcpy(buf->data + buf->len, extra->data, extra->len);
223 	buf->len += extra->len;
224 }
225 
226 void
fz_append_data(fz_context * ctx,fz_buffer * buf,const void * data,size_t len)227 fz_append_data(fz_context *ctx, fz_buffer *buf, const void *data, size_t len)
228 {
229 	if (buf->len + len > buf->cap)
230 		fz_ensure_buffer(ctx, buf, buf->len + len);
231 	memcpy(buf->data + buf->len, data, len);
232 	buf->len += len;
233 	buf->unused_bits = 0;
234 }
235 
236 void
fz_append_string(fz_context * ctx,fz_buffer * buf,const char * data)237 fz_append_string(fz_context *ctx, fz_buffer *buf, const char *data)
238 {
239 	size_t len = strlen(data);
240 	if (buf->len + len > buf->cap)
241 		fz_ensure_buffer(ctx, buf, buf->len + len);
242 	memcpy(buf->data + buf->len, data, len);
243 	buf->len += len;
244 	buf->unused_bits = 0;
245 }
246 
247 void
fz_append_byte(fz_context * ctx,fz_buffer * buf,int val)248 fz_append_byte(fz_context *ctx, fz_buffer *buf, int val)
249 {
250 	if (buf->len + 1 > buf->cap)
251 		fz_grow_buffer(ctx, buf);
252 	buf->data[buf->len++] = val;
253 	buf->unused_bits = 0;
254 }
255 
256 void
fz_append_rune(fz_context * ctx,fz_buffer * buf,int c)257 fz_append_rune(fz_context *ctx, fz_buffer *buf, int c)
258 {
259 	char data[10];
260 	int len = fz_runetochar(data, c);
261 	if (buf->len + len > buf->cap)
262 		fz_ensure_buffer(ctx, buf, buf->len + len);
263 	memcpy(buf->data + buf->len, data, len);
264 	buf->len += len;
265 	buf->unused_bits = 0;
266 }
267 
268 void
fz_append_int32_be(fz_context * ctx,fz_buffer * buf,int x)269 fz_append_int32_be(fz_context *ctx, fz_buffer *buf, int x)
270 {
271 	fz_append_byte(ctx, buf, (x >> 24) & 0xFF);
272 	fz_append_byte(ctx, buf, (x >> 16) & 0xFF);
273 	fz_append_byte(ctx, buf, (x >> 8) & 0xFF);
274 	fz_append_byte(ctx, buf, (x) & 0xFF);
275 }
276 
277 void
fz_append_int16_be(fz_context * ctx,fz_buffer * buf,int x)278 fz_append_int16_be(fz_context *ctx, fz_buffer *buf, int x)
279 {
280 	fz_append_byte(ctx, buf, (x >> 8) & 0xFF);
281 	fz_append_byte(ctx, buf, (x) & 0xFF);
282 }
283 
284 void
fz_append_int32_le(fz_context * ctx,fz_buffer * buf,int x)285 fz_append_int32_le(fz_context *ctx, fz_buffer *buf, int x)
286 {
287 	fz_append_byte(ctx, buf, (x)&0xFF);
288 	fz_append_byte(ctx, buf, (x>>8)&0xFF);
289 	fz_append_byte(ctx, buf, (x>>16)&0xFF);
290 	fz_append_byte(ctx, buf, (x>>24)&0xFF);
291 }
292 
293 void
fz_append_int16_le(fz_context * ctx,fz_buffer * buf,int x)294 fz_append_int16_le(fz_context *ctx, fz_buffer *buf, int x)
295 {
296 	fz_append_byte(ctx, buf, (x)&0xFF);
297 	fz_append_byte(ctx, buf, (x>>8)&0xFF);
298 }
299 
300 void
fz_append_bits(fz_context * ctx,fz_buffer * buf,int val,int bits)301 fz_append_bits(fz_context *ctx, fz_buffer *buf, int val, int bits)
302 {
303 	int shift;
304 
305 	/* Throughout this code, the invariant is that we need to write the
306 	 * bottom 'bits' bits of 'val' into the stream. On entry we assume
307 	 * that val & ((1<<bits)-1) == val, but we do not rely on this after
308 	 * having written the first partial byte. */
309 
310 	if (bits == 0)
311 		return;
312 
313 	/* buf->len always covers all the bits in the buffer, including
314 	 * any unused ones in the last byte, which will always be 0.
315 	 * buf->unused_bits = the number of unused bits in the last byte.
316 	 */
317 
318 	/* Find the amount we need to shift val up by so that it will be in
319 	 * the correct position to be inserted into any existing data byte. */
320 	shift = (buf->unused_bits - bits);
321 
322 	/* Extend the buffer as required before we start; that way we never
323 	 * fail part way during writing. If shift < 0, then we'll need -shift
324 	 * more bits. */
325 	if (shift < 0)
326 	{
327 		int extra = (7-shift)>>3; /* Round up to bytes */
328 		fz_ensure_buffer(ctx, buf, buf->len + extra);
329 	}
330 
331 	/* Write any bits that will fit into the existing byte */
332 	if (buf->unused_bits)
333 	{
334 		buf->data[buf->len-1] |= (shift >= 0 ? (((unsigned int)val)<<shift) : (((unsigned int)val)>>-shift));
335 		if (shift >= 0)
336 		{
337 			/* If we were shifting up, we're done. */
338 			buf->unused_bits -= bits;
339 			return;
340 		}
341 		/* The number of bits left to write is the number that didn't
342 		 * fit in this first byte. */
343 		bits = -shift;
344 	}
345 
346 	/* Write any whole bytes */
347 	while (bits >= 8)
348 	{
349 		bits -= 8;
350 		buf->data[buf->len++] = val>>bits;
351 	}
352 
353 	/* Write trailing bits (with 0's in unused bits) */
354 	if (bits > 0)
355 	{
356 		bits = 8-bits;
357 		buf->data[buf->len++] = val<<bits;
358 	}
359 	buf->unused_bits = bits;
360 }
361 
362 void
fz_append_bits_pad(fz_context * ctx,fz_buffer * buf)363 fz_append_bits_pad(fz_context *ctx, fz_buffer *buf)
364 {
365 	buf->unused_bits = 0;
366 }
367 
fz_append_emit(fz_context * ctx,void * buffer,int c)368 static void fz_append_emit(fz_context *ctx, void *buffer, int c)
369 {
370 	fz_append_byte(ctx, buffer, c);
371 }
372 
373 void
fz_append_printf(fz_context * ctx,fz_buffer * buffer,const char * fmt,...)374 fz_append_printf(fz_context *ctx, fz_buffer *buffer, const char *fmt, ...)
375 {
376 	va_list args;
377 	va_start(args, fmt);
378 	fz_format_string(ctx, buffer, fz_append_emit, fmt, args);
379 	va_end(args);
380 }
381 
382 void
fz_append_vprintf(fz_context * ctx,fz_buffer * buffer,const char * fmt,va_list args)383 fz_append_vprintf(fz_context *ctx, fz_buffer *buffer, const char *fmt, va_list args)
384 {
385 	fz_format_string(ctx, buffer, fz_append_emit, fmt, args);
386 }
387 
388 void
fz_append_pdf_string(fz_context * ctx,fz_buffer * buffer,const char * text)389 fz_append_pdf_string(fz_context *ctx, fz_buffer *buffer, const char *text)
390 {
391 	size_t len = 2;
392 	const char *s = text;
393 	char *d;
394 	char c;
395 
396 	while ((c = *s++) != 0)
397 	{
398 		switch (c)
399 		{
400 		case '\n':
401 		case '\r':
402 		case '\t':
403 		case '\b':
404 		case '\f':
405 		case '(':
406 		case ')':
407 		case '\\':
408 			len++;
409 			break;
410 		}
411 		len++;
412 	}
413 
414 	while(buffer->cap - buffer->len < len)
415 		fz_grow_buffer(ctx, buffer);
416 
417 	s = text;
418 	d = (char *)buffer->data + buffer->len;
419 	*d++ = '(';
420 	while ((c = *s++) != 0)
421 	{
422 		switch (c)
423 		{
424 		case '\n':
425 			*d++ = '\\';
426 			*d++ = 'n';
427 			break;
428 		case '\r':
429 			*d++ = '\\';
430 			*d++ = 'r';
431 			break;
432 		case '\t':
433 			*d++ = '\\';
434 			*d++ = 't';
435 			break;
436 		case '\b':
437 			*d++ = '\\';
438 			*d++ = 'b';
439 			break;
440 		case '\f':
441 			*d++ = '\\';
442 			*d++ = 'f';
443 			break;
444 		case '(':
445 			*d++ = '\\';
446 			*d++ = '(';
447 			break;
448 		case ')':
449 			*d++ = '\\';
450 			*d++ = ')';
451 			break;
452 		case '\\':
453 			*d++ = '\\';
454 			*d++ = '\\';
455 			break;
456 		default:
457 			*d++ = c;
458 		}
459 	}
460 	*d = ')';
461 	buffer->len += len;
462 }
463 
464 void
fz_md5_buffer(fz_context * ctx,fz_buffer * buffer,unsigned char digest[16])465 fz_md5_buffer(fz_context *ctx, fz_buffer *buffer, unsigned char digest[16])
466 {
467 	fz_md5 state;
468 	fz_md5_init(&state);
469 	if (buffer)
470 		fz_md5_update(&state, buffer->data, buffer->len);
471 	fz_md5_final(&state, digest);
472 }
473 
474 #ifdef TEST_BUFFER_WRITE
475 
476 #define TEST_LEN 1024
477 
478 void
fz_test_buffer_write(fz_context * ctx)479 fz_test_buffer_write(fz_context *ctx)
480 {
481 	fz_buffer *master = fz_new_buffer(ctx, TEST_LEN);
482 	fz_buffer *copy = fz_new_buffer(ctx, TEST_LEN);
483 	fz_stream *stm;
484 	int i, j, k;
485 
486 	/* Make us a dummy buffer */
487 	for (i = 0; i < TEST_LEN; i++)
488 	{
489 		master->data[i] = rand();
490 	}
491 	master->len = TEST_LEN;
492 
493 	/* Now copy that buffer several times, checking it for validity */
494 	stm = fz_open_buffer(ctx, master);
495 	for (i = 0; i < 256; i++)
496 	{
497 		memset(copy->data, i, TEST_LEN);
498 		copy->len = 0;
499 		j = TEST_LEN * 8;
500 		do
501 		{
502 			k = (rand() & 31)+1;
503 			if (k > j)
504 				k = j;
505 			fz_append_bits(ctx, copy, fz_read_bits(ctx, stm, k), k);
506 			j -= k;
507 		}
508 		while (j);
509 
510 		if (memcmp(copy->data, master->data, TEST_LEN) != 0)
511 			fprintf(stderr, "Copied buffer is different!\n");
512 		fz_seek(stm, 0, 0);
513 	}
514 	fz_drop_stream(stm);
515 	fz_drop_buffer(ctx, master);
516 	fz_drop_buffer(ctx, copy);
517 }
518 #endif
519