mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-05 09:17:44 +03:00
stub: Fix unaligned read
This commit is contained in:
parent
377d36898c
commit
024951fb22
@ -3,6 +3,7 @@
|
||||
#include "graphics.h"
|
||||
#include "proto/graphics-output.h"
|
||||
#include "splash.h"
|
||||
#include "unaligned-fundamental.h"
|
||||
#include "util.h"
|
||||
|
||||
struct bmp_file {
|
||||
@ -26,8 +27,16 @@ struct bmp_dib {
|
||||
int32_t y_pixel_meter;
|
||||
uint32_t colors_used;
|
||||
uint32_t colors_important;
|
||||
uint32_t channel_mask_r;
|
||||
uint32_t channel_mask_g;
|
||||
uint32_t channel_mask_b;
|
||||
uint32_t channel_mask_a;
|
||||
} _packed_;
|
||||
|
||||
#define SIZEOF_BMP_DIB offsetof(struct bmp_dib, channel_mask_r)
|
||||
#define SIZEOF_BMP_DIB_RGB offsetof(struct bmp_dib, channel_mask_a)
|
||||
#define SIZEOF_BMP_DIB_RGBA sizeof(struct bmp_dib)
|
||||
|
||||
struct bmp_map {
|
||||
uint8_t blue;
|
||||
uint8_t green;
|
||||
@ -47,7 +56,7 @@ static EFI_STATUS bmp_parse_header(
|
||||
assert(ret_map);
|
||||
assert(pixmap);
|
||||
|
||||
if (size < sizeof(struct bmp_file) + sizeof(struct bmp_dib))
|
||||
if (size < sizeof(struct bmp_file) + SIZEOF_BMP_DIB)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
/* check file header */
|
||||
@ -61,7 +70,7 @@ static EFI_STATUS bmp_parse_header(
|
||||
|
||||
/* check device-independent bitmap */
|
||||
struct bmp_dib *dib = (struct bmp_dib *) (bmp + sizeof(struct bmp_file));
|
||||
if (dib->size < sizeof(struct bmp_dib))
|
||||
if (dib->size < SIZEOF_BMP_DIB)
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
switch (dib->depth) {
|
||||
@ -125,22 +134,21 @@ static void read_channel_maks(
|
||||
|
||||
assert(dib);
|
||||
|
||||
if (IN_SET(dib->depth, 16, 32) && dib->size >= sizeof(*dib) + 3 * sizeof(uint32_t)) {
|
||||
uint32_t *mask = (uint32_t *) ((uint8_t *) dib + sizeof(*dib));
|
||||
channel_mask[R] = mask[R];
|
||||
channel_mask[G] = mask[G];
|
||||
channel_mask[B] = mask[B];
|
||||
channel_shift[R] = __builtin_ctz(mask[R]);
|
||||
channel_shift[G] = __builtin_ctz(mask[G]);
|
||||
channel_shift[B] = __builtin_ctz(mask[B]);
|
||||
channel_scale[R] = 0xff / ((1 << __builtin_popcount(mask[R])) - 1);
|
||||
channel_scale[G] = 0xff / ((1 << __builtin_popcount(mask[G])) - 1);
|
||||
channel_scale[B] = 0xff / ((1 << __builtin_popcount(mask[B])) - 1);
|
||||
if (IN_SET(dib->depth, 16, 32) && dib->size >= SIZEOF_BMP_DIB_RGB) {
|
||||
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 << __builtin_popcount(dib->channel_mask_r)) - 1);
|
||||
channel_scale[G] = 0xff / ((1 << __builtin_popcount(dib->channel_mask_g)) - 1);
|
||||
channel_scale[B] = 0xff / ((1 << __builtin_popcount(dib->channel_mask_b)) - 1);
|
||||
|
||||
if (dib->size >= sizeof(*dib) + 4 * sizeof(uint32_t) && mask[A] != 0) {
|
||||
channel_mask[A] = mask[A];
|
||||
channel_shift[A] = __builtin_ctz(mask[A]);
|
||||
channel_scale[A] = 0xff / ((1 << __builtin_popcount(mask[A])) - 1);
|
||||
if (dib->size >= SIZEOF_BMP_DIB_RGBA && dib->channel_mask_a != 0) {
|
||||
channel_mask[A] = dib->channel_mask_a;
|
||||
channel_shift[A] = __builtin_ctz(dib->channel_mask_a);
|
||||
channel_scale[A] = 0xff / ((1 << __builtin_popcount(dib->channel_mask_a)) - 1);
|
||||
} else {
|
||||
channel_mask[A] = 0;
|
||||
channel_shift[A] = 0;
|
||||
@ -231,7 +239,8 @@ static EFI_STATUS bmp_to_blt(
|
||||
|
||||
case 16:
|
||||
case 32: {
|
||||
uint32_t i = dib->depth == 16 ? *(uint16_t *) in : *(uint32_t *) in;
|
||||
uint32_t i = dib->depth == 16 ? unaligned_read_ne16(in) :
|
||||
unaligned_read_ne32(in);
|
||||
|
||||
uint8_t r = ((i & channel_mask[R]) >> channel_shift[R]) * channel_scale[R],
|
||||
g = ((i & channel_mask[G]) >> channel_shift[G]) * channel_scale[G],
|
||||
|
Loading…
Reference in New Issue
Block a user