/src/ghostpdl/pdf/pdf_cmap.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2020-2025 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., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, 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 | 301 | { |
33 | 301 | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
34 | 301 | pdf_name *n = NULL; |
35 | 301 | pdf_cmap *upcmap = NULL; |
36 | 301 | int code = 0; |
37 | | |
38 | 301 | if (pdf_ps_stack_count(s) < 1) |
39 | 3 | return_error(gs_error_stackunderflow); |
40 | | |
41 | | /* If we've already got some definitions, ignore the usecmap op */ |
42 | 298 | if (pdficmap->code_space.num_ranges == 0) { |
43 | 298 | byte *nstr = NULL; |
44 | 298 | int len = s->cur[0].size; |
45 | | |
46 | 298 | if (pdf_ps_obj_has_type(&(s->cur[0]), PDF_PS_OBJ_NAME)) { |
47 | 298 | nstr = s->cur[0].val.name; |
48 | 298 | } |
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 | 298 | if (code >= 0) |
56 | 298 | code = pdfi_name_alloc(pdficmap->ctx, nstr, len, (pdf_obj **)&n); |
57 | 298 | if (code >= 0) { |
58 | 298 | pdfi_countup(n); |
59 | 298 | code = pdfi_read_cmap(pdficmap->ctx, (pdf_obj *)n, &upcmap); |
60 | 298 | if (code >= 0) { |
61 | 278 | gx_code_space_range_t * ranges = |
62 | 278 | (gx_code_space_range_t *)gs_alloc_byte_array(mem, upcmap->code_space.num_ranges, |
63 | 278 | sizeof(gx_code_space_range_t), "cmap_usecmap_func(ranges)"); |
64 | 278 | if (ranges != NULL) { |
65 | 278 | int i; |
66 | 278 | memcpy(&pdficmap->code_space, &upcmap->code_space, sizeof(pdficmap->code_space)); |
67 | 664 | for (i = 0; i < upcmap->code_space.num_ranges; i++) { |
68 | 386 | memcpy(&(ranges[i]), &(upcmap->code_space.ranges[i]), sizeof(ranges[i])); |
69 | 386 | } |
70 | 278 | pdficmap->code_space.ranges = ranges; |
71 | 278 | memcpy(&pdficmap->cmap_range, &upcmap->cmap_range, sizeof(pdficmap->cmap_range)); |
72 | 278 | 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 | 278 | upcmap->cmap_range.ranges = NULL; |
75 | 278 | upcmap->notdef_cmap_range.ranges = NULL; |
76 | | /* But we keep the subcmap itself because we rely on its storage */ |
77 | 278 | pdficmap->next = upcmap; |
78 | 278 | pdfi_countup(upcmap); |
79 | 278 | } |
80 | 278 | } |
81 | 298 | } |
82 | 298 | } |
83 | 298 | pdfi_countdown(upcmap); |
84 | 298 | pdfi_countdown(n); |
85 | 298 | if (code < 0) { |
86 | 20 | (void)pdf_ps_stack_pop(s, 1); |
87 | 20 | return code; |
88 | 20 | } |
89 | 278 | return pdf_ps_stack_pop(s, 1); |
90 | 298 | } |
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 | 78.0k | { |
102 | 78.0k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
103 | 78.0k | int i, numranges, to_pop = pdf_ps_stack_count_to_mark(s, PDF_PS_OBJ_MARK); |
104 | 78.0k | gx_code_space_t *code_space = &pdficmap->code_space; |
105 | 78.0k | int nr = code_space->num_ranges; |
106 | 78.0k | gx_code_space_range_t *gcsr = code_space->ranges; |
107 | | |
108 | | /* increment to_pop to cover the mark object */ |
109 | 78.0k | numranges = to_pop++; |
110 | 78.1k | while (numranges % 2) numranges--; |
111 | | |
112 | | /* The following hard limit is an implementation limit */ |
113 | 78.0k | if (numranges < 0 || numranges + 1 > PDF_PS_STACK_MAX) { |
114 | 403 | pdfi_set_error(s->pdfi_ctx, 0, NULL, E_PDF_BAD_TYPE0_CMAP, "cmap_endcodespacerange_func", NULL); |
115 | 403 | return_error(gs_error_syntaxerror); |
116 | 403 | } |
117 | | |
118 | | /* The following "soft" limit is according to the spec */ |
119 | 77.6k | if (numranges > 200) { |
120 | 0 | int code; |
121 | 0 | if ((code = pdfi_set_warning_stop(s->pdfi_ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_LIMITCHECK_TYPE0_CMAP, "cmap_endcodespacerange_func", NULL)) < 0) { |
122 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
123 | 0 | return code; |
124 | 0 | } |
125 | 0 | } |
126 | | |
127 | 77.6k | if (numranges > 0 |
128 | 77.6k | && pdf_ps_obj_has_type(&(s->cur[0]), PDF_PS_OBJ_STRING) && s->cur[0].size <= MAX_CMAP_CODE_SIZE |
129 | 77.6k | && pdf_ps_obj_has_type(&(s->cur[-1]), PDF_PS_OBJ_STRING) && s->cur[-1].size <= MAX_CMAP_CODE_SIZE) { |
130 | | |
131 | 77.5k | code_space->num_ranges += numranges >> 1; |
132 | | |
133 | 77.5k | code_space->ranges = (gx_code_space_range_t *)gs_alloc_byte_array(mem, code_space->num_ranges, |
134 | 77.5k | sizeof(gx_code_space_range_t), "cmap_endcodespacerange_func(ranges)"); |
135 | 77.5k | if (code_space->ranges != NULL) { |
136 | 77.5k | if (nr > 0) { |
137 | 42 | memcpy(code_space->ranges, gcsr, nr * sizeof(gx_code_space_range_t)); |
138 | 42 | gs_free_object(mem, gcsr, "cmap_endcodespacerange_func(gcsr"); |
139 | 42 | } |
140 | | |
141 | 155k | for (i = nr; i < code_space->num_ranges; i++) { |
142 | 78.4k | int si = i - nr; |
143 | 78.4k | int s1 = s->cur[-((si * 2) + 1)].size < MAX_CMAP_CODE_SIZE ? s->cur[-((si * 2) + 1)].size : MAX_CMAP_CODE_SIZE; |
144 | 78.4k | int s2 = s->cur[-(si * 2)].size < MAX_CMAP_CODE_SIZE ? s->cur[-(si * 2)].size : MAX_CMAP_CODE_SIZE; |
145 | | |
146 | 78.4k | memcpy(code_space->ranges[i].first, s->cur[-((si * 2) + 1)].val.string, s1); |
147 | 78.4k | memcpy(code_space->ranges[i].last, s->cur[-(si * 2)].val.string, s2); |
148 | 78.4k | code_space->ranges[i].size = s->cur[-(si * 2)].size; |
149 | 78.4k | } |
150 | 77.5k | } |
151 | 0 | else { |
152 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
153 | 0 | return_error(gs_error_VMerror); |
154 | 0 | } |
155 | 77.5k | } |
156 | 77.6k | return pdf_ps_stack_pop(s, to_pop); |
157 | 77.6k | } |
158 | | |
159 | | static int cmap_insert_map(pdfi_cmap_range_t *cmap_range, pdfi_cmap_range_map_t *pdfir) |
160 | 14.8M | { |
161 | 14.8M | if (cmap_range->ranges == NULL) { |
162 | 75.6k | cmap_range->ranges = cmap_range->ranges_tail = pdfir; |
163 | 75.6k | } |
164 | 14.7M | else { |
165 | 14.7M | cmap_range->ranges_tail->next = pdfir; |
166 | 14.7M | cmap_range->ranges_tail = pdfir; |
167 | 14.7M | } |
168 | 14.8M | cmap_range->numrangemaps++; |
169 | 14.8M | return 0; |
170 | 14.8M | } |
171 | | |
172 | | static int general_endcidrange_func(gs_memory_t *mem, pdf_ps_ctx_t *s, pdf_cmap *pdficmap, pdfi_cmap_range_t *cmap_range) |
173 | 135k | { |
174 | 135k | int ncodemaps, to_pop = pdf_ps_stack_count_to_mark(s, PDF_PS_OBJ_MARK); |
175 | 135k | unsigned int i, j; |
176 | 135k | pdfi_cmap_range_map_t *pdfir; |
177 | 135k | pdf_ps_stack_object_t *stobj; |
178 | | |
179 | | /* increment to_pop to cover the mark object */ |
180 | 135k | ncodemaps = to_pop++; |
181 | | /* mapping should have 3 objects on the stack: |
182 | | * startcode, endcode and basecid |
183 | | */ |
184 | 135k | while (ncodemaps % 3) ncodemaps--; |
185 | | |
186 | | /* The following hard limit is an implementation limit */ |
187 | 135k | if (ncodemaps < 0 || ncodemaps + 1 > PDF_PS_STACK_MAX) { |
188 | 13 | pdfi_set_error(s->pdfi_ctx, 0, NULL, E_PDF_BAD_TYPE0_CMAP, "general_endcidrange_func", NULL); |
189 | 13 | return_error(gs_error_syntaxerror); |
190 | 13 | } |
191 | | |
192 | | /* The following "soft" limit is according to the spec */ |
193 | 135k | if (ncodemaps > 300) { |
194 | 2 | int code; |
195 | 2 | if ((code = pdfi_set_warning_stop(s->pdfi_ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_LIMITCHECK_TYPE0_CMAP, "general_endcidrange_func", NULL)) < 0) { |
196 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
197 | 0 | return code; |
198 | 0 | } |
199 | 2 | } |
200 | | |
201 | 135k | stobj = &s->cur[-ncodemaps] + 1; |
202 | | |
203 | 11.6M | for (i = 0; i < ncodemaps; i += 3) { |
204 | 11.5M | int preflen, valuelen; |
205 | | |
206 | 11.5M | if (pdf_ps_obj_has_type(&(stobj[i + 2]), PDF_PS_OBJ_INTEGER) |
207 | 11.5M | && pdf_ps_obj_has_type(&(stobj[i + 1]), PDF_PS_OBJ_STRING) |
208 | 11.5M | && pdf_ps_obj_has_type(&(stobj[i]), PDF_PS_OBJ_STRING) |
209 | 11.5M | && pdf_ps_obj_size(&(stobj[i])) > 0 |
210 | 11.5M | && pdf_ps_obj_size(&(stobj[i])) == pdf_ps_obj_size(&(stobj[i + 1]))){ |
211 | | |
212 | 11.5M | uint cidbase = stobj[i + 2].val.i; |
213 | | |
214 | | /* First, find the length of the prefix */ |
215 | 23.7M | for (preflen = 0; preflen < stobj[i].size; preflen++) { |
216 | 23.1M | if(stobj[i].val.string[preflen] != stobj[i + 1].val.string[preflen]) { |
217 | 10.9M | break; |
218 | 10.9M | } |
219 | 23.1M | } |
220 | | |
221 | 11.5M | if (preflen == stobj[i].size) { |
222 | 593k | preflen = 1; |
223 | 593k | } |
224 | | |
225 | 11.5M | if (preflen > MAX_CMAP_CODE_SIZE || stobj[i].size - preflen > MAX_CMAP_CODE_SIZE || stobj[i + 1].size - preflen > MAX_CMAP_CODE_SIZE |
226 | 11.5M | || ((int64_t)stobj[i].size) - preflen < 0 || ((int64_t)stobj[i + 1].size) - preflen < 0) { |
227 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
228 | 0 | return_error(gs_error_syntaxerror); |
229 | 0 | } |
230 | | |
231 | | /* Find how many bytes we need for the cidbase value */ |
232 | | /* We always store at least two bytes for the cidbase value */ |
233 | 11.5M | for (valuelen = 16; valuelen < 32 && (cidbase >> valuelen) > 0; valuelen += 1) |
234 | 11.5M | DO_NOTHING; |
235 | | |
236 | 11.5M | valuelen = ((valuelen + 7) & ~7) >> 3; |
237 | | |
238 | | /* The prefix is already directly in the gx_cmap_lookup_range_t |
239 | | * We need to store the lower and upper character codes, after lopping the prefix |
240 | | * off them. The upper and lower codes must be the same number of bytes. |
241 | | */ |
242 | 11.5M | j = sizeof(pdfi_cmap_range_map_t) + 2 * (stobj[i].size - preflen) + valuelen; |
243 | | |
244 | 11.5M | pdfir = (pdfi_cmap_range_map_t *)gs_alloc_bytes(mem, j, "cmap_endcidrange_func(pdfi_cmap_range_map_t)"); |
245 | 11.5M | if (pdfir != NULL) { |
246 | 11.5M | gx_cmap_lookup_range_t *gxr = &pdfir->range; |
247 | 11.5M | pdfir->next = NULL; |
248 | 11.5M | gxr->num_entries = 1; |
249 | 11.5M | gxr->keys.data = (byte *)&(pdfir[1]); |
250 | 11.5M | gxr->values.data = gxr->keys.data + 2 * (stobj[i].size - preflen); |
251 | | |
252 | 11.5M | gxr->cmap = NULL; |
253 | 11.5M | gxr->font_index = 0; |
254 | 11.5M | gxr->key_is_range = true; |
255 | 11.5M | gxr->value_type = cmap_range == &(pdficmap->cmap_range) ? CODE_VALUE_CID : CODE_VALUE_NOTDEF; |
256 | 11.5M | gxr->key_prefix_size = preflen; |
257 | 11.5M | gxr->key_size = stobj[i].size - gxr->key_prefix_size; |
258 | 11.5M | memcpy(gxr->key_prefix, stobj[i].val.string, gxr->key_prefix_size); |
259 | | |
260 | 11.5M | memcpy(gxr->keys.data, stobj[i].val.string + gxr->key_prefix_size, stobj[i].size - gxr->key_prefix_size); |
261 | 11.5M | 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); |
262 | | |
263 | 11.5M | gxr->keys.size = (stobj[i].size - gxr->key_prefix_size) + (stobj[i + 1].size - gxr->key_prefix_size); |
264 | 34.6M | for (j = 0; j < valuelen; j++) { |
265 | 23.1M | gxr->values.data[j] = (cidbase >> ((valuelen - 1 - j) * 8)) & 255; |
266 | 23.1M | } |
267 | 11.5M | gxr->value_size = valuelen; /* I'm not sure.... */ |
268 | 11.5M | gxr->values.size = valuelen; |
269 | 11.5M | if (cmap_insert_map(cmap_range, pdfir) < 0) break; |
270 | 11.5M | } |
271 | 0 | else { |
272 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
273 | 0 | return_error(gs_error_VMerror); |
274 | 0 | } |
275 | 11.5M | } |
276 | 11.5M | } |
277 | 135k | return pdf_ps_stack_pop(s, to_pop); |
278 | 135k | } |
279 | | |
280 | | static int cmap_endcidrange_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
281 | 135k | { |
282 | 135k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
283 | 135k | return general_endcidrange_func(mem, s, pdficmap, &pdficmap->cmap_range); |
284 | 135k | } |
285 | | |
286 | | static int cmap_endnotdefrange_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
287 | 375 | { |
288 | 375 | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
289 | 375 | return general_endcidrange_func(mem, s, pdficmap, &pdficmap->notdef_cmap_range); |
290 | 375 | } |
291 | | |
292 | | static int cmap_endfbrange_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
293 | 20.2k | { |
294 | 20.2k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
295 | 20.2k | int ncodemaps, to_pop = pdf_ps_stack_count_to_mark(s, PDF_PS_OBJ_MARK); |
296 | 20.2k | unsigned int i, j, k; |
297 | 20.2k | pdfi_cmap_range_map_t *pdfir; |
298 | 20.2k | pdf_ps_stack_object_t *stobj; |
299 | | |
300 | | /* increment to_pop to cover the mark object */ |
301 | 20.2k | ncodemaps = to_pop++; |
302 | | /* mapping should have 3 objects on the stack |
303 | | */ |
304 | 20.9k | while (ncodemaps % 3) ncodemaps--; |
305 | | |
306 | | /* The following hard limit is an implementation limit */ |
307 | 20.2k | if (ncodemaps < 0 || ncodemaps + 1 > PDF_PS_STACK_MAX) { |
308 | 36 | pdfi_set_error(s->pdfi_ctx, 0, NULL, E_PDF_BAD_TYPE0_CMAP, "cmap_endfbrange_func", NULL); |
309 | 36 | return_error(gs_error_syntaxerror); |
310 | 36 | } |
311 | | /* The following "soft" limit is according to the spec */ |
312 | | |
313 | 20.2k | if (ncodemaps > 300) { |
314 | 135 | int code; |
315 | 135 | if ((code = pdfi_set_warning_stop(s->pdfi_ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_LIMITCHECK_TYPE0_CMAP, "cmap_endfbrange_func", NULL)) < 0) { |
316 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
317 | 0 | return code; |
318 | 0 | } |
319 | 135 | } |
320 | | |
321 | 20.2k | stobj = &s->cur[-ncodemaps] + 1; |
322 | 465k | for (i = 0; i < ncodemaps; i += 3) { |
323 | | /* Lazy: to make the loop below simpler, put single |
324 | | values into a one element array |
325 | | */ |
326 | 445k | if (pdf_ps_obj_has_type(&(stobj[i + 2]), PDF_PS_OBJ_STRING)) { |
327 | 434k | pdf_ps_stack_object_t *arr; |
328 | 434k | arr = (pdf_ps_stack_object_t *) gs_alloc_bytes(mem, sizeof(pdf_ps_stack_object_t), "cmap_endfbrange_func(pdf_ps_stack_object_t"); |
329 | 434k | if (arr == NULL) { |
330 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
331 | 0 | return_error(gs_error_VMerror); |
332 | 0 | } |
333 | 434k | else { |
334 | 434k | memcpy(arr, &(stobj[i + 2]), sizeof(pdf_ps_stack_object_t)); |
335 | 434k | pdf_ps_make_array(&(stobj[i + 2]), arr, 1); |
336 | 434k | } |
337 | 434k | } |
338 | 445k | } |
339 | | |
340 | 20.2k | stobj = &s->cur[-ncodemaps] + 1; |
341 | | |
342 | 463k | for (i = 0; i < ncodemaps; i += 3) { |
343 | 443k | int preflen, valuelen; |
344 | | |
345 | 443k | if (pdf_ps_obj_has_type(&(stobj[i + 2]), PDF_PS_OBJ_ARRAY) |
346 | 443k | && pdf_ps_obj_has_type(&(stobj[i + 1]), PDF_PS_OBJ_STRING) |
347 | 443k | && pdf_ps_obj_has_type(&(stobj[i]), PDF_PS_OBJ_STRING) |
348 | 443k | && pdf_ps_obj_size(&(stobj[i + 1])) > 0 |
349 | 443k | && pdf_ps_obj_size(&(stobj[i])) > 0){ |
350 | | |
351 | 432k | uint cidbase; |
352 | 432k | int m, size; |
353 | | |
354 | 432k | if (stobj[i + 2].size < 1) |
355 | 27 | continue; |
356 | | |
357 | 432k | else if (stobj[i + 2].size == 1) { |
358 | 430k | if (stobj[i + 2].val.arr[0].type != PDF_PS_OBJ_STRING) |
359 | 0 | continue; |
360 | | |
361 | 430k | size = stobj[i + 2].val.arr[0].size; |
362 | | |
363 | 430k | cidbase = 0; |
364 | 1.29M | for (m = 0; m < size; m++) { |
365 | 866k | cidbase |= stobj[i + 2].val.arr[0].val.string[size - m - 1] << (8 * m); |
366 | 866k | } |
367 | | |
368 | | /* First, find the length of the prefix */ |
369 | 906k | for (preflen = 0; preflen < stobj[i].size; preflen++) { |
370 | 726k | if(stobj[i].val.string[preflen] != stobj[i + 1].val.string[preflen]) { |
371 | 250k | break; |
372 | 250k | } |
373 | 726k | } |
374 | | |
375 | 430k | if (preflen == stobj[i].size) { |
376 | 180k | preflen = 1; |
377 | 180k | } |
378 | | |
379 | 430k | if (preflen > MAX_CMAP_CODE_SIZE || stobj[i].size - preflen > MAX_CMAP_CODE_SIZE || stobj[i + 1].size - preflen > MAX_CMAP_CODE_SIZE |
380 | 430k | || ((int64_t)stobj[i].size) - preflen < 0 || ((int64_t)stobj[i + 1].size) - preflen < 0) { |
381 | 74 | (void)pdf_ps_stack_pop(s, to_pop); |
382 | 74 | return_error(gs_error_syntaxerror); |
383 | 74 | } |
384 | | |
385 | | /* Find how many bytes we need for the cidbase value */ |
386 | | /* We always store at least two bytes for the cidbase value */ |
387 | 487k | for (valuelen = 16; valuelen < 32 && (cidbase >> valuelen) > 0; valuelen += 1) |
388 | 430k | DO_NOTHING; |
389 | | |
390 | 430k | valuelen = ((valuelen + 7) & ~7) >> 3; |
391 | | |
392 | | /* The prefix is already directly in the gx_cmap_lookup_range_t |
393 | | * We need to store the lower and upper character codes, after lopping the prefix |
394 | | * off them. The upper and lower codes must be the same number of bytes. |
395 | | */ |
396 | 430k | j = sizeof(pdfi_cmap_range_map_t) + 2 * (stobj[i].size - preflen) + valuelen; |
397 | | |
398 | 430k | pdfir = (pdfi_cmap_range_map_t *)gs_alloc_bytes(mem, j, "cmap_endcidrange_func(pdfi_cmap_range_map_t)"); |
399 | 430k | if (pdfir != NULL) { |
400 | 430k | gx_cmap_lookup_range_t *gxr = &pdfir->range; |
401 | 430k | pdfir->next = NULL; |
402 | 430k | gxr->num_entries = 1; |
403 | 430k | gxr->keys.data = (byte *)&(pdfir[1]); |
404 | 430k | gxr->values.data = gxr->keys.data + 2 * (stobj[i].size - preflen); |
405 | | |
406 | 430k | gxr->cmap = NULL; |
407 | 430k | gxr->font_index = 0; |
408 | 430k | gxr->key_is_range = true; |
409 | 430k | gxr->value_type = CODE_VALUE_CID; |
410 | 430k | gxr->key_prefix_size = preflen; |
411 | 430k | gxr->key_size = stobj[i].size - gxr->key_prefix_size; |
412 | 430k | memcpy(gxr->key_prefix, stobj[i].val.string, gxr->key_prefix_size); |
413 | | |
414 | 430k | memcpy(gxr->keys.data, stobj[i].val.string + gxr->key_prefix_size, stobj[i].size - gxr->key_prefix_size); |
415 | 430k | 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); |
416 | | |
417 | 430k | gxr->keys.size = (stobj[i].size - gxr->key_prefix_size) + (stobj[i + 1].size - gxr->key_prefix_size); |
418 | 1.29M | for (j = 0; j < valuelen; j++) { |
419 | 868k | gxr->values.data[j] = (cidbase >> ((valuelen - 1 - j) * 8)) & 255; |
420 | 868k | } |
421 | 430k | gxr->value_size = valuelen; /* I'm not sure.... */ |
422 | 430k | gxr->values.size = valuelen; |
423 | 430k | if (cmap_insert_map(&pdficmap->cmap_range, pdfir) < 0) break; |
424 | 430k | } |
425 | 0 | else { |
426 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
427 | 0 | return_error(gs_error_VMerror); |
428 | 0 | } |
429 | 430k | } |
430 | 1.51k | else { |
431 | 1.51k | int m, size, keysize; |
432 | 1.51k | uint codelo = 0, codehi = 0; |
433 | | |
434 | 1.51k | size = stobj[i].size; |
435 | 4.16k | for (m = 0; m < size; m++) { |
436 | 2.65k | codelo |= stobj[i].val.string[size - m - 1] << (8 * m); |
437 | 2.65k | } |
438 | 1.51k | size = stobj[i + 1].size; |
439 | 4.16k | for (m = 0; m < size; m++) { |
440 | 2.65k | codehi |= stobj[i + 1].val.string[size - m - 1] << (8 * m); |
441 | 2.65k | } |
442 | | |
443 | 1.51k | if (codehi <= codelo || stobj[i + 2].size < (codehi - codelo)) |
444 | 21 | continue; |
445 | | |
446 | 104k | for (k = codelo; k <= codehi; k++) { |
447 | 103k | uint cidbase; |
448 | 103k | int ind = k - codelo; |
449 | | |
450 | 103k | if (stobj[i + 2].val.arr[ind].type != PDF_PS_OBJ_STRING) |
451 | 8 | continue; |
452 | | |
453 | 103k | size = stobj[i + 2].val.arr[ind].size; |
454 | | |
455 | 103k | cidbase = 0; |
456 | 310k | for (m = 0; m < size; m++) { |
457 | 206k | cidbase |= stobj[i + 2].val.arr[ind].val.string[size - m - 1] << (8 * m); |
458 | 206k | } |
459 | | /* Find how many bytes we need for the cidbase value */ |
460 | | /* We always store at least two bytes for the cidbase value */ |
461 | 103k | for (valuelen = 16; valuelen < 32 && (cidbase >> valuelen) > 0; valuelen += 1) |
462 | 103k | DO_NOTHING; |
463 | | |
464 | 103k | valuelen = ((valuelen + 7) & ~7) >> 3; |
465 | | |
466 | | /* Find how many bytes we need for the cidbase value */ |
467 | | /* We always store at least two bytes for the cidbase value */ |
468 | 103k | for (keysize = 16; keysize < 32 && (cidbase >> keysize) > 0; keysize += 1) |
469 | 103k | DO_NOTHING; |
470 | | |
471 | 103k | keysize = ((keysize + 7) & ~7) >> 3; |
472 | 103k | if (keysize > MAX_CMAP_CODE_SIZE * 2) { |
473 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
474 | 0 | return_error(gs_error_syntaxerror); |
475 | 0 | } |
476 | 103k | preflen = keysize > 4 ? 4 : keysize; |
477 | 103k | keysize -= preflen; |
478 | | |
479 | | /* The prefix is already directly in the gx_cmap_lookup_range_t |
480 | | * We need to store the lower and upper character codes, after lopping the prefix |
481 | | * off them. The upper and lower codes must be the same number of bytes. |
482 | | */ |
483 | 103k | j = sizeof(pdfi_cmap_range_map_t) + keysize + valuelen; |
484 | | |
485 | 103k | pdfir = (pdfi_cmap_range_map_t *)gs_alloc_bytes(mem, j, "cmap_endcidrange_func(pdfi_cmap_range_map_t)"); |
486 | 103k | if (pdfir != NULL) { |
487 | 103k | gx_cmap_lookup_range_t *gxr = &pdfir->range; |
488 | 103k | pdfir->next = NULL; |
489 | 103k | gxr->num_entries = 1; |
490 | 103k | gxr->keys.data = (byte *)&(pdfir[1]); |
491 | 103k | gxr->values.data = gxr->keys.data + keysize; |
492 | | |
493 | 103k | gxr->cmap = NULL; |
494 | 103k | gxr->font_index = 0; |
495 | 103k | gxr->key_is_range = false; |
496 | 103k | gxr->value_type = CODE_VALUE_CID; |
497 | 103k | gxr->key_prefix_size = preflen; |
498 | 103k | gxr->key_size = keysize; |
499 | 310k | for (j = 0; j < preflen; j++) { |
500 | 206k | gxr->key_prefix[j] = (k >> ((preflen - 1 - j) * 8)) & 255; |
501 | 206k | } |
502 | | |
503 | 103k | for (j = preflen; j < preflen + keysize; j++) { |
504 | 0 | gxr->keys.data[j] = (k >> (((preflen + keysize) - 1 - j) * 8)) & 255; |
505 | 0 | } |
506 | | |
507 | 103k | gxr->keys.size = keysize; |
508 | 310k | for (j = 0; j < valuelen; j++) { |
509 | 206k | gxr->values.data[j] = (cidbase >> ((valuelen - 1 - j) * 8)) & 255; |
510 | 206k | } |
511 | 103k | gxr->value_size = valuelen; /* I'm not sure.... */ |
512 | 103k | gxr->values.size = valuelen; |
513 | 103k | if (cmap_insert_map(&pdficmap->cmap_range, pdfir) < 0) break; |
514 | 103k | } |
515 | 0 | else { |
516 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
517 | 0 | return_error(gs_error_VMerror); |
518 | 0 | } |
519 | 103k | } |
520 | 1.48k | } |
521 | 432k | } |
522 | 443k | } |
523 | 20.1k | return pdf_ps_stack_pop(s, to_pop); |
524 | 20.2k | } |
525 | | |
526 | | static int general_endcidchar_func(gs_memory_t *mem, pdf_ps_ctx_t *s, pdf_cmap *pdficmap, pdfi_cmap_range_t *cmap_range) |
527 | 46.7k | { |
528 | 46.7k | int ncodemaps, to_pop = pdf_ps_stack_count_to_mark(s, PDF_PS_OBJ_MARK); |
529 | 46.7k | int i, j; |
530 | 46.7k | pdfi_cmap_range_map_t *pdfir; |
531 | 46.7k | pdf_ps_stack_object_t *stobj; |
532 | | |
533 | | /* increment to_pop to cover the mark object */ |
534 | 46.7k | ncodemaps = to_pop++; |
535 | | /* mapping should have 2 objects on the stack: |
536 | | * startcode, endcode and basecid |
537 | | */ |
538 | 47.0k | while (ncodemaps % 2) ncodemaps--; |
539 | | |
540 | 46.7k | if (ncodemaps < 0 || ncodemaps + 1 > PDF_PS_STACK_MAX) { |
541 | 16 | pdfi_set_error(s->pdfi_ctx, 0, NULL, E_PDF_BAD_TYPE0_CMAP, "general_endcidchar_func", NULL); |
542 | 16 | return_error(gs_error_syntaxerror); |
543 | 16 | } |
544 | | |
545 | 46.7k | if (ncodemaps > 200) { |
546 | 269 | int code; |
547 | 269 | if ((code = pdfi_set_warning_stop(s->pdfi_ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_LIMITCHECK_TYPE0_CMAP, "general_endcidchar_func", NULL)) < 0) { |
548 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
549 | 0 | return code; |
550 | 0 | } |
551 | 269 | } |
552 | | |
553 | 46.7k | stobj = &s->cur[-ncodemaps] + 1; |
554 | | |
555 | 2.83M | for (i = 0; i < ncodemaps; i += 2) { |
556 | 2.78M | int preflen = 1, valuelen; |
557 | | |
558 | 2.78M | if (pdf_ps_obj_has_type(&(stobj[i + 1]), PDF_PS_OBJ_INTEGER) |
559 | 2.78M | && pdf_ps_obj_has_type(&(stobj[i]), PDF_PS_OBJ_STRING) && stobj[i].size > 0) { |
560 | 2.76M | uint cidbase = stobj[i + 1].val.i; |
561 | | |
562 | | /* Find how many bytes we need for the cidbase value */ |
563 | | /* We always store at least two bytes for the cidbase value */ |
564 | 3.81M | for (valuelen = 16; valuelen < 32 && (cidbase >> valuelen) > 0; valuelen += 1) |
565 | 2.76M | DO_NOTHING; |
566 | | |
567 | 2.76M | preflen = stobj[i].size > 4 ? 4 : stobj[i].size; |
568 | | |
569 | 2.76M | valuelen = ((valuelen + 7) & ~7) >> 3; |
570 | | |
571 | | /* The prefix is already directly in the gx_cmap_lookup_range_t |
572 | | * We need to store the lower and upper character codes, after lopping the prefix |
573 | | * off them. The upper and lower codes must be the same number of bytes. |
574 | | */ |
575 | 2.76M | j = sizeof(pdfi_cmap_range_map_t) + (stobj[i].size - preflen) + valuelen; |
576 | | |
577 | 2.76M | pdfir = (pdfi_cmap_range_map_t *)gs_alloc_bytes(mem, j, "cmap_endcidrange_func(pdfi_cmap_range_map_t)"); |
578 | 2.76M | if (pdfir != NULL) { |
579 | 2.76M | gx_cmap_lookup_range_t *gxr = &pdfir->range; |
580 | 2.76M | pdfir->next = NULL; |
581 | 2.76M | gxr->num_entries = 1; |
582 | 2.76M | gxr->keys.data = (byte *)&(pdfir[1]); |
583 | 2.76M | gxr->values.data = gxr->keys.data + (stobj[i].size - preflen); |
584 | | |
585 | 2.76M | gxr->cmap = NULL; |
586 | 2.76M | gxr->font_index = 0; |
587 | 2.76M | gxr->key_is_range = false; |
588 | 2.76M | gxr->value_type = cmap_range == &(pdficmap->cmap_range) ? CODE_VALUE_CID : CODE_VALUE_NOTDEF; |
589 | 2.76M | gxr->key_prefix_size = preflen; |
590 | 2.76M | gxr->key_size = stobj[i].size - gxr->key_prefix_size; |
591 | 2.76M | memcpy(gxr->key_prefix, stobj[i].val.string, gxr->key_prefix_size); |
592 | | |
593 | 2.76M | memcpy(gxr->keys.data, stobj[i].val.string + gxr->key_prefix_size, stobj[i].size - gxr->key_prefix_size); |
594 | | |
595 | 2.76M | gxr->keys.size = stobj[i].size - gxr->key_prefix_size; |
596 | 8.43M | for (j = 0; j < valuelen; j++) { |
597 | 5.67M | gxr->values.data[j] = (cidbase >> ((valuelen - 1 - j) * 8)) & 255; |
598 | 5.67M | } |
599 | 2.76M | gxr->value_size = valuelen; /* I'm not sure.... */ |
600 | 2.76M | gxr->values.size = valuelen; |
601 | 2.76M | if (cmap_insert_map(cmap_range, pdfir) < 0) break; |
602 | 2.76M | } |
603 | 0 | else { |
604 | 0 | (void)pdf_ps_stack_pop(s, to_pop); |
605 | 0 | return_error(gs_error_VMerror); |
606 | 0 | } |
607 | 2.76M | } |
608 | 2.78M | } |
609 | 46.7k | return pdf_ps_stack_pop(s, to_pop); |
610 | 46.7k | } |
611 | | |
612 | | static int cmap_endcidchar_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
613 | 8.93k | { |
614 | 8.93k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
615 | 8.93k | return general_endcidchar_func(mem, s, pdficmap, &pdficmap->cmap_range); |
616 | 8.93k | } |
617 | | |
618 | | static int cmap_endnotdefchar_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
619 | 0 | { |
620 | 0 | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
621 | 0 | return general_endcidchar_func(mem, s, pdficmap, &pdficmap->notdef_cmap_range); |
622 | 0 | } |
623 | | |
624 | | static int cmap_endbfchar_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
625 | 37.9k | { |
626 | 37.9k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
627 | 37.9k | int ncodemaps = pdf_ps_stack_count_to_mark(s, PDF_PS_OBJ_MARK); |
628 | 37.9k | pdf_ps_stack_object_t *stobj; |
629 | 37.9k | int i, j; |
630 | | |
631 | | /* The following hard limit is an implementation limit */ |
632 | 37.9k | if (ncodemaps < 0 || ncodemaps + 1 > PDF_PS_STACK_MAX) { |
633 | 149 | pdfi_set_error(s->pdfi_ctx, 0, NULL, E_PDF_BAD_TYPE0_CMAP, "cmap_endbfchar_func", NULL); |
634 | 149 | return_error(gs_error_syntaxerror); |
635 | 149 | } |
636 | | |
637 | | /* The following "soft" limit is according to the spec */ |
638 | 37.8k | if (ncodemaps > 200) { |
639 | 269 | int code; |
640 | 269 | if ((code = pdfi_set_warning_stop(s->pdfi_ctx, gs_note_error(gs_error_syntaxerror), NULL, W_PDF_LIMITCHECK_TYPE0_CMAP, "cmap_endbfchar_func", NULL)) < 0) { |
641 | 0 | (void)pdf_ps_stack_pop(s, ncodemaps); |
642 | 0 | return code; |
643 | 0 | } |
644 | 269 | } |
645 | | |
646 | 37.8k | stobj = &s->cur[-ncodemaps] + 1; |
647 | | |
648 | 2.01M | for (i = 0; i < ncodemaps; i += 2) { |
649 | 1.97M | if (pdf_ps_obj_has_type(&(stobj[i + 1]), PDF_PS_OBJ_STRING)) { |
650 | 1.97M | byte *c = stobj[i + 1].val.string; |
651 | 1.97M | int l = stobj[i + 1].size; |
652 | 1.97M | unsigned int v = 0; |
653 | | |
654 | 6.32M | for (j = 0; j < l; j++) { |
655 | 4.35M | v += c[l - j - 1] << (8 * j); |
656 | 4.35M | } |
657 | 1.97M | pdf_ps_make_int(&(stobj[i + 1]), v); |
658 | 1.97M | } |
659 | 4.82k | else { |
660 | 4.82k | continue; |
661 | 4.82k | } |
662 | 1.97M | } |
663 | 37.8k | return general_endcidchar_func(mem, s, pdficmap, &pdficmap->cmap_range); |
664 | 37.8k | } |
665 | | |
666 | 1.98M | #define CMAP_NAME_AND_LEN(s) PDF_PS_OPER_NAME_AND_LEN(s) |
667 | | |
668 | | static int cmap_def_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) |
669 | 490k | { |
670 | 490k | int code = 0, code2 = 0; |
671 | 490k | pdf_cmap *pdficmap = (pdf_cmap *)s->client_data; |
672 | | |
673 | 490k | if (pdf_ps_stack_count(s) < 2) { |
674 | 44.0k | return pdf_ps_stack_pop(s, 1); |
675 | 44.0k | } |
676 | | |
677 | 446k | if (pdf_ps_obj_has_type(&s->cur[-1], PDF_PS_OBJ_NAME)) { |
678 | 445k | if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("Registry"))) { |
679 | 44.1k | if (pdficmap->csi_reg.data != NULL) |
680 | 18 | gs_free_object(mem, pdficmap->csi_reg.data, "cmap_def_func(Registry)"); |
681 | | |
682 | 44.1k | pdficmap->csi_reg.data = gs_alloc_bytes(mem, s->cur[0].size + 1, "cmap_def_func(Registry)"); |
683 | 44.1k | if (pdficmap->csi_reg.data != NULL) { |
684 | 44.1k | pdficmap->csi_reg.size = s->cur[0].size; |
685 | 44.1k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_STRING)) { |
686 | 44.1k | memcpy(pdficmap->csi_reg.data, s->cur[0].val.string, s->cur[0].size); |
687 | 44.1k | } |
688 | 4 | else { |
689 | 4 | memcpy(pdficmap->csi_reg.data, s->cur[0].val.name, s->cur[0].size); |
690 | 4 | } |
691 | 44.1k | pdficmap->csi_reg.data[pdficmap->csi_reg.size] = '\0'; |
692 | 44.1k | } |
693 | 0 | else { |
694 | 0 | code = gs_note_error(gs_error_VMerror); |
695 | 0 | } |
696 | 44.1k | } |
697 | 401k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("Ordering"))) { |
698 | 44.1k | if (pdficmap->csi_ord.data != NULL) |
699 | 18 | gs_free_object(mem, pdficmap->csi_ord.data, "cmap_def_func(Ordering)"); |
700 | | |
701 | 44.1k | pdficmap->csi_ord.data = gs_alloc_bytes(mem, s->cur[0].size + 1, "cmap_def_func(Ordering)"); |
702 | 44.1k | if (pdficmap->csi_ord.data != NULL) { |
703 | 44.1k | pdficmap->csi_ord.size = s->cur[0].size; |
704 | 44.1k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_STRING)) |
705 | 44.1k | memcpy(pdficmap->csi_ord.data, s->cur[0].val.string, s->cur[0].size); |
706 | 4 | else |
707 | 4 | memcpy(pdficmap->csi_ord.data, s->cur[0].val.name, s->cur[0].size); |
708 | 44.1k | pdficmap->csi_ord.data[pdficmap->csi_ord.size] = '\0'; |
709 | 44.1k | } |
710 | 0 | else { |
711 | 0 | code = gs_note_error(gs_error_VMerror); |
712 | 0 | } |
713 | 44.1k | } |
714 | 357k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("Supplement"))) { |
715 | 74.5k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { |
716 | 74.5k | pdficmap->csi_supplement = s->cur[0].val.i; |
717 | 74.5k | } |
718 | 0 | else { |
719 | 0 | pdficmap->csi_supplement = 0; |
720 | 0 | } |
721 | 74.5k | } |
722 | 282k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("CMapName"))) { |
723 | 78.1k | if (pdficmap->name.data != NULL) |
724 | 29 | gs_free_object(mem, pdficmap->name.data, "cmap_def_func(CMapName)"); |
725 | | |
726 | 78.1k | pdficmap->name.data = gs_alloc_bytes(mem, s->cur[0].size + 1, "cmap_def_func(CMapName)"); |
727 | 78.1k | if (pdficmap->name.data != NULL) { |
728 | 78.1k | pdficmap->name.size = s->cur[0].size; |
729 | 78.1k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_STRING)) |
730 | 0 | memcpy(pdficmap->name.data, s->cur[0].val.string, s->cur[0].size); |
731 | 78.1k | else |
732 | 78.1k | memcpy(pdficmap->name.data, s->cur[0].val.name, s->cur[0].size); |
733 | 78.1k | pdficmap->name.data[pdficmap->name.size] = '\0'; |
734 | 78.1k | } |
735 | 0 | else { |
736 | 0 | code = gs_note_error(gs_error_VMerror); |
737 | 0 | } |
738 | 78.1k | } |
739 | 204k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("CMapVersion"))) { |
740 | 42.3k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { |
741 | 312 | pdficmap->vers = (float)s->cur[0].val.i; |
742 | 312 | } |
743 | 42.0k | else if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_FLOAT)){ |
744 | 42.0k | pdficmap->vers = s->cur[0].val.f; |
745 | 42.0k | } |
746 | 0 | else { |
747 | 0 | pdficmap->vers = (float)0; |
748 | 0 | } |
749 | 42.3k | } |
750 | 162k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("CMapType"))) { |
751 | 76.6k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { |
752 | 76.6k | pdficmap->cmaptype = s->cur[0].val.i; |
753 | 76.6k | } |
754 | 0 | else { |
755 | 0 | pdficmap->cmaptype = 1; |
756 | 0 | } |
757 | 76.6k | } |
758 | 85.5k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("XUID"))) { |
759 | 42.0k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { |
760 | 42.0k | int len = s->cur->size; |
761 | | |
762 | 42.0k | if (pdficmap->uid.xvalues != NULL) |
763 | 0 | gs_free_object(mem, pdficmap->uid.xvalues, "cmap_def_func(XUID)"); |
764 | | |
765 | 42.0k | pdficmap->uid.xvalues = (long *)gs_alloc_bytes(mem, len * sizeof(*pdficmap->uid.xvalues), "cmap_def_func(XUID)"); |
766 | 42.0k | if (pdficmap->uid.xvalues != NULL) { |
767 | 42.0k | int i; |
768 | 42.0k | pdf_ps_stack_object_t *a = s->cur->val.arr; |
769 | 42.0k | pdficmap->uid.id = -len; |
770 | 209k | for (i = 0; i < len; i++) { |
771 | 167k | if (pdf_ps_obj_has_type(&a[i], PDF_PS_OBJ_INTEGER)) { |
772 | 167k | pdficmap->uid.xvalues[i] = (long)a[i].val.i; |
773 | 167k | } |
774 | 0 | else { |
775 | 0 | pdficmap->uid.xvalues[i] = 0; |
776 | 0 | } |
777 | 167k | } |
778 | 42.0k | } |
779 | 0 | else { |
780 | 0 | code = gs_note_error(gs_error_VMerror); |
781 | 0 | } |
782 | 42.0k | } |
783 | 42.0k | } |
784 | 43.5k | else if (!memcmp(s->cur[-1].val.name, CMAP_NAME_AND_LEN("WMode"))) { |
785 | 42.7k | if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { |
786 | 42.7k | if (s->cur[0].val.i != 0) { |
787 | 285 | if (s->cur[0].val.i != 1) { |
788 | 7 | code = pdfi_set_warning_stop(s->pdfi_ctx, gs_note_error(gs_error_rangecheck), NULL, W_PDF_BAD_WMODE, "cmap_def_func", NULL); |
789 | 7 | } |
790 | 285 | pdficmap->wmode = 1; |
791 | 285 | } |
792 | 42.4k | else |
793 | 42.4k | pdficmap->wmode = 0; |
794 | 42.7k | } |
795 | 0 | else { |
796 | 0 | pdficmap->wmode = 0; |
797 | 0 | } |
798 | 42.7k | } |
799 | 445k | } |
800 | | |
801 | 446k | code2 = pdf_ps_stack_pop(s, 2); |
802 | 446k | if (code < 0) |
803 | 0 | return code; |
804 | 446k | else |
805 | 446k | return code2; |
806 | 446k | } |
807 | | |
808 | | static pdf_ps_oper_list_t cmap_oper_list[] = |
809 | | { |
810 | | {PDF_PS_OPER_NAME_AND_LEN("usecmap"), cmap_usecmap_func}, |
811 | | {PDF_PS_OPER_NAME_AND_LEN("usefont"), ps_pdf_null_oper_func}, |
812 | | {PDF_PS_OPER_NAME_AND_LEN("beginusematrix"), ps_pdf_null_oper_func}, |
813 | | {PDF_PS_OPER_NAME_AND_LEN("endusematrix"), ps_pdf_null_oper_func}, |
814 | | {PDF_PS_OPER_NAME_AND_LEN("begincodespacerange"), pdf_ps_pop_and_pushmark_func}, |
815 | | {PDF_PS_OPER_NAME_AND_LEN("endcodespacerange"), cmap_endcodespacerange_func}, |
816 | | {PDF_PS_OPER_NAME_AND_LEN("begincmap"), ps_pdf_null_oper_func}, |
817 | | {PDF_PS_OPER_NAME_AND_LEN("beginbfchar"), pdf_ps_pop_and_pushmark_func}, |
818 | | {PDF_PS_OPER_NAME_AND_LEN("endbfchar"), cmap_endbfchar_func}, |
819 | | {PDF_PS_OPER_NAME_AND_LEN("beginbfrange"), pdf_ps_pop_and_pushmark_func}, |
820 | | {PDF_PS_OPER_NAME_AND_LEN("endbfrange"), cmap_endfbrange_func}, |
821 | | {PDF_PS_OPER_NAME_AND_LEN("begincidchar"), pdf_ps_pop_and_pushmark_func}, |
822 | | {PDF_PS_OPER_NAME_AND_LEN("endcidchar"), cmap_endcidchar_func}, |
823 | | {PDF_PS_OPER_NAME_AND_LEN("begincidrange"), pdf_ps_pop_and_pushmark_func}, |
824 | | {PDF_PS_OPER_NAME_AND_LEN("endcidrange"), cmap_endcidrange_func}, |
825 | | {PDF_PS_OPER_NAME_AND_LEN("beginnotdefchar"), pdf_ps_pop_and_pushmark_func}, |
826 | | {PDF_PS_OPER_NAME_AND_LEN("endnotdefchar"), cmap_endnotdefchar_func}, |
827 | | {PDF_PS_OPER_NAME_AND_LEN("beginnotdefrange"), pdf_ps_pop_and_pushmark_func}, |
828 | | {PDF_PS_OPER_NAME_AND_LEN("endnotdefrange"), cmap_endnotdefrange_func}, |
829 | | {PDF_PS_OPER_NAME_AND_LEN("findresource"), clear_stack_oper_func}, |
830 | | {PDF_PS_OPER_NAME_AND_LEN("dict"), pdf_ps_pop_oper_func}, |
831 | | {PDF_PS_OPER_NAME_AND_LEN("begin"), ps_pdf_null_oper_func}, |
832 | | {PDF_PS_OPER_NAME_AND_LEN("end"), ps_pdf_null_oper_func}, |
833 | | {PDF_PS_OPER_NAME_AND_LEN("pop"), ps_pdf_null_oper_func}, |
834 | | {PDF_PS_OPER_NAME_AND_LEN("def"), cmap_def_func}, |
835 | | {PDF_PS_OPER_NAME_AND_LEN("dup"), ps_pdf_null_oper_func}, |
836 | | {PDF_PS_OPER_NAME_AND_LEN("defineresource"), clear_stack_oper_func}, |
837 | | {PDF_PS_OPER_NAME_AND_LEN("beginrearrangedfont"), clear_stack_oper_func}, /* we should never see this */ |
838 | | {NULL, 0, NULL} |
839 | | }; |
840 | | |
841 | | static int |
842 | | pdf_cmap_open_file(pdf_context *ctx, gs_string *cmap_name, byte **buf, int64_t *buflen) |
843 | 42.1k | { |
844 | 42.1k | int code = 0; |
845 | 42.1k | stream *s; |
846 | 42.1k | char fname[gp_file_name_sizeof]; |
847 | 42.1k | const char *path_pfx = "CMap/"; |
848 | 42.1k | fname[0] = '\0'; |
849 | | |
850 | 42.1k | if (strlen(path_pfx) + cmap_name->size >= gp_file_name_sizeof) |
851 | 6 | return_error(gs_error_rangecheck); |
852 | | |
853 | 42.1k | strncat(fname, path_pfx, strlen(path_pfx)); |
854 | 42.1k | strncat(fname, (char *)cmap_name->data, cmap_name->size); |
855 | 42.1k | code = pdfi_open_resource_file(ctx, (const char *)fname, (const int)strlen(fname), &s); |
856 | 42.1k | if (code >= 0) { |
857 | 41.7k | sfseek(s, 0, SEEK_END); |
858 | 41.7k | *buflen = sftell(s); |
859 | 41.7k | sfseek(s, 0, SEEK_SET); |
860 | 41.7k | *buf = gs_alloc_bytes(ctx->memory, *buflen, "pdf_cmap_open_file(buf)"); |
861 | 41.7k | if (*buf != NULL) { |
862 | 41.7k | sfread(*buf, 1, *buflen, s); |
863 | 41.7k | } |
864 | 0 | else { |
865 | 0 | code = gs_note_error(gs_error_VMerror); |
866 | 0 | } |
867 | 41.7k | sfclose(s); |
868 | 41.7k | } |
869 | 42.1k | return code; |
870 | 42.1k | } |
871 | | |
872 | | static int |
873 | | pdfi_make_gs_cmap(gs_memory_t *mem, pdf_cmap *pdficmap) |
874 | 79.4k | { |
875 | 79.4k | int code = 0, i; |
876 | 79.4k | gs_cmap_adobe1_t *pgscmap = 0; |
877 | 79.4k | gx_cmap_lookup_range_t *lookups, *ndlookups = NULL; |
878 | 79.4k | pdfi_cmap_range_map_t *l; |
879 | | /* FIXME: We have to use gs_cmap_adobe1_alloc() to get the cmap procs |
880 | | but even if it gets passed num_ranges = 0 it still allocates |
881 | | a zero length array. Change gs_cmap_adobe1_alloc to work better |
882 | | */ |
883 | 79.4k | if ((code = gs_cmap_adobe1_alloc(&pgscmap, pdficmap->wmode, |
884 | 79.4k | pdficmap->name.data, |
885 | 79.4k | pdficmap->name.size, |
886 | 79.4k | 1, |
887 | 79.4k | 0, 0, 0, 0, 0, mem)) >= 0) { |
888 | 79.4k | gs_free_object(mem, pgscmap->code_space.ranges, "empty ranges"); |
889 | | |
890 | 79.4k | lookups = gs_alloc_struct_array(mem, pdficmap->cmap_range.numrangemaps, |
891 | 79.4k | gx_cmap_lookup_range_t, |
892 | 79.4k | &st_cmap_lookup_range_element, |
893 | 79.4k | "pdfi_make_gs_cmap(lookup ranges)"); |
894 | 79.4k | if (lookups == NULL) { |
895 | 0 | gs_free_object(mem, pgscmap, "pdfi_make_gs_cmap(pgscmap)"); |
896 | 0 | code = gs_note_error(gs_error_VMerror); |
897 | 0 | goto done; |
898 | 0 | } |
899 | 79.4k | if (pdficmap->notdef_cmap_range.numrangemaps > 0){ |
900 | 410 | ndlookups = gs_alloc_struct_array(mem, pdficmap->notdef_cmap_range.numrangemaps, |
901 | 410 | gx_cmap_lookup_range_t, |
902 | 410 | &st_cmap_lookup_range_element, |
903 | 410 | "pdfi_make_gs_cmap(notdef lookup ranges)"); |
904 | 410 | if (ndlookups == NULL) { |
905 | 0 | gs_free_object(mem, lookups, "pdfi_make_gs_cmap(lookups)"); |
906 | 0 | gs_free_object(mem, pgscmap, "pdfi_make_gs_cmap(pgscmap)"); |
907 | 0 | code = gs_note_error(gs_error_VMerror); |
908 | 0 | goto done; |
909 | 0 | } |
910 | 410 | } |
911 | 79.4k | pgscmap->def.lookup = lookups; |
912 | 79.4k | pgscmap->def.num_lookup = pdficmap->cmap_range.numrangemaps; |
913 | 79.4k | pgscmap->notdef.lookup = ndlookups; |
914 | 79.4k | pgscmap->notdef.num_lookup = pdficmap->notdef_cmap_range.numrangemaps; |
915 | | |
916 | 79.4k | pgscmap->CIDSystemInfo[0].Registry.data = pdficmap->csi_reg.data; |
917 | 79.4k | pgscmap->CIDSystemInfo[0].Registry.size = pdficmap->csi_reg.size; |
918 | 79.4k | pgscmap->CIDSystemInfo[0].Ordering.data = pdficmap->csi_ord.data; |
919 | 79.4k | pgscmap->CIDSystemInfo[0].Ordering.size = pdficmap->csi_ord.size; |
920 | 79.4k | pgscmap->CIDSystemInfo[0].Supplement = pdficmap->csi_supplement; |
921 | 79.4k | memcpy(&pgscmap->code_space, &pdficmap->code_space, sizeof(pgscmap->code_space)); |
922 | 79.4k | memcpy(&pgscmap->uid, &pdficmap->uid, sizeof(pdficmap->uid)); |
923 | 79.4k | l = pdficmap->cmap_range.ranges; |
924 | 14.8M | for (i = 0; i < pdficmap->cmap_range.numrangemaps && l != NULL; i++) { |
925 | 14.7M | memcpy(&lookups[i], &l->range, sizeof(gx_cmap_lookup_range_t)); |
926 | 14.7M | l = l->next; |
927 | 14.7M | } |
928 | | |
929 | 79.4k | l = pdficmap->notdef_cmap_range.ranges; |
930 | 79.8k | for (i = 0; i < pdficmap->notdef_cmap_range.numrangemaps && l != NULL; i++) { |
931 | 410 | memcpy(&ndlookups[i], &l->range, sizeof(gx_cmap_lookup_range_t)); |
932 | 410 | l = l->next; |
933 | 410 | } |
934 | | |
935 | 79.4k | pdficmap->gscmap = pgscmap; |
936 | 79.4k | } |
937 | | |
938 | 79.4k | done: |
939 | 79.4k | return code; |
940 | 79.4k | } |
941 | | |
942 | | int |
943 | | pdfi_read_cmap(pdf_context *ctx, pdf_obj *cmap, pdf_cmap **pcmap) |
944 | 80.8k | { |
945 | 80.8k | int code = 0; |
946 | 80.8k | pdf_cmap pdficm[3] = {0}; |
947 | 80.8k | pdf_cmap *pdfi_cmap = &(pdficm[1]); |
948 | 80.8k | byte *buf = NULL; |
949 | 80.8k | int64_t buflen = 0; |
950 | 80.8k | pdf_ps_ctx_t cmap_ctx; |
951 | | |
952 | 80.8k | pdfi_cmap->ctx = ctx; |
953 | 80.8k | switch (pdfi_type_of(cmap)) { |
954 | 42.1k | case PDF_NAME: |
955 | 42.1k | { |
956 | 42.1k | gs_string cmname; |
957 | 42.1k | pdf_name *cmapn = (pdf_name *)cmap; |
958 | 42.1k | cmname.data = cmapn->data; |
959 | 42.1k | cmname.size = cmapn->length; |
960 | 42.1k | code = pdf_cmap_open_file(ctx, &cmname, &buf, &buflen); |
961 | 42.1k | if (code < 0) |
962 | 325 | goto error_out; |
963 | 41.7k | break; |
964 | 42.1k | } |
965 | 41.7k | case PDF_STREAM: |
966 | 38.6k | { |
967 | 38.6k | pdf_obj *ucmap; |
968 | 38.6k | pdf_cmap *upcmap = NULL; |
969 | 38.6k | pdf_dict *cmap_dict = NULL; |
970 | | |
971 | 38.6k | code = pdfi_dict_from_obj(ctx, cmap, &cmap_dict); |
972 | 38.6k | if (code < 0) |
973 | 0 | goto error_out; |
974 | | |
975 | 38.6k | code = pdfi_dict_knownget(ctx, cmap_dict, "UseCMap", &ucmap); |
976 | 38.6k | if (code > 0) { |
977 | 0 | code = pdfi_read_cmap(ctx, ucmap, &upcmap); |
978 | 0 | pdfi_countdown(ucmap); |
979 | 0 | if (code >= 0) { |
980 | 0 | gx_code_space_range_t * ranges = |
981 | 0 | (gx_code_space_range_t *)gs_alloc_byte_array(ctx->memory, upcmap->code_space.num_ranges, |
982 | 0 | sizeof(gx_code_space_range_t), "cmap_usecmap_func(ranges)"); |
983 | 0 | if (ranges != NULL) { |
984 | 0 | int i; |
985 | 0 | memcpy(&pdfi_cmap->code_space, &upcmap->code_space, sizeof(pdfi_cmap->code_space)); |
986 | 0 | for (i = 0; i < upcmap->code_space.num_ranges; i++) { |
987 | 0 | memcpy(&(ranges[i]), &(upcmap->code_space.ranges[i]), sizeof(ranges[i])); |
988 | 0 | } |
989 | 0 | pdfi_cmap->code_space.ranges = ranges; |
990 | 0 | memcpy(&pdfi_cmap->cmap_range, &upcmap->cmap_range, sizeof(pdfi_cmap->cmap_range)); |
991 | 0 | memcpy(&pdfi_cmap->notdef_cmap_range, &upcmap->notdef_cmap_range, sizeof(pdfi_cmap->notdef_cmap_range)); |
992 | | /* Once we've assumed control of these, NULL out entries for the sub-cmap. */ |
993 | 0 | upcmap->cmap_range.ranges = NULL; |
994 | 0 | upcmap->notdef_cmap_range.ranges = NULL; |
995 | | /* But we keep the subcmap itself because we rely on its storage */ |
996 | 0 | pdfi_cmap->next = upcmap; |
997 | 0 | } else { |
998 | 0 | code = gs_note_error(gs_error_VMerror); |
999 | 0 | goto error_out; |
1000 | 0 | } |
1001 | 0 | } |
1002 | 0 | else { |
1003 | 0 | pdfi_countdown(upcmap); |
1004 | 0 | } |
1005 | 0 | } |
1006 | | |
1007 | 38.6k | code = pdfi_stream_to_buffer(ctx, (pdf_stream *)cmap, &buf, &buflen); |
1008 | 38.6k | if (code < 0) { |
1009 | 203 | goto error_out; |
1010 | 203 | } |
1011 | 38.4k | break; |
1012 | 38.6k | } |
1013 | 38.4k | default: |
1014 | 59 | code = gs_note_error(gs_error_typecheck); |
1015 | 59 | goto error_out; |
1016 | 80.8k | } |
1017 | 80.2k | pdfi_cmap->ctx = ctx; |
1018 | 80.2k | pdfi_cmap->buf = buf; |
1019 | 80.2k | pdfi_cmap->buflen = buflen; |
1020 | | |
1021 | | /* In case of technically invalid CMap files which do not contain a CMapType, See Bug #690737. |
1022 | | * This makes sure we clean up the CMap contents in pdfi_free_cmap() below. |
1023 | | */ |
1024 | 80.2k | pdfi_cmap->cmaptype = 1; |
1025 | | |
1026 | 80.2k | pdfi_pscript_stack_init(ctx, cmap_oper_list, (void *)pdfi_cmap, &cmap_ctx); |
1027 | | |
1028 | 80.2k | code = pdfi_pscript_interpret(&cmap_ctx, buf, buflen); |
1029 | 80.2k | pdfi_pscript_stack_finit(&cmap_ctx); |
1030 | 80.2k | if (code < 0) goto error_out; |
1031 | | |
1032 | 79.4k | code = pdfi_make_gs_cmap(ctx->memory, pdfi_cmap); |
1033 | | |
1034 | 79.4k | if (code >= 0) { |
1035 | 79.4k | *pcmap = (pdf_cmap *)gs_alloc_bytes(ctx->memory, sizeof(pdf_cmap), "pdfi_read_cmap(*pcmap)"); |
1036 | 79.4k | if (*pcmap != NULL) { |
1037 | 79.4k | pdfi_cmap->type = PDF_CMAP; |
1038 | 79.4k | pdfi_cmap->ctx = ctx; |
1039 | 79.4k | pdfi_cmap->refcnt = 1; |
1040 | 79.4k | pdfi_cmap->object_num = cmap->object_num; |
1041 | 79.4k | pdfi_cmap->generation_num = cmap->generation_num; |
1042 | 79.4k | pdfi_cmap->indirect_num = cmap->indirect_num; |
1043 | 79.4k | pdfi_cmap->indirect_gen = cmap->indirect_gen; |
1044 | 79.4k | memcpy(*pcmap, pdfi_cmap, sizeof(pdf_cmap)); |
1045 | 79.4k | pdfi_cmap = *pcmap; |
1046 | | /* object_num can be zero if the dictionary was defined inline */ |
1047 | 79.4k | if (pdfi_cmap->object_num != 0) { |
1048 | 37.6k | code = replace_cache_entry(ctx, (pdf_obj *)pdfi_cmap); |
1049 | 37.6k | } |
1050 | 79.4k | } else { |
1051 | 0 | code = gs_note_error(gs_error_VMerror); |
1052 | 0 | goto error_out; |
1053 | 0 | } |
1054 | 79.4k | } |
1055 | 0 | else { |
1056 | 0 | goto error_out; |
1057 | 0 | } |
1058 | 79.4k | return 0; |
1059 | | |
1060 | 1.37k | error_out: |
1061 | 1.37k | pdfi_free_cmap_contents(pdfi_cmap); |
1062 | 1.37k | memset(pdfi_cmap, 0x00, sizeof(pdf_cmap)); |
1063 | 1.37k | return code; |
1064 | 79.4k | } |
1065 | | |
1066 | | static int pdfi_free_cmap_contents(pdf_cmap *cmap) |
1067 | 80.8k | { |
1068 | 80.8k | pdfi_cmap_range_map_t *pdfir; |
1069 | 80.8k | gs_cmap_adobe1_t *pgscmap = cmap->gscmap; |
1070 | | |
1071 | 80.8k | if (pgscmap != NULL) { |
1072 | 79.4k | gs_free_object(OBJ_MEMORY(cmap), pgscmap->def.lookup, "pdfi_free_cmap(def.lookup)"); |
1073 | 79.4k | gs_free_object(OBJ_MEMORY(cmap), pgscmap->notdef.lookup, "pdfi_free_cmap(notdef.lookup)"); |
1074 | 79.4k | (void)gs_cmap_free((gs_cmap_t *)pgscmap, OBJ_MEMORY(cmap)); |
1075 | 79.4k | } |
1076 | 80.8k | gs_free_object(OBJ_MEMORY(cmap), cmap->code_space.ranges, "pdfi_free_cmap(code_space.ranges"); |
1077 | 80.8k | pdfir = cmap->cmap_range.ranges; |
1078 | 14.9M | while (pdfir != NULL) { |
1079 | 14.8M | pdfi_cmap_range_map_t *pdfir2 = pdfir->next; |
1080 | 14.8M | gs_free_object(OBJ_MEMORY(cmap), pdfir, "pdfi_free_cmap(cmap_range.ranges"); |
1081 | 14.8M | pdfir = pdfir2; |
1082 | 14.8M | } |
1083 | 80.8k | pdfir = cmap->notdef_cmap_range.ranges; |
1084 | 81.1k | while (pdfir != NULL) { |
1085 | 375 | pdfi_cmap_range_map_t *pdfir2 = pdfir->next; |
1086 | 375 | gs_free_object(OBJ_MEMORY(cmap), pdfir, "pdfi_free_cmap(cmap_range.ranges"); |
1087 | 375 | pdfir = pdfir2; |
1088 | 375 | } |
1089 | 80.8k | gs_free_object(OBJ_MEMORY(cmap), cmap->csi_reg.data, "pdfi_free_cmap(csi_reg.data"); |
1090 | 80.8k | gs_free_object(OBJ_MEMORY(cmap), cmap->csi_ord.data, "pdfi_free_cmap(csi_ord.data"); |
1091 | 80.8k | gs_free_object(OBJ_MEMORY(cmap), cmap->name.data, "pdfi_free_cmap(name.data"); |
1092 | 80.8k | gs_free_object(OBJ_MEMORY(cmap), cmap->uid.xvalues, "pdfi_free_cmap(xuid.xvalues"); |
1093 | 80.8k | pdfi_countdown(cmap->next); |
1094 | 80.8k | gs_free_object(OBJ_MEMORY(cmap), cmap->buf, "pdfi_free_cmap(cmap->buf"); |
1095 | | |
1096 | 80.8k | return 0; |
1097 | 80.8k | } |
1098 | | |
1099 | | int pdfi_free_cmap(pdf_obj *cmapo) |
1100 | 79.4k | { |
1101 | 79.4k | pdf_cmap *cmap = (pdf_cmap *)cmapo; |
1102 | | /* |
1103 | | * Note there is some inconsistency in the various specifications regarding CMapType; the |
1104 | | * Adobe tech note 5014 specifically says it only documents CMaps with a CmapType of 0, the |
1105 | | * PLRM says that CMapType can be 0 or 1, and the two are equivalent, the PDF Reference Manual |
1106 | | * doesn't say, it just refers to tech note 5014 but the example has a CMapType of 1. The PDF |
1107 | | * Reference does describe ToUnicode CMaps which have a CMapType of 2. |
1108 | | */ |
1109 | | /* Well it seems we have PDF files which use CMapType 2 CMaps as values for a /Encoding, which is |
1110 | | * I believe incorrect, as these are ToUnicode CMaps.... |
1111 | | * There's nothing for it, we'll just haev to free all CMaps for now. Note for Chris when implementing |
1112 | | * ToUnicode CMaps, we'll obviously have to rely on the context to know whether a CMap is an Encoding |
1113 | | * or a ToUnicode, we cna't use the CmMapType, just as you suspected. :-( |
1114 | | * See bug #696449 633_R00728_E.pdf |
1115 | | */ |
1116 | | /* |
1117 | | * For now, we represent ToUnicode CMaps (CMapType 2) in the same data structures as regular CMaps |
1118 | | * (CMapType 0/1) so there is no reason (yet!) to differentiate between the two. |
1119 | | */ |
1120 | | |
1121 | 79.4k | pdfi_free_cmap_contents(cmap); |
1122 | 79.4k | gs_free_object(OBJ_MEMORY(cmap), cmap, "pdfi_free_cmap(cmap"); |
1123 | 79.4k | return 0; |
1124 | 79.4k | } |