return EFI_UNSUPPORTED;
}
- size_t row_size = ((size_t) dib->depth * dib->x + 31) / 32 * 4;
- if (file->size - file->offset < dib->y * row_size)
+ if (dib->x == 0 || dib->y == 0)
+ return EFI_INVALID_PARAMETER;
+
+ /* Bound dimensions before computing row_size to prevent overflow
+ * in the (size_t) dib->depth * dib->x multiplication on 32-bit. */
+ if (dib->x > (size_t) 64 * 1024 * 1024 / dib->depth ||
+ dib->y > (size_t) 64 * 1024 * 1024 / dib->depth / dib->x)
return EFI_INVALID_PARAMETER;
- if (row_size * dib->y > 64 * 1024 * 1024)
+
+ size_t row_size = ((size_t) dib->depth * dib->x + 31) / 32 * 4;
+ if (file->size - file->offset < dib->y * row_size)
return EFI_INVALID_PARAMETER;
/* check color table */
if (dib->channel_mask_r == 0 || dib->channel_mask_g == 0 || dib->channel_mask_b == 0)
return EFI_INVALID_PARAMETER;
+ /* Reject masks where all bits are set (popcount == 32), since
+ * 1U << 32 is undefined behavior and causes division by zero
+ * on architectures where it evaluates to zero. */
+ if (popcount(dib->channel_mask_r) >= 32 ||
+ popcount(dib->channel_mask_g) >= 32 ||
+ popcount(dib->channel_mask_b) >= 32)
+ return EFI_INVALID_PARAMETER;
+
channel_mask[R] = dib->channel_mask_r;
channel_mask[G] = dib->channel_mask_g;
channel_mask[B] = dib->channel_mask_b;
channel_shift[R] = __builtin_ctz(dib->channel_mask_r);
channel_shift[G] = __builtin_ctz(dib->channel_mask_g);
channel_shift[B] = __builtin_ctz(dib->channel_mask_b);
- channel_scale[R] = 0xff / ((1 << popcount(dib->channel_mask_r)) - 1);
- channel_scale[G] = 0xff / ((1 << popcount(dib->channel_mask_g)) - 1);
- channel_scale[B] = 0xff / ((1 << popcount(dib->channel_mask_b)) - 1);
+ channel_scale[R] = 0xff / ((1U << popcount(dib->channel_mask_r)) - 1);
+ channel_scale[G] = 0xff / ((1U << popcount(dib->channel_mask_g)) - 1);
+ channel_scale[B] = 0xff / ((1U << popcount(dib->channel_mask_b)) - 1);
if (dib->size >= SIZEOF_BMP_DIB_RGBA && dib->channel_mask_a != 0) {
+ if (popcount(dib->channel_mask_a) >= 32)
+ return EFI_INVALID_PARAMETER;
+
channel_mask[A] = dib->channel_mask_a;
channel_shift[A] = __builtin_ctz(dib->channel_mask_a);
- channel_scale[A] = 0xff / ((1 << popcount(dib->channel_mask_a)) - 1);
+ channel_scale[A] = 0xff / ((1U << popcount(dib->channel_mask_a)) - 1);
} else {
channel_mask[A] = 0;
channel_shift[A] = 0;