|
|
* Developed by Arnaud Le Hors * | * Developed by Arnaud Le Hors * |
\*****************************************************************************/ | \*****************************************************************************/ |
| |
|
/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ |
|
|
|
|
#include "XpmI.h" | #include "XpmI.h" |
| |
LFUNC(WriteColors, int, (char **dataptr, unsigned int *data_size, | LFUNC(WriteColors, int, (char **dataptr, unsigned int *data_size, |
unsigned int *used_size, XpmColor *colors, | unsigned int *used_size, XpmColor *colors, |
unsigned int ncolors, unsigned int cpp)); | unsigned int ncolors, unsigned int cpp)); |
| |
LFUNC(WritePixels, void, (char *dataptr, unsigned int *used_size, |
LFUNC(WritePixels, void, (char *dataptr, unsigned int data_size, |
|
unsigned int *used_size, |
unsigned int width, unsigned int height, | unsigned int width, unsigned int height, |
unsigned int cpp, unsigned int *pixels, | unsigned int cpp, unsigned int *pixels, |
XpmColor *colors)); | XpmColor *colors)); |
| |
LFUNC(WriteExtensions, void, (char *dataptr, unsigned int *used_size, |
LFUNC(WriteExtensions, void, (char *dataptr, unsigned int data_size, |
|
unsigned int *used_size, |
XpmExtension *ext, unsigned int num)); | XpmExtension *ext, unsigned int num)); |
| |
LFUNC(ExtensionsSize, int, (XpmExtension *ext, unsigned int num)); |
LFUNC(ExtensionsSize, unsigned int, (XpmExtension *ext, unsigned int num)); |
LFUNC(CommentsSize, int, (XpmInfo *info)); | LFUNC(CommentsSize, int, (XpmInfo *info)); |
| |
int | int |
|
|
| |
#undef RETURN | #undef RETURN |
#define RETURN(status) \ | #define RETURN(status) \ |
|
do \ |
{ \ | { \ |
if (ptr) \ | if (ptr) \ |
XpmFree(ptr); \ | XpmFree(ptr); \ |
return(status); \ | return(status); \ |
} |
} while(0) |
| |
int | int |
XpmCreateBufferFromXpmImage(buffer_return, image, info) | XpmCreateBufferFromXpmImage(buffer_return, image, info) |
|
|
unsigned int cmts, extensions, ext_size = 0; | unsigned int cmts, extensions, ext_size = 0; |
unsigned int l, cmt_size = 0; | unsigned int l, cmt_size = 0; |
char *ptr = NULL, *p; | char *ptr = NULL, *p; |
unsigned int ptr_size, used_size; |
unsigned int ptr_size, used_size, tmp; |
| |
*buffer_return = NULL; | *buffer_return = NULL; |
| |
|
|
#ifdef VOID_SPRINTF | #ifdef VOID_SPRINTF |
used_size = strlen(buf); | used_size = strlen(buf); |
#endif | #endif |
ptr_size = used_size + ext_size + cmt_size + 1; |
ptr_size = used_size + ext_size + cmt_size + 1; /* ptr_size can't be 0 */ |
|
if(ptr_size <= used_size || |
|
ptr_size <= ext_size || |
|
ptr_size <= cmt_size) |
|
{ |
|
return XpmNoMemory; |
|
} |
ptr = (char *) XpmMalloc(ptr_size); | ptr = (char *) XpmMalloc(ptr_size); |
if (!ptr) | if (!ptr) |
return XpmNoMemory; | return XpmNoMemory; |
|
|
#ifndef VOID_SPRINTF | #ifndef VOID_SPRINTF |
used_size += | used_size += |
#endif | #endif |
sprintf(ptr + used_size, "/*%s*/\n", info->hints_cmt); |
snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->hints_cmt); |
#ifdef VOID_SPRINTF | #ifdef VOID_SPRINTF |
used_size += strlen(info->hints_cmt) + 5; | used_size += strlen(info->hints_cmt) + 5; |
#endif | #endif |
|
|
#ifndef VOID_SPRINTF | #ifndef VOID_SPRINTF |
l += | l += |
#endif | #endif |
sprintf(buf + l, " %d %d", info->x_hotspot, info->y_hotspot); |
snprintf(buf + l, sizeof(buf)-l, " %d %d", info->x_hotspot, info->y_hotspot); |
#ifdef VOID_SPRINTF | #ifdef VOID_SPRINTF |
l = strlen(buf); | l = strlen(buf); |
#endif | #endif |
|
|
l = strlen(buf); | l = strlen(buf); |
#endif | #endif |
ptr_size += l; | ptr_size += l; |
|
if(ptr_size <= l) |
|
RETURN(XpmNoMemory); |
p = (char *) XpmRealloc(ptr, ptr_size); | p = (char *) XpmRealloc(ptr, ptr_size); |
if (!p) | if (!p) |
RETURN(XpmNoMemory); | RETURN(XpmNoMemory); |
|
|
#ifndef VOID_SPRINTF | #ifndef VOID_SPRINTF |
used_size += | used_size += |
#endif | #endif |
sprintf(ptr + used_size, "/*%s*/\n", info->colors_cmt); |
snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->colors_cmt); |
#ifdef VOID_SPRINTF | #ifdef VOID_SPRINTF |
used_size += strlen(info->colors_cmt) + 5; | used_size += strlen(info->colors_cmt) + 5; |
#endif | #endif |
|
|
* 4 = 1 (for '"') + 3 (for '",\n') | * 4 = 1 (for '"') + 3 (for '",\n') |
* 1 = - 2 (because the last line does not end with ',\n') + 3 (for '};\n') | * 1 = - 2 (because the last line does not end with ',\n') + 3 (for '};\n') |
*/ | */ |
ptr_size += image->height * (image->width * image->cpp + 4) + 1; |
if(image->width > UINT_MAX / image->cpp || |
|
(tmp = image->width * image->cpp + 4) <= 4 || |
|
image->height > UINT_MAX / tmp || |
|
(tmp = image->height * tmp + 1) <= 1 || |
|
(ptr_size += tmp) <= tmp) |
|
RETURN(XpmNoMemory); |
| |
p = (char *) XpmRealloc(ptr, ptr_size); | p = (char *) XpmRealloc(ptr, ptr_size); |
if (!p) | if (!p) |
|
|
#ifndef VOID_SPRINTF | #ifndef VOID_SPRINTF |
used_size += | used_size += |
#endif | #endif |
sprintf(ptr + used_size, "/*%s*/\n", info->pixels_cmt); |
snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->pixels_cmt); |
#ifdef VOID_SPRINTF | #ifdef VOID_SPRINTF |
used_size += strlen(info->pixels_cmt) + 5; | used_size += strlen(info->pixels_cmt) + 5; |
#endif | #endif |
} | } |
WritePixels(ptr + used_size, &used_size, image->width, image->height, |
WritePixels(ptr + used_size, ptr_size - used_size, &used_size, image->width, image->height, |
image->cpp, image->data, image->colorTable); | image->cpp, image->data, image->colorTable); |
| |
/* print extensions */ | /* print extensions */ |
if (extensions) | if (extensions) |
WriteExtensions(ptr + used_size, &used_size, |
WriteExtensions(ptr + used_size, ptr_size-used_size, &used_size, |
info->extensions, info->nextensions); | info->extensions, info->nextensions); |
| |
/* close the array */ | /* close the array */ |
|
|
return (XpmSuccess); | return (XpmSuccess); |
} | } |
| |
|
|
static int | static int |
WriteColors(dataptr, data_size, used_size, colors, ncolors, cpp) | WriteColors(dataptr, data_size, used_size, colors, ncolors, cpp) |
char **dataptr; | char **dataptr; |
|
|
unsigned int ncolors; | unsigned int ncolors; |
unsigned int cpp; | unsigned int cpp; |
{ | { |
char buf[BUFSIZ]; |
char buf[BUFSIZ] = {0}; |
unsigned int a, key, l; | unsigned int a, key, l; |
char *s, *s2; | char *s, *s2; |
char **defaults; | char **defaults; |
|
|
| |
defaults = (char **) colors; | defaults = (char **) colors; |
s = buf + 1; | s = buf + 1; |
|
if(cpp > (sizeof(buf) - (s-buf))) |
|
return(XpmNoMemory); |
strncpy(s, *defaults++, cpp); | strncpy(s, *defaults++, cpp); |
s += cpp; | s += cpp; |
| |
for (key = 1; key <= NKEYS; key++, defaults++) { | for (key = 1; key <= NKEYS; key++, defaults++) { |
if (s2 = *defaults) { |
if ((s2 = *defaults)) { |
#ifndef VOID_SPRINTF | #ifndef VOID_SPRINTF |
s += | s += |
#endif | #endif |
sprintf(s, "\t%s %s", xpmColorKeys[key - 1], s2); |
/* assume C99 compliance */ |
|
snprintf(s, sizeof(buf) - (s-buf), "\t%s %s", xpmColorKeys[key - 1], s2); |
#ifdef VOID_SPRINTF | #ifdef VOID_SPRINTF |
s += strlen(s); | s += strlen(s); |
#endif | #endif |
|
/* now let's check if s points out-of-bounds */ |
|
if((s-buf) > sizeof(buf)) |
|
return(XpmNoMemory); |
} | } |
} | } |
|
if(sizeof(buf) - (s-buf) < 4) |
|
return(XpmNoMemory); |
strcpy(s, "\",\n"); | strcpy(s, "\",\n"); |
l = s + 3 - buf; | l = s + 3 - buf; |
|
if( *data_size >= UINT_MAX-l || |
|
*data_size + l <= *used_size || |
|
(*data_size + l - *used_size) <= sizeof(buf)) |
|
return(XpmNoMemory); |
s = (char *) XpmRealloc(*dataptr, *data_size + l); | s = (char *) XpmRealloc(*dataptr, *data_size + l); |
if (!s) | if (!s) |
return (XpmNoMemory); | return (XpmNoMemory); |
|
|
} | } |
| |
static void | static void |
WritePixels(dataptr, used_size, width, height, cpp, pixels, colors) |
WritePixels(dataptr, data_size, used_size, width, height, cpp, pixels, colors) |
char *dataptr; | char *dataptr; |
|
unsigned int data_size; |
unsigned int *used_size; | unsigned int *used_size; |
unsigned int width; | unsigned int width; |
unsigned int height; | unsigned int height; |
|
|
char *s = dataptr; | char *s = dataptr; |
unsigned int x, y, h; | unsigned int x, y, h; |
| |
|
if(height <= 1) |
|
return; |
|
|
h = height - 1; | h = height - 1; |
for (y = 0; y < h; y++) { | for (y = 0; y < h; y++) { |
*s++ = '"'; | *s++ = '"'; |
for (x = 0; x < width; x++, pixels++) { | for (x = 0; x < width; x++, pixels++) { |
strncpy(s, colors[*pixels].string, cpp); |
if(cpp >= (data_size - (s-dataptr))) |
|
return; |
|
strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? :-\ */ |
s += cpp; | s += cpp; |
} | } |
|
if((data_size - (s-dataptr)) < 4) |
|
return; |
strcpy(s, "\",\n"); | strcpy(s, "\",\n"); |
s += 3; | s += 3; |
} | } |
/* duplicate some code to avoid a test in the loop */ | /* duplicate some code to avoid a test in the loop */ |
*s++ = '"'; | *s++ = '"'; |
for (x = 0; x < width; x++, pixels++) { | for (x = 0; x < width; x++, pixels++) { |
strncpy(s, colors[*pixels].string, cpp); |
if(cpp >= (data_size - (s-dataptr))) |
|
return; |
|
strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? */ |
s += cpp; | s += cpp; |
} | } |
*s++ = '"'; | *s++ = '"'; |
*used_size += s - dataptr; | *used_size += s - dataptr; |
} | } |
| |
static int |
static unsigned int |
ExtensionsSize(ext, num) | ExtensionsSize(ext, num) |
XpmExtension *ext; | XpmExtension *ext; |
unsigned int num; | unsigned int num; |
|
|
char **line; | char **line; |
| |
size = 0; | size = 0; |
|
if(num == 0) |
|
return(0); /* ok? */ |
for (x = 0; x < num; x++, ext++) { | for (x = 0; x < num; x++, ext++) { |
/* 11 = 10 (for ',\n"XPMEXT ') + 1 (for '"') */ | /* 11 = 10 (for ',\n"XPMEXT ') + 1 (for '"') */ |
size += strlen(ext->name) + 11; | size += strlen(ext->name) + 11; |
a = ext->nlines; |
a = ext->nlines; /* how can we trust ext->nlines to be not out-of-bounds? */ |
for (y = 0, line = ext->lines; y < a; y++, line++) | for (y = 0, line = ext->lines; y < a; y++, line++) |
/* 4 = 3 (for ',\n"') + 1 (for '"') */ | /* 4 = 3 (for ',\n"') + 1 (for '"') */ |
size += strlen(*line) + 4; | size += strlen(*line) + 4; |
} | } |
/* 13 is for ',\n"XPMENDEXT"' */ | /* 13 is for ',\n"XPMENDEXT"' */ |
|
if(size > UINT_MAX - 13) /* unlikely */ |
|
return(0); |
return size + 13; | return size + 13; |
} | } |
| |
static void | static void |
WriteExtensions(dataptr, used_size, ext, num) |
WriteExtensions(dataptr, data_size, used_size, ext, num) |
char *dataptr; | char *dataptr; |
|
unsigned int data_size; |
unsigned int *used_size; | unsigned int *used_size; |
XpmExtension *ext; | XpmExtension *ext; |
unsigned int num; | unsigned int num; |
|
|
| |
for (x = 0; x < num; x++, ext++) { | for (x = 0; x < num; x++, ext++) { |
#ifndef VOID_SPRINTF | #ifndef VOID_SPRINTF |
s += 11 + |
s += |
#endif | #endif |
sprintf(s, ",\n\"XPMEXT %s\"", ext->name); |
snprintf(s, data_size - (s-dataptr), ",\n\"XPMEXT %s\"", ext->name); |
#ifdef VOID_SPRINTF | #ifdef VOID_SPRINTF |
s += strlen(ext->name) + 11; | s += strlen(ext->name) + 11; |
#endif | #endif |
a = ext->nlines; | a = ext->nlines; |
for (y = 0, line = ext->lines; y < a; y++, line++) { | for (y = 0, line = ext->lines; y < a; y++, line++) { |
#ifndef VOID_SPRINTF | #ifndef VOID_SPRINTF |
s += 4 + |
s += |
#endif | #endif |
sprintf(s, ",\n\"%s\"", *line); |
snprintf(s, data_size - (s-dataptr), ",\n\"%s\"", *line); |
#ifdef VOID_SPRINTF | #ifdef VOID_SPRINTF |
s += strlen(*line) + 4; | s += strlen(*line) + 4; |
#endif | #endif |
} | } |
} | } |
strcpy(s, ",\n\"XPMENDEXT\""); |
strncpy(s, ",\n\"XPMENDEXT\"", data_size - (s-dataptr)-1); |
*used_size += s - dataptr + 13; | *used_size += s - dataptr + 13; |
} | } |
| |
|
|
int size = 0; | int size = 0; |
| |
/* 5 = 2 (for "/_*") + 3 (for "*_/\n") */ | /* 5 = 2 (for "/_*") + 3 (for "*_/\n") */ |
|
/* wrap possible but *very* unlikely */ |
if (info->hints_cmt) | if (info->hints_cmt) |
size += 5 + strlen(info->hints_cmt); | size += 5 + strlen(info->hints_cmt); |
| |