From c910863e19f9c9cc3db56924634315a37ecfe2bb Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 10 Feb 2012 23:55:24 +0000 Subject: proposed fix for bug-3486474 --- doc/GetColor.3 | 5 ++-- generic/tkColor.c | 55 ++++++++++++++++++++++++++++++++++ generic/tkCursor.c | 4 +-- generic/tkImgBmap.c | 4 +-- generic/tkImgPhoto.c | 2 +- generic/tkInt.h | 7 +++++ mac/tkMacColor.c | 2 +- macosx/tkMacOSXColor.c | 2 +- unix/tkUnixColor.c | 2 +- unix/tkUnixCursor.c | 10 +++---- win/tkWinColor.c | 2 +- xlib/xcolors.c | 81 +++++++++++++++++++++++++++++++++++++++----------- 12 files changed, 143 insertions(+), 33 deletions(-) diff --git a/doc/GetColor.3 b/doc/GetColor.3 index 201edab..abd1620 100644 --- a/doc/GetColor.3 +++ b/doc/GetColor.3 @@ -95,8 +95,9 @@ to use to display the color. Each \fIR\fR, \fIG\fR, or \fIB\fR represents a single hexadecimal digit. The four forms permit colors to be specified with 4-bit, 8-bit, 12-bit or 16-bit values. When fewer than 16 bits are provided for each color, they represent -the most significant bits of the color. For example, #3a7 is the -same as #3000a0007000. +the most significant bits of the color, while the lower unfilled +bits will be repeatedly replicated from the available higher bits. +For example, #3a7 is the same as #3333aaaa7777. .PP .VS 8.1 \fBTk_AllocColorFromObj\fR returns a pointer to diff --git a/generic/tkColor.c b/generic/tkColor.c index f06c43f..87f3209 100644 --- a/generic/tkColor.c +++ b/generic/tkColor.c @@ -809,3 +809,58 @@ TkDebugColor(tkwin, name) } return resultPtr; } + +#ifndef __WIN32__ +/* This function is not necessary for Win32, + * since XParseColor already does the right thing */ +Status +TkParseColor(display, map, spec, colorPtr) + Display * display; /* The display */ + Colormap map; /* Color map */ + _Xconst char* spec; /* String to be parsed */ + XColor * colorPtr; +{ + if (*spec == '#') { + char buf[14]; + buf[0] = '#'; buf[13] = '\0'; + if (!spec[1] || !spec[2] || !spec[3]) { + /* Not at least 3 hex digits, so invalid */ + return 0; + } else if (!spec[4]) { + /* Exactly 3 hex digits */ + buf[1] = buf[2] = buf[3] = buf[4] = spec[1]; + buf[5] = buf[6] = buf[7] = buf[8] = spec[2]; + buf[9] = buf[10] = buf[11] = buf[12] = spec[3]; + return XParseColor(display, map, buf, colorPtr); + } else if (!spec[5] || !spec[6]) { + /* Not at least 6 hex digits, so invalid */ + return 0; + } else if (!spec[7]) { + /* Exactly 6 hex digits */ + buf[1] = buf[3] = spec[1]; + buf[2] = buf[4] = spec[2]; + buf[5] = buf[7] = spec[3]; + buf[6] = buf[8] = spec[4]; + buf[9] = buf[11] = spec[5]; + buf[10] = buf[12] = spec[6]; + return XParseColor(display, map, buf, colorPtr); + } else if (!spec[8] || !spec[9]) { + /* Not at least 9 hex digits, so invalid */ + return 0; + } else if (!spec[10]) { + /* Exactly 9 hex digits */ + buf[1] = buf[4] = spec[1]; + buf[2] = spec[2]; + buf[3] = spec[3]; + buf[5] = buf[8] = spec[4]; + buf[6] = spec[5]; + buf[7] = spec[6]; + buf[9] = buf[12] = spec[7]; + buf[10] = spec[8]; + buf[11] = spec[9]; + return XParseColor(display, map, buf, colorPtr); + } + } + return XParseColor(display, map, spec, colorPtr); +} +#endif /* __WIN32__ */ diff --git a/generic/tkCursor.c b/generic/tkCursor.c index 466d0ef..f599083 100644 --- a/generic/tkCursor.c +++ b/generic/tkCursor.c @@ -357,12 +357,12 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height, * available and add it to the database. */ - if (XParseColor(dataKey.display, Tk_Colormap(tkwin), fg, &fgColor) == 0) { + if (TkParseColor(dataKey.display, Tk_Colormap(tkwin), fg, &fgColor) == 0) { Tcl_AppendResult(interp, "invalid color name \"", fg, "\"", (char *) NULL); goto error; } - if (XParseColor(dataKey.display, Tk_Colormap(tkwin), bg, &bgColor) == 0) { + if (TkParseColor(dataKey.display, Tk_Colormap(tkwin), bg, &bgColor) == 0) { Tcl_AppendResult(interp, "invalid color name \"", bg, "\"", (char *) NULL); goto error; diff --git a/generic/tkImgBmap.c b/generic/tkImgBmap.c index 99ae050..e1ccecb 100644 --- a/generic/tkImgBmap.c +++ b/generic/tkImgBmap.c @@ -1266,7 +1266,7 @@ ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height, */ if ((masterPtr->bgUid != NULL) && (masterPtr->bgUid[0] != '\000')) { XColor color; - XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid, + TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->bgUid, &color); if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) { return TCL_ERROR; @@ -1286,7 +1286,7 @@ ImgBmapPostscript(clientData, interp, tkwin, psinfo, x, y, width, height, */ if ( (masterPtr->fgUid != NULL) && (masterPtr->data != NULL) ) { XColor color; - XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid, + TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), masterPtr->fgUid, &color); if (Tk_PostscriptColor(interp, psinfo, &color) != TCL_OK) { return TCL_ERROR; diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index 80b44d7..ffbb47c 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -1150,7 +1150,7 @@ ImgPhotoCmd(clientData, interp, objc, objv) break; } for (x = 0; x < dataWidth; ++x) { - if (!XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), + if (!TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), listArgv[x], &color)) { Tcl_AppendResult(interp, "can't parse color \"", listArgv[x], "\"", (char *) NULL); diff --git a/generic/tkInt.h b/generic/tkInt.h index 777201e..c274236 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -1213,6 +1213,13 @@ EXTERN int TkParsePadAmount _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, int *pad1Ptr, int *pad2Ptr)); EXTERN int TkpAlwaysShowSelection _ANSI_ARGS_((Tk_Window tkwin)); +#ifdef __WIN32__ +#define TkParseColor XParseColor +#else +EXTERN Status TkParseColor _ANSI_ARGS_((Display * display, + Colormap map, _Xconst char* spec, + XColor * colorPtr)); +#endif /* * Unsupported commands. diff --git a/mac/tkMacColor.c b/mac/tkMacColor.c index 6fd0263..6c3c230 100644 --- a/mac/tkMacColor.c +++ b/mac/tkMacColor.c @@ -274,7 +274,7 @@ TkpGetColor( } } - if (XParseColor(display, colormap, name, &color) == 0) { + if (TkParseColor(display, colormap, name, &color) == 0) { return (TkColor *) NULL; } diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 6ddb95e..9520a77 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -591,7 +591,7 @@ TkpGetColor( } } - if (XParseColor(display, colormap, name, &color) == 0) { + if (TkParseColor(display, colormap, name, &color) == 0) { return (TkColor *) NULL; } diff --git a/unix/tkUnixColor.c b/unix/tkUnixColor.c index d001be5..aebbbca 100644 --- a/unix/tkUnixColor.c +++ b/unix/tkUnixColor.c @@ -168,7 +168,7 @@ TkpGetColor(tkwin, name) FindClosestColor(tkwin, &screen, &color); } } else { - if (XParseColor(display, colormap, buf, &color) == 0) { + if (TkParseColor(display, colormap, buf, &color) == 0) { return (TkColor *) NULL; } if (XAllocColor(display, colormap, &color) != 0) { diff --git a/unix/tkUnixCursor.c b/unix/tkUnixCursor.c index 70e8b93..a4ee0cb 100644 --- a/unix/tkUnixCursor.c +++ b/unix/tkUnixCursor.c @@ -194,7 +194,7 @@ TkGetCursorByName(interp, tkwin, string) fg.red = fg.green = fg.blue = 0; bg.red = bg.green = bg.blue = 65535; } else { - if (XParseColor(display, Tk_Colormap(tkwin), argv[1], + if (TkParseColor(display, Tk_Colormap(tkwin), argv[1], &fg) == 0) { Tcl_AppendResult(interp, "invalid color name \"", argv[1], "\"", (char *) NULL); @@ -204,7 +204,7 @@ TkGetCursorByName(interp, tkwin, string) bg.red = bg.green = bg.blue = 0; maskIndex = namePtr->shape; } else { - if (XParseColor(display, Tk_Colormap(tkwin), argv[2], + if (TkParseColor(display, Tk_Colormap(tkwin), argv[2], &bg) == 0) { Tcl_AppendResult(interp, "invalid color name \"", argv[2], "\"", (char *) NULL); @@ -262,7 +262,7 @@ TkGetCursorByName(interp, tkwin, string) goto cleanup; } if (argc == 2) { - if (XParseColor(display, Tk_Colormap(tkwin), argv[1], + if (TkParseColor(display, Tk_Colormap(tkwin), argv[1], &fg) == 0) { Tcl_AppendResult(interp, "invalid color name \"", argv[1], "\"", (char *) NULL); @@ -285,13 +285,13 @@ TkGetCursorByName(interp, tkwin, string) TCL_STATIC); goto cleanup; } - if (XParseColor(display, Tk_Colormap(tkwin), argv[2], + if (TkParseColor(display, Tk_Colormap(tkwin), argv[2], &fg) == 0) { Tcl_AppendResult(interp, "invalid color name \"", argv[2], "\"", (char *) NULL); goto cleanup; } - if (XParseColor(display, Tk_Colormap(tkwin), argv[3], + if (TkParseColor(display, Tk_Colormap(tkwin), argv[3], &bg) == 0) { Tcl_AppendResult(interp, "invalid color name \"", argv[3], "\"", (char *) NULL); diff --git a/win/tkWinColor.c b/win/tkWinColor.c index d3b3cad..088c216 100644 --- a/win/tkWinColor.c +++ b/win/tkWinColor.c @@ -201,7 +201,7 @@ TkpGetColor(tkwin, name) if (((strncasecmp(name, "system", 6) == 0) && FindSystemColor(name+6, &color, &index)) - || XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name, + || TkParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name, &color)) { winColPtr = (WinColor *) ckalloc(sizeof(WinColor)); winColPtr->info.color = color; diff --git a/xlib/xcolors.c b/xlib/xcolors.c index 32c53bd..598f27b 100644 --- a/xlib/xcolors.c +++ b/xlib/xcolors.c @@ -882,24 +882,71 @@ XParseColor(display, map, spec, colorPtr) XColor *colorPtr; { if (spec[0] == '#') { - char fmt[16]; - int i, red, green, blue; + char rstr[5], gstr[5], bstr[5]; - if ((i = (int) strlen(spec+1))%3) { - return 0; - } - i /= 3; - - sprintf(fmt, "%%%dx%%%dx%%%dx", i, i, i); - if (sscanf(spec+1, fmt, &red, &green, &blue) != 3) { - return 0; - } - colorPtr->red = (((unsigned short) red) << (4 * (4 - i))) - | ((unsigned short) red); - colorPtr->green = (((unsigned short) green) << (4 * (4 - i))) - | ((unsigned short) green); - colorPtr->blue = (((unsigned short) blue) << (4 * (4 - i))) - | ((unsigned short) blue); + if (!isxdigit((unsigned char) spec[1]) + || !isxdigit((unsigned char) spec[2]) + || !isxdigit((unsigned char) spec[3])) { + /* Not at least 3 hex digits, so invalid */ + return 0; + } else if (!spec[4]) { + /* Exactly 3 hex digits */ + rstr[0] = rstr[1] = rstr[2] = rstr[3] = spec[1]; + gstr[0] = gstr[1] = gstr[2] = gstr[3] = spec[2]; + bstr[0] = bstr[1] = bstr[2] = bstr[3] = spec[3]; + } else if (!isxdigit((unsigned char) spec[4]) + || !isxdigit((unsigned char) spec[5]) + || !isxdigit((unsigned char) spec[6])) { + /* Not at least 6 hex digits, so invalid */ + return 0; + } else if (!spec[7]) { + /* Exactly 6 hex digits */ + rstr[0] = rstr[2] = spec[1]; + rstr[1] = rstr[3] = spec[2]; + gstr[0] = gstr[2] = spec[3]; + gstr[1] = gstr[3] = spec[4]; + bstr[0] = bstr[2] = spec[5]; + bstr[1] = bstr[3] = spec[6]; + } else if (!isxdigit((unsigned char) spec[7]) + || !isxdigit((unsigned char) spec[8]) + || !isxdigit((unsigned char) spec[9])) { + /* Not at least 9 hex digits, so invalid */ + return 0; + } else if (!spec[10]) { + /* Exactly 9 hex digits */ + rstr[0] = rstr[3] = spec[1]; + rstr[1] = spec[2]; + rstr[2] = spec[3]; + gstr[0] = gstr[3] = spec[4]; + gstr[1] = spec[5]; + gstr[2] = spec[6]; + bstr[0] = bstr[3] = spec[7]; + bstr[1] = spec[8]; + bstr[2] = spec[9]; + } else if (!isxdigit((unsigned char) spec[10]) + || !isxdigit((unsigned char) spec[11]) + || !isxdigit((unsigned char) spec[12]) || spec[13]) { + /* Not exactly 12 hex digits, so invalid */ + return 0; + } else { + /* Exactly 12 hex digits */ + rstr[0] = spec[1]; + rstr[1] = spec[2]; + rstr[2] = spec[3]; + rstr[3] = spec[4]; + gstr[0] = spec[5]; + gstr[1] = spec[6]; + gstr[2] = spec[7]; + gstr[3] = spec[8]; + bstr[0] = spec[9]; + bstr[1] = spec[10]; + bstr[2] = spec[11]; + bstr[3] = spec[12]; + } + rstr[4] = gstr[4] = bstr[4] = '\0'; + colorPtr->red = strtol(rstr, NULL, 16); + colorPtr->green = strtol(gstr, NULL, 16); + colorPtr->blue = strtol(bstr, NULL, 16); } else { if (!FindColor(spec, colorPtr)) { return 0; -- cgit v0.12