Bug Summary

File:win32/pngtoico.c
Location:line 116, column 13
Description:Call to 'malloc' has an allocation size of 0 bytes

Annotated Source Code

1/* $Id: pngtoico.c,v 1.1 2003-10-10 18:54:30 rprix Exp $ */
2/* ----------------------------------------------------------------------- *
3 *
4 * Copyright 2001 H. Peter Anvin - All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
9 * Bostom MA 02111-1307, USA; either version 2 of the License, or
10 * (at your option) any later version; incorporated herein by reference.
11 *
12 * ----------------------------------------------------------------------- */
13
14/*
15 * pngtoico.c
16 *
17 * Convert a set of palettized .png files to a Windoze .ico file
18 *
19 * The .png files may have transparency which will be reflected in
20 * the .ico file; however, partial transparency (alpha values other
21 * than 0 and 255) are not supported by the .ico format.
22 *
23 * Usage: pngtoico file1.png file2.png file3.png > file.ico
24 */
25
26#include <errno(*__errno_location ()).h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30#include <inttypes.h>
31#include <png.h>
32
33#define min(x,y)(((x) < (y)) ? (x) : (y)) (((x) < (y)) ? (x) : (y))
34#define max(x,y)(((x) > (y)) ? (x) : (y)) (((x) > (y)) ? (x) : (y))
35
36#ifndef png_jmpbuf
37# define png_jmpbuf(png_ptr)(*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) ((png_ptr)->jmpbuf)
38#endif
39
40/* argv[0] */
41const char *program;
42
43/* Functions to write unaligned littleendian data */
44static inline void
45write_le16(uint8_t *ptr, uint16_t v)
46{
47#if defined(__i386__) || defined(__x86_64__1)
48 *(uint16_t *)ptr = v;
49#else
50 ptr[0] = (v & 0xff);
51 ptr[1] = (v >> 8) & 0xff;
52#endif
53}
54
55static inline void
56write_le32(uint8_t *ptr, uint32_t v)
57{
58#if defined(__i386__) || defined(__x86_64__1)
59 *(uint32_t *)ptr = v;
60#else
61 ptr[0] = (v & 0xff);
62 ptr[1] = (v >> 8) & 0xff;
63 ptr[2] = (v >> 16) & 0xff;
64 ptr[3] = (v >> 24) & 0xff;
65#endif
66}
67
68struct ico_common {
69 uint8_t resv[2];
70 uint8_t type[2]; /* == 1 */
71 uint8_t count[2]; /* Number of icons */
72};
73
74struct ico_hdr {
75 uint8_t width;
76 uint8_t height;
77 uint8_t colorcount;
78 uint8_t resv; /* Always 0 */
79 uint8_t planes[2]; /* Always 1 */
80 uint8_t bitcount[2]; /* Bits per pixel (1, 4, 8) */
81 uint8_t sizeinbytes[4];
82 uint8_t fileoffset[4];
83};
84
85struct ico_info {
86 uint8_t headersize[4];
87 uint8_t width[4];
88 uint8_t height[4]; /* Actually 2xheight */
89 uint8_t planes[2]; /* Always 1 */
90 uint8_t bitcount[2]; /* Bits per pixel (1, 4, 8) */
91 uint8_t unused[6*4]; /* Always 0 */
92};
93
94struct ico_color {
95 uint8_t b, g, r;
96 uint8_t resv;
97};
98
99struct ico_fragment {
100 struct ico_fragment *next;
101 uint32_t offset;
102
103 struct ico_hdr hdr;
104 struct ico_info info;
105 struct ico_color *pal;
106 uint32_t pal_size;
107 uint8_t *data;
108 uint32_t data_size;
109 uint8_t *alpha;
110 uint32_t alpha_size;
111};
112
113void *
114xmalloc(size_t s)
115{
116 void *p = malloc(s);
28
Call to 'malloc' has an allocation size of 0 bytes
117 if ( !p ) {
118 perror(program);
119 exit(1);
120 }
121
122 return p;
123}
124
125void *
126zalloc(size_t s)
127{
128 void *p = xmalloc(s);
26
Passing the value 0 via 1st parameter 's'
27
Calling 'xmalloc'
129 memset(p, 0, s);
130 return p;
131}
132
133/*
134 * Read a single PNG file and create corresponding ICO header and
135 * body data.
136 */
137static struct ico_fragment *
138read_png(const char *file)
139{
140 struct ico_fragment *frag;
141 struct ico_hdr *hdr;
142 struct ico_info *info;
143 struct ico_color *pal = NULL((void*)0);
144 uint8_t *data = NULL((void*)0);
145 uint8_t *alpha = NULL((void*)0);
146 FILE *fp = NULL((void*)0);
147 png_structp png_ptr = NULL((void*)0);
148 png_infop info_ptr = NULL((void*)0), end_info = NULL((void*)0);
149 png_uint_32 width, height;
150 int dwidth, awidth, bit_depth, color_type;
151 png_colorp palette;
152 int num_palette, max_colors;
153 png_bytep trans;
154 int num_trans;
155 uint8_t **row_pointers;
156 uint8_t *dbyte, *abyte;
157 int dshift, ashift, pixelshift;
158 unsigned int x, y;
159 int i;
160 int datasize, alphasize;
161
162 frag = zalloc(sizeof(*frag));
163
164 hdr = &frag->hdr;
165 info = &frag->info;
166
167 write_le32(info->headersize, sizeof(*info));
168 write_le16(hdr->planes, 1);
169 write_le16(info->planes, 1);
170
171 fp = fopen(file, "rb");
172 if ( !fp ) {
1
Assuming 'fp' is non-null
2
Taking false branch
173 goto perrexit;
174 }
175
176 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING"1.6.10",
177 NULL((void*)0), NULL((void*)0), NULL((void*)0));
178 if ( !png_ptr ) {
3
Assuming 'png_ptr' is non-null
4
Taking false branch
179 errno(*__errno_location ()) = ENOMEM12;
180 goto perrexit;
181 }
182
183 info_ptr = png_create_info_struct(png_ptr);
184 if ( !info_ptr ) {
5
Assuming 'info_ptr' is non-null
6
Taking false branch
185 errno(*__errno_location ()) = ENOMEM12;
186 goto perrexit;
187 }
188
189 end_info = png_create_info_struct(png_ptr);
190 if ( !end_info ) {
7
Assuming 'end_info' is non-null
8
Taking false branch
191 errno(*__errno_location ()) = ENOMEM12;
192 goto perrexit;
193 }
194
195 if ( setjmp(png_jmpbuf(png_ptr))_setjmp ((*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf
)))))
) {
9
Taking false branch
196 fprintf(stderrstderr, "%s: PNG format error\n", file);
197 goto errexit;
198 }
199
200 png_init_io(png_ptr, fp);
201 png_read_info(png_ptr, info_ptr);
202
203
204 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
205 NULL((void*)0), NULL((void*)0), NULL((void*)0));
206
207 if ( height > 255 || width > 255 ) {
10
Assuming 'height' is <= 255
11
Assuming 'width' is <= 255
12
Taking false branch
208 fprintf(stderrstderr, "%s: Image too large\n", file);
209 goto errexit;
210 }
211
212 if ( color_type != PNG_COLOR_TYPE_PALETTE(2 | 1) ) {
13
Taking false branch
213 fprintf(stderrstderr, "%s: Not a palettized image\n", file);
214 goto errexit;
215 }
216
217 if ( bit_depth > 8 ) {
14
Assuming 'bit_depth' is <= 8
15
Taking false branch
218 fprintf(stderrstderr, "%s: Too many colors used\n", file);
219 goto errexit;
220 }
221
222 if ( !png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) ) {
16
Taking false branch
223 fprintf(stderrstderr, "%s: Palette data missing\n", file);
224 goto errexit;
225 }
226 if ( !png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, 0) ) {
17
Taking false branch
227 num_trans = 0; /* Everything is fully opaque */
228 }
229
230 /* Expand data to one pixel/byte */
231 if ( bit_depth < 8 )
18
Assuming 'bit_depth' is >= 8
19
Taking false branch
232 png_set_packing(png_ptr);
233
234 /* Activate transforms */
235 png_read_update_info(png_ptr, info_ptr);
236
237 row_pointers = xmalloc(sizeof(uint8_t *) * height);
238 for ( y = 0 ; y < height ; y++ ) {
20
Assuming 'y' is >= 'height'
21
Loop condition is false. Execution continues on line 242
239 row_pointers[y] = xmalloc(width);
240 }
241
242 png_read_image(png_ptr, row_pointers);
243
244 /* Now we have the image in memory. Allocate memory for the
245 icon output data. */
246
247 hdr->width = width; write_le32(info->width, width);
248 hdr->height = height; write_le32(info->height, 2*height);
249
250 if ( num_palette <= 2 ) {
22
Assuming 'num_palette' is <= 2
23
Taking true branch
251 /* 1 bit/pixel */
252 dwidth = ((width+31) & ~31) >> 3;
253 pixelshift = 1;
254 } else if ( num_palette <= 16 ) {
255 /* 4 bits/pixel */
256 dwidth = ((width+7) & ~7) >> 1;
257 pixelshift = 4;
258 } else {
259 /* 8 bits/pixel */
260 dwidth = (width+3) & ~3;
261 pixelshift = 8;
262 }
263 max_colors = 1 << pixelshift;
264 awidth = ((width+31) & ~31) >> 3;
265
266 write_le16(hdr->bitcount, pixelshift);
267 write_le16(info->bitcount, pixelshift);
268
269 frag->data = data = zalloc(datasize = dwidth*height);
24
Passing the value 0 via 1st parameter 's'
25
Calling 'zalloc'
270 frag->data_size = datasize;
271 frag->alpha = alpha = zalloc(alphasize = awidth*height);
272 frag->alpha_size = alphasize;
273
274 hdr->colorcount = max_colors & 0xff;
275 frag->pal = pal = zalloc(max_colors * sizeof(*pal));
276 frag->pal_size = max_colors * sizeof(*pal);
277
278 write_le32(hdr->sizeinbytes,
279 sizeof(*info)+frag->pal_size+datasize+alphasize);
280
281 for ( i = 0 ; i < min(num_palette, max_colors)(((num_palette) < (max_colors)) ? (num_palette) : (max_colors
))
; i++ ) {
282 pal[i].r = palette[i].red;
283 pal[i].g = palette[i].green;
284 pal[i].b = palette[i].blue;
285 }
286
287 for ( y = 0 ; y < height ; y++ ) {
288 dbyte = data + (height-y-1)*dwidth;
289 abyte = alpha + (height-y-1)*awidth;
290 dshift = 8-pixelshift; ashift = 7;
291
292 for ( x = 0 ; x < width ; x++ ) {
293 uint8_t index = row_pointers[y][x];
294 uint8_t pixel = index;
295 uint8_t ptran = (index < num_trans) ? trans[index] : 255;
296
297 if ( ptran == 0 ) {
298 pixel = 0;
299 } else if ( ptran != 255 ) {
300 fprintf(stderrstderr, "%s: Warning: partial transparency (%d/255) ignored\n",
301 file, ptran);
302 }
303
304 *dbyte |= pixel << dshift;
305 dshift -= pixelshift;
306 if ( dshift < 0 ) {
307 dshift += 8;
308 dbyte++;
309 }
310
311 *abyte |= (ptran ? 0 : 1) << ashift;
312 ashift--;
313 if ( ashift < 0 ) {
314 ashift += 8;
315 abyte++;
316 }
317 }
318
319 /* Done with this row */
320 free(row_pointers[y]);
321 }
322 free(row_pointers);
323
324 /* Okay, we're done, clean up and return success */
325
326 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
327 fclose(fp);
328 return frag;
329
330 perrexit:
331 perror(file);
332 errexit:
333 if ( png_ptr ) {
334 png_destroy_read_struct(png_ptr ? &png_ptr : NULL((void*)0),
335 info_ptr ? &info_ptr : NULL((void*)0),
336 end_info ? &end_info : NULL((void*)0));
337 }
338 if ( fp ) fclose(fp);
339 if ( pal ) free(pal);
340 if ( data ) free(data);
341 if ( alpha ) free(alpha);
342 free(frag);
343 return NULL((void*)0);
344}
345
346/*
347 * Main program: read all files, then stitch the ICO file together.
348 */
349
350int main(int argc, char *argv[])
351{
352 struct ico_fragment *frag;
353 struct ico_fragment *list = NULL((void*)0);
354 struct ico_fragment **tail = &list;
355 struct ico_common common;
356 int count = 0;
357 int i;
358 uint32_t offset;
359
360 for ( i = 1 ; i < argc ; i++ ) {
361 if ( !(frag = read_png(argv[i])) )
362 return 1;
363
364 count++;
365 *tail = frag;
366 tail = &frag->next;
367 }
368
369 memset(&common, 0, sizeof(common));
370 write_le16(common.type, 1);
371 write_le16(common.count, count);
372
373 /* Write header */
374 fwrite(&common, sizeof(common), 1, stdoutstdout);
375
376 offset = sizeof(common) + count*sizeof(struct ico_hdr);
377
378 for ( frag = list ; frag ; frag = frag->next ) {
379 write_le32(frag->hdr.fileoffset, offset);
380 fwrite(&frag->hdr, sizeof(struct ico_hdr), 1, stdoutstdout);
381
382 offset += sizeof(struct ico_info) + frag->pal_size + frag->data_size + frag->alpha_size;
383 }
384
385 for ( frag = list ; frag ; frag = frag->next ) {
386 fwrite(&frag->info, sizeof(struct ico_info), 1, stdoutstdout);
387 fwrite(frag->pal, 1, frag->pal_size, stdoutstdout);
388 fwrite(frag->data, 1, frag->data_size, stdoutstdout);
389 fwrite(frag->alpha, 1, frag->alpha_size, stdoutstdout);
390 }
391
392 return 0;
393}
394