/src/ghostpdl/pdf/pdf_cmap.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2020-2022 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | #include "strmio.h" |
17 | | #include "stream.h" |
18 | | #include "scanchar.h" |
19 | | |
20 | | #include "pdf_int.h" |
21 | | #include "pdf_cmap.h" |
22 | | |
23 | | #include "pdf_stack.h" |
24 | | #include "pdf_dict.h" |
25 | | #include "pdf_file.h" |
26 | | #include "pdf_fontps.h" |
27 | | #include "pdf_deref.h" |
28 | | |
29 | | static int pdfi_free_cmap_contents(pdf_cmap *cmap); |
30 | | |
31 | | static int cmap_usecmap_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
32 | 65 | { |
33 | 65 | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
34 | 65 | pdf_name *n = NULL; |
35 | 65 | pdf_cmap *upcmap = NULL; |
36 | 65 | int code = 0; |
37 | | |
38 | 65 | if (pdf_ps_stack_count(s) < 1) |
39 | 0 | return_error(gs_error_stackunderflow); |
40 | | |
41 | | /* If we've already got some definitions, ignore the usecmap op */ |
42 | 65 | if (pdficmap->code_space.num_ranges == 0) { |
43 | 65 | byte *nstr = NULL; |
44 | 65 | int len = s->cur[0].size; |
45 | | |
46 | 65 | if (pdf_ps_obj_has_type(&(s->cur[0]), PDF_PS_OBJ_NAME)) { |
47 | 65 | nstr = s->cur[0].val.name; |
48 | 65 | } |
49 | 0 | else if (pdf_ps_obj_has_type(&(s->cur[0]), PDF_PS_OBJ_STRING)) { |
50 | 0 | nstr = s->cur[0].val.string; |
51 | 0 | } |
52 | 0 | else { |
53 | 0 | code = gs_note_error(gs_error_typecheck); |
54 | 0 | } |
55 | 65 | if (code >= 0) |
56 | 65 | code = pdfi_name_alloc(pdficmap->ctx, nstr, len, (pdf_obj **)&n); |
57 | 65 | if (code >= 0) { |
58 | 65 | pdfi_countup(n); |
59 | 65 | code = pdfi_read_cmap(pdficmap->ctx, (pdf_obj *)n, &upcmap); |
60 | 65 | if (code >= 0) { |
61 | 42 | gx_code_space_range_t * ranges = |
62 | 42 | (gx_code_space_range_t *)gs_alloc_byte_array(mem, upcmap->code_space.num_ranges, |
63 | 42 | sizeof(gx_code_space_range_t), "cmap_usecmap_func(ranges)"); |
64 | 42 | if (ranges != NULL) { |
65 | 42 | int i; |
66 | 42 | memcpy(&pdficmap->code_space, &upcmap->code_space, sizeof(pdficmap->code_space)); |
67 | 114 | for (i = 0; i < upcmap->code_space.num_ranges; i++) { |
68 | 72 | memcpy(&(ranges[i]), &(upcmap->code_space.ranges[i]), sizeof(ranges[i])); |
69 | 72 | } |
70 | 42 | pdficmap->code_space.ranges = ranges; |
71 | 42 | memcpy(&pdficmap->cmap_range, &upcmap->cmap_range, sizeof(pdficmap->cmap_range)); |
72 | 42 | memcpy(&pdficmap->notdef_cmap_range, &upcmap->notdef_cmap_range, sizeof(pdficmap->notdef_cmap_range)); |
73 | | /* Once we've assumed control of these, NULL out entries for the sub-cmap. */ |
74 | 42 | upcmap->cmap_range.ranges = NULL; |
75 | 42 | upcmap->notdef_cmap_range.ranges = NULL; |
76 | | /* But we keep the subcmap itself because we rely on its storage */ |
77 | 42 | pdficmap->next = upcmap; |
78 | 42 | pdfi_countup(upcmap); |
79 | 42 | } |
80 | 42 | } |
81 | 65 | } |
82 | 65 | } |
83 | 65 | pdfi_countdown(upcmap); |
84 | 65 | pdfi_countdown(n); |
85 | 65 | if (code < 0) { |
86 | 23 | (void)pdf_ps_stack_pop(s, 1); |
87 | 23 | return code; |
88 | 23 | } |
89 | 42 | return pdf_ps_stack_pop(s, 1); |
90 | 65 | } |
91 | | |
92 | | #if 0 /* no longer used */ |
93 | | static int cmap_pushmark_func(gs_memory_t *mem, pdf_ps_ctx_t *stack, pdf_cmap *pdficmap) |
94 | | { |
95 | | return pdf_ps_stack_push_mark(stack); |
96 | | } |
97 | | #endif |
98 | | |
99 | | |
100 | | static int cmap_endcodespacerange_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
101 | 16.7k | { |
102 | 16.7k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
103 | 16.7k | int i, numranges, to_pop = pdf_ps_stack_count_to_mark(s, PDF_PS_OBJ_MARK); |
104 | 16.7k | gx_code_space_t *code_space = &pdficmap->code_space; |
105 | 16.7k | int nr = code_space->num_ranges; |
106 | 16.7k | gx_code_space_range_t *gcsr = code_space->ranges; |
107 | | |
108 | | /* increment to_pop to cover the mark object */ |
109 | 16.7k | numranges = to_pop++; |
110 | 16.7k | while (numranges % 2) numranges--; |
111 | 16.7k | if (numranges > 200) { |
112 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
113 | 0 | return_error(gs_error_syntaxerror); |
114 | 0 | } |
115 | | |
116 | 16.7k | if (numranges > 0 |
117 | 16.7k | && pdf_ps_obj_has_type(&(s->cur[0]), PDF_PS_OBJ_STRING) && s->cur[0].size <= MAX_CMAP_CODE_SIZE |
118 | 16.7k | && pdf_ps_obj_has_type(&(s->cur[-1]), PDF_PS_OBJ_STRING) && s->cur[-1].size <= MAX_CMAP_CODE_SIZE) { |
119 | | |
120 | 16.6k | code_space->num_ranges += numranges >> 1; |
121 | | |
122 | 16.6k | code_space->ranges = (gx_code_space_range_t *)gs_alloc_byte_array(mem, code_space->num_ranges, |
123 | 16.6k | sizeof(gx_code_space_range_t), "cmap_endcodespacerange_func(ranges)"); |
124 | 16.6k | if (code_space->ranges != NULL) { |
125 | 16.6k | if (nr > 0) { |
126 | 11 | memcpy(code_space->ranges, gcsr, nr); |
127 | 11 | gs_free_object(mem, gcsr, "cmap_endcodespacerange_func(gcsr"); |
128 | 11 | } |
129 | | |
130 | 33.5k | for (i = nr; i < code_space->num_ranges; i++) { |
131 | 16.8k | int si = i - nr; |
132 | 16.8k | int s1 = s->cur[-((si * 2) + 1)].size < MAX_CMAP_CODE_SIZE ? s->cur[-((si * 2) + 1)].size : MAX_CMAP_CODE_SIZE; |
133 | 16.8k | int s2 = s->cur[-(si * 2)].size < MAX_CMAP_CODE_SIZE ? s->cur[-(si * 2)].size : MAX_CMAP_CODE_SIZE; |
134 | | |
135 | 16.8k | memcpy(code_space->ranges[i].first, s->cur[-((si * 2) + 1)].val.string, s1); |
136 | 16.8k | memcpy(code_space->ranges[i].last, s->cur[-(si * 2)].val.string, s2); |
137 | 16.8k | code_space->ranges[i].size = s->cur[-(si * 2)].size; |
138 | 16.8k | } |
139 | 16.6k | } |
140 | 0 | else { |
141 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
142 | 0 | return_error(gs_error_VMerror); |
143 | 0 | } |
144 | 16.6k | } |
145 | 16.7k | return pdf_ps_stack_pop(s, to_pop); |
146 | 16.7k | } |
147 | | |
148 | | static int cmap_insert_map(pdfi_cmap_range_t *cmap_range, pdfi_cmap_range_map_t *pdfir) |
149 | 480M | { |
150 | 480M | if (cmap_range->ranges == NULL) { |
151 | 16.0k | cmap_range->ranges = cmap_range->ranges_tail = pdfir; |
152 | 16.0k | } |
153 | 480M | else { |
154 | 480M | cmap_range->ranges_tail->next = pdfir; |
155 | 480M | cmap_range->ranges_tail = pdfir; |
156 | 480M | } |
157 | 480M | cmap_range->numrangemaps++; |
158 | 480M | return 0; |
159 | 480M | } |
160 | | |
161 | | static int general_endcidrange_func(gs_memory_t *mem, pdf_ps_ctx_t *s, pdf_cmap *pdficmap, pdfi_cmap_range_t *cmap_range) |
162 | 21.5k | { |
163 | 21.5k | int ncodemaps, to_pop = pdf_ps_stack_count_to_mark(s, PDF_PS_OBJ_MARK); |
164 | 21.5k | int i, j; |
165 | 21.5k | pdfi_cmap_range_map_t *pdfir; |
166 | 21.5k | pdf_ps_stack_object_t *stobj; |
167 | | |
168 | | /* increment to_pop to cover the mark object */ |
169 | 21.5k | ncodemaps = to_pop++; |
170 | | /* mapping should have 3 objects on the stack: |
171 | | * startcode, endcode and basecid |
172 | | */ |
173 | 21.5k | while (ncodemaps % 3) ncodemaps--; |
174 | 21.5k | if (ncodemaps > 300) { |
175 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
176 | 0 | return_error(gs_error_syntaxerror); |
177 | 0 | } |
178 | | |
179 | 21.5k | stobj = &s->cur[-ncodemaps] + 1; |
180 | | |
181 | 1.81M | for (i = 0; i < ncodemaps; i += 3) { |
182 | 1.79M | int preflen, valuelen; |
183 | | |
184 | 1.79M | if (pdf_ps_obj_has_type(&(stobj[i + 2]), PDF_PS_OBJ_INTEGER) |
185 | 1.79M | && pdf_ps_obj_has_type(&(stobj[i + 1]), PDF_PS_OBJ_STRING) |
186 | 1.79M | && pdf_ps_obj_has_type(&(stobj[i]), PDF_PS_OBJ_STRING)){ |
187 | 1.79M | uint cidbase = stobj[i + 2].val.i; |
188 | | |
189 | | /* First, find the length of the prefix */ |
190 | 3.64M | for (preflen = 0; preflen < stobj[i].size; preflen++) { |
191 | 3.59M | if(stobj[i].val.string[preflen] != stobj[i + 1].val.string[preflen]) { |
192 | 1.73M | break; |
193 | 1.73M | } |
194 | 3.59M | } |
195 | | |
196 | 1.79M | if (preflen == stobj[i].size) { |
197 | 56.2k | preflen = 1; |
198 | 56.2k | } |
199 | | |
200 | 1.79M | if (preflen > MAX_CMAP_CODE_SIZE || stobj[i].size - preflen > MAX_CMAP_CODE_SIZE || stobj[i + 1].size - preflen > MAX_CMAP_CODE_SIZE |
201 | 1.79M | || stobj[i].size - preflen < 0 || stobj[i + 1].size - preflen < 0) { |
202 | 7 | (void)pdf_ps_stack_pop(s, to_pop); |
203 | 7 | return_error(gs_error_syntaxerror); |
204 | 7 | } |
205 | | |
206 | | /* Find how many bytes we need for the cidbase value */ |
207 | | /* We always store at least two bytes for the cidbase value */ |
208 | 1.79M | for (valuelen = 16; valuelen < 32 && (cidbase >> valuelen) > 0; valuelen += 1) |
209 | 1.79M | DO_NOTHING; |
210 | | |
211 | 1.79M | valuelen = ((valuelen + 7) & ~7) >> 3; |
212 | | |
213 | | /* The prefix is already directly in the gx_cmap_lookup_range_t |
214 | | * We need to store the lower and upper character codes, after lopping the prefix |
215 | | * off them. The upper and lower codes must be the same number of bytes. |
216 | | */ |
217 | 1.79M | j = sizeof(pdfi_cmap_range_map_t) + 2 * (stobj[i].size - preflen) + valuelen; |
218 | | |
219 | 1.79M | pdfir = (pdfi_cmap_range_map_t *)gs_alloc_bytes(mem, j, "cmap_endcidrange_func(pdfi_cmap_range_map_t)"); |
220 | 1.79M | if (pdfir != NULL) { |
221 | 1.79M | gx_cmap_lookup_range_t *gxr = &pdfir->range; |
222 | 1.79M | pdfir->next = NULL; |
223 | 1.79M | gxr->num_entries = 1; |
224 | 1.79M | gxr->keys.data = (byte *)&(pdfir[1]); |
225 | 1.79M | gxr->values.data = gxr->keys.data + 2 * (stobj[i].size - preflen); |
226 | | |
227 | 1.79M | gxr->cmap = NULL; |
228 | 1.79M | gxr->font_index = 0; |
229 | 1.79M | gxr->key_is_range = true; |
230 | 1.79M | gxr->value_type = cmap_range == &(pdficmap->cmap_range) ? CODE_VALUE_CID : CODE_VALUE_NOTDEF; |
231 | 1.79M | gxr->key_prefix_size = preflen; |
232 | 1.79M | gxr->key_size = stobj[i].size - gxr->key_prefix_size; |
233 | 1.79M | memcpy(gxr->key_prefix, stobj[i].val.string, gxr->key_prefix_size); |
234 | | |
235 | 1.79M | memcpy(gxr->keys.data, stobj[i].val.string + gxr->key_prefix_size, stobj[i].size - gxr->key_prefix_size); |
236 | 1.79M | memcpy(gxr->keys.data + (stobj[i].size - gxr->key_prefix_size), stobj[i + 1].val.string + gxr->key_prefix_size, stobj[i + 1].size - gxr->key_prefix_size); |
237 | | |
238 | 1.79M | gxr->keys.size = (stobj[i].size - gxr->key_prefix_size) + (stobj[i + 1].size - gxr->key_prefix_size); |
239 | 5.38M | for (j = 0; j < valuelen; j++) { |
240 | 3.59M | gxr->values.data[j] = (cidbase >> ((valuelen - 1 - j) * 8)) & 255; |
241 | 3.59M | } |
242 | 1.79M | gxr->value_size = valuelen; /* I'm not sure.... */ |
243 | 1.79M | gxr->values.size = valuelen; |
244 | 1.79M | if (cmap_insert_map(cmap_range, pdfir) < 0) break; |
245 | 1.79M | } |
246 | 0 | else { |
247 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
248 | 0 | return_error(gs_error_VMerror); |
249 | 0 | } |
250 | 1.79M | } |
251 | 1.79M | } |
252 | 21.5k | return pdf_ps_stack_pop(s, to_pop); |
253 | 21.5k | } |
254 | | |
255 | | static int cmap_endcidrange_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
256 | 21.4k | { |
257 | 21.4k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
258 | 21.4k | return general_endcidrange_func(mem, s, pdficmap, &pdficmap->cmap_range); |
259 | 21.4k | } |
260 | | |
261 | | static int cmap_endnotdefrange_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
262 | 79 | { |
263 | 79 | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
264 | 79 | return general_endcidrange_func(mem, s, pdficmap, &pdficmap->notdef_cmap_range); |
265 | 79 | } |
266 | | |
267 | | static int cmap_endfbrange_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
268 | 4.25k | { |
269 | 4.25k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
270 | 4.25k | int ncodemaps, to_pop = pdf_ps_stack_count_to_mark(s, PDF_PS_OBJ_MARK); |
271 | 4.25k | int i, j, k; |
272 | 4.25k | pdfi_cmap_range_map_t *pdfir; |
273 | 4.25k | pdf_ps_stack_object_t *stobj; |
274 | | |
275 | | /* increment to_pop to cover the mark object */ |
276 | 4.25k | ncodemaps = to_pop++; |
277 | | /* mapping should have 3 objects on the stack |
278 | | */ |
279 | 4.32k | while (ncodemaps % 3) ncodemaps--; |
280 | | |
281 | 4.25k | if (ncodemaps > 300) { |
282 | 5 | (void)pdf_ps_stack_pop(s, to_pop); |
283 | 5 | return_error(gs_error_syntaxerror); |
284 | 5 | } |
285 | | |
286 | 4.25k | stobj = &s->cur[-ncodemaps] + 1; |
287 | 80.2k | for (i = 0; i < ncodemaps; i += 3) { |
288 | | /* Lazy: to make the loop below simpler, put single |
289 | | values into a one element array |
290 | | */ |
291 | 75.9k | if (pdf_ps_obj_has_type(&(stobj[i + 2]), PDF_PS_OBJ_STRING)) { |
292 | 74.5k | pdf_ps_stack_object_t *arr; |
293 | 74.5k | arr = (pdf_ps_stack_object_t *) gs_alloc_bytes(mem, sizeof(pdf_ps_stack_object_t), "cmap_endfbrange_func(pdf_ps_stack_object_t"); |
294 | 74.5k | if (arr == NULL) { |
295 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
296 | 0 | return_error(gs_error_VMerror); |
297 | 0 | } |
298 | 74.5k | else { |
299 | 74.5k | memcpy(arr, &(stobj[i + 2]), sizeof(pdf_ps_stack_object_t)); |
300 | 74.5k | pdf_ps_make_array(&(stobj[i + 2]), arr, 1); |
301 | 74.5k | } |
302 | 74.5k | } |
303 | 75.9k | } |
304 | | |
305 | 4.25k | stobj = &s->cur[-ncodemaps] + 1; |
306 | | |
307 | 78.9k | for (i = 0; i < ncodemaps; i += 3) { |
308 | 74.7k | int preflen, valuelen; |
309 | | |
310 | 74.7k | if (pdf_ps_obj_has_type(&(stobj[i + 2]), PDF_PS_OBJ_ARRAY) |
311 | 74.7k | && pdf_ps_obj_has_type(&(stobj[i + 1]), PDF_PS_OBJ_STRING) |
312 | 74.7k | && pdf_ps_obj_has_type(&(stobj[i]), PDF_PS_OBJ_STRING)){ |
313 | | |
314 | 74.7k | uint cidbase = 0; |
315 | 74.7k | int srcs = 0, srce = 0; |
316 | 74.7k | int kslen = stobj[i].size; |
317 | | |
318 | 74.7k | if (kslen > 4) { |
319 | 25 | dprintf("CMap: value out of range\n"); |
320 | 25 | continue; |
321 | 25 | } |
322 | | |
323 | 196k | for (k = 0; k < stobj[i].size; k++) { |
324 | 121k | srcs |= stobj[i].val.string[stobj[i].size - k - 1] << (8 * k); |
325 | 121k | } |
326 | 196k | for (k = 0; k < stobj[i + 1].size; k++) { |
327 | 121k | srce |= stobj[i + 1].val.string[stobj[i + 1].size - k - 1] << (8 * k); |
328 | 121k | } |
329 | | |
330 | 476M | for (k = srcs; k < srce + 1; k++) { |
331 | 476M | int m, size; |
332 | 476M | char srccode[4]; /* we only deal with up to 4 bytes */ |
333 | 476M | char *psrccode = &(srccode[4 - kslen]); |
334 | | |
335 | 476M | if ((k - srcs) < stobj[i + 2].size) { |
336 | 129k | if (stobj[i + 2].val.arr[k - srcs].type != PDF_PS_OBJ_STRING) |
337 | 0 | continue; |
338 | 129k | size = stobj[i + 2].val.arr[k - srcs].size; |
339 | | |
340 | 129k | cidbase = 0; |
341 | 390k | for (m = 0; m < size; m++) { |
342 | 261k | cidbase |= stobj[i + 2].val.arr[k - srcs].val.string[size - m - 1] << (8 * m); |
343 | 261k | } |
344 | 129k | } |
345 | 476M | else { |
346 | 476M | cidbase++; |
347 | 476M | } |
348 | | |
349 | 1.13G | for (m = 0; m < kslen; m++) { |
350 | 659M | psrccode[m] = (k >> (8 * (kslen - m - 1))) & 0xff; |
351 | 659M | } |
352 | | |
353 | | /* Find how many bytes we need for the cidbase value */ |
354 | | /* We always store at least two bytes for the cidbase value */ |
355 | 5.11G | for (valuelen = 16; valuelen < 32 && (cidbase >> valuelen) > 0; valuelen += 1) |
356 | 4.63G | DO_NOTHING; |
357 | | |
358 | 476M | preflen = kslen > 4 ? 4 : kslen; |
359 | | |
360 | 476M | valuelen = ((valuelen + 7) & ~7) >> 3; |
361 | | |
362 | | /* The prefix is already directly in the gx_cmap_lookup_range_t |
363 | | * We need to store the lower and upper character codes, after lopping the prefix |
364 | | * off them. The upper and lower codes must be the same number of bytes. |
365 | | */ |
366 | 476M | j = sizeof(pdfi_cmap_range_map_t) + (kslen - preflen) + valuelen; |
367 | | |
368 | 476M | pdfir = (pdfi_cmap_range_map_t *)gs_alloc_bytes(mem, j, "cmap_endcidrange_func(pdfi_cmap_range_map_t)"); |
369 | 476M | if (pdfir != NULL) { |
370 | 476M | gx_cmap_lookup_range_t *gxr = &pdfir->range; |
371 | 476M | pdfir->next = NULL; |
372 | 476M | gxr->num_entries = 1; |
373 | 476M | gxr->keys.data = (byte *)&(pdfir[1]); |
374 | 476M | gxr->values.data = gxr->keys.data + (kslen - preflen); |
375 | | |
376 | 476M | gxr->cmap = NULL; |
377 | 476M | gxr->font_index = 0; |
378 | 476M | gxr->key_is_range = false; |
379 | 476M | gxr->value_type = CODE_VALUE_CID; |
380 | 476M | gxr->key_prefix_size = preflen; |
381 | 476M | gxr->key_size = kslen - gxr->key_prefix_size; |
382 | 476M | memcpy(gxr->key_prefix, psrccode, gxr->key_prefix_size); |
383 | | |
384 | 476M | memcpy(gxr->keys.data, psrccode + gxr->key_prefix_size, kslen - gxr->key_prefix_size); |
385 | | |
386 | 476M | gxr->keys.size = kslen - gxr->key_prefix_size; |
387 | 2.07G | for (j = 0; j < valuelen; j++) { |
388 | 1.59G | gxr->values.data[j] = (cidbase >> ((valuelen - 1 - j) * 8)) & 255; |
389 | 1.59G | } |
390 | 476M | gxr->value_size = valuelen; /* I'm not sure.... */ |
391 | 476M | gxr->values.size = valuelen; |
392 | 476M | if (cmap_insert_map(&(pdficmap->cmap_range), pdfir) < 0) break; |
393 | 476M | } |
394 | 55 | else { |
395 | 55 | (void)pdf_ps_stack_pop(s, to_pop); |
396 | 55 | return_error(gs_error_VMerror); |
397 | 55 | } |
398 | 476M | } |
399 | 74.7k | } |
400 | 74.7k | } |
401 | 4.19k | return pdf_ps_stack_pop(s, to_pop); |
402 | 4.25k | } |
403 | | |
404 | | static int general_endcidchar_func(gs_memory_t *mem, pdf_ps_ctx_t *s, pdf_cmap *pdficmap, pdfi_cmap_range_t *cmap_range) |
405 | 20.5k | { |
406 | 20.5k | int ncodemaps, to_pop = pdf_ps_stack_count_to_mark(s, PDF_PS_OBJ_MARK); |
407 | 20.5k | int i, j; |
408 | 20.5k | pdfi_cmap_range_map_t *pdfir; |
409 | 20.5k | pdf_ps_stack_object_t *stobj; |
410 | | |
411 | | /* increment to_pop to cover the mark object */ |
412 | 20.5k | ncodemaps = to_pop++; |
413 | | /* mapping should have 2 objects on the stack: |
414 | | * startcode, endcode and basecid |
415 | | */ |
416 | 20.5k | while (ncodemaps % 2) ncodemaps--; |
417 | | |
418 | 20.5k | if (ncodemaps > 200) { |
419 | 5 | (void)pdf_ps_stack_pop(s, to_pop); |
420 | 5 | return_error(gs_error_syntaxerror); |
421 | 5 | } |
422 | | |
423 | 20.5k | stobj = &s->cur[-ncodemaps] + 1; |
424 | | |
425 | 1.48M | for (i = 0; i < ncodemaps; i += 2) { |
426 | 1.46M | int preflen = 1, valuelen; |
427 | | |
428 | 1.46M | if (pdf_ps_obj_has_type(&(stobj[i + 1]), PDF_PS_OBJ_INTEGER) |
429 | 1.46M | && pdf_ps_obj_has_type(&(stobj[i]), PDF_PS_OBJ_STRING)) { |
430 | 1.46M | uint cidbase = stobj[i + 1].val.i; |
431 | | |
432 | | /* Find how many bytes we need for the cidbase value */ |
433 | | /* We always store at least two bytes for the cidbase value */ |
434 | 2.36M | for (valuelen = 16; valuelen < 32 && (cidbase >> valuelen) > 0; valuelen += 1) |
435 | 1.46M | DO_NOTHING; |
436 | | |
437 | 1.46M | preflen = stobj[i].size > 4 ? 4 : stobj[i].size; |
438 | | |
439 | 1.46M | valuelen = ((valuelen + 7) & ~7) >> 3; |
440 | | |
441 | | /* The prefix is already directly in the gx_cmap_lookup_range_t |
442 | | * We need to store the lower and upper character codes, after lopping the prefix |
443 | | * off them. The upper and lower codes must be the same number of bytes. |
444 | | */ |
445 | 1.46M | j = sizeof(pdfi_cmap_range_map_t) + (stobj[i].size - preflen) + valuelen; |
446 | | |
447 | 1.46M | pdfir = (pdfi_cmap_range_map_t *)gs_alloc_bytes(mem, j, "cmap_endcidrange_func(pdfi_cmap_range_map_t)"); |
448 | 1.46M | if (pdfir != NULL) { |
449 | 1.46M | gx_cmap_lookup_range_t *gxr = &pdfir->range; |
450 | 1.46M | pdfir->next = NULL; |
451 | 1.46M | gxr->num_entries = 1; |
452 | 1.46M | gxr->keys.data = (byte *)&(pdfir[1]); |
453 | 1.46M | gxr->values.data = gxr->keys.data + (stobj[i].size - preflen); |
454 | | |
455 | 1.46M | gxr->cmap = NULL; |
456 | 1.46M | gxr->font_index = 0; |
457 | 1.46M | gxr->key_is_range = false; |
458 | 1.46M | gxr->value_type = cmap_range == &(pdficmap->cmap_range) ? CODE_VALUE_CID : CODE_VALUE_NOTDEF; |
459 | 1.46M | gxr->key_prefix_size = preflen; |
460 | 1.46M | gxr->key_size = stobj[i].size - gxr->key_prefix_size; |
461 | 1.46M | memcpy(gxr->key_prefix, stobj[i].val.string, gxr->key_prefix_size); |
462 | | |
463 | 1.46M | memcpy(gxr->keys.data, stobj[i].val.string + gxr->key_prefix_size, stobj[i].size - gxr->key_prefix_size); |
464 | | |
465 | 1.46M | gxr->keys.size = stobj[i].size - gxr->key_prefix_size; |
466 | 4.52M | for (j = 0; j < valuelen; j++) { |
467 | 3.05M | gxr->values.data[j] = (cidbase >> ((valuelen - 1 - j) * 8)) & 255; |
468 | 3.05M | } |
469 | 1.46M | gxr->value_size = valuelen; /* I'm not sure.... */ |
470 | 1.46M | gxr->values.size = valuelen; |
471 | 1.46M | if (cmap_insert_map(cmap_range, pdfir) < 0) break; |
472 | 1.46M | } |
473 | 0 | else { |
474 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
475 | 0 | return_error(gs_error_VMerror); |
476 | 0 | } |
477 | 1.46M | } |
478 | 1.46M | } |
479 | 20.5k | return pdf_ps_stack_pop(s, to_pop); |
480 | 20.5k | } |
481 | | |
482 | | static int cmap_endcidchar_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
483 | 3.26k | { |
484 | 3.26k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
485 | 3.26k | return general_endcidchar_func(mem, s, pdficmap, &pdficmap->cmap_range); |
486 | 3.26k | } |
487 | | |
488 | | static int cmap_endnotdefchar_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
489 | 0 | { |
490 | 0 | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
491 | 0 | return general_endcidchar_func(mem, s, pdficmap, &pdficmap->notdef_cmap_range); |
492 | 0 | } |
493 | | |
494 | | static int cmap_endbfchar_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
495 | 17.3k | { |
496 | 17.3k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
497 | 17.3k | int ncodemaps = pdf_ps_stack_count_to_mark(s, PDF_PS_OBJ_MARK); |
498 | 17.3k | pdf_ps_stack_object_t *stobj; |
499 | 17.3k | int i, j; |
500 | | |
501 | 17.3k | if (ncodemaps > 200) { |
502 | 40 | (void)pdf_ps_stack_pop(s, ncodemaps); |
503 | 40 | return_error(gs_error_syntaxerror); |
504 | 40 | } |
505 | | |
506 | 17.2k | stobj = &s->cur[-ncodemaps] + 1; |
507 | | |
508 | 1.19M | for (i = 0; i < ncodemaps; i += 2) { |
509 | 1.17M | if (pdf_ps_obj_has_type(&(stobj[i + 1]), PDF_PS_OBJ_STRING)) { |
510 | 1.17M | byte *c = stobj[i + 1].val.string; |
511 | 1.17M | int l = stobj[i + 1].size; |
512 | 1.17M | unsigned int v = 0; |
513 | | |
514 | 3.88M | for (j = 0; j < l; j++) { |
515 | 2.70M | v += c[l - j - 1] << (8 * j); |
516 | 2.70M | } |
517 | 1.17M | pdf_ps_make_int(&(stobj[i + 1]), v); |
518 | 1.17M | } |
519 | 67 | else { |
520 | 67 | continue; |
521 | 67 | } |
522 | 1.17M | } |
523 | 17.2k | return general_endcidchar_func(mem, s, pdficmap, &pdficmap->cmap_range); |
524 | 17.3k | } |
525 | | |
526 | 374k | #define CMAP_NAME_AND_LEN(s) PDF_PS_OPER_NAME_AND_LEN(s) |
527 | | |
528 | | static int cmap_def_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
529 | 92.2k | { |
530 | 92.2k | int code = 0, code2 = 0; |
531 | 92.2k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
532 | | |
533 | 92.2k | if (pdf_ps_stack_count(s) < 2) { |
534 | 7.41k | return pdf_ps_stack_pop(s, 1); |
535 | 7.41k | } |
536 | | |
537 | 84.8k | if (pdf_ps_obj_has_type(&s->cur[-1], PDF_PS_OBJ_NAME)) { |
538 | 84.7k | if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("Registry"))) { |
539 | 7.44k | pdficmap->csi_reg.data = gs_alloc_bytes(mem, s->cur[0].size + 1, "cmap_def_func(Registry)"); |
540 | 7.44k | if (pdficmap->csi_reg.data != NULL) { |
541 | 7.44k | pdficmap->csi_reg.size = s->cur[0].size; |
542 | 7.44k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_STRING)) { |
543 | 7.44k | memcpy(pdficmap->csi_reg.data, s->cur[0].val.string, s->cur[0].size); |
544 | 7.44k | } |
545 | 0 | else { |
546 | 0 | memcpy(pdficmap->csi_reg.data, s->cur[0].val.name, s->cur[0].size); |
547 | 0 | } |
548 | 7.44k | pdficmap->csi_reg.data[pdficmap->csi_reg.size] = '\0'; |
549 | 7.44k | } |
550 | 0 | else { |
551 | 0 | code = gs_note_error(gs_error_VMerror); |
552 | 0 | } |
553 | 7.44k | } |
554 | 77.3k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("Ordering"))) { |
555 | 7.44k | pdficmap->csi_ord.data = gs_alloc_bytes(mem, s->cur[0].size + 1, "cmap_def_func(Ordering)"); |
556 | 7.44k | if (pdficmap->csi_ord.data != NULL) { |
557 | 7.44k | pdficmap->csi_ord.size = s->cur[0].size; |
558 | 7.44k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_STRING)) |
559 | 7.44k | memcpy(pdficmap->csi_ord.data, s->cur[0].val.string, s->cur[0].size); |
560 | 0 | else |
561 | 0 | memcpy(pdficmap->csi_ord.data, s->cur[0].val.name, s->cur[0].size); |
562 | 7.44k | pdficmap->csi_ord.data[pdficmap->csi_ord.size] = '\0'; |
563 | 7.44k | } |
564 | 0 | else { |
565 | 0 | code = gs_note_error(gs_error_VMerror); |
566 | 0 | } |
567 | 7.44k | } |
568 | 69.8k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("Supplement"))) { |
569 | 16.1k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { |
570 | 16.1k | pdficmap->csi_supplement = s->cur[0].val.i; |
571 | 16.1k | } |
572 | 1 | else { |
573 | 1 | pdficmap->csi_supplement = 0; |
574 | 1 | } |
575 | 16.1k | } |
576 | 53.6k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("CMapName"))) { |
577 | 16.6k | pdficmap->name.data = gs_alloc_bytes(mem, s->cur[0].size + 1, "cmap_def_func(CMapName)"); |
578 | 16.6k | if (pdficmap->name.data != NULL) { |
579 | 16.6k | pdficmap->name.size = s->cur[0].size; |
580 | 16.6k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_STRING)) |
581 | 0 | memcpy(pdficmap->name.data, s->cur[0].val.string, s->cur[0].size); |
582 | 16.6k | else |
583 | 16.6k | memcpy(pdficmap->name.data, s->cur[0].val.name, s->cur[0].size); |
584 | 16.6k | pdficmap->name.data[pdficmap->name.size] = '\0'; |
585 | 16.6k | } |
586 | 0 | else { |
587 | 0 | code = gs_note_error(gs_error_VMerror); |
588 | 0 | } |
589 | 16.6k | } |
590 | 37.0k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("CMapVersion"))) { |
591 | 6.78k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { |
592 | 84 | pdficmap->vers = (float)s->cur[0].val.i; |
593 | 84 | } |
594 | 6.69k | else if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_FLOAT)){ |
595 | 6.69k | pdficmap->vers = s->cur[0].val.f; |
596 | 6.69k | } |
597 | 0 | else { |
598 | 0 | pdficmap->vers = (float)0; |
599 | 0 | } |
600 | 6.78k | } |
601 | 30.2k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("CMapType"))) { |
602 | 16.2k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { |
603 | 16.2k | pdficmap->cmaptype = s->cur[0].val.i; |
604 | 16.2k | } |
605 | 0 | else { |
606 | 0 | pdficmap->cmaptype = 1; |
607 | 0 | } |
608 | 16.2k | } |
609 | 13.9k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("XUID"))) { |
610 | 6.71k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { |
611 | 6.71k | int len = s->cur->size; |
612 | 6.71k | pdficmap->uid.xvalues = (long *)gs_alloc_bytes(mem, len * sizeof(*pdficmap->uid.xvalues), "cmap_def_func(XUID)"); |
613 | 6.71k | if (pdficmap->uid.xvalues != NULL) { |
614 | 6.71k | int i; |
615 | 6.71k | pdf_ps_stack_object_t *a = s->cur->val.arr; |
616 | 6.71k | pdficmap->uid.id = -len; |
617 | 33.4k | for (i = 0; i < len; i++) { |
618 | 26.7k | if (pdf_ps_obj_has_type(&a[i], PDF_PS_OBJ_INTEGER)) { |
619 | 26.7k | pdficmap->uid.xvalues[i] = (long)a[i].val.i; |
620 | 26.7k | } |
621 | 0 | else { |
622 | 0 | pdficmap->uid.xvalues[i] = 0; |
623 | 0 | } |
624 | 26.7k | } |
625 | 6.71k | } |
626 | 0 | else { |
627 | 0 | code = gs_note_error(gs_error_VMerror); |
628 | 0 | } |
629 | 6.71k | } |
630 | 6.71k | } |
631 | 7.23k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("WMode"))) { |
632 | 6.90k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { |
633 | 6.90k | pdficmap->wmode = s->cur[0].val.i; |
634 | 6.90k | } |
635 | 0 | else { |
636 | 0 | pdficmap->wmode = 0; |
637 | 0 | } |
638 | 6.90k | } |
639 | 84.7k | } |
640 | | |
641 | 84.8k | code2 = pdf_ps_stack_pop(s, 2); |
642 | 84.8k | if (code < 0) |
643 | 0 | return code; |
644 | 84.8k | else |
645 | 84.8k | return code2; |
646 | 84.8k | } |
647 | | |
648 | | static pdf_ps_oper_list_t cmap_oper_list[] = |
649 | | { |
650 | | {PDF_PS_OPER_NAME_AND_LEN("usecmap"), cmap_usecmap_func}, |
651 | | {PDF_PS_OPER_NAME_AND_LEN("usefont"), ps_pdf_null_oper_func}, |
652 | | {PDF_PS_OPER_NAME_AND_LEN("beginusematrix"), ps_pdf_null_oper_func}, |
653 | | {PDF_PS_OPER_NAME_AND_LEN("endusematrix"), ps_pdf_null_oper_func}, |
654 | | {PDF_PS_OPER_NAME_AND_LEN("begincodespacerange"), pdf_ps_pop_and_pushmark_func}, |
655 | | {PDF_PS_OPER_NAME_AND_LEN("endcodespacerange"), cmap_endcodespacerange_func}, |
656 | | {PDF_PS_OPER_NAME_AND_LEN("begincmap"), ps_pdf_null_oper_func}, |
657 | | {PDF_PS_OPER_NAME_AND_LEN("beginbfchar"), pdf_ps_pop_and_pushmark_func}, |
658 | | {PDF_PS_OPER_NAME_AND_LEN("endbfchar"), cmap_endbfchar_func}, |
659 | | {PDF_PS_OPER_NAME_AND_LEN("beginbfrange"), pdf_ps_pop_and_pushmark_func}, |
660 | | {PDF_PS_OPER_NAME_AND_LEN("endbfrange"), cmap_endfbrange_func}, |
661 | | {PDF_PS_OPER_NAME_AND_LEN("begincidchar"), pdf_ps_pop_and_pushmark_func}, |
662 | | {PDF_PS_OPER_NAME_AND_LEN("endcidchar"), cmap_endcidchar_func}, |
663 | | {PDF_PS_OPER_NAME_AND_LEN("begincidrange"), pdf_ps_pop_and_pushmark_func}, |
664 | | {PDF_PS_OPER_NAME_AND_LEN("endcidrange"), cmap_endcidrange_func}, |
665 | | {PDF_PS_OPER_NAME_AND_LEN("beginnotdefchar"), pdf_ps_pop_and_pushmark_func}, |
666 | | {PDF_PS_OPER_NAME_AND_LEN("endnotdefchar"), cmap_endnotdefchar_func}, |
667 | | {PDF_PS_OPER_NAME_AND_LEN("beginnotdefrange"), pdf_ps_pop_and_pushmark_func}, |
668 | | {PDF_PS_OPER_NAME_AND_LEN("endnotdefrange"), cmap_endnotdefrange_func}, |
669 | | {PDF_PS_OPER_NAME_AND_LEN("findresource"), clear_stack_oper_func}, |
670 | | {PDF_PS_OPER_NAME_AND_LEN("dict"), pdf_ps_pop_oper_func}, |
671 | | {PDF_PS_OPER_NAME_AND_LEN("begin"), ps_pdf_null_oper_func}, |
672 | | {PDF_PS_OPER_NAME_AND_LEN("end"), ps_pdf_null_oper_func}, |
673 | | {PDF_PS_OPER_NAME_AND_LEN("pop"), ps_pdf_null_oper_func}, |
674 | | {PDF_PS_OPER_NAME_AND_LEN("def"), cmap_def_func}, |
675 | | {PDF_PS_OPER_NAME_AND_LEN("dup"), ps_pdf_null_oper_func}, |
676 | | {PDF_PS_OPER_NAME_AND_LEN("defineresource"), clear_stack_oper_func}, |
677 | | {PDF_PS_OPER_NAME_AND_LEN("beginrearrangedfont"), clear_stack_oper_func}, /* we should never see this */ |
678 | | {NULL, 0, NULL} |
679 | | }; |
680 | | |
681 | | static int |
682 | | pdf_cmap_open_file(pdf_context *ctx, gs_string *cmap_name, byte **buf, int64_t *buflen) |
683 | 6.68k | { |
684 | 6.68k | int code = 0; |
685 | 6.68k | stream *s; |
686 | 6.68k | char fname[gp_file_name_sizeof]; |
687 | 6.68k | const char *path_pfx = "CMap/"; |
688 | 6.68k | fname[0] = '\0'; |
689 | | |
690 | 6.68k | if (strlen(path_pfx) + cmap_name->size >= gp_file_name_sizeof) |
691 | 6 | return_error(gs_error_rangecheck); |
692 | | |
693 | 6.67k | strncat(fname, path_pfx, strlen(path_pfx)); |
694 | 6.67k | strncat(fname, (char *)cmap_name->data, cmap_name->size); |
695 | 6.67k | code = pdfi_open_resource_file(ctx, (const char *)fname, (const int)strlen(fname), &s); |
696 | 6.67k | if (code >= 0) { |
697 | 6.63k | sfseek(s, 0, SEEK_END); |
698 | 6.63k | *buflen = sftell(s); |
699 | 6.63k | sfseek(s, 0, SEEK_SET); |
700 | 6.63k | *buf = gs_alloc_bytes(ctx->memory, *buflen, "pdf_cmap_open_file(buf)"); |
701 | 6.63k | if (*buf != NULL) { |
702 | 6.63k | sfread(*buf, 1, *buflen, s); |
703 | 6.63k | } |
704 | 0 | else { |
705 | 0 | code = gs_note_error(gs_error_VMerror); |
706 | 0 | } |
707 | 6.63k | sfclose(s); |
708 | 6.63k | } |
709 | 6.67k | return code; |
710 | 6.68k | } |
711 | | |
712 | | static int |
713 | | pdfi_make_gs_cmap(gs_memory_t *mem, pdf_cmap *pdficmap) |
714 | 16.8k | { |
715 | 16.8k | int code = 0, i; |
716 | 16.8k | gs_cmap_adobe1_t *pgscmap = 0; |
717 | 16.8k | gx_cmap_lookup_range_t *lookups, *ndlookups = NULL; |
718 | 16.8k | pdfi_cmap_range_map_t *l; |
719 | | /* FIXME: We have to use gs_cmap_adobe1_alloc() to get the cmap procs |
720 | | but even if it gets passed num_ranges = 0 it still allocates |
721 | | a zero length array. Change gs_cmap_adobe1_alloc to work better |
722 | | */ |
723 | 16.8k | if ((code = gs_cmap_adobe1_alloc(&pgscmap, pdficmap->wmode, |
724 | 16.8k | pdficmap->name.data, |
725 | 16.8k | pdficmap->name.size, |
726 | 16.8k | 1, |
727 | 16.8k | 0, 0, 0, 0, 0, mem)) >= 0) { |
728 | 16.8k | gs_free_object(mem, pgscmap->code_space.ranges, "empty ranges"); |
729 | | |
730 | 16.8k | lookups = gs_alloc_struct_array(mem, pdficmap->cmap_range.numrangemaps, |
731 | 16.8k | gx_cmap_lookup_range_t, |
732 | 16.8k | &st_cmap_lookup_range_element, |
733 | 16.8k | "pdfi_make_gs_cmap(lookup ranges)"); |
734 | 16.8k | if (lookups == NULL) { |
735 | 3 | gs_free_object(mem, pgscmap, "pdfi_make_gs_cmap(pgscmap)"); |
736 | 3 | code = gs_note_error(gs_error_VMerror); |
737 | 3 | goto done; |
738 | 3 | } |
739 | 16.8k | if (pdficmap->notdef_cmap_range.numrangemaps > 0){ |
740 | 87 | ndlookups = gs_alloc_struct_array(mem, pdficmap->notdef_cmap_range.numrangemaps, |
741 | 87 | gx_cmap_lookup_range_t, |
742 | 87 | &st_cmap_lookup_range_element, |
743 | 87 | "pdfi_make_gs_cmap(notdef lookup ranges)"); |
744 | 87 | if (ndlookups == NULL) { |
745 | 0 | gs_free_object(mem, lookups, "pdfi_make_gs_cmap(lookups)"); |
746 | 0 | gs_free_object(mem, pgscmap, "pdfi_make_gs_cmap(pgscmap)"); |
747 | 0 | code = gs_note_error(gs_error_VMerror); |
748 | 0 | goto done; |
749 | 0 | } |
750 | 87 | } |
751 | 16.8k | pgscmap->def.lookup = lookups; |
752 | 16.8k | pgscmap->def.num_lookup = pdficmap->cmap_range.numrangemaps; |
753 | 16.8k | pgscmap->notdef.lookup = ndlookups; |
754 | 16.8k | pgscmap->notdef.num_lookup = pdficmap->notdef_cmap_range.numrangemaps; |
755 | | |
756 | 16.8k | pgscmap->CIDSystemInfo[0].Registry.data = pdficmap->csi_reg.data; |
757 | 16.8k | pgscmap->CIDSystemInfo[0].Registry.size = pdficmap->csi_reg.size; |
758 | 16.8k | pgscmap->CIDSystemInfo[0].Ordering.data = pdficmap->csi_ord.data; |
759 | 16.8k | pgscmap->CIDSystemInfo[0].Ordering.size = pdficmap->csi_ord.size; |
760 | 16.8k | pgscmap->CIDSystemInfo[0].Supplement = pdficmap->csi_supplement; |
761 | 16.8k | memcpy(&pgscmap->code_space, &pdficmap->code_space, sizeof(pgscmap->code_space)); |
762 | 16.8k | memcpy(&pgscmap->uid, &pdficmap->uid, sizeof(pdficmap->uid)); |
763 | 16.8k | l = pdficmap->cmap_range.ranges; |
764 | 24.7M | for (i = 0; i < pdficmap->cmap_range.numrangemaps && l != NULL; i++) { |
765 | 24.7M | memcpy(&lookups[i], &l->range, sizeof(gx_cmap_lookup_range_t)); |
766 | 24.7M | l = l->next; |
767 | 24.7M | } |
768 | | |
769 | 16.8k | l = pdficmap->notdef_cmap_range.ranges; |
770 | 16.9k | for (i = 0; i < pdficmap->notdef_cmap_range.numrangemaps && l != NULL; i++) { |
771 | 87 | memcpy(&ndlookups[i], &l->range, sizeof(gx_cmap_lookup_range_t)); |
772 | 87 | l = l->next; |
773 | 87 | } |
774 | | |
775 | 16.8k | pdficmap->gscmap = pgscmap; |
776 | 16.8k | } |
777 | | |
778 | 16.8k | done: |
779 | 16.8k | return code; |
780 | 16.8k | } |
781 | | |
782 | | int |
783 | | pdfi_read_cmap(pdf_context *ctx, pdf_obj *cmap, pdf_cmap **pcmap) |
784 | 17.2k | { |
785 | 17.2k | int code = 0; |
786 | 17.2k | pdf_cmap pdficm[3] = {0}; |
787 | 17.2k | pdf_cmap *pdfi_cmap = &(pdficm[1]); |
788 | 17.2k | byte *buf = NULL; |
789 | 17.2k | int64_t buflen = 0; |
790 | 17.2k | pdf_ps_ctx_t cmap_ctx; |
791 | | |
792 | 17.2k | pdfi_cmap->ctx = ctx; |
793 | 17.2k | switch (pdfi_type_of(cmap)) { |
794 | 6.68k | case PDF_NAME: |
795 | 6.68k | { |
796 | 6.68k | gs_string cmname; |
797 | 6.68k | pdf_name *cmapn = (pdf_name *)cmap; |
798 | 6.68k | cmname.data = cmapn->data; |
799 | 6.68k | cmname.size = cmapn->length; |
800 | 6.68k | code = pdf_cmap_open_file(ctx, &cmname, &buf, &buflen); |
801 | 6.68k | if (code < 0) |
802 | 41 | goto error_out; |
803 | 6.63k | break; |
804 | 6.68k | } |
805 | 10.5k | case PDF_STREAM: |
806 | 10.5k | { |
807 | 10.5k | pdf_obj *ucmap; |
808 | 10.5k | pdf_cmap *upcmap = NULL; |
809 | 10.5k | pdf_dict *cmap_dict = NULL; |
810 | | |
811 | 10.5k | code = pdfi_dict_from_obj(ctx, cmap, &cmap_dict); |
812 | 10.5k | if (code < 0) |
813 | 0 | goto error_out; |
814 | | |
815 | 10.5k | code = pdfi_dict_knownget(ctx, cmap_dict, "UseCMap", &ucmap); |
816 | 10.5k | if (code > 0) { |
817 | 0 | code = pdfi_read_cmap(ctx, ucmap, &upcmap); |
818 | 0 | pdfi_countdown(ucmap); |
819 | 0 | if (code >= 0) { |
820 | 0 | gx_code_space_range_t * ranges = |
821 | 0 | (gx_code_space_range_t *)gs_alloc_byte_array(ctx->memory, upcmap->code_space.num_ranges, |
822 | 0 | sizeof(gx_code_space_range_t), "cmap_usecmap_func(ranges)"); |
823 | 0 | if (ranges != NULL) { |
824 | 0 | int i; |
825 | 0 | memcpy(&pdfi_cmap->code_space, &upcmap->code_space, sizeof(pdfi_cmap->code_space)); |
826 | 0 | for (i = 0; i < upcmap->code_space.num_ranges; i++) { |
827 | 0 | memcpy(&(ranges[i]), &(upcmap->code_space.ranges[i]), sizeof(ranges[i])); |
828 | 0 | } |
829 | 0 | pdfi_cmap->code_space.ranges = ranges; |
830 | 0 | memcpy(&pdfi_cmap->cmap_range, &upcmap->cmap_range, sizeof(pdfi_cmap->cmap_range)); |
831 | 0 | memcpy(&pdfi_cmap->notdef_cmap_range, &upcmap->notdef_cmap_range, sizeof(pdfi_cmap->notdef_cmap_range)); |
832 | | /* Once we've assumed control of these, NULL out entries for the sub-cmap. */ |
833 | 0 | upcmap->cmap_range.ranges = NULL; |
834 | 0 | upcmap->notdef_cmap_range.ranges = NULL; |
835 | | /* But we keep the subcmap itself because we rely on its storage */ |
836 | 0 | pdfi_cmap->next = upcmap; |
837 | 0 | } |
838 | 0 | } |
839 | 0 | else { |
840 | 0 | pdfi_countdown(upcmap); |
841 | 0 | } |
842 | 0 | } |
843 | | |
844 | 10.5k | code = pdfi_stream_to_buffer(ctx, (pdf_stream *)cmap, &buf, &buflen); |
845 | 10.5k | if (code < 0) { |
846 | 23 | goto error_out; |
847 | 23 | } |
848 | 10.5k | break; |
849 | 10.5k | } |
850 | 10.5k | default: |
851 | 3 | code = gs_note_error(gs_error_typecheck); |
852 | 3 | goto error_out; |
853 | 17.2k | } |
854 | 17.1k | pdfi_cmap->ctx = ctx; |
855 | 17.1k | pdfi_cmap->buf = buf; |
856 | 17.1k | pdfi_cmap->buflen = buflen; |
857 | | |
858 | | /* In case of technically invalid CMap files which do not contain a CMapType, See Bug #690737. |
859 | | * This makes sure we clean up the CMap contents in pdfi_free_cmap() below. |
860 | | */ |
861 | 17.1k | pdfi_cmap->cmaptype = 1; |
862 | | |
863 | 17.1k | pdfi_pscript_stack_init(ctx, cmap_oper_list, (void *)pdfi_cmap, &cmap_ctx); |
864 | | |
865 | 17.1k | code = pdfi_pscript_interpret(&cmap_ctx, buf, buflen); |
866 | 17.1k | pdfi_pscript_stack_finit(&cmap_ctx); |
867 | 17.1k | if (code < 0) goto error_out; |
868 | | |
869 | 16.8k | code = pdfi_make_gs_cmap(ctx->memory, pdfi_cmap); |
870 | | |
871 | 16.8k | if (code >= 0) { |
872 | 16.8k | *pcmap = (pdf_cmap *)gs_alloc_bytes(ctx->memory, sizeof(pdf_cmap), "pdfi_read_cmap(*pcmap)"); |
873 | 16.8k | if (*pcmap != NULL) { |
874 | 16.8k | pdfi_cmap->type = PDF_CMAP; |
875 | 16.8k | pdfi_cmap->ctx = ctx; |
876 | 16.8k | pdfi_cmap->refcnt = 1; |
877 | 16.8k | pdfi_cmap->object_num = cmap->object_num; |
878 | 16.8k | pdfi_cmap->generation_num = cmap->generation_num; |
879 | 16.8k | pdfi_cmap->indirect_num = cmap->indirect_num; |
880 | 16.8k | pdfi_cmap->indirect_gen = cmap->indirect_gen; |
881 | 16.8k | memcpy(*pcmap, pdfi_cmap, sizeof(pdf_cmap)); |
882 | 16.8k | pdfi_cmap = *pcmap; |
883 | | /* object_num can be zero if the dictionary was defined inline */ |
884 | 16.8k | if (pdfi_cmap->object_num != 0) { |
885 | 10.2k | code = replace_cache_entry(ctx, (pdf_obj *)pdfi_cmap); |
886 | 10.2k | } |
887 | 16.8k | } |
888 | 16.8k | } |
889 | 3 | else { |
890 | 3 | goto error_out; |
891 | 3 | } |
892 | 16.8k | return 0; |
893 | | |
894 | 329 | error_out: |
895 | 329 | pdfi_free_cmap_contents(pdfi_cmap); |
896 | 329 | memset(pdfi_cmap, 0x00, sizeof(pdf_cmap)); |
897 | 329 | return code; |
898 | 16.8k | } |
899 | | |
900 | | static int pdfi_free_cmap_contents(pdf_cmap *cmap) |
901 | 17.2k | { |
902 | 17.2k | pdfi_cmap_range_map_t *pdfir; |
903 | 17.2k | gs_cmap_adobe1_t *pgscmap = cmap->gscmap; |
904 | | |
905 | 17.2k | if (pgscmap != NULL) { |
906 | 16.8k | gs_free_object(OBJ_MEMORY(cmap), pgscmap->def.lookup, "pdfi_free_cmap(def.lookup)"); |
907 | 16.8k | gs_free_object(OBJ_MEMORY(cmap), pgscmap->notdef.lookup, "pdfi_free_cmap(notdef.lookup)"); |
908 | 16.8k | (void)gs_cmap_free((gs_cmap_t *)pgscmap, OBJ_MEMORY(cmap)); |
909 | 16.8k | } |
910 | 17.2k | gs_free_object(OBJ_MEMORY(cmap), cmap->code_space.ranges, "pdfi_free_cmap(code_space.ranges"); |
911 | 17.2k | pdfir = cmap->cmap_range.ranges; |
912 | 480M | while (pdfir != NULL) { |
913 | 480M | pdfi_cmap_range_map_t *pdfir2 = pdfir->next; |
914 | 480M | gs_free_object(OBJ_MEMORY(cmap), pdfir, "pdfi_free_cmap(cmap_range.ranges"); |
915 | 480M | pdfir = pdfir2; |
916 | 480M | } |
917 | 17.2k | pdfir = cmap->notdef_cmap_range.ranges; |
918 | 17.2k | while (pdfir != NULL) { |
919 | 79 | pdfi_cmap_range_map_t *pdfir2 = pdfir->next; |
920 | 79 | gs_free_object(OBJ_MEMORY(cmap), pdfir, "pdfi_free_cmap(cmap_range.ranges"); |
921 | 79 | pdfir = pdfir2; |
922 | 79 | } |
923 | 17.2k | gs_free_object(OBJ_MEMORY(cmap), cmap->csi_reg.data, "pdfi_free_cmap(csi_reg.data"); |
924 | 17.2k | gs_free_object(OBJ_MEMORY(cmap), cmap->csi_ord.data, "pdfi_free_cmap(csi_ord.data"); |
925 | 17.2k | gs_free_object(OBJ_MEMORY(cmap), cmap->name.data, "pdfi_free_cmap(name.data"); |
926 | 17.2k | gs_free_object(OBJ_MEMORY(cmap), cmap->uid.xvalues, "pdfi_free_cmap(xuid.xvalues"); |
927 | 17.2k | pdfi_countdown(cmap->next); |
928 | 17.2k | gs_free_object(OBJ_MEMORY(cmap), cmap->buf, "pdfi_free_cmap(cmap->buf"); |
929 | | |
930 | 17.2k | return 0; |
931 | 17.2k | } |
932 | | |
933 | | int pdfi_free_cmap(pdf_obj *cmapo) |
934 | 16.8k | { |
935 | 16.8k | pdf_cmap *cmap = (pdf_cmap *)cmapo; |
936 | | /* |
937 | | * Note there is some inconsistency in the various specifications regarding CMapType; the |
938 | | * Adobe tech note 5014 specifically says it only documents CMaps with a CmapType of 0, the |
939 | | * PLRM says that CMapType can be 0 or 1, and the two are equivalent, the PDF Reference Manual |
940 | | * doesn't say, it just refers to tech note 5014 but the example has a CMapType of 1. The PDF |
941 | | * Reference does describe ToUnicode CMaps which have a CMapType of 2. |
942 | | */ |
943 | | /* Well it seems we have PDF files which use CMapType 2 CMaps as values for a /Encoding, which is |
944 | | * I believe incorrect, as these are ToUnicode CMaps.... |
945 | | * There's nothing for it, we'll just haev to free all CMaps for now. Note for Chris when implementing |
946 | | * ToUnicode CMaps, we'll obviously have to rely on the context to know whether a CMap is an Encoding |
947 | | * or a ToUnicode, we cna't use the CmMapType, just as you suspected. :-( |
948 | | * See bug #696449 633_R00728_E.pdf |
949 | | */ |
950 | | /* |
951 | | * For now, we represent ToUnicode CMaps (CMapType 2) in the same data structures as regular CMaps |
952 | | * (CMapType 0/1) so there is no reason (yet!) to differentiate between the two. |
953 | | */ |
954 | | |
955 | 16.8k | pdfi_free_cmap_contents(cmap); |
956 | 16.8k | gs_free_object(OBJ_MEMORY(cmap), cmap, "pdfi_free_cmap(cmap"); |
957 | 16.8k | return 0; |
958 | 16.8k | } |