@@ -454,24 +454,29 @@ static uint64_t hash_cursor(uint32_t w, uint32_t h,
454454
455455// Fallback function to lookup an unnamed cursor by its bitmap
456456static uint32_t find_cursor_by_image (Ghandles * g ) {
457- XFixesCursorImage * img = XFixesGetCursorImage (g -> display );
458- if (!img ) return CURSOR_DEFAULT ;
457+ XFixesCursorImage * live_img = XFixesGetCursorImage (g -> display );
458+ if (!live_img ) return CURSOR_DEFAULT ;
459+
460+ // SEC: Abort immediately on suspiciously huge cursors to avoid mallocating too much RAM
461+ if (live_img -> width > 512 || live_img -> height > 512 ) {
462+ return CURSOR_DEFAULT ;
463+ }
459464
460465 /* Narrow unsigned long pixels to uint32_t */
461- size_t npx = (size_t )img -> width * img -> height ;
466+ size_t npx = (size_t )live_img -> width * live_img -> height ;
462467 uint32_t * live_px = malloc (npx * sizeof (uint32_t ));
463468 if (!live_px ) {
464- XFree (img );
469+ XFree (live_img );
465470 return CURSOR_DEFAULT ;
466471 }
467- for (size_t i = 0 ; i < npx ; i ++ ) live_px [i ] = (uint32_t )img -> pixels [i ];
472+ for (size_t i = 0 ; i < npx ; i ++ ) live_px [i ] = (uint32_t )live_img -> pixels [i ];
468473
469- uint64_t live_hash = hash_cursor (img -> width , img -> height , img -> xhot , img -> yhot , live_px );
474+ uint64_t live_hash = hash_cursor (live_img -> width , live_img -> height , live_img -> xhot , live_img -> yhot , live_px );
470475 free (live_px );
471476
472477 /* Use the live cursor's own size to avoid potential discrepancies between root's and the user's themes */
473- uint32_t size = (img -> width > img -> height ) ? img -> width : img -> height ;
474- XFree (img );
478+ uint32_t size = (live_img -> width > live_img -> height ) ? live_img -> width : live_img -> height ;
479+ XFree (live_img );
475480
476481 char * theme = XcursorGetTheme (g -> display );
477482 for (size_t i = 0 ; i < NUM_SUPPORTED_CURSORS ; i ++ ) {
@@ -483,7 +488,10 @@ static uint32_t find_cursor_by_image(Ghandles *g) {
483488
484489 if (hash == live_hash ) {
485490 uint32_t found = CURSOR_X11 + supported_cursors [i ].cursor_id ;
486- assert (found < CURSOR_X11_MAX );
491+ // SEC: Check bounds at runtime
492+ if (found >= CURSOR_X11_MAX ) {
493+ return CURSOR_DEFAULT ;
494+ }
487495 return found ;
488496 }
489497 }
0 commit comments