]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
stub: Fix unaligned read
authorJan Janssen <medhefgo@web.de>
Tue, 21 Feb 2023 17:05:10 +0000 (18:05 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 21 Feb 2023 20:01:47 +0000 (21:01 +0100)
src/boot/efi/splash.c

index 0dc58675cca63a6e63509a601ae3d9fa66fc64bd..f2d9f20e96854450e447d9190ffa93da771e1dcc 100644 (file)
@@ -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 (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 (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_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],