http://bugs.winehq.org/show_bug.cgi?id=4298
Summary: Potential metafile NULL-pointer dereference Product: Wine Version: CVS Platform: All OS/Version: All Status: UNCONFIRMED Severity: critical Priority: P2 Component: wine-gdi-(printing) AssignedTo: wine-bugs@winehq.org ReportedBy: chris.kcat@gmail.com
A(n im)properly crafted wmf file can cause a NULL-pointer dereference if it contains a META_ESCAPE record with GETPHYSPAGESIZE or GETPRINTINGOFFSET, in a similar way to GETSCALINGFACTOR (which is currently filtered out).
Part of me thinks META_ESCAPE should be filtered out completely since it looks like a few of the remaining Escape codes can reference potentially un-allocated memory if given (purposely) mis-crafted data, and it also calls ExtEscape for unknown Escape codes, which grabs the DC pointer and calls its ExtEscape callback, if existing.
However, I'm not sure how metafiles work with META_ESCAPE, and they may or may not need some of the Escape codes to work properly. If that's the case, then someone with more knowledge should find what codes are valid and only call Escape if it's one of them.
Here is a patch to prevent potential NULL-pointer dereferences in dlls/gdi/driver.c, and modifies dlls/gdi/metafile.c so it doesn't do a redundant check for GETSCALINGFACTOR.
Index: dlls/gdi/metafile.c =================================================================== RCS file: /home/wine/wine/dlls/gdi/metafile.c,v retrieving revision 1.12 diff -u -r1.12 metafile.c --- dlls/gdi/metafile.c 6 Jan 2006 20:52:46 -0000 1.12 +++ dlls/gdi/metafile.c 14 Jan 2006 06:43:10 -0000 @@ -864,8 +864,6 @@
case META_ESCAPE: switch (mr->rdParm[0]) { - case GETSCALINGFACTOR: /* get function ... would just NULL dereference */ - return FALSE; case SETABORTPROC: FIXME("Filtering Escape(SETABORTPROC), possible virus?\n"); return FALSE; Index: dlls/gdi/driver.c =================================================================== RCS file: /home/wine/wine/dlls/gdi/driver.c,v retrieving revision 1.44 diff -u -r1.44 driver.c --- dlls/gdi/driver.c 3 Jan 2006 12:39:25 -0000 1.44 +++ dlls/gdi/driver.c 14 Jan 2006 06:43:10 -0000 @@ -582,18 +582,24 @@ return EndDoc( hdc );
case GETPHYSPAGESIZE: + if(!out_data) + return 0; pt = out_data; pt->x = GetDeviceCaps( hdc, PHYSICALWIDTH ); pt->y = GetDeviceCaps( hdc, PHYSICALHEIGHT ); return 1;
case GETPRINTINGOFFSET: + if(!out_data) + return 0; pt = out_data; pt->x = GetDeviceCaps( hdc, PHYSICALOFFSETX ); pt->y = GetDeviceCaps( hdc, PHYSICALOFFSETY ); return 1;
case GETSCALINGFACTOR: + if(!out_data) + return 0; pt = out_data; pt->x = GetDeviceCaps( hdc, SCALINGFACTORX ); pt->y = GetDeviceCaps( hdc, SCALINGFACTORY );