Fix potential buffer overflow on Windows when loading fonts (#1221)
This commit is bigger than necessary to fix the buffer allocation but it also prevents some unnecessary string copies: the font name is converted from UTF-16 to UTF-8 directly in the buffer used later. Code reformatted and clarified as well, some duplicated code was removed.
This commit is contained in:
parent
24aec69f27
commit
2e1730d2f0
@ -84,30 +84,47 @@ const char* Fl_GDI_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap) {
|
|||||||
|
|
||||||
static int fl_free_font = FL_FREE_FONT;
|
static int fl_free_font = FL_FREE_FONT;
|
||||||
|
|
||||||
|
// helper function for `enumcbw()` to avoid code repetition
|
||||||
|
// input:
|
||||||
|
// ft: font "type", i.e. ' ', 'B', 'I', or 'P'
|
||||||
|
// fn: font name whose first byte is overwritten and then stored
|
||||||
|
|
||||||
|
static void set_font_name(const char ft, char *fn) {
|
||||||
|
fn[0] = ft;
|
||||||
|
Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback for EnumFontFamiliesW():
|
||||||
|
// return 1 to continue, 0 to stop enumeration
|
||||||
|
|
||||||
static int CALLBACK
|
static int CALLBACK
|
||||||
enumcbw(CONST LOGFONTW *lpelf,
|
enumcbw(CONST LOGFONTW *lpelf,
|
||||||
CONST TEXTMETRICW * /*lpntm*/,
|
CONST TEXTMETRICW * /* lpntm */,
|
||||||
DWORD /*FontType*/,
|
DWORD /* FontType */,
|
||||||
LPARAM p) {
|
LPARAM p) {
|
||||||
if (!p && lpelf->lfCharSet != ANSI_CHARSET) return 1;
|
if (!p && lpelf->lfCharSet != ANSI_CHARSET) return 1;
|
||||||
char *n = NULL;
|
char *fn = nullptr; // FLTK font name
|
||||||
size_t l = wcslen(lpelf->lfFaceName);
|
unsigned lw = (unsigned)wcslen(lpelf->lfFaceName);
|
||||||
unsigned dstlen = fl_utf8fromwc(n, 0, (wchar_t*)lpelf->lfFaceName, (unsigned) l) + 1; // measure the string
|
unsigned dstlen = fl_utf8fromwc(fn, 0, (wchar_t*)lpelf->lfFaceName, lw); // measure the string
|
||||||
n = (char*) malloc(dstlen);
|
fn = (char*)malloc((size_t)dstlen + 2); // "?" + name + NUL
|
||||||
//n[fl_unicode2utf((wchar_t*)lpelf->lfFaceName, l, n)] = 0;
|
if (!fn) return 1;
|
||||||
dstlen = fl_utf8fromwc(n, dstlen, (wchar_t*)lpelf->lfFaceName, (unsigned) l); // convert the string
|
fn[0] = ' ';
|
||||||
n[dstlen] = 0;
|
dstlen = fl_utf8fromwc(fn+1, dstlen+1, (wchar_t*)lpelf->lfFaceName, lw); // convert the string
|
||||||
for (int i=0; i<FL_FREE_FONT; i++) // skip if one of our built-in fonts
|
fn[dstlen] = 0;
|
||||||
if (!strcmp(Fl::get_font_name((Fl_Font)i),n)) {free(n);return 1;}
|
// skip if it is one of our built-in fonts
|
||||||
char buffer[LF_FACESIZE + 1];
|
for (int i = 0; i < FL_FREE_FONT; i++) {
|
||||||
strcpy(buffer+1, n);
|
if (!strcmp(Fl::get_font_name((Fl_Font)i), fn+1)) {
|
||||||
buffer[0] = ' '; Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(buffer));
|
free(fn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_font_name(' ', fn);
|
||||||
if (lpelf->lfWeight <= 400)
|
if (lpelf->lfWeight <= 400)
|
||||||
buffer[0] = 'B', Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(buffer));
|
set_font_name('B', fn);
|
||||||
buffer[0] = 'I'; Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(buffer));
|
set_font_name('I', fn);
|
||||||
if (lpelf->lfWeight <= 400)
|
if (lpelf->lfWeight <= 400)
|
||||||
buffer[0] = 'P', Fl::set_font((Fl_Font)(fl_free_font++), fl_strdup(buffer));
|
set_font_name('P', fn);
|
||||||
free(n);
|
free(fn);
|
||||||
return 1;
|
return 1;
|
||||||
} /* enumcbw */
|
} /* enumcbw */
|
||||||
|
|
||||||
@ -129,9 +146,9 @@ static int sizes[128];
|
|||||||
static int CALLBACK
|
static int CALLBACK
|
||||||
|
|
||||||
EnumSizeCbW(CONST LOGFONTW * /*lpelf*/,
|
EnumSizeCbW(CONST LOGFONTW * /*lpelf*/,
|
||||||
CONST TEXTMETRICW *lpntm,
|
CONST TEXTMETRICW *lpntm,
|
||||||
DWORD fontType,
|
DWORD fontType,
|
||||||
LPARAM /*p*/) {
|
LPARAM /*p*/) {
|
||||||
if ((fontType & RASTER_FONTTYPE) == 0) {
|
if ((fontType & RASTER_FONTTYPE) == 0) {
|
||||||
sizes[0] = 0;
|
sizes[0] = 0;
|
||||||
nbSize = 1;
|
nbSize = 1;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user