https://bugs.winehq.org/show_bug.cgi?id=37689
Michael Müller michael@fds-team.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |michael@fds-team.de
--- Comment #1 from Michael Müller michael@fds-team.de --- Hi,
I tried to debug this problem further, but it seems to be very likely just an application bug - it works with native gdiplus just by chance.
The application creates a GDI+ image from a buffer (0x108e780) which is part of the stack: ---- 0027:trace:gdiplus:GdipCreateBitmapFromScan0 32 4 128 0x26200a 0x108e780 0x108e548 [...] 0027:trace:gdiplus:GdipCreateBitmapFromScan0 <-- 0x14b5c8 ----
Now the application creates a GDI+ graphic context from this GDI+ image: ---- 0027:trace:gdiplus:GdipGetImageGraphicsContext 0x14b5c8 0x108e548 [...] 0027:trace:gdiplus:graphics_from_image <-- 0x17c920 ----
As next step the application requests a DC context, modifies it and releases it again. ---- 0027:trace:gdiplus:GdipGetDC (0x17c920, 0x108e964) 0027:trace:gdiplus:GdipGetImageBounds 0x14b5c8 0x108e8e8 0x108e864 0027:trace:gdiplus:GdipGetImageBounds returning (0.000000, 0.000000) (32.000000, 4.000000) unit type 2 0027:trace:gdiplus:GdipReleaseDC (0x17c920, 0x33007a) ----
The function GdipReleaseDC tries to sync the content between the DC context and the original image buffer by calling alpha_blend_pixels_hrgn which redirects the call to alpha_blend_bmp_pixels.
The crash occurs in alpha_blend_bmp_pixels: ---- static GpStatus alpha_blend_bmp_pixels(GpGraphics *graphics, INT dst_x, INT dst_y, const BYTE *src, INT src_width, INT src_height, INT src_stride) { GpBitmap *dst_bitmap = (GpBitmap*)graphics->image; INT x, y;
for (x=0; x<src_width; x++) { for (y=0; y<src_height; y++) { ARGB dst_color, src_color; GdipBitmapGetPixel(dst_bitmap, x+dst_x, y+dst_y, &dst_color); src_color = ((ARGB*)(src + src_stride * y))[x]; GdipBitmapSetPixel(dst_bitmap, x+dst_x, y+dst_y, color_over(dst_color, src_color)); } }
return Ok; } ----
The function reads the color from the DC image, mixes it with the destination image (i.e. the image we tracked before) and saves the final color into the destination image.
Here is an excerpt of my crash dump: ---- Unhandled exception: page fault on read access to 0x00371000 in 32-bit code (0x7ebb224d). Register dump: CS:0023 SS:002b DS:002b ES:002b FS:0063 GS:006b EIP:7ebb224d ESP:0108e810 EBP:0108e8f8 EFLAGS:00010206( R- -- I - -P- ) EAX:00371000 EBX:7ec0a000 ECX:00000000 EDX:0108ef3c ESI:00000001 EDI:00000000 ----
As you can see the ESP value 0x0108e810 and the address of the original image buffer 0x108e780 are pretty close. The difference is just 144 bytes while the image uses 512 byte (4 * 128). What happens now, is that our local variables overlap with the original image buffer and get overwritten by the image content. This causes Wine to crash since the calculated source pointer is now invalid: ---- 0x7ebb224d alpha_blend_pixels_hrgn+0x65d [/home/michael/wine/wine32/dlls/gdiplus/../../../../projects/wine/dlls/gdiplus/graphics.c:384] in gdiplus: movl 0x0(%eax),%edi 369 src_color = ((ARGB*)(src + src_stride * y))[x]; ----
The problem is most probably caused by the application since it passes a buffer which is no longer valid. If there is no special case in which this buffer is copied instead of using the original one, this is most probably an upstream bug.
The reason why the native gdiplus.dll works is that either uses less or more memory on the stack so that the internal variables of the copy function do not overlap.
Regards, Michael