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