d3dx9: Fix memory access for images with less than 4 bytes per pixel (Valgrind). (try 2)

Matteo Bruni matteo.mystral at gmail.com
Wed Feb 23 06:08:19 CST 2011


Since try 1 I removed the endianness stuff, as it is not taken into
account elsewhere, and I replaced the for loops with memcpy.
-------------- next part --------------
From 337ee51631a5f8fa53dce424692063ba24d7f183 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <mbruni at codeweavers.com>
Date: Wed, 16 Feb 2011 02:39:21 +0100
Subject: d3dx9: Fix memory access for images with less than 4 bytes per pixel (Valgrind).

---
 dlls/d3dx9_36/surface.c |   78 +++++++++++++++++++++++++++++++++++++---------
 1 files changed, 62 insertions(+), 16 deletions(-)

diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c
index 48cd2c2..961b4cf 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -598,6 +598,40 @@ static void init_argb_conversion_info(CONST PixelFormatDesc *srcformat, CONST Pi
     }
 }
 
+static DWORD dword_from_bytes(CONST BYTE *src, UINT bytes_per_pixel)
+{
+    DWORD ret = 0;
+    static BOOL fixme_once;
+
+    if(bytes_per_pixel > sizeof(DWORD)) {
+        if(!fixme_once) {
+            FIXME("Unsupported image: %u bytes per pixel\n", bytes_per_pixel);
+            fixme_once = TRUE;
+        }
+        bytes_per_pixel = sizeof(DWORD);
+    }
+
+    memcpy(&ret, src, bytes_per_pixel);
+    return ret;
+}
+
+static void dword_to_bytes(BYTE *dst, DWORD dword, UINT bytes_per_pixel)
+{
+    static BOOL fixme_once;
+
+    ZeroMemory(dst, bytes_per_pixel);
+
+    if(bytes_per_pixel > sizeof(DWORD)) {
+        if(!fixme_once) {
+            FIXME("Unsupported image: %u bytes per pixel\n", bytes_per_pixel);
+            fixme_once = TRUE;
+        }
+        bytes_per_pixel = sizeof(DWORD);
+    }
+
+    memcpy(dst, &dword, bytes_per_pixel);
+}
+
 /************************************************************
  * get_relevant_argb_components
  *
@@ -618,20 +652,21 @@ static void get_relevant_argb_components(CONST struct argb_conversion_info *info
  * Recombines the output of get_relevant_argb_components and converts
  * it to the destination format.
  */
-static void make_argb_color(CONST struct argb_conversion_info *info, CONST DWORD *in, DWORD *out)
+static DWORD make_argb_color(CONST struct argb_conversion_info *info, CONST DWORD *in)
 {
     UINT i;
-    *out = 0;
+    DWORD val = 0;
 
     for(i = 0;i < 4;i++) {
         if(info->process_channel[i]) {
             /* necessary to make sure that e.g. an X4R4G4B4 white maps to an R8G8B8 white instead of 0xf0f0f0 */
             signed int shift;
-            for(shift = info->destshift[i]; shift > info->destformat->shift[i]; shift -= info->srcformat->bits[i]) *out |= in[i] << shift;
-            *out |= (in[i] >> (info->destformat->shift[i] - shift)) << info->destformat->shift[i];
+            for(shift = info->destshift[i]; shift > info->destformat->shift[i]; shift -= info->srcformat->bits[i]) val |= in[i] << shift;
+            val |= (in[i] >> (info->destformat->shift[i] - shift)) << info->destformat->shift[i];
         }
     }
-    *out |= info->channelmask;   /* new channels are set to their maximal value */
+    val |= info->channelmask;   /* new channels are set to their maximal value */
+    return val;
 }
 
 /************************************************************
@@ -668,23 +703,29 @@ static void copy_simple_data(CONST BYTE *src, UINT srcpitch, POINT srcsize,
     }
 
     for(y = 0;y < minheight;y++) {
-        const BYTE *srcptr = src + y *  srcpitch;
+        const BYTE *srcptr = src + y * srcpitch;
         BYTE *destptr = dest + y * destpitch;
+        DWORD val = 0;
+
         for(x = 0;x < minwidth;x++) {
             /* extract source color components */
-            if(srcformat->type == FORMAT_ARGB) get_relevant_argb_components(&conv_info, *(const DWORD*)srcptr, channels);
+            if(srcformat->type == FORMAT_ARGB) {
+                pixel = dword_from_bytes(srcptr, srcformat->bytes_per_pixel);
+                get_relevant_argb_components(&conv_info, pixel, channels);
+            }
 
             /* recombine the components */
-            if(destformat->type == FORMAT_ARGB) make_argb_color(&conv_info, channels, (DWORD*)destptr);
+            if(destformat->type == FORMAT_ARGB) val = make_argb_color(&conv_info, channels);
 
             if(colorkey) {
-                get_relevant_argb_components(&ck_conv_info, *(const DWORD*)srcptr, channels);
-                make_argb_color(&ck_conv_info, channels, &pixel);
+                get_relevant_argb_components(&ck_conv_info, pixel, channels);
+                pixel = make_argb_color(&ck_conv_info, channels);
                 if(pixel == colorkey)
                     /* make this pixel transparent */
-                    *(DWORD *)destptr &= ~conv_info.destmask[0];
+                    val &= ~conv_info.destmask[0];
             }
 
+            dword_to_bytes(destptr, val, destformat->bytes_per_pixel);
             srcptr  +=  srcformat->bytes_per_pixel;
             destptr += destformat->bytes_per_pixel;
         }
@@ -732,21 +773,26 @@ static void point_filter_simple_data(CONST BYTE *src, UINT srcpitch, POINT srcsi
 
         for(x = 0;x < destsize.x;x++) {
             const BYTE *srcptr = bufptr + (x * srcsize.x / destsize.x) * srcformat->bytes_per_pixel;
+            DWORD val = 0;
 
             /* extract source color components */
-            if(srcformat->type == FORMAT_ARGB) get_relevant_argb_components(&conv_info, *(const DWORD*)srcptr, channels);
+            if(srcformat->type == FORMAT_ARGB) {
+                pixel = dword_from_bytes(srcptr, srcformat->bytes_per_pixel);
+                get_relevant_argb_components(&conv_info, pixel, channels);
+            }
 
             /* recombine the components */
-            if(destformat->type == FORMAT_ARGB) make_argb_color(&conv_info, channels, (DWORD*)destptr);
+            if(destformat->type == FORMAT_ARGB) val = make_argb_color(&conv_info, channels);
 
             if(colorkey) {
-                get_relevant_argb_components(&ck_conv_info, *(const DWORD*)srcptr, channels);
-                make_argb_color(&ck_conv_info, channels, &pixel);
+                get_relevant_argb_components(&ck_conv_info, pixel, channels);
+                pixel = make_argb_color(&ck_conv_info, channels);
                 if(pixel == colorkey)
                     /* make this pixel transparent */
-                    *(DWORD *)destptr &= ~conv_info.destmask[0];
+                    val &= ~conv_info.destmask[0];
             }
 
+            dword_to_bytes(destptr, val, destformat->bytes_per_pixel);
             destptr += destformat->bytes_per_pixel;
         }
     }
-- 
1.7.3.4


More information about the wine-patches mailing list