ソースを参照

Fix CopyMem() not handling overlaps

Per https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/BaseMemoryLib.h
"(CopyMem) must handle the case where SourceBuffer overlaps DestinationBuffer".

Having the gnu-efi version of CopyMem differ from the EDK2 version can lead to
extremely hard to troubleshoot issues as well as very unexpected results. So
make sure our version follows the same guidelines.
Pete Batard 4 年 前
コミット
41e4d11d11
1 ファイル変更19 行追加9 行削除
  1. 19 9
      lib/runtime/efirtlib.c

+ 19 - 9
lib/runtime/efirtlib.c

@@ -46,7 +46,7 @@ RUNTIMEFUNCTION
 RtSetMem (
     IN VOID     *Buffer,
     IN UINTN    Size,
-    IN UINT8    Value    
+    IN UINT8    Value
     )
 {
     INT8        *pt;
@@ -63,16 +63,26 @@ RtSetMem (
 VOID
 RUNTIMEFUNCTION
 RtCopyMem (
-    IN VOID     *Dest,
-    IN CONST VOID     *Src,
-    IN UINTN    len
+    IN VOID        *Dest,
+    IN CONST VOID  *Src,
+    IN UINTN       len
     )
 {
-    CHAR8   *d;
-    CONST CHAR8 *s = Src;
-    d = Dest;
-    while (len--) {
-        *(d++) = *(s++);
+    CHAR8 *d = (CHAR8*)Dest;
+    CHAR8 *s = (CHAR8*)Src;
+
+    if (d == NULL || s == NULL || s == d)
+        return;
+
+    // If the beginning of the destination range overlaps with the end of
+    // the source range, make sure to start the copy from the end so that
+    // we don't end up overwriting source data that we need for the copy.
+    if ((d > s) && (d < s + len)) {
+        for (d += len, s += len; len--; )
+            *--d = *--s;
+    } else {
+        while (len--)
+            *d++ = *s++;
     }
 }