https://bugs.winehq.org/show_bug.cgi?id=48877
Bug ID: 48877 Summary: [regression] Melodyne crashes when using the Pitch tool Product: Wine Version: unspecified Hardware: x86 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: gdiplus Assignee: wine-bugs@winehq.org Reporter: marcan@marcansoft.com Distribution: ---
Created attachment 66814 --> https://bugs.winehq.org/attachment.cgi?id=66814 Partial fix
Tested on git master. Regression was introduced by commit 9bc6f004ce, but that commit is not the root cause.
The assertion `assert( obj->numRects <= nb_points / 2 );` would fail, but the code actually crashes earlier due to memory corruption as obj->rects overflows.
In the normal case of nb_points == 0, ET->ymin..ymax are 2147483647..-2147483648, which makes the code iterate over zero scanlines as ymax < ymin. However, in the crash case, ymin..ymax are -2147483648..378 (note the negative ymin), so it tries to iterate over two billion scanlines and adds rects to the obj until it crashes.
This happens because create_polypolygon_region gets passed an insane polygon with a -2147483648,-2147483648 vertex.
The actual bug is in GdipWidenPath, which produces NaN float points, which get converted to that insane int after rounding.
And this happens because Melodyne is passing in a degenerate path with the first two points at the same position (added debugging trace to dump the path points):
format: "index: [type] X, Y" 00df:err:gdiplus:GdipWidenPath 0: [0] 4.000000, 4.000946 00df:err:gdiplus:GdipWidenPath 1: [1] 4.000000, 4.000946 00df:err:gdiplus:GdipWidenPath 2: [3] 4.000000, 4.000946 00df:err:gdiplus:GdipWidenPath 3: [3] 4.000000, 4.000000 00df:err:gdiplus:GdipWidenPath 4: [3] 4.000000, 4.000000
The code goes GdipWidenPath -> widen_open_figure -> widen_cap, where the segment length is computed as 0 and it ends up dividing by zero.
I'm not sure what Windows does here. add_bevel_point handles the special case by just placing a point coincident with the path, ignoring the pen width.
The attached patch generalizes that to widen_cap as a whole. It fixes the Melodyne crash for me, but I'm not sure if it's the correct behavior, and degenerate segments will probably cause problems in other code paths (e.g. add_anchor seems to have the same bug). Maybe a better solution would be to just remove coincident points from the path before widening (being careful of cases where the path ends up with one point after this). Someone with more experience with the GDI code should look at this, and perhaps test it on Windows to see how it behaves.