CrDatFrI.c revision edce3322
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* CrDataFI.c: * 28* * 29* XPM library * 30* Scan an image and possibly its mask and create an XPM array * 31* * 32* Developed by Arnaud Le Hors * 33\*****************************************************************************/ 34 35/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ 36 37#ifdef HAVE_CONFIG_H 38#include <config.h> 39#endif 40#include "XpmI.h" 41 42#ifdef FOR_MSW 43#define snprintf _snprintf 44#endif 45 46LFUNC(CreateColors, int, (char **dataptr, unsigned int *data_size, 47 XpmColor *colors, unsigned int ncolors, 48 unsigned int cpp)); 49 50LFUNC(CreatePixels, void, (char **dataptr, unsigned int data_size, 51 unsigned int width, 52 unsigned int height, unsigned int cpp, 53 unsigned int *pixels, XpmColor *colors)); 54 55LFUNC(CountExtensions, int, (XpmExtension *ext, unsigned int num, 56 unsigned int *ext_size, 57 unsigned int *ext_nlines)); 58 59LFUNC(CreateExtensions, void, (char **dataptr, unsigned int data_size, 60 unsigned int offset, 61 XpmExtension *ext, unsigned int num, 62 unsigned int ext_nlines)); 63 64int 65XpmCreateDataFromImage( 66 Display *display, 67 char ***data_return, 68 XImage *image, 69 XImage *shapeimage, 70 XpmAttributes *attributes) 71{ 72 XpmImage xpmimage; 73 XpmInfo info; 74 int ErrorStatus; 75 76 /* initialize return value */ 77 if (data_return) 78 *data_return = NULL; 79 80 /* create an XpmImage from the image */ 81 ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage, 82 &xpmimage, attributes); 83 if (ErrorStatus != XpmSuccess) 84 return (ErrorStatus); 85 86 /* create the data from the XpmImage */ 87 if (attributes) { 88 xpmSetInfo(&info, attributes); 89 ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info); 90 } else 91 ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL); 92 93 /* free the XpmImage */ 94 XpmFreeXpmImage(&xpmimage); 95 96 return (ErrorStatus); 97} 98 99#undef RETURN 100#define RETURN(status) \ 101do \ 102{ \ 103 ErrorStatus = status; \ 104 goto exit; \ 105} while(0) 106 107int 108XpmCreateDataFromXpmImage( 109 char ***data_return, 110 XpmImage *image, 111 XpmInfo *info) 112{ 113 /* calculation variables */ 114 int ErrorStatus; 115 char buf[BUFSIZ]; 116 char **header = NULL, **data, **sptr, **sptr2, *s; 117 unsigned int header_size, header_nlines; 118 unsigned int data_size, data_nlines; 119 unsigned int extensions = 0, ext_size = 0, ext_nlines = 0; 120 unsigned int offset, l, n; 121 122 *data_return = NULL; 123 124 extensions = info && (info->valuemask & XpmExtensions) 125 && info->nextensions; 126 127 /* compute the number of extensions lines and size */ 128 if (extensions) 129 if (CountExtensions(info->extensions, info->nextensions, 130 &ext_size, &ext_nlines)) 131 return(XpmNoMemory); 132 133 /* 134 * alloc a temporary array of char pointer for the header section which 135 * is the hints line + the color table lines 136 */ 137 header_nlines = 1 + image->ncolors; /* this may wrap and/or become 0 */ 138 139 /* 2nd check superfluous if we do not need header_nlines any further */ 140 if(header_nlines <= image->ncolors || 141 header_nlines >= UINT_MAX / sizeof(char *)) 142 return(XpmNoMemory); 143 144 header_size = sizeof(char *) * header_nlines; 145 if (header_size >= UINT_MAX / sizeof(char *)) 146 return (XpmNoMemory); 147 header = (char **) XpmCalloc(header_size, sizeof(char *)); /* can we trust image->ncolors */ 148 if (!header) 149 return (XpmNoMemory); 150 151 /* print the hints line */ 152 s = buf; 153#ifndef VOID_SPRINTF 154 s += 155#endif 156 sprintf(s, "%d %d %d %d", image->width, image->height, 157 image->ncolors, image->cpp); 158#ifdef VOID_SPRINTF 159 s += strlen(s); 160#endif 161 162 if (info && (info->valuemask & XpmHotspot)) { 163#ifndef VOID_SPRINTF 164 s += 165#endif 166 sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot); 167#ifdef VOID_SPRINTF 168 s += strlen(s); 169#endif 170 } 171 if (extensions) { 172 strcpy(s, " XPMEXT"); 173 s += 7; 174 } 175 l = s - buf + 1; 176 *header = (char *) XpmMalloc(l); 177 if (!*header) 178 RETURN(XpmNoMemory); 179 header_size += l; 180 strcpy(*header, buf); 181 182 /* print colors */ 183 ErrorStatus = CreateColors(header + 1, &header_size, 184 image->colorTable, image->ncolors, image->cpp); 185 186 if (ErrorStatus != XpmSuccess) 187 RETURN(ErrorStatus); 188 189 /* now we know the size needed, alloc the data and copy the header lines */ 190 offset = image->width * image->cpp + 1; 191 192 if(offset <= image->width || offset <= image->cpp) 193 RETURN(XpmNoMemory); 194 195 if (image->height > UINT_MAX - ext_nlines || 196 image->height + ext_nlines >= UINT_MAX / sizeof(char *)) 197 RETURN(XpmNoMemory); 198 data_size = (image->height + ext_nlines) * sizeof(char *); 199 200 if (image->height > UINT_MAX / offset || 201 image->height * offset > UINT_MAX - data_size) 202 RETURN(XpmNoMemory); 203 data_size += image->height * offset; 204 205 if (header_size > UINT_MAX - ext_size || 206 header_size + ext_size >= (UINT_MAX - data_size) ) 207 RETURN(XpmNoMemory); 208 data_size += header_size + ext_size; 209 210 data = (char **) XpmMalloc(data_size); 211 if (!data) 212 RETURN(XpmNoMemory); 213 214 data_nlines = header_nlines + image->height + ext_nlines; 215 *data = (char *) (data + data_nlines); 216 217 /* can header have less elements then n suggests? */ 218 n = image->ncolors; 219 for (l = 0, sptr = data, sptr2 = header; l <= n && sptr && sptr2; l++, sptr++, sptr2++) { 220 strcpy(*sptr, *sptr2); 221 *(sptr + 1) = *sptr + strlen(*sptr2) + 1; 222 } 223 224 /* print pixels */ 225 data[header_nlines] = (char *) data + header_size 226 + (image->height + ext_nlines) * sizeof(char *); 227 228 CreatePixels(data + header_nlines, data_size-header_nlines, image->width, image->height, 229 image->cpp, image->data, image->colorTable); 230 231 /* print extensions */ 232 if (extensions) 233 CreateExtensions(data + header_nlines + image->height - 1, 234 data_size - header_nlines - image->height + 1, offset, 235 info->extensions, info->nextensions, 236 ext_nlines); 237 238 *data_return = data; 239 ErrorStatus = XpmSuccess; 240 241/* exit point, free only locally allocated variables */ 242exit: 243 if (header) { 244 for (l = 0; l < header_nlines; l++) 245 if (header[l]) 246 XpmFree(header[l]); 247 XpmFree(header); 248 } 249 return(ErrorStatus); 250} 251 252static int 253CreateColors( 254 char **dataptr, 255 unsigned int *data_size, 256 XpmColor *colors, 257 unsigned int ncolors, 258 unsigned int cpp) 259{ 260 char buf[BUFSIZ]; 261 unsigned int a, key, l; 262 char *s, *s2; 263 char **defaults; 264 265 /* can ncolors be trusted here? */ 266 for (a = 0; a < ncolors; a++, colors++, dataptr++) { 267 268 defaults = (char **) colors; 269 if(sizeof(buf) <= cpp) 270 return(XpmNoMemory); 271 strncpy(buf, *defaults++, cpp); 272 s = buf + cpp; 273 274 if(sizeof(buf) <= (s-buf)) 275 return XpmNoMemory; 276 277 for (key = 1; key <= NKEYS; key++, defaults++) { 278 if ((s2 = *defaults)) { 279#ifndef VOID_SPRINTF 280 s += 281#endif 282 /* assume C99 compliance */ 283 snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2); 284#ifdef VOID_SPRINTF 285 s += strlen(s); 286#endif 287 /* does s point out-of-bounds? */ 288 if(sizeof(buf) < (s-buf)) 289 return XpmNoMemory; 290 } 291 } 292 /* what about using strdup()? */ 293 l = s - buf + 1; 294 s = (char *) XpmMalloc(l); 295 if (!s) 296 return (XpmNoMemory); 297 *data_size += l; 298 *dataptr = strcpy(s, buf); 299 } 300 return (XpmSuccess); 301} 302 303static void 304CreatePixels( 305 char **dataptr, 306 unsigned int data_size, 307 unsigned int width, 308 unsigned int height, 309 unsigned int cpp, 310 unsigned int *pixels, 311 XpmColor *colors) 312{ 313 char *s; 314 unsigned int x, y, h, offset; 315 316 if(height <= 1) 317 return; 318 319 h = height - 1; 320 321 offset = width * cpp + 1; 322 323 if(offset <= width || offset <= cpp) 324 return; 325 326 /* why trust h? */ 327 for (y = 0; y < h; y++, dataptr++) { 328 s = *dataptr; 329 /* why trust width? */ 330 for (x = 0; x < width; x++, pixels++) { 331 if(cpp > (data_size - (s - *dataptr))) 332 return; 333 strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */ 334 s += cpp; 335 } 336 *s = '\0'; 337 if(offset > data_size) 338 return; 339 *(dataptr + 1) = *dataptr + offset; 340 } 341 /* duplicate some code to avoid a test in the loop */ 342 s = *dataptr; 343 /* why trust width? */ 344 for (x = 0; x < width; x++, pixels++) { 345 if(cpp > data_size - (s - *dataptr)) 346 return; 347 strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */ 348 s += cpp; 349 } 350 *s = '\0'; 351} 352 353static int 354CountExtensions( 355 XpmExtension *ext, 356 unsigned int num, 357 unsigned int *ext_size, 358 unsigned int *ext_nlines) 359{ 360 size_t len; 361 unsigned int x, y, a, size, nlines; 362 char **line; 363 364 size = 0; 365 nlines = 0; 366 for (x = 0; x < num; x++, ext++) { 367 /* 1 for the name */ 368 if (ext->nlines == UINT_MAX || nlines > UINT_MAX - ext->nlines - 1) 369 return (1); 370 nlines += ext->nlines + 1; 371 /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */ 372 len = strlen(ext->name) + 8; 373 if (len > UINT_MAX - size) 374 return (1); 375 size += len; 376 a = ext->nlines; 377 for (y = 0, line = ext->lines; y < a; y++, line++) { 378 len = strlen(*line) + 1; 379 if (len > UINT_MAX - size) 380 return (1); 381 size += len; 382 } 383 } 384 if (size > UINT_MAX - 10 || nlines > UINT_MAX - 1) 385 return (1); 386 /* 10 and 1 are for the ending "XPMENDEXT" */ 387 *ext_size = size + 10; 388 *ext_nlines = nlines + 1; 389 return (0); 390} 391 392static void 393CreateExtensions( 394 char **dataptr, 395 unsigned int data_size, 396 unsigned int offset, 397 XpmExtension *ext, 398 unsigned int num, 399 unsigned int ext_nlines) 400{ 401 unsigned int x, y, a, b; 402 char **line; 403 404 *(dataptr + 1) = *dataptr + offset; 405 dataptr++; 406 a = 0; 407 for (x = 0; x < num; x++, ext++) { 408 snprintf(*dataptr, data_size, "XPMEXT %s", ext->name); 409 a++; 410 if (a < ext_nlines) 411 *(dataptr + 1) = *dataptr + strlen(ext->name) + 8; 412 dataptr++; 413 b = ext->nlines; /* can we trust these values? */ 414 for (y = 0, line = ext->lines; y < b; y++, line++) { 415 strcpy(*dataptr, *line); 416 a++; 417 if (a < ext_nlines) 418 *(dataptr + 1) = *dataptr + strlen(*line) + 1; 419 dataptr++; 420 } 421 } 422 strcpy(*dataptr, "XPMENDEXT"); 423} 424