File: | parse.c |
Location: | line 350, column 3 |
Description: | Potential leak of memory pointed to by 'color' |
1 | /* | |||||
2 | * Copyright (C) 1989-95 GROUPE BULL | |||||
3 | * | |||||
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
5 | * of this software and associated documentation files (the "Software"), to | |||||
6 | * deal in the Software without restriction, including without limitation the | |||||
7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |||||
8 | * sell copies of the Software, and to permit persons to whom the Software is | |||||
9 | * furnished to do so, subject to the following conditions: | |||||
10 | * | |||||
11 | * The above copyright notice and this permission notice shall be included in | |||||
12 | * all copies or substantial portions of the Software. | |||||
13 | * | |||||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||||
17 | * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||||
18 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||||
20 | * | |||||
21 | * Except as contained in this notice, the name of GROUPE BULL shall not be | |||||
22 | * used in advertising or otherwise to promote the sale, use or other dealings | |||||
23 | * in this Software without prior written authorization from GROUPE BULL. | |||||
24 | */ | |||||
25 | ||||||
26 | /*****************************************************************************\ | |||||
27 | * parse.c: * | |||||
28 | * * | |||||
29 | * XPM library * | |||||
30 | * Parse an XPM file or array and store the found informations * | |||||
31 | * in the given XpmImage structure. * | |||||
32 | * * | |||||
33 | * Developed by Arnaud Le Hors * | |||||
34 | \*****************************************************************************/ | |||||
35 | ||||||
36 | /* | |||||
37 | * The code related to FOR_MSW has been added by | |||||
38 | * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94 | |||||
39 | */ | |||||
40 | ||||||
41 | /* October 2004, source code review by Thomas Biege <thomas@suse.de> */ | |||||
42 | ||||||
43 | #ifdef HAVE_CONFIG_H1 | |||||
44 | #include <config.h> | |||||
45 | #endif | |||||
46 | #include "XpmI.h" | |||||
47 | #include <ctype.h> | |||||
48 | #include <string.h> | |||||
49 | ||||||
50 | #if defined(HAS_STRLCAT) || defined(HAVE_STRLCAT1) | |||||
51 | # define STRLCAT(dst, src, dstsize)do { if (__builtin___strlcat_chk (dst, src, dstsize, __builtin_object_size (dst, 2 > 1 ? 1 : 0)) >= (dstsize)) return (-2); } while (0) do { \ | |||||
52 | if (strlcat(dst, src, dstsize)__builtin___strlcat_chk (dst, src, dstsize, __builtin_object_size (dst, 2 > 1 ? 1 : 0)) >= (dstsize)) \ | |||||
53 | return (XpmFileInvalid-2); } while(0) | |||||
54 | # define STRLCPY(dst, src, dstsize)do { if (__builtin___strlcpy_chk (dst, src, dstsize, __builtin_object_size (dst, 2 > 1 ? 1 : 0)) >= (dstsize)) return (-2); } while (0) do { \ | |||||
55 | if (strlcpy(dst, src, dstsize)__builtin___strlcpy_chk (dst, src, dstsize, __builtin_object_size (dst, 2 > 1 ? 1 : 0)) >= (dstsize)) \ | |||||
56 | return (XpmFileInvalid-2); } while(0) | |||||
57 | #else | |||||
58 | # define STRLCAT(dst, src, dstsize)do { if (__builtin___strlcat_chk (dst, src, dstsize, __builtin_object_size (dst, 2 > 1 ? 1 : 0)) >= (dstsize)) return (-2); } while (0) do { \ | |||||
59 | if ((strlen(dst) + strlen(src)) < (dstsize)) \ | |||||
60 | strcat(dst, src)__builtin___strcat_chk (dst, src, __builtin_object_size (dst, 2 > 1 ? 1 : 0)); \ | |||||
61 | else return (XpmFileInvalid-2); } while(0) | |||||
62 | # define STRLCPY(dst, src, dstsize)do { if (__builtin___strlcpy_chk (dst, src, dstsize, __builtin_object_size (dst, 2 > 1 ? 1 : 0)) >= (dstsize)) return (-2); } while (0) do { \ | |||||
63 | if (strlen(src) < (dstsize)) \ | |||||
64 | strcpy(dst, src)__builtin___strcpy_chk (dst, src, __builtin_object_size (dst, 2 > 1 ? 1 : 0)); \ | |||||
65 | else return (XpmFileInvalid-2); } while(0) | |||||
66 | #endif | |||||
67 | ||||||
68 | LFUNC(ParsePixels, int, (xpmData *data, unsigned int width,static int ParsePixels (xpmData *data, unsigned int width, unsigned int height, unsigned int ncolors, unsigned int cpp, XpmColor *colorTable, xpmHashTable *hashtable, unsigned int **pixels) | |||||
69 | unsigned int height, unsigned int ncolors,static int ParsePixels (xpmData *data, unsigned int width, unsigned int height, unsigned int ncolors, unsigned int cpp, XpmColor *colorTable, xpmHashTable *hashtable, unsigned int **pixels) | |||||
70 | unsigned int cpp, XpmColor *colorTable,static int ParsePixels (xpmData *data, unsigned int width, unsigned int height, unsigned int ncolors, unsigned int cpp, XpmColor *colorTable, xpmHashTable *hashtable, unsigned int **pixels) | |||||
71 | xpmHashTable *hashtable, unsigned int **pixels))static int ParsePixels (xpmData *data, unsigned int width, unsigned int height, unsigned int ncolors, unsigned int cpp, XpmColor *colorTable, xpmHashTable *hashtable, unsigned int **pixels); | |||||
72 | ||||||
73 | const char *xpmColorKeys[] = { | |||||
74 | "s", /* key #1: symbol */ | |||||
75 | "m", /* key #2: mono visual */ | |||||
76 | "g4", /* key #3: 4 grays visual */ | |||||
77 | "g", /* key #4: gray visual */ | |||||
78 | "c", /* key #5: color visual */ | |||||
79 | }; | |||||
80 | ||||||
81 | int | |||||
82 | xpmParseValues( | |||||
83 | xpmData *data, | |||||
84 | unsigned int *width, | |||||
85 | unsigned int *height, | |||||
86 | unsigned int *ncolors, | |||||
87 | unsigned int *cpp, | |||||
88 | unsigned int *x_hotspot, | |||||
89 | unsigned int *y_hotspot, | |||||
90 | unsigned int *hotspot, | |||||
91 | unsigned int *extensions) | |||||
92 | { | |||||
93 | unsigned int l; | |||||
94 | char buf[BUFSIZ1024 + 1]; | |||||
95 | ||||||
96 | if (!data->format) { /* XPM 2 or 3 */ | |||||
97 | ||||||
98 | /* | |||||
99 | * read values: width, height, ncolors, chars_per_pixel | |||||
100 | */ | |||||
101 | if (!(xpmNextUI(data, width) && xpmNextUI(data, height) | |||||
102 | && xpmNextUI(data, ncolors) && xpmNextUI(data, cpp))) | |||||
103 | return (XpmFileInvalid-2); | |||||
104 | ||||||
105 | /* | |||||
106 | * read optional information (hotspot and/or XPMEXT) if any | |||||
107 | */ | |||||
108 | l = xpmNextWord(data, buf, BUFSIZ1024); | |||||
109 | if (l) { | |||||
110 | *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6)); | |||||
111 | if (*extensions) | |||||
112 | *hotspot = (xpmNextUI(data, x_hotspot) | |||||
113 | && xpmNextUI(data, y_hotspot)); | |||||
114 | else { | |||||
115 | *hotspot = (xpmatoui(buf, l, x_hotspot) | |||||
116 | && xpmNextUI(data, y_hotspot)); | |||||
117 | l = xpmNextWord(data, buf, BUFSIZ1024); | |||||
118 | *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6)); | |||||
119 | } | |||||
120 | } | |||||
121 | } else { | |||||
122 | ||||||
123 | /* | |||||
124 | * XPM 1 file read values: width, height, ncolors, chars_per_pixel | |||||
125 | */ | |||||
126 | int i; | |||||
127 | char *ptr; | |||||
128 | Boolint got_one, saw_width = False0, saw_height = False0; | |||||
129 | Boolint saw_ncolors = False0, saw_chars_per_pixel = False0; | |||||
130 | ||||||
131 | for (i = 0; i < 4; i++) { | |||||
132 | l = xpmNextWord(data, buf, BUFSIZ1024); | |||||
133 | if (l != 7 || strncmp("#define", buf, 7)) | |||||
134 | return (XpmFileInvalid-2); | |||||
135 | l = xpmNextWord(data, buf, BUFSIZ1024); | |||||
136 | if (!l) | |||||
137 | return (XpmFileInvalid-2); | |||||
138 | buf[l] = '\0'; | |||||
139 | ptr = buf; | |||||
140 | got_one = False0; | |||||
141 | while (!got_one) { | |||||
142 | ptr = strchr(ptr, '_'); | |||||
143 | if (!ptr) | |||||
144 | return (XpmFileInvalid-2); | |||||
145 | switch (l - (ptr - buf)) { | |||||
146 | case 6: | |||||
147 | if (saw_width || strncmp("_width", ptr, 6) | |||||
148 | || !xpmNextUI(data, width)) | |||||
149 | return (XpmFileInvalid-2); | |||||
150 | else | |||||
151 | saw_width = True1; | |||||
152 | got_one = True1; | |||||
153 | break; | |||||
154 | case 7: | |||||
155 | if (saw_height || strncmp("_height", ptr, 7) | |||||
156 | || !xpmNextUI(data, height)) | |||||
157 | return (XpmFileInvalid-2); | |||||
158 | else | |||||
159 | saw_height = True1; | |||||
160 | got_one = True1; | |||||
161 | break; | |||||
162 | case 8: | |||||
163 | if (saw_ncolors || strncmp("_ncolors", ptr, 8) | |||||
164 | || !xpmNextUI(data, ncolors)) | |||||
165 | return (XpmFileInvalid-2); | |||||
166 | else | |||||
167 | saw_ncolors = True1; | |||||
168 | got_one = True1; | |||||
169 | break; | |||||
170 | case 16: | |||||
171 | if (saw_chars_per_pixel | |||||
172 | || strncmp("_chars_per_pixel", ptr, 16) | |||||
173 | || !xpmNextUI(data, cpp)) | |||||
174 | return (XpmFileInvalid-2); | |||||
175 | else | |||||
176 | saw_chars_per_pixel = True1; | |||||
177 | got_one = True1; | |||||
178 | break; | |||||
179 | default: | |||||
180 | ptr++; | |||||
181 | } | |||||
182 | } | |||||
183 | /* skip the end of line */ | |||||
184 | xpmNextString(data); | |||||
185 | } | |||||
186 | if (!saw_width || !saw_height || !saw_ncolors || !saw_chars_per_pixel) | |||||
187 | return (XpmFileInvalid-2); | |||||
188 | ||||||
189 | *hotspot = 0; | |||||
190 | *extensions = 0; | |||||
191 | } | |||||
192 | return (XpmSuccess0); | |||||
193 | } | |||||
194 | ||||||
195 | int | |||||
196 | xpmParseColors( | |||||
197 | xpmData *data, | |||||
198 | unsigned int ncolors, | |||||
199 | unsigned int cpp, | |||||
200 | XpmColor **colorTablePtr, | |||||
201 | xpmHashTable *hashtable) | |||||
202 | { | |||||
203 | unsigned int key = 0, l, a, b, len; | |||||
204 | unsigned int curkey; /* current color key */ | |||||
205 | unsigned int lastwaskey; /* key read */ | |||||
206 | char buf[BUFSIZ1024+1]; | |||||
207 | char curbuf[BUFSIZ1024]; /* current buffer */ | |||||
208 | const char **sptr; | |||||
209 | char *s; | |||||
210 | XpmColor *color; | |||||
211 | XpmColor *colorTable; | |||||
212 | char **defaults; | |||||
213 | int ErrorStatus; | |||||
214 | ||||||
215 | if (ncolors >= UINT_MAX(2147483647 *2U +1U) / sizeof(XpmColor)) | |||||
| ||||||
216 | return (XpmNoMemory-3); | |||||
217 | colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor))calloc((ncolors), (sizeof(XpmColor))); | |||||
218 | if (!colorTable) | |||||
219 | return (XpmNoMemory-3); | |||||
220 | ||||||
221 | if (!data->format) { /* XPM 2 or 3 */ | |||||
222 | for (a = 0, color = colorTable; a < ncolors; a++, color++) { | |||||
223 | xpmNextString(data); /* skip the line */ | |||||
224 | ||||||
225 | /* | |||||
226 | * read pixel value | |||||
227 | */ | |||||
228 | if (cpp >= UINT_MAX(2147483647 *2U +1U) - 1) { | |||||
229 | xpmFreeColorTable(colorTable, ncolors); | |||||
230 | return (XpmNoMemory-3); | |||||
231 | } | |||||
232 | color->string = (char *) XpmMalloc(cpp + 1)malloc((cpp + 1)); | |||||
233 | if (!color->string) { | |||||
234 | xpmFreeColorTable(colorTable, ncolors); | |||||
235 | return (XpmNoMemory-3); | |||||
236 | } | |||||
237 | for (b = 0, s = color->string; b < cpp; b++, s++) | |||||
238 | *s = xpmGetC(data)((!data->type || data->type == 3) ? (*data->cptr++) : (getc(data->stream.file))); | |||||
239 | *s = '\0'; | |||||
240 | ||||||
241 | /* | |||||
242 | * store the string in the hashtable with its color index number | |||||
243 | */ | |||||
244 | if (USE_HASHTABLE(cpp > 2 && ncolors > 4)) { | |||||
245 | ErrorStatus = | |||||
246 | xpmHashIntern(hashtable, color->string, HashAtomData(a)((void *)(long)a)); | |||||
247 | if (ErrorStatus != XpmSuccess0) { | |||||
248 | xpmFreeColorTable(colorTable, ncolors); | |||||
249 | return (ErrorStatus); | |||||
250 | } | |||||
251 | } | |||||
252 | ||||||
253 | /* | |||||
254 | * read color keys and values | |||||
255 | */ | |||||
256 | defaults = (char **) color; | |||||
257 | curkey = 0; | |||||
258 | lastwaskey = 0; | |||||
259 | *curbuf = '\0'; /* init curbuf */ | |||||
260 | while ((l = xpmNextWord(data, buf, BUFSIZ1024))) { | |||||
261 | if (!lastwaskey) { | |||||
262 | for (key = 0, sptr = xpmColorKeys; key < NKEYS5; key++, | |||||
263 | sptr++) | |||||
264 | if ((strlen(*sptr) == l) && (!strncmp(*sptr, buf, l))) | |||||
265 | break; | |||||
266 | } | |||||
267 | if (!lastwaskey && key < NKEYS5) { /* open new key */ | |||||
268 | if (curkey) { /* flush string */ | |||||
269 | len = strlen(curbuf) + 1; | |||||
270 | s = (char *) XpmMalloc(len)malloc((len)); | |||||
271 | if (!s) { | |||||
272 | xpmFreeColorTable(colorTable, ncolors); | |||||
273 | return (XpmNoMemory-3); | |||||
274 | } | |||||
275 | defaults[curkey] = s; | |||||
276 | memcpy(s, curbuf, len)__builtin___memcpy_chk (s, curbuf, len, __builtin_object_size (s, 0)); | |||||
277 | } | |||||
278 | curkey = key + 1; /* set new key */ | |||||
279 | *curbuf = '\0'; /* reset curbuf */ | |||||
280 | lastwaskey = 1; | |||||
281 | } else { | |||||
282 | if (!curkey) { /* key without value */ | |||||
283 | xpmFreeColorTable(colorTable, ncolors); | |||||
284 | return (XpmFileInvalid-2); | |||||
285 | } | |||||
286 | if (!lastwaskey) | |||||
287 | STRLCAT(curbuf, " ", sizeof(curbuf))do { if (__builtin___strlcat_chk (curbuf, " ", sizeof(curbuf) , __builtin_object_size (curbuf, 2 > 1 ? 1 : 0)) >= (sizeof (curbuf))) return (-2); } while(0);/* append space */ | |||||
288 | buf[l] = '\0'; | |||||
289 | STRLCAT(curbuf, buf, sizeof(curbuf))do { if (__builtin___strlcat_chk (curbuf, buf, sizeof(curbuf) , __builtin_object_size (curbuf, 2 > 1 ? 1 : 0)) >= (sizeof (curbuf))) return (-2); } while(0); /* append buf */ | |||||
290 | lastwaskey = 0; | |||||
291 | } | |||||
292 | } | |||||
293 | if (!curkey) { /* key without value */ | |||||
294 | xpmFreeColorTable(colorTable, ncolors); | |||||
295 | return (XpmFileInvalid-2); | |||||
296 | } | |||||
297 | len = strlen(curbuf) + 1; /* integer overflow just theoretically possible */ | |||||
298 | s = defaults[curkey] = (char *) XpmMalloc(len)malloc((len)); | |||||
299 | if (!s) { | |||||
300 | xpmFreeColorTable(colorTable, ncolors); | |||||
301 | return (XpmNoMemory-3); | |||||
302 | } | |||||
303 | memcpy(s, curbuf, len)__builtin___memcpy_chk (s, curbuf, len, __builtin_object_size (s, 0)); | |||||
304 | } | |||||
305 | } else { /* XPM 1 */ | |||||
306 | /* get to the beginning of the first string */ | |||||
307 | data->Bos = '"'; | |||||
308 | data->Eos = '\0'; | |||||
309 | xpmNextString(data); | |||||
310 | data->Eos = '"'; | |||||
311 | for (a = 0, color = colorTable; a < ncolors; a++, color++) { | |||||
312 | ||||||
313 | /* | |||||
314 | * read pixel value | |||||
315 | */ | |||||
316 | if (cpp >= UINT_MAX(2147483647 *2U +1U) - 1) { | |||||
317 | xpmFreeColorTable(colorTable, ncolors); | |||||
318 | return (XpmNoMemory-3); | |||||
319 | } | |||||
320 | color->string = (char *) XpmMalloc(cpp + 1)malloc((cpp + 1)); | |||||
321 | if (!color->string) { | |||||
322 | xpmFreeColorTable(colorTable, ncolors); | |||||
323 | return (XpmNoMemory-3); | |||||
324 | } | |||||
325 | for (b = 0, s = color->string; b < cpp; b++, s++) | |||||
326 | *s = xpmGetC(data)((!data->type || data->type == 3) ? (*data->cptr++) : (getc(data->stream.file))); | |||||
327 | *s = '\0'; | |||||
328 | ||||||
329 | /* | |||||
330 | * store the string in the hashtable with its color index number | |||||
331 | */ | |||||
332 | if (USE_HASHTABLE(cpp > 2 && ncolors > 4)) { | |||||
333 | ErrorStatus = | |||||
334 | xpmHashIntern(hashtable, color->string, HashAtomData(a)((void *)(long)a)); | |||||
335 | if (ErrorStatus != XpmSuccess0) { | |||||
336 | xpmFreeColorTable(colorTable, ncolors); | |||||
337 | return (ErrorStatus); | |||||
338 | } | |||||
339 | } | |||||
340 | ||||||
341 | /* | |||||
342 | * read color values | |||||
343 | */ | |||||
344 | xpmNextString(data); /* get to the next string */ | |||||
345 | *curbuf = '\0'; /* init curbuf */ | |||||
346 | while ((l = xpmNextWord(data, buf, BUFSIZ1024))) { | |||||
347 | if (*curbuf != '\0') | |||||
348 | STRLCAT(curbuf, " ", sizeof(curbuf))do { if (__builtin___strlcat_chk (curbuf, " ", sizeof(curbuf) , __builtin_object_size (curbuf, 2 > 1 ? 1 : 0)) >= (sizeof (curbuf))) return (-2); } while(0);/* append space */ | |||||
349 | buf[l] = '\0'; | |||||
350 | STRLCAT(curbuf, buf, sizeof(curbuf))do { if (__builtin___strlcat_chk (curbuf, buf, sizeof(curbuf) , __builtin_object_size (curbuf, 2 > 1 ? 1 : 0)) >= (sizeof (curbuf))) return (-2); } while(0); /* append buf */ | |||||
| ||||||
351 | } | |||||
352 | len = strlen(curbuf) + 1; | |||||
353 | s = (char *) XpmMalloc(len)malloc((len)); | |||||
354 | if (!s) { | |||||
355 | xpmFreeColorTable(colorTable, ncolors); | |||||
356 | return (XpmNoMemory-3); | |||||
357 | } | |||||
358 | memcpy(s, curbuf, len)__builtin___memcpy_chk (s, curbuf, len, __builtin_object_size (s, 0)); | |||||
359 | color->c_color = s; | |||||
360 | *curbuf = '\0'; /* reset curbuf */ | |||||
361 | if (a < ncolors - 1) /* can we trust ncolors -> leave data's bounds */ | |||||
362 | xpmNextString(data); /* get to the next string */ | |||||
363 | } | |||||
364 | } | |||||
365 | *colorTablePtr = colorTable; | |||||
366 | return (XpmSuccess0); | |||||
367 | } | |||||
368 | ||||||
369 | static int | |||||
370 | ParsePixels( | |||||
371 | xpmData *data, | |||||
372 | unsigned int width, | |||||
373 | unsigned int height, | |||||
374 | unsigned int ncolors, | |||||
375 | unsigned int cpp, | |||||
376 | XpmColor *colorTable, | |||||
377 | xpmHashTable *hashtable, | |||||
378 | unsigned int **pixels) | |||||
379 | { | |||||
380 | unsigned int *iptr, *iptr2 = NULL((void*)0); /* found by Egbert Eich */ | |||||
381 | unsigned int a, x, y; | |||||
382 | ||||||
383 | if ((height > 0 && width >= UINT_MAX(2147483647 *2U +1U) / height) || | |||||
384 | width * height >= UINT_MAX(2147483647 *2U +1U) / sizeof(unsigned int)) | |||||
385 | return XpmNoMemory-3; | |||||
386 | #ifndef FOR_MSW | |||||
387 | iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height)malloc((sizeof(unsigned int) * width * height)); | |||||
388 | #else | |||||
389 | ||||||
390 | /* | |||||
391 | * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!! | |||||
392 | * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary | |||||
393 | */ | |||||
394 | iptr2 = (unsigned int *) | |||||
395 | XpmMalloc((long) sizeof(unsigned int) * (long) width * (long) height)malloc(((long) sizeof(unsigned int) * (long) width * (long) height )); | |||||
396 | #endif | |||||
397 | if (!iptr2) | |||||
398 | return (XpmNoMemory-3); | |||||
399 | ||||||
400 | iptr = iptr2; | |||||
401 | ||||||
402 | switch (cpp) { | |||||
403 | ||||||
404 | case (1): /* Optimize for single character | |||||
405 | * colors */ | |||||
406 | { | |||||
407 | unsigned short colidx[256]; | |||||
408 | ||||||
409 | if (ncolors > 256) { | |||||
410 | XpmFree(iptr2)free(iptr2); /* found by Egbert Eich */ | |||||
411 | return (XpmFileInvalid-2); | |||||
412 | } | |||||
413 | ||||||
414 | bzero((char *)colidx, 256 * sizeof(short))__builtin___memset_chk ((char *)colidx, 0, 256 * sizeof(short ), __builtin_object_size ((char *)colidx, 0)); | |||||
415 | for (a = 0; a < ncolors; a++) | |||||
416 | colidx[(unsigned char)colorTable[a].string[0]] = a + 1; | |||||
417 | ||||||
418 | for (y = 0; y < height; y++) { | |||||
419 | xpmNextString(data); | |||||
420 | for (x = 0; x < width; x++, iptr++) { | |||||
421 | int c = xpmGetC(data)((!data->type || data->type == 3) ? (*data->cptr++) : (getc(data->stream.file))); | |||||
422 | ||||||
423 | if (c > 0 && c < 256 && colidx[c] != 0) | |||||
424 | *iptr = colidx[c] - 1; | |||||
425 | else { | |||||
426 | XpmFree(iptr2)free(iptr2); | |||||
427 | return (XpmFileInvalid-2); | |||||
428 | } | |||||
429 | } | |||||
430 | } | |||||
431 | } | |||||
432 | break; | |||||
433 | ||||||
434 | case (2): /* Optimize for double character | |||||
435 | * colors */ | |||||
436 | { | |||||
437 | ||||||
438 | /* free all allocated pointers at all exits */ | |||||
439 | #define FREE_CIDXdo { int f; for (f = 0; f < 256; f++) if (cidx[f]) free(cidx [f]); } while(0) \ | |||||
440 | do \ | |||||
441 | { \ | |||||
442 | int f; for (f = 0; f < 256; f++) \ | |||||
443 | if (cidx[f]) XpmFree(cidx[f])free(cidx[f]); \ | |||||
444 | } while(0) | |||||
445 | ||||||
446 | /* array of pointers malloced by need */ | |||||
447 | unsigned short *cidx[256]; | |||||
448 | unsigned int char1; | |||||
449 | ||||||
450 | bzero((char *)cidx, 256 * sizeof(unsigned short *))__builtin___memset_chk ((char *)cidx, 0, 256 * sizeof(unsigned short *), __builtin_object_size ((char *)cidx, 0)); /* init */ | |||||
451 | for (a = 0; a < ncolors; a++) { | |||||
452 | char1 = (unsigned char) colorTable[a].string[0]; | |||||
453 | if (cidx[char1] == NULL((void*)0)) { /* get new memory */ | |||||
454 | cidx[char1] = (unsigned short *) | |||||
455 | XpmCalloc(256, sizeof(unsigned short))calloc((256), (sizeof(unsigned short))); | |||||
456 | if (cidx[char1] == NULL((void*)0)) { /* new block failed */ | |||||
457 | FREE_CIDXdo { int f; for (f = 0; f < 256; f++) if (cidx[f]) free(cidx [f]); } while(0); | |||||
458 | XpmFree(iptr2)free(iptr2); | |||||
459 | return (XpmNoMemory-3); | |||||
460 | } | |||||
461 | } | |||||
462 | cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1; | |||||
463 | } | |||||
464 | ||||||
465 | for (y = 0; y < height; y++) { | |||||
466 | xpmNextString(data); | |||||
467 | for (x = 0; x < width; x++, iptr++) { | |||||
468 | int cc1 = xpmGetC(data)((!data->type || data->type == 3) ? (*data->cptr++) : (getc(data->stream.file))); | |||||
469 | if (cc1 > 0 && cc1 < 256) { | |||||
470 | int cc2 = xpmGetC(data)((!data->type || data->type == 3) ? (*data->cptr++) : (getc(data->stream.file))); | |||||
471 | if (cc2 > 0 && cc2 < 256 && | |||||
472 | cidx[cc1] && cidx[cc1][cc2] != 0) | |||||
473 | *iptr = cidx[cc1][cc2] - 1; | |||||
474 | else { | |||||
475 | FREE_CIDXdo { int f; for (f = 0; f < 256; f++) if (cidx[f]) free(cidx [f]); } while(0); | |||||
476 | XpmFree(iptr2)free(iptr2); | |||||
477 | return (XpmFileInvalid-2); | |||||
478 | } | |||||
479 | } else { | |||||
480 | FREE_CIDXdo { int f; for (f = 0; f < 256; f++) if (cidx[f]) free(cidx [f]); } while(0); | |||||
481 | XpmFree(iptr2)free(iptr2); | |||||
482 | return (XpmFileInvalid-2); | |||||
483 | } | |||||
484 | } | |||||
485 | } | |||||
486 | FREE_CIDXdo { int f; for (f = 0; f < 256; f++) if (cidx[f]) free(cidx [f]); } while(0); | |||||
487 | } | |||||
488 | break; | |||||
489 | ||||||
490 | default: /* Non-optimized case of long color | |||||
491 | * names */ | |||||
492 | { | |||||
493 | char *s; | |||||
494 | char buf[BUFSIZ1024]; | |||||
495 | ||||||
496 | if (cpp >= sizeof(buf)) { | |||||
497 | XpmFree(iptr2)free(iptr2); /* found by Egbert Eich */ | |||||
498 | return (XpmFileInvalid-2); | |||||
499 | } | |||||
500 | ||||||
501 | buf[cpp] = '\0'; | |||||
502 | if (USE_HASHTABLE(cpp > 2 && ncolors > 4)) { | |||||
503 | xpmHashAtom *slot; | |||||
504 | ||||||
505 | for (y = 0; y < height; y++) { | |||||
506 | xpmNextString(data); | |||||
507 | for (x = 0; x < width; x++, iptr++) { | |||||
508 | for (a = 0, s = buf; a < cpp; a++, s++) | |||||
509 | *s = xpmGetC(data)((!data->type || data->type == 3) ? (*data->cptr++) : (getc(data->stream.file))); /* int assigned to char, not a problem here */ | |||||
510 | slot = xpmHashSlot(hashtable, buf); | |||||
511 | if (!*slot) { /* no color matches */ | |||||
512 | XpmFree(iptr2)free(iptr2); | |||||
513 | return (XpmFileInvalid-2); | |||||
514 | } | |||||
515 | *iptr = HashColorIndex(slot)((unsigned long)((*slot)->data)); | |||||
516 | } | |||||
517 | } | |||||
518 | } else { | |||||
519 | for (y = 0; y < height; y++) { | |||||
520 | xpmNextString(data); | |||||
521 | for (x = 0; x < width; x++, iptr++) { | |||||
522 | for (a = 0, s = buf; a < cpp; a++, s++) | |||||
523 | *s = xpmGetC(data)((!data->type || data->type == 3) ? (*data->cptr++) : (getc(data->stream.file))); /* int assigned to char, not a problem here */ | |||||
524 | for (a = 0; a < ncolors; a++) | |||||
525 | if (!strcmp(colorTable[a].string, buf)) | |||||
526 | break; | |||||
527 | if (a == ncolors) { /* no color matches */ | |||||
528 | XpmFree(iptr2)free(iptr2); | |||||
529 | return (XpmFileInvalid-2); | |||||
530 | } | |||||
531 | *iptr = a; | |||||
532 | } | |||||
533 | } | |||||
534 | } | |||||
535 | } | |||||
536 | break; | |||||
537 | } | |||||
538 | *pixels = iptr2; | |||||
539 | return (XpmSuccess0); | |||||
540 | } | |||||
541 | ||||||
542 | int | |||||
543 | xpmParseExtensions( | |||||
544 | xpmData *data, | |||||
545 | XpmExtension **extensions, | |||||
546 | unsigned int *nextensions) | |||||
547 | { | |||||
548 | XpmExtension *exts = NULL((void*)0), *ext; | |||||
549 | unsigned int num = 0; | |||||
550 | unsigned int nlines, a, l, notstart, notend = 0; | |||||
551 | int status; | |||||
552 | char *string, *s, *s2, **sp; | |||||
553 | ||||||
554 | xpmNextString(data); | |||||
555 | exts = (XpmExtension *) XpmMalloc(sizeof(XpmExtension))malloc((sizeof(XpmExtension))); | |||||
556 | /* get the whole string */ | |||||
557 | status = xpmGetString(data, &string, &l); | |||||
558 | if (status != XpmSuccess0) { | |||||
559 | XpmFree(exts)free(exts); | |||||
560 | return (status); | |||||
561 | } | |||||
562 | /* look for the key word XPMEXT, skip lines before this */ | |||||
563 | while ((notstart = strncmp("XPMEXT", string, 6)) | |||||
564 | && (notend = strncmp("XPMENDEXT", string, 9))) { | |||||
565 | XpmFree(string)free(string); | |||||
566 | xpmNextString(data); | |||||
567 | status = xpmGetString(data, &string, &l); | |||||
568 | if (status != XpmSuccess0) { | |||||
569 | XpmFree(exts)free(exts); | |||||
570 | return (status); | |||||
571 | } | |||||
572 | } | |||||
573 | if (!notstart) | |||||
574 | notend = strncmp("XPMENDEXT", string, 9); | |||||
575 | while (!notstart && notend) { | |||||
576 | /* there starts an extension */ | |||||
577 | ext = (XpmExtension *) | |||||
578 | XpmRealloc(exts, (num + 1) * sizeof(XpmExtension))realloc((exts), ((num + 1) * sizeof(XpmExtension))); /* can the loop be forced to iterate often enough to make "(num + 1) * sizeof(XpmExtension)" wrapping? */ | |||||
579 | if (!ext) { | |||||
580 | XpmFree(string)free(string); | |||||
581 | XpmFreeExtensions(exts, num); | |||||
582 | return (XpmNoMemory-3); | |||||
583 | } | |||||
584 | exts = ext; | |||||
585 | ext += num; | |||||
586 | /* skip whitespace and store its name */ | |||||
587 | s2 = s = string + 6; | |||||
588 | while (isspace(*s2)) | |||||
589 | s2++; | |||||
590 | a = s2 - s; | |||||
591 | ext->name = (char *) XpmMalloc(l - a - 6)malloc((l - a - 6)); | |||||
592 | if (!ext->name) { | |||||
593 | XpmFree(string)free(string); | |||||
594 | ext->lines = NULL((void*)0); | |||||
595 | ext->nlines = 0; | |||||
596 | XpmFreeExtensions(exts, num + 1); | |||||
597 | return (XpmNoMemory-3); | |||||
598 | } | |||||
599 | strncpy(ext->name, s + a, l - a - 6)__builtin___strncpy_chk (ext->name, s + a, l - a - 6, __builtin_object_size (ext->name, 2 > 1 ? 1 : 0)); | |||||
600 | XpmFree(string)free(string); | |||||
601 | /* now store the related lines */ | |||||
602 | xpmNextString(data); | |||||
603 | status = xpmGetString(data, &string, &l); | |||||
604 | if (status != XpmSuccess0) { | |||||
605 | ext->lines = NULL((void*)0); | |||||
606 | ext->nlines = 0; | |||||
607 | XpmFreeExtensions(exts, num + 1); | |||||
608 | return (status); | |||||
609 | } | |||||
610 | ext->lines = (char **) XpmMalloc(sizeof(char *))malloc((sizeof(char *))); | |||||
611 | nlines = 0; | |||||
612 | while ((notstart = strncmp("XPMEXT", string, 6)) | |||||
613 | && (notend = strncmp("XPMENDEXT", string, 9))) { | |||||
614 | sp = (char **) | |||||
615 | XpmRealloc(ext->lines, (nlines + 1) * sizeof(char *))realloc((ext->lines), ((nlines + 1) * sizeof(char *))); /* can we iterate enough for a wrapping? */ | |||||
616 | if (!sp) { | |||||
617 | XpmFree(string)free(string); | |||||
618 | ext->nlines = nlines; | |||||
619 | XpmFreeExtensions(exts, num + 1); | |||||
620 | return (XpmNoMemory-3); | |||||
621 | } | |||||
622 | ext->lines = sp; | |||||
623 | ext->lines[nlines] = string; | |||||
624 | nlines++; | |||||
625 | xpmNextString(data); | |||||
626 | status = xpmGetString(data, &string, &l); | |||||
627 | if (status != XpmSuccess0) { | |||||
628 | ext->nlines = nlines; | |||||
629 | XpmFreeExtensions(exts, num + 1); | |||||
630 | return (status); | |||||
631 | } | |||||
632 | } | |||||
633 | if (!nlines) { | |||||
634 | XpmFree(ext->lines)free(ext->lines); | |||||
635 | ext->lines = NULL((void*)0); | |||||
636 | } | |||||
637 | ext->nlines = nlines; | |||||
638 | num++; | |||||
639 | } | |||||
640 | if (!num) { | |||||
641 | XpmFree(string)free(string); | |||||
642 | XpmFree(exts)free(exts); | |||||
643 | exts = NULL((void*)0); | |||||
644 | } else if (!notend) | |||||
645 | XpmFree(string)free(string); | |||||
646 | *nextensions = num; | |||||
647 | *extensions = exts; | |||||
648 | return (XpmSuccess0); | |||||
649 | } | |||||
650 | ||||||
651 | ||||||
652 | /* function call in case of error */ | |||||
653 | #undef RETURN | |||||
654 | #define RETURN(status)do { goto error; } while(0) \ | |||||
655 | do { \ | |||||
656 | goto error; \ | |||||
657 | } while(0) | |||||
658 | ||||||
659 | /* | |||||
660 | * This function parses an Xpm file or data and store the found informations | |||||
661 | * in an an XpmImage structure which is returned. | |||||
662 | */ | |||||
663 | int | |||||
664 | xpmParseData( | |||||
665 | xpmData *data, | |||||
666 | XpmImage *image, | |||||
667 | XpmInfo *info) | |||||
668 | { | |||||
669 | /* variables to return */ | |||||
670 | unsigned int width, height, ncolors, cpp; | |||||
671 | unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0; | |||||
672 | XpmColor *colorTable = NULL((void*)0); | |||||
673 | unsigned int *pixelindex = NULL((void*)0); | |||||
674 | char *hints_cmt = NULL((void*)0); | |||||
675 | char *colors_cmt = NULL((void*)0); | |||||
676 | char *pixels_cmt = NULL((void*)0); | |||||
677 | ||||||
678 | unsigned int cmts; | |||||
679 | int ErrorStatus; | |||||
680 | xpmHashTable hashtable; | |||||
681 | ||||||
682 | cmts = info && (info->valuemask & XpmReturnComments(1L<<8)); | |||||
683 | ||||||
684 | /* | |||||
685 | * parse the header | |||||
686 | */ | |||||
687 | ErrorStatus = xpmParseHeader(data); | |||||
688 | if (ErrorStatus != XpmSuccess0) | |||||
689 | return (ErrorStatus); | |||||
690 | ||||||
691 | /* | |||||
692 | * read values | |||||
693 | */ | |||||
694 | ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp, | |||||
695 | &x_hotspot, &y_hotspot, &hotspot, | |||||
696 | &extensions); | |||||
697 | if (ErrorStatus != XpmSuccess0) | |||||
698 | return (ErrorStatus); | |||||
699 | ||||||
700 | /* | |||||
701 | * store the hints comment line | |||||
702 | */ | |||||
703 | if (cmts) | |||||
704 | xpmGetCmt(data, &hints_cmt); | |||||
705 | ||||||
706 | /* | |||||
707 | * init the hashtable | |||||
708 | */ | |||||
709 | if (USE_HASHTABLE(cpp > 2 && ncolors > 4)) { | |||||
710 | ErrorStatus = xpmHashTableInit(&hashtable); | |||||
711 | if (ErrorStatus != XpmSuccess0) | |||||
712 | RETURN(ErrorStatus)do { goto error; } while(0); | |||||
713 | } | |||||
714 | ||||||
715 | /* | |||||
716 | * read colors | |||||
717 | */ | |||||
718 | ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable); | |||||
719 | if (ErrorStatus != XpmSuccess0) { | |||||
720 | if (USE_HASHTABLE(cpp > 2 && ncolors > 4)) | |||||
721 | xpmHashTableFree(&hashtable); | |||||
722 | RETURN(ErrorStatus)do { goto error; } while(0); | |||||
723 | } | |||||
724 | ||||||
725 | /* | |||||
726 | * store the colors comment line | |||||
727 | */ | |||||
728 | if (cmts) | |||||
729 | xpmGetCmt(data, &colors_cmt); | |||||
730 | ||||||
731 | /* | |||||
732 | * read pixels and index them on color number | |||||
733 | */ | |||||
734 | ErrorStatus = ParsePixels(data, width, height, ncolors, cpp, colorTable, | |||||
735 | &hashtable, &pixelindex); | |||||
736 | ||||||
737 | /* | |||||
738 | * free the hastable | |||||
739 | */ | |||||
740 | if (USE_HASHTABLE(cpp > 2 && ncolors > 4)) | |||||
741 | xpmHashTableFree(&hashtable); | |||||
742 | ||||||
743 | if (ErrorStatus != XpmSuccess0) | |||||
744 | RETURN(ErrorStatus)do { goto error; } while(0); | |||||
745 | ||||||
746 | /* | |||||
747 | * store the pixels comment line | |||||
748 | */ | |||||
749 | if (cmts) | |||||
750 | xpmGetCmt(data, &pixels_cmt); | |||||
751 | ||||||
752 | /* | |||||
753 | * parse extensions | |||||
754 | */ | |||||
755 | if (info && (info->valuemask & XpmReturnExtensions(1L<<10))) { | |||||
756 | if (extensions) { | |||||
757 | ErrorStatus = xpmParseExtensions(data, &info->extensions, | |||||
758 | &info->nextensions); | |||||
759 | if (ErrorStatus != XpmSuccess0) | |||||
760 | RETURN(ErrorStatus)do { goto error; } while(0); | |||||
761 | } else { | |||||
762 | info->extensions = NULL((void*)0); | |||||
763 | info->nextensions = 0; | |||||
764 | } | |||||
765 | } | |||||
766 | ||||||
767 | /* | |||||
768 | * store found informations in the XpmImage structure | |||||
769 | */ | |||||
770 | image->width = width; | |||||
771 | image->height = height; | |||||
772 | image->cpp = cpp; | |||||
773 | image->ncolors = ncolors; | |||||
774 | image->colorTable = colorTable; | |||||
775 | image->data = pixelindex; | |||||
776 | ||||||
777 | if (info) { | |||||
778 | if (cmts) { | |||||
779 | info->hints_cmt = hints_cmt; | |||||
780 | info->colors_cmt = colors_cmt; | |||||
781 | info->pixels_cmt = pixels_cmt; | |||||
782 | } | |||||
783 | if (hotspot) { | |||||
784 | info->x_hotspot = x_hotspot; | |||||
785 | info->y_hotspot = y_hotspot; | |||||
786 | info->valuemask |= XpmHotspot(1L<<4); | |||||
787 | } | |||||
788 | } | |||||
789 | return (XpmSuccess0); | |||||
790 | ||||||
791 | /* exit point in case of error, free only locally allocated variables */ | |||||
792 | error: | |||||
793 | if (colorTable) | |||||
794 | xpmFreeColorTable(colorTable, ncolors); | |||||
795 | if (pixelindex) | |||||
796 | XpmFree(pixelindex)free(pixelindex); | |||||
797 | if (hints_cmt) | |||||
798 | XpmFree(hints_cmt)free(hints_cmt); | |||||
799 | if (colors_cmt) | |||||
800 | XpmFree(colors_cmt)free(colors_cmt); | |||||
801 | if (pixels_cmt) | |||||
802 | XpmFree(pixels_cmt)free(pixels_cmt); | |||||
803 | ||||||
804 | return(ErrorStatus); | |||||
805 | } |