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