diff options
| author | Eli Zaretskii | 2014-05-30 12:02:55 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2014-05-30 12:02:55 +0300 |
| commit | 6c572f9ab3d028dbc399fc97ff8d8a9835be20fe (patch) | |
| tree | 4d6846e1dddd574a1b890c6ffd424a0424270ae6 /src/w32heap.c | |
| parent | 8d3103b1efd32a2faf257e26a5474e12543ce798 (diff) | |
| download | emacs-6c572f9ab3d028dbc399fc97ff8d8a9835be20fe.tar.gz emacs-6c572f9ab3d028dbc399fc97ff8d8a9835be20fe.zip | |
Enhance error checking in heap allocation routines on MS-Windows.
src/w32heap.c (malloc_before_dump, malloc_after_dump)
(malloc_before_dump, realloc_after_dump, realloc_before_dump)
(mmap_alloc, mmap_realloc): Check for errors more thoroughly and
set errno where appropriate to emulate CRT functions.
Diffstat (limited to 'src/w32heap.c')
| -rw-r--r-- | src/w32heap.c | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/src/w32heap.c b/src/w32heap.c index be097901747..cc08dc37219 100644 --- a/src/w32heap.c +++ b/src/w32heap.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | 47 | ||
| 48 | #include <config.h> | 48 | #include <config.h> |
| 49 | #include <stdio.h> | 49 | #include <stdio.h> |
| 50 | #include <errno.h> | ||
| 50 | 51 | ||
| 51 | #include <sys/mman.h> | 52 | #include <sys/mman.h> |
| 52 | #include "w32common.h" | 53 | #include "w32common.h" |
| @@ -241,7 +242,8 @@ init_heap (void) | |||
| 241 | if (s_pfn_Heap_Set_Information ((PVOID) heap, | 242 | if (s_pfn_Heap_Set_Information ((PVOID) heap, |
| 242 | HeapCompatibilityInformation, | 243 | HeapCompatibilityInformation, |
| 243 | &enable_lfh, sizeof(enable_lfh)) == 0) | 244 | &enable_lfh, sizeof(enable_lfh)) == 0) |
| 244 | DebPrint (("Enabling Low Fragmentation Heap failed\n")); | 245 | DebPrint (("Enabling Low Fragmentation Heap failed: error %ld\n", |
| 246 | GetLastError ())); | ||
| 245 | #endif | 247 | #endif |
| 246 | 248 | ||
| 247 | the_malloc_fn = malloc_after_dump; | 249 | the_malloc_fn = malloc_after_dump; |
| @@ -298,7 +300,10 @@ malloc_after_dump (size_t size) | |||
| 298 | void *p = HeapAlloc (heap, 0, size); | 300 | void *p = HeapAlloc (heap, 0, size); |
| 299 | 301 | ||
| 300 | /* After dump, keep track of the last allocated byte for sbrk(0). */ | 302 | /* After dump, keep track of the last allocated byte for sbrk(0). */ |
| 301 | data_region_end = p + size - 1; | 303 | if (p) |
| 304 | data_region_end = p + size - 1; | ||
| 305 | else | ||
| 306 | errno = ENOMEM; | ||
| 302 | return p; | 307 | return p; |
| 303 | } | 308 | } |
| 304 | 309 | ||
| @@ -313,6 +318,8 @@ malloc_before_dump (size_t size) | |||
| 313 | { | 318 | { |
| 314 | /* Use the private heap if possible. */ | 319 | /* Use the private heap if possible. */ |
| 315 | p = HeapAlloc (heap, 0, size); | 320 | p = HeapAlloc (heap, 0, size); |
| 321 | if (!p) | ||
| 322 | errno = ENOMEM; | ||
| 316 | } | 323 | } |
| 317 | else | 324 | else |
| 318 | { | 325 | { |
| @@ -371,16 +378,22 @@ realloc_after_dump (void *ptr, size_t size) | |||
| 371 | { | 378 | { |
| 372 | /* Reallocate the block since it lies in the new heap. */ | 379 | /* Reallocate the block since it lies in the new heap. */ |
| 373 | p = HeapReAlloc (heap, 0, ptr, size); | 380 | p = HeapReAlloc (heap, 0, ptr, size); |
| 381 | if (!p) | ||
| 382 | errno = ENOMEM; | ||
| 374 | } | 383 | } |
| 375 | else | 384 | else |
| 376 | { | 385 | { |
| 377 | /* If the block lies in the dumped data, do not free it. Only | 386 | /* If the block lies in the dumped data, do not free it. Only |
| 378 | allocate a new one. */ | 387 | allocate a new one. */ |
| 379 | p = HeapAlloc (heap, 0, size); | 388 | p = HeapAlloc (heap, 0, size); |
| 380 | CopyMemory (p, ptr, size); | 389 | if (p) |
| 390 | CopyMemory (p, ptr, size); | ||
| 391 | else | ||
| 392 | errno = ENOMEM; | ||
| 381 | } | 393 | } |
| 382 | /* After dump, keep track of the last allocated byte for sbrk(0). */ | 394 | /* After dump, keep track of the last allocated byte for sbrk(0). */ |
| 383 | data_region_end = p + size - 1; | 395 | if (p) |
| 396 | data_region_end = p + size - 1; | ||
| 384 | return p; | 397 | return p; |
| 385 | } | 398 | } |
| 386 | 399 | ||
| @@ -392,7 +405,11 @@ realloc_before_dump (void *ptr, size_t size) | |||
| 392 | /* Before dumping. */ | 405 | /* Before dumping. */ |
| 393 | if (dumped_data < (unsigned char *)ptr | 406 | if (dumped_data < (unsigned char *)ptr |
| 394 | && (unsigned char *)ptr < bc_limit && size <= MaxBlockSize) | 407 | && (unsigned char *)ptr < bc_limit && size <= MaxBlockSize) |
| 395 | p = HeapReAlloc (heap, 0, ptr, size); | 408 | { |
| 409 | p = HeapReAlloc (heap, 0, ptr, size); | ||
| 410 | if (!p) | ||
| 411 | errno = ENOMEM; | ||
| 412 | } | ||
| 396 | else | 413 | else |
| 397 | { | 414 | { |
| 398 | /* In this case, either the new block is too large for the heap, | 415 | /* In this case, either the new block is too large for the heap, |
| @@ -400,8 +417,11 @@ realloc_before_dump (void *ptr, size_t size) | |||
| 400 | malloc_before_dump() and free_before_dump() will take care of | 417 | malloc_before_dump() and free_before_dump() will take care of |
| 401 | reallocation. */ | 418 | reallocation. */ |
| 402 | p = malloc_before_dump (size); | 419 | p = malloc_before_dump (size); |
| 403 | CopyMemory (p, ptr, size); | 420 | if (p) |
| 404 | free_before_dump (ptr); | 421 | { |
| 422 | CopyMemory (p, ptr, size); | ||
| 423 | free_before_dump (ptr); | ||
| 424 | } | ||
| 405 | } | 425 | } |
| 406 | return p; | 426 | return p; |
| 407 | } | 427 | } |
| @@ -508,8 +528,16 @@ mmap_alloc (void **var, size_t nbytes) | |||
| 508 | *var = VirtualAlloc (p, nbytes, MEM_COMMIT, PAGE_READWRITE); | 528 | *var = VirtualAlloc (p, nbytes, MEM_COMMIT, PAGE_READWRITE); |
| 509 | } | 529 | } |
| 510 | 530 | ||
| 511 | if (!p && GetLastError () != ERROR_NOT_ENOUGH_MEMORY) | 531 | if (!p) |
| 512 | DebPrint (("mmap_alloc: error %ld\n", GetLastError())); | 532 | { |
| 533 | if (GetLastError () == ERROR_NOT_ENOUGH_MEMORY) | ||
| 534 | errno = ENOMEM; | ||
| 535 | else | ||
| 536 | { | ||
| 537 | DebPrint (("mmap_alloc: error %ld\n", GetLastError ())); | ||
| 538 | errno = EINVAL; | ||
| 539 | } | ||
| 540 | } | ||
| 513 | 541 | ||
| 514 | return *var = p; | 542 | return *var = p; |
| 515 | } | 543 | } |
| @@ -520,7 +548,7 @@ mmap_free (void **var) | |||
| 520 | if (*var) | 548 | if (*var) |
| 521 | { | 549 | { |
| 522 | if (VirtualFree (*var, 0, MEM_RELEASE) == 0) | 550 | if (VirtualFree (*var, 0, MEM_RELEASE) == 0) |
| 523 | DebPrint (("mmap_free: error %ld\n", GetLastError())); | 551 | DebPrint (("mmap_free: error %ld\n", GetLastError ())); |
| 524 | *var = NULL; | 552 | *var = NULL; |
| 525 | } | 553 | } |
| 526 | } | 554 | } |
| @@ -541,13 +569,14 @@ mmap_realloc (void **var, size_t nbytes) | |||
| 541 | } | 569 | } |
| 542 | 570 | ||
| 543 | if (VirtualQuery (*var, &memInfo, sizeof (memInfo)) == 0) | 571 | if (VirtualQuery (*var, &memInfo, sizeof (memInfo)) == 0) |
| 544 | DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError())); | 572 | DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError ())); |
| 545 | 573 | ||
| 546 | /* We need to enlarge the block. */ | 574 | /* We need to enlarge the block. */ |
| 547 | if (memInfo.RegionSize < nbytes) | 575 | if (memInfo.RegionSize < nbytes) |
| 548 | { | 576 | { |
| 549 | if (VirtualQuery (*var + memInfo.RegionSize, &m2, sizeof(m2)) == 0) | 577 | if (VirtualQuery (*var + memInfo.RegionSize, &m2, sizeof(m2)) == 0) |
| 550 | DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", GetLastError())); | 578 | DebPrint (("mmap_realloc: VirtualQuery error = %ld\n", |
| 579 | GetLastError ())); | ||
| 551 | /* If there is enough room in the current reserved area, then | 580 | /* If there is enough room in the current reserved area, then |
| 552 | commit more pages as needed. */ | 581 | commit more pages as needed. */ |
| 553 | if (m2.State == MEM_RESERVE | 582 | if (m2.State == MEM_RESERVE |
| @@ -559,8 +588,11 @@ mmap_realloc (void **var, size_t nbytes) | |||
| 559 | nbytes - memInfo.RegionSize, | 588 | nbytes - memInfo.RegionSize, |
| 560 | MEM_COMMIT, PAGE_READWRITE); | 589 | MEM_COMMIT, PAGE_READWRITE); |
| 561 | if (!p /* && GetLastError() != ERROR_NOT_ENOUGH_MEMORY */) | 590 | if (!p /* && GetLastError() != ERROR_NOT_ENOUGH_MEMORY */) |
| 562 | DebPrint (("realloc enlarge: VirtualAlloc error %ld\n", | 591 | { |
| 563 | GetLastError())); | 592 | DebPrint (("realloc enlarge: VirtualAlloc error %ld\n", |
| 593 | GetLastError ())); | ||
| 594 | errno = ENOMEM; | ||
| 595 | } | ||
| 564 | return *var; | 596 | return *var; |
| 565 | } | 597 | } |
| 566 | else | 598 | else |
| @@ -615,7 +647,7 @@ mmap_realloc (void **var, size_t nbytes) | |||
| 615 | if (VirtualFree (*var + nbytes + get_page_size(), | 647 | if (VirtualFree (*var + nbytes + get_page_size(), |
| 616 | memInfo.RegionSize - nbytes - get_page_size(), | 648 | memInfo.RegionSize - nbytes - get_page_size(), |
| 617 | MEM_DECOMMIT) == 0) | 649 | MEM_DECOMMIT) == 0) |
| 618 | DebPrint (("mmap_realloc: VirtualFree error %ld\n", GetLastError())); | 650 | DebPrint (("mmap_realloc: VirtualFree error %ld\n", GetLastError ())); |
| 619 | return *var; | 651 | return *var; |
| 620 | } | 652 | } |
| 621 | 653 | ||