CrDatFrI.c revision 74835918
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 } 248 XpmFree(header); 249 } 250 return(ErrorStatus); 251} 252 253static int 254CreateColors( 255 char **dataptr, 256 unsigned int *data_size, 257 XpmColor *colors, 258 unsigned int ncolors, 259 unsigned int cpp) 260{ 261 char buf[BUFSIZ]; 262 unsigned int a, key, l; 263 char *s, *s2; 264 char **defaults; 265 266 /* can ncolors be trusted here? */ 267 for (a = 0; a < ncolors; a++, colors++, dataptr++) { 268 269 defaults = (char **) colors; 270 if(sizeof(buf) <= cpp) 271 return(XpmNoMemory); 272 strncpy(buf, *defaults++, cpp); 273 s = buf + cpp; 274 275 if(sizeof(buf) <= (s-buf)) 276 return XpmNoMemory; 277 278 for (key = 1; key <= NKEYS; key++, defaults++) { 279 if ((s2 = *defaults)) { 280#ifndef VOID_SPRINTF 281 s += 282#endif 283 /* assume C99 compliance */ 284 snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2); 285#ifdef VOID_SPRINTF 286 s += strlen(s); 287#endif 288 /* does s point out-of-bounds? */ 289 if(sizeof(buf) < (s-buf)) 290 return XpmNoMemory; 291 } 292 } 293 /* what about using strdup()? */ 294 l = s - buf + 1; 295 s = (char *) XpmMalloc(l); 296 if (!s) 297 return (XpmNoMemory); 298 *data_size += l; 299 *dataptr = strcpy(s, buf); 300 } 301 return (XpmSuccess); 302} 303 304static void 305CreatePixels( 306 char **dataptr, 307 unsigned int data_size, 308 unsigned int width, 309 unsigned int height, 310 unsigned int cpp, 311 unsigned int *pixels, 312 XpmColor *colors) 313{ 314 char *s; 315 unsigned int x, y, h, offset; 316 317 if(height <= 1) 318 return; 319 320 h = height - 1; 321 322 offset = width * cpp + 1; 323 324 if(offset <= width || offset <= cpp) 325 return; 326 327 /* why trust h? */ 328 for (y = 0; y < h; y++, dataptr++) { 329 s = *dataptr; 330 /* why trust width? */ 331 for (x = 0; x < width; x++, pixels++) { 332 if(cpp > (data_size - (s - *dataptr))) 333 return; 334 strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */ 335 s += cpp; 336 } 337 *s = '\0'; 338 if(offset > data_size) 339 return; 340 *(dataptr + 1) = *dataptr + offset; 341 } 342 /* duplicate some code to avoid a test in the loop */ 343 s = *dataptr; 344 /* why trust width? */ 345 for (x = 0; x < width; x++, pixels++) { 346 if(cpp > data_size - (s - *dataptr)) 347 return; 348 strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */ 349 s += cpp; 350 } 351 *s = '\0'; 352} 353 354static int 355CountExtensions( 356 XpmExtension *ext, 357 unsigned int num, 358 unsigned int *ext_size, 359 unsigned int *ext_nlines) 360{ 361 size_t len; 362 unsigned int x, y, a, size, nlines; 363 char **line; 364 365 size = 0; 366 nlines = 0; 367 for (x = 0; x < num; x++, ext++) { 368 /* 1 for the name */ 369 if (ext->nlines == UINT_MAX || nlines > UINT_MAX - ext->nlines - 1) 370 return (1); 371 nlines += ext->nlines + 1; 372 /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */ 373 len = strlen(ext->name) + 8; 374 if (len > UINT_MAX - size) 375 return (1); 376 size += len; 377 a = ext->nlines; 378 for (y = 0, line = ext->lines; y < a; y++, line++) { 379 len = strlen(*line) + 1; 380 if (len > UINT_MAX - size) 381 return (1); 382 size += len; 383 } 384 } 385 if (size > UINT_MAX - 10 || nlines > UINT_MAX - 1) 386 return (1); 387 /* 10 and 1 are for the ending "XPMENDEXT" */ 388 *ext_size = size + 10; 389 *ext_nlines = nlines + 1; 390 return (0); 391} 392 393static void 394CreateExtensions( 395 char **dataptr, 396 unsigned int data_size, 397 unsigned int offset, 398 XpmExtension *ext, 399 unsigned int num, 400 unsigned int ext_nlines) 401{ 402 unsigned int x, y, a, b; 403 char **line; 404 405 *(dataptr + 1) = *dataptr + offset; 406 dataptr++; 407 a = 0; 408 for (x = 0; x < num; x++, ext++) { 409 snprintf(*dataptr, data_size, "XPMEXT %s", ext->name); 410 a++; 411 if (a < ext_nlines) 412 *(dataptr + 1) = *dataptr + strlen(ext->name) + 8; 413 dataptr++; 414 b = ext->nlines; /* can we trust these values? */ 415 for (y = 0, line = ext->lines; y < b; y++, line++) { 416 strcpy(*dataptr, *line); 417 a++; 418 if (a < ext_nlines) 419 *(dataptr + 1) = *dataptr + strlen(*line) + 1; 420 dataptr++; 421 } 422 } 423 strcpy(*dataptr, "XPMENDEXT"); 424} 425