Andrew Nguyen : windowscodecs: Use memmove in StreamOnMemory:: Read and StreamOnMemory:: Write to cope with potentially overlapped memory copying.

Alexandre Julliard julliard at winehq.org
Fri Jan 21 11:08:20 CST 2011


Module: wine
Branch: master
Commit: ae1e5b79fa9a92108e251875cc724de7740a3210
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=ae1e5b79fa9a92108e251875cc724de7740a3210

Author: Andrew Nguyen <anguyen at codeweavers.com>
Date:   Fri Jan 21 05:03:19 2011 -0600

windowscodecs: Use memmove in StreamOnMemory::Read and StreamOnMemory::Write to cope with potentially overlapped memory copying.

Spotted with Valgrind.

---

 dlls/windowscodecs/stream.c       |    4 +-
 dlls/windowscodecs/tests/stream.c |   50 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/dlls/windowscodecs/stream.c b/dlls/windowscodecs/stream.c
index 561719d..1ed08f3 100644
--- a/dlls/windowscodecs/stream.c
+++ b/dlls/windowscodecs/stream.c
@@ -108,7 +108,7 @@ static HRESULT WINAPI StreamOnMemory_Read(IStream *iface,
 
     EnterCriticalSection(&This->lock);
     uBytesRead = min(cb, This->dwMemsize - This->dwCurPos);
-    memcpy(pv, This->pbMemory + This->dwCurPos, uBytesRead);
+    memmove(pv, This->pbMemory + This->dwCurPos, uBytesRead);
     This->dwCurPos += uBytesRead;
     LeaveCriticalSection(&This->lock);
 
@@ -131,7 +131,7 @@ static HRESULT WINAPI StreamOnMemory_Write(IStream *iface,
         hr = STG_E_MEDIUMFULL;
     }
     else {
-        memcpy(This->pbMemory + This->dwCurPos, pv, cb);
+        memmove(This->pbMemory + This->dwCurPos, pv, cb);
         This->dwCurPos += cb;
         hr = S_OK;
         if (pcbWritten) *pcbWritten = cb;
diff --git a/dlls/windowscodecs/tests/stream.c b/dlls/windowscodecs/tests/stream.c
index d5b2918..a55b898 100644
--- a/dlls/windowscodecs/tests/stream.c
+++ b/dlls/windowscodecs/tests/stream.c
@@ -31,8 +31,15 @@ static void test_StreamOnMemory(void)
         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
     };
+    const BYTE CmpMemOverlap[] = {
+        0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+    };
+    const BYTE ZeroMem[10] = {0};
     BYTE Memory[64], MemBuf[64];
-    LARGE_INTEGER LargeNull, LargeInt;
+    LARGE_INTEGER LargeNull, LargeInt, SeekPos;
     ULARGE_INTEGER uLargeNull, uNewPos;
     ULONG uBytesRead, uBytesWritten;
     HRESULT hr;
@@ -40,6 +47,7 @@ static void test_StreamOnMemory(void)
 
     LargeNull.QuadPart = 0;
     uLargeNull.QuadPart = 0;
+    SeekPos.QuadPart = 5;
 
     memcpy(Memory, CmpMem, sizeof(CmpMem));
 
@@ -76,6 +84,19 @@ static void test_StreamOnMemory(void)
     hr = IWICStream_InitializeFromMemory(pStream, Memory, sizeof(Memory));
     ok(hr == S_OK, "InitializeFromMemory returned with %#x, expected %#x\n", hr, S_OK);
 
+    /* IWICStream does not maintain an independent copy of the backing memory buffer. */
+    memcpy(Memory, ZeroMem, sizeof(ZeroMem));
+    hr = IWICStream_Read(pStream, MemBuf, sizeof(ZeroMem), &uBytesRead);
+    ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
+    if(SUCCEEDED(hr)) {
+        ok(uBytesRead == sizeof(ZeroMem), "Read %u bytes\n", uBytesRead);
+        ok(memcmp(MemBuf, ZeroMem, sizeof(ZeroMem)) == 0, "Read returned invalid data!\n");
+    }
+
+    IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
+
+    hr = IWICStream_Write(pStream, CmpMem, sizeof(CmpMem), &uBytesWritten);
+    ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
 
     /* Seek */
     hr = IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, &uNewPos);
@@ -152,6 +173,17 @@ static void test_StreamOnMemory(void)
         ok(memcmp(Memory, CmpMem, uBytesRead) == 0, "Read returned invalid data!\n");
     }
 
+    IWICStream_Seek(pStream, SeekPos, STREAM_SEEK_SET, NULL);
+
+    hr = IWICStream_Read(pStream, Memory, 10, &uBytesRead);   /* source and dest overlap */
+    ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
+    if(SUCCEEDED(hr)) {
+        ok(uBytesRead == 10, "Read %u bytes, expected %u\n", uBytesRead, 10);
+        ok(memcmp(Memory, CmpMemOverlap, uBytesRead) == 0, "Read returned invalid data!\n");
+    }
+
+    memcpy(Memory, CmpMem, sizeof(CmpMem));
+
     IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
 
     hr = IWICStream_Read(pStream, Memory, sizeof(Memory) + 10, &uBytesRead);   /* request too many bytes */
@@ -206,6 +238,22 @@ static void test_StreamOnMemory(void)
     hr = IWICStream_Write(pStream, MemBuf, 0, &uBytesWritten);
     ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
 
+    /* Restore the original contents of the memory stream. */
+    hr = IWICStream_Write(pStream, CmpMem, sizeof(CmpMem), &uBytesWritten);
+    ok(hr == S_OK, "Read returned with %#x, expected %#x\n", hr, S_OK);
+
+    IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
+
+    /* Source and destination overlap. */
+    hr = IWICStream_Write(pStream, Memory + 5, 10, &uBytesWritten);
+    ok(hr == S_OK, "Write returned with %#x, expected %#x\n", hr, S_OK);
+    if(SUCCEEDED(hr)) {
+        ok(uBytesWritten == 10, "Wrote %u bytes, expected %u\n", uBytesWritten, 10);
+        ok(memcmp(CmpMemOverlap, Memory, sizeof(CmpMemOverlap)) == 0, "Wrote returned invalid data!\n");
+    }
+
+    IWICStream_Seek(pStream, LargeNull, STREAM_SEEK_SET, NULL);
+
     uBytesWritten = 0xdeadbeef;
     hr = IWICStream_Write(pStream, NULL, 3, &uBytesWritten);
     ok(hr == E_INVALIDARG, "Write returned with %#x, expected %#x\n", hr, E_INVALIDARG);




More information about the wine-cvs mailing list