]> code.delx.au - gnu-emacs/commitdiff
Fix w32 memory-management problem when extending buffer text
authorEli Zaretskii <eliz@gnu.org>
Fri, 15 Apr 2016 14:26:37 +0000 (17:26 +0300)
committerEli Zaretskii <eliz@gnu.org>
Fri, 15 Apr 2016 14:26:37 +0000 (17:26 +0300)
* src/w32heap.c (mmap_realloc): Only attempt extending a region if
the following region has the same allocation base.  Also, use the
original allocation base and enlarged size to commit reserved
memory, to ensure that the allocation base stays at its original
value.  This fixes several hard-to-debug problems whereby part of
buffer text was overwritten with binary nulls, because
mmap_realloc copied only part of buffer text when extending it.
See
http://lists.gnu.org/archive/html/emacs-devel/2016-04/msg00325.html
and http://debbugs.gnu.org/cgi/bugreport.cgi?bug=23223#55 for two
examples of the related problems.

src/w32heap.c

index df2fe0a8fa39cdc2b3b5930bc28d6ae1a67e928d..6643b439a2674f095ff18b1fcfebdf9805d92734 100644 (file)
@@ -714,13 +714,12 @@ mmap_realloc (void **var, size_t nbytes)
       /* If there is enough room in the current reserved area, then
         commit more pages as needed.  */
       if (m2.State == MEM_RESERVE
+         && m2.AllocationBase == memInfo.AllocationBase
          && nbytes <= memInfo.RegionSize + m2.RegionSize)
        {
          void *p;
 
-         p = VirtualAlloc (*var + memInfo.RegionSize,
-                           nbytes - memInfo.RegionSize,
-                           MEM_COMMIT, PAGE_READWRITE);
+         p = VirtualAlloc (*var, nbytes, MEM_COMMIT, PAGE_READWRITE);
          if (!p /* && GetLastError() != ERROR_NOT_ENOUGH_MEMORY */)
            {
              DebPrint (("realloc enlarge: VirtualAlloc (%p + %I64x, %I64x) error %ld\n",
@@ -728,7 +727,8 @@ mmap_realloc (void **var, size_t nbytes)
                         (uint64_t)(nbytes - memInfo.RegionSize),
                         GetLastError ()));
              DebPrint (("next region: %p %p %I64x %x\n", m2.BaseAddress,
-                        m2.AllocationBase, m2.RegionSize, m2.AllocationProtect));
+                        m2.AllocationBase, (uint64_t)m2.RegionSize,
+                        m2.AllocationProtect));
            }
          else
            return *var;