Memory corruption in System.Move due to changed 8087CW mode (png + stretchblt)

早过忘川 提交于 2019-11-30 04:39:42

I haven't seen this particular issue, but Move can definitely get messed up if the FPU is in a bad state. Cisco's VPN driver can screw things up horribly, even if you're not doing anything network related.

http://brianorr.blogspot.com/2006/11/intel-pentium-d-floating-point-unit.html [broken]

https://web.archive.org/web/20160601043520/http://www.dankohn.com/archives/343

http://blog.excastle.com/2007/08/28/delphi-bug-of-the-day-fpu-stack-leak/ (comments by Ritchie Annand)

In our case we detect the buggy VPN driver and swap out Move and FillChar with the Delphi 7 versions, replace IntToStr with a Pascal version (Int64-version uses the FPU), and, since we're using FastMM, we disable its custom fixed size move routines too, since they're even more susceptible than System.Move.

It might be a bug in your video driver that does not preserve the 8087 control word when it performs the StretchBlt operation.
In the past I have seen similar behaviour when using certain printer drivers. They think they own the 8087 CW and are wrong...

Note the default value of the 8087 CW in Delphi seems $1372; for a more detailed explanation of the CW values, see this article: it also explains a situation that Michael Justin described when his 8087CW got hosed.

--jeroen

Just for your information (in case some else has same problem too): we did an upgrade of our software for a customer, and the complete touchscreen locked up when our application was started! Windows was completely frozen! The pc had to be restarted (power off). It took some time to figure out the cause of the complete freeze.

Fortunately we had one (only 1!) stacktrace of an AV in FastMove.LargeSSEMove. I disabled the usage of SSE in fastmove, and the problem is gone.

By the way: touchscreen has an VIA Nehemiah cpu with an S3 chipset.

So not only you can get memory corruptions when using the FPU, but also a complete freeze!

For those still interested in this: There's yet another possible cause of problems:

Delphi Rio still ships with a broken ASM version of Move.

I had the pleasure to run into that bug today, luckily enough I had a reproducible test case. The issue is this piece of code:

* ***** BEGIN LICENSE BLOCK *****
 *
 * The assembly function Move is licensed under the CodeGear license terms.
 *
 * The initial developer of the original code is Fastcode
 *
 * Portions created by the initial developer are Copyright (C) 2002-2004
 * the initial developer. All Rights Reserved.
 *
 * Contributor(s): John O'Harrow
 *
 * ***** END LICENSE BLOCK ***** *)

// ... some less interesting parts omitted ...

@@LargeMove:
        JNG     @@LargeDone {Count < 0}
        CMP     EAX, EDX
        JA      @@LargeForwardMove

        // the following overlap test is broken
        // when size>uint(destaddr), EDX underflows to $FFxxxxxx, in which case 
        // we jump to @LargeForwardMove even if a backward loop would be appropriate
        // this will effectively shred everything at EDX + size
        SUB     EDX, ECX              // when this underflows ...
        CMP     EAX, EDX              // ... we also get CF=1 here (EDX is usually < $FFxxxxxx)
        LEA     EDX, [EDX+ECX]        // (does not affect flags)
        JNA     @@LargeForwardMove    // ... CF=1 so let's jump into disaster!

        SUB     ECX, 8 {Backward Move}
        PUSH    ECX
        FILD    QWORD PTR [EAX+ECX] {Last 8}
        FILD    QWORD PTR [EAX] {First 8}
        ADD     ECX, EDX
        AND     ECX, -8 {8-Byte Align Writes}
        SUB     ECX, EDX

References

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!