CVE-2023-42822
- font_items in struct xrdp_font renamed to chars to catch all accesses to it. This name is consistent with the type of the array elements (struct xrdp_font_char). - Additional fields added to struct xrdp_font to allow for range checking and for a default character to be provided - Additional checks and logic added to xrdp_font_create() - New macro XRDP_FONT_GET_CHAR() added to perform checked access to chars field in struct xrdp_font
This commit is contained in:
parent
4db9323413
commit
58c9c1f06a
@ -345,6 +345,15 @@ xrdp_font_delete(struct xrdp_font *self);
|
||||
int
|
||||
xrdp_font_item_compare(struct xrdp_font_char *font1,
|
||||
struct xrdp_font_char *font2);
|
||||
/**
|
||||
* Gets a checked xrdp_font_char from a font
|
||||
* @param f Font
|
||||
* @param c32 Unicode codepoint
|
||||
*/
|
||||
#define XRDP_FONT_GET_CHAR(f, c32) \
|
||||
(((unsigned int)(c32) >= ' ') && ((unsigned int)(c32) < (f)->char_count) \
|
||||
? ((f)->chars + (unsigned int)(c32)) \
|
||||
: (f)->default_char)
|
||||
|
||||
/* funcs.c */
|
||||
int
|
||||
|
||||
113
xrdp/xrdp_font.c
113
xrdp/xrdp_font.c
@ -65,6 +65,12 @@ static char w_char[] =
|
||||
};
|
||||
#endif
|
||||
|
||||
// Unicode definitions
|
||||
#define UNICODE_WHITE_SQUARE 0x25a1
|
||||
|
||||
// First character allocated in the 'struct xrdp_font.chars' array
|
||||
#define FIRST_CHAR ' '
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_font *
|
||||
xrdp_font_create(struct xrdp_wm *wm)
|
||||
@ -74,7 +80,7 @@ xrdp_font_create(struct xrdp_wm *wm)
|
||||
int fd;
|
||||
int b;
|
||||
int i;
|
||||
int index;
|
||||
unsigned int char_count;
|
||||
int datasize;
|
||||
int file_size;
|
||||
struct xrdp_font_char *f;
|
||||
@ -100,17 +106,39 @@ xrdp_font_create(struct xrdp_wm *wm)
|
||||
}
|
||||
|
||||
self = (struct xrdp_font *)g_malloc(sizeof(struct xrdp_font), 1);
|
||||
if (self == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_font_create: "
|
||||
"Can't allocate memory for font");
|
||||
return self;
|
||||
}
|
||||
self->wm = wm;
|
||||
make_stream(s);
|
||||
init_stream(s, file_size + 1024);
|
||||
fd = g_file_open(file_path);
|
||||
|
||||
if (fd != -1)
|
||||
if (fd < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_font_create: Can't open %s - %s", file_path,
|
||||
g_get_strerror());
|
||||
g_free(self);
|
||||
self = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
b = g_file_read(fd, s->data, file_size + 1024);
|
||||
g_file_close(fd);
|
||||
|
||||
if (b > 0)
|
||||
// Got at least a header?
|
||||
if (b < (4 + 32 + 2 + 2 + 8))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_font_create: Font %s is truncated", file_path);
|
||||
g_free(self);
|
||||
self = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->end = s->data + b;
|
||||
in_uint8s(s, 4);
|
||||
@ -118,11 +146,27 @@ xrdp_font_create(struct xrdp_wm *wm)
|
||||
in_uint16_le(s, self->size);
|
||||
in_uint16_le(s, self->style);
|
||||
in_uint8s(s, 8);
|
||||
index = 32;
|
||||
char_count = FIRST_CHAR;
|
||||
|
||||
while (s_check_rem(s, 16))
|
||||
while (!s_check_end(s))
|
||||
{
|
||||
f = self->font_items + index;
|
||||
if (!s_check_rem(s, 16))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"xrdp_font_create: "
|
||||
"Can't parse header for character U+%X", char_count);
|
||||
break;
|
||||
}
|
||||
|
||||
if (char_count >= MAX_FONT_CHARS)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"xrdp_font_create: "
|
||||
"Ignoring characters >= U+%x", MAX_FONT_CHARS);
|
||||
break;
|
||||
}
|
||||
|
||||
f = self->chars + char_count;
|
||||
in_sint16_le(s, i);
|
||||
f->width = i;
|
||||
in_sint16_le(s, i);
|
||||
@ -139,23 +183,56 @@ xrdp_font_create(struct xrdp_wm *wm)
|
||||
if (datasize < 0 || datasize > 512)
|
||||
{
|
||||
/* shouldn't happen */
|
||||
LOG(LOG_LEVEL_ERROR, "error in xrdp_font_create, datasize wrong "
|
||||
"width %d, height %d, datasize %d, index %d",
|
||||
f->width, f->height, datasize, index);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_font_create: "
|
||||
"datasize for U+%x wrong "
|
||||
"width %d, height %d, datasize %d",
|
||||
char_count, f->width, f->height, datasize);
|
||||
break;
|
||||
}
|
||||
|
||||
if (s_check_rem(s, datasize))
|
||||
if (!s_check_rem(s, datasize))
|
||||
{
|
||||
f->data = (char *)g_malloc(datasize, 0);
|
||||
in_uint8a(s, f->data, datasize);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_font_create: "
|
||||
"Not enough data for character U+%X", char_count);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((f->data = (char *)g_malloc(datasize, 0)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_font_create: "
|
||||
"Allocation error for character U+%X", char_count);
|
||||
break;
|
||||
}
|
||||
in_uint8a(s, f->data, datasize);
|
||||
|
||||
++char_count;
|
||||
}
|
||||
|
||||
self->char_count = char_count;
|
||||
if (char_count <= FIRST_CHAR)
|
||||
{
|
||||
/* We read no characters from the font */
|
||||
xrdp_font_delete(self);
|
||||
self = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find a default glyph
|
||||
if (char_count > UNICODE_WHITE_SQUARE)
|
||||
{
|
||||
self->default_char = &self->chars[UNICODE_WHITE_SQUARE];
|
||||
}
|
||||
else if (char_count > '?')
|
||||
{
|
||||
self->default_char = &self->chars['?'];
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "error in xrdp_font_create");
|
||||
self->default_char = &self->chars[FIRST_CHAR];
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,16 +255,16 @@ xrdp_font_create(struct xrdp_wm *wm)
|
||||
void
|
||||
xrdp_font_delete(struct xrdp_font *self)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
if (self == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_FONTS; i++)
|
||||
for (i = FIRST_CHAR; i < self->char_count; i++)
|
||||
{
|
||||
g_free(self->font_items[i].data);
|
||||
g_free(self->chars[i].data);
|
||||
}
|
||||
|
||||
g_free(self);
|
||||
|
||||
@ -455,7 +455,7 @@ xrdp_painter_text_width(struct xrdp_painter *self, const char *text)
|
||||
|
||||
for (index = 0; index < len; index++)
|
||||
{
|
||||
font_item = self->font->font_items + wstr[index];
|
||||
font_item = XRDP_FONT_GET_CHAR(self->font, wstr[index]);
|
||||
rv = rv + font_item->incby;
|
||||
}
|
||||
|
||||
@ -493,7 +493,7 @@ xrdp_painter_text_height(struct xrdp_painter *self, const char *text)
|
||||
|
||||
for (index = 0; index < len; index++)
|
||||
{
|
||||
font_item = self->font->font_items + wstr[index];
|
||||
font_item = XRDP_FONT_GET_CHAR(self->font, wstr[index]);
|
||||
rv = MAX(rv, font_item->height);
|
||||
}
|
||||
|
||||
@ -870,7 +870,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
|
||||
total_height = 0;
|
||||
for (index = 0; index < len; index++)
|
||||
{
|
||||
font_item = font->font_items + wstr[index];
|
||||
font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
|
||||
k = font_item->incby;
|
||||
total_width += k;
|
||||
total_height = MAX(total_height, font_item->height);
|
||||
@ -904,7 +904,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
|
||||
draw_rect.bottom - draw_rect.top);
|
||||
for (index = 0; index < len; index++)
|
||||
{
|
||||
font_item = font->font_items + wstr[index];
|
||||
font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
|
||||
g_memset(&pat, 0, sizeof(pat));
|
||||
pat.format = PT_FORMAT_c1;
|
||||
pat.width = font_item->width;
|
||||
@ -946,7 +946,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
|
||||
|
||||
for (index = 0; index < len; index++)
|
||||
{
|
||||
font_item = font->font_items + wstr[index];
|
||||
font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
|
||||
i = xrdp_cache_add_char(self->wm->cache, font_item);
|
||||
f = HIWORD(i);
|
||||
c = LOWORD(i);
|
||||
|
||||
@ -574,7 +574,7 @@ struct xrdp_bitmap
|
||||
int crc16;
|
||||
};
|
||||
|
||||
#define NUM_FONTS 0x4e00
|
||||
#define MAX_FONT_CHARS 0x4e00
|
||||
#define DEFAULT_FONT_NAME "sans-10.fv1"
|
||||
|
||||
#define DEFAULT_ELEMENT_TOP 35
|
||||
@ -594,7 +594,11 @@ struct xrdp_bitmap
|
||||
struct xrdp_font
|
||||
{
|
||||
struct xrdp_wm *wm;
|
||||
struct xrdp_font_char font_items[NUM_FONTS];
|
||||
// Font characters, accessed by Unicode codepoint. The first 32
|
||||
// entries are unused.
|
||||
struct xrdp_font_char chars[MAX_FONT_CHARS];
|
||||
unsigned int char_count; // # elements in above array
|
||||
struct xrdp_font_char *default_char; // Pointer into above array
|
||||
char name[32];
|
||||
int size;
|
||||
int style;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user