diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 68 |
1 files changed, 47 insertions, 21 deletions
diff --git a/src/alloc.c b/src/alloc.c index ad1741e308f..ead5c8a8ca4 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -490,19 +490,45 @@ buffer_memory_full (EMACS_INT nbytes) | |||
| 490 | /* Check for overrun in malloc'ed buffers by wrapping a header and trailer | 490 | /* Check for overrun in malloc'ed buffers by wrapping a header and trailer |
| 491 | around each block. | 491 | around each block. |
| 492 | 492 | ||
| 493 | The header consists of 16 fixed bytes followed by sizeof (size_t) bytes | 493 | The header consists of XMALLOC_OVERRUN_CHECK_SIZE fixed bytes |
| 494 | containing the original block size in little-endian order, | 494 | followed by XMALLOC_OVERRUN_SIZE_SIZE bytes containing the original |
| 495 | while the trailer consists of 16 fixed bytes. | 495 | block size in little-endian order. The trailer consists of |
| 496 | XMALLOC_OVERRUN_CHECK_SIZE fixed bytes. | ||
| 496 | 497 | ||
| 497 | The header is used to detect whether this block has been allocated | 498 | The header is used to detect whether this block has been allocated |
| 498 | through these functions -- as it seems that some low-level libc | 499 | through these functions, as some low-level libc functions may |
| 499 | functions may bypass the malloc hooks. | 500 | bypass the malloc hooks. */ |
| 500 | */ | ||
| 501 | |||
| 502 | 501 | ||
| 503 | #define XMALLOC_OVERRUN_CHECK_SIZE 16 | 502 | #define XMALLOC_OVERRUN_CHECK_SIZE 16 |
| 504 | #define XMALLOC_OVERRUN_CHECK_OVERHEAD \ | 503 | #define XMALLOC_OVERRUN_CHECK_OVERHEAD \ |
| 505 | (2 * XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t)) | 504 | (2 * XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE) |
| 505 | |||
| 506 | /* Define XMALLOC_OVERRUN_SIZE_SIZE so that (1) it's large enough to | ||
| 507 | hold a size_t value and (2) the header size is a multiple of the | ||
| 508 | alignment that Emacs needs for C types and for USE_LSB_TAG. */ | ||
| 509 | #define XMALLOC_BASE_ALIGNMENT \ | ||
| 510 | offsetof ( \ | ||
| 511 | struct { \ | ||
| 512 | union { long double d; intmax_t i; void *p; } u; \ | ||
| 513 | char c; \ | ||
| 514 | }, \ | ||
| 515 | c) | ||
| 516 | #ifdef USE_LSB_TAG | ||
| 517 | /* A common multiple of the positive integers A and B. Ideally this | ||
| 518 | would be the least common multiple, but there's no way to do that | ||
| 519 | as a constant expression in C, so do the best that we can easily do. */ | ||
| 520 | # define COMMON_MULTIPLE(a, b) \ | ||
| 521 | ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b)) | ||
| 522 | # define XMALLOC_HEADER_ALIGNMENT \ | ||
| 523 | COMMON_MULTIPLE (1 << GCTYPEBITS, XMALLOC_BASE_ALIGNMENT) | ||
| 524 | #else | ||
| 525 | # define XMALLOC_HEADER_ALIGNMENT XMALLOC_BASE_ALIGNMENT | ||
| 526 | #endif | ||
| 527 | #define XMALLOC_OVERRUN_SIZE_SIZE \ | ||
| 528 | (((XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t) \ | ||
| 529 | + XMALLOC_HEADER_ALIGNMENT - 1) \ | ||
| 530 | / XMALLOC_HEADER_ALIGNMENT * XMALLOC_HEADER_ALIGNMENT) \ | ||
| 531 | - XMALLOC_OVERRUN_CHECK_SIZE) | ||
| 506 | 532 | ||
| 507 | static char const xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE] = | 533 | static char const xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE] = |
| 508 | { '\x9a', '\x9b', '\xae', '\xaf', | 534 | { '\x9a', '\x9b', '\xae', '\xaf', |
| @@ -522,9 +548,9 @@ static void | |||
| 522 | xmalloc_put_size (unsigned char *ptr, size_t size) | 548 | xmalloc_put_size (unsigned char *ptr, size_t size) |
| 523 | { | 549 | { |
| 524 | int i; | 550 | int i; |
| 525 | for (i = 0; i < sizeof (size_t); i++) | 551 | for (i = 0; i < XMALLOC_OVERRUN_SIZE_SIZE; i++) |
| 526 | { | 552 | { |
| 527 | *--ptr = size & (1 << CHAR_BIT) - 1; | 553 | *--ptr = size & ((1 << CHAR_BIT) - 1); |
| 528 | size >>= CHAR_BIT; | 554 | size >>= CHAR_BIT; |
| 529 | } | 555 | } |
| 530 | } | 556 | } |
| @@ -534,8 +560,8 @@ xmalloc_get_size (unsigned char *ptr) | |||
| 534 | { | 560 | { |
| 535 | size_t size = 0; | 561 | size_t size = 0; |
| 536 | int i; | 562 | int i; |
| 537 | ptr -= sizeof (size_t); | 563 | ptr -= XMALLOC_OVERRUN_SIZE_SIZE; |
| 538 | for (i = 0; i < sizeof (size_t); i++) | 564 | for (i = 0; i < XMALLOC_OVERRUN_SIZE_SIZE; i++) |
| 539 | { | 565 | { |
| 540 | size <<= CHAR_BIT; | 566 | size <<= CHAR_BIT; |
| 541 | size += *ptr++; | 567 | size += *ptr++; |
| @@ -579,7 +605,7 @@ overrun_check_malloc (size_t size) | |||
| 579 | if (val && check_depth == 1) | 605 | if (val && check_depth == 1) |
| 580 | { | 606 | { |
| 581 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); | 607 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); |
| 582 | val += XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t); | 608 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| 583 | xmalloc_put_size (val, size); | 609 | xmalloc_put_size (val, size); |
| 584 | memcpy (val + size, xmalloc_overrun_check_trailer, | 610 | memcpy (val + size, xmalloc_overrun_check_trailer, |
| 585 | XMALLOC_OVERRUN_CHECK_SIZE); | 611 | XMALLOC_OVERRUN_CHECK_SIZE); |
| @@ -603,7 +629,7 @@ overrun_check_realloc (POINTER_TYPE *block, size_t size) | |||
| 603 | if (val | 629 | if (val |
| 604 | && check_depth == 1 | 630 | && check_depth == 1 |
| 605 | && memcmp (xmalloc_overrun_check_header, | 631 | && memcmp (xmalloc_overrun_check_header, |
| 606 | val - XMALLOC_OVERRUN_CHECK_SIZE - sizeof (size_t), | 632 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, |
| 607 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) | 633 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) |
| 608 | { | 634 | { |
| 609 | size_t osize = xmalloc_get_size (val); | 635 | size_t osize = xmalloc_get_size (val); |
| @@ -611,8 +637,8 @@ overrun_check_realloc (POINTER_TYPE *block, size_t size) | |||
| 611 | XMALLOC_OVERRUN_CHECK_SIZE)) | 637 | XMALLOC_OVERRUN_CHECK_SIZE)) |
| 612 | abort (); | 638 | abort (); |
| 613 | memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE); | 639 | memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE); |
| 614 | val -= XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t); | 640 | val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| 615 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t)); | 641 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE); |
| 616 | } | 642 | } |
| 617 | 643 | ||
| 618 | val = (unsigned char *) realloc ((POINTER_TYPE *)val, size + overhead); | 644 | val = (unsigned char *) realloc ((POINTER_TYPE *)val, size + overhead); |
| @@ -620,7 +646,7 @@ overrun_check_realloc (POINTER_TYPE *block, size_t size) | |||
| 620 | if (val && check_depth == 1) | 646 | if (val && check_depth == 1) |
| 621 | { | 647 | { |
| 622 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); | 648 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); |
| 623 | val += XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t); | 649 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| 624 | xmalloc_put_size (val, size); | 650 | xmalloc_put_size (val, size); |
| 625 | memcpy (val + size, xmalloc_overrun_check_trailer, | 651 | memcpy (val + size, xmalloc_overrun_check_trailer, |
| 626 | XMALLOC_OVERRUN_CHECK_SIZE); | 652 | XMALLOC_OVERRUN_CHECK_SIZE); |
| @@ -640,7 +666,7 @@ overrun_check_free (POINTER_TYPE *block) | |||
| 640 | if (val | 666 | if (val |
| 641 | && check_depth == 1 | 667 | && check_depth == 1 |
| 642 | && memcmp (xmalloc_overrun_check_header, | 668 | && memcmp (xmalloc_overrun_check_header, |
| 643 | val - XMALLOC_OVERRUN_CHECK_SIZE - sizeof (size_t), | 669 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, |
| 644 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) | 670 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) |
| 645 | { | 671 | { |
| 646 | size_t osize = xmalloc_get_size (val); | 672 | size_t osize = xmalloc_get_size (val); |
| @@ -648,12 +674,12 @@ overrun_check_free (POINTER_TYPE *block) | |||
| 648 | XMALLOC_OVERRUN_CHECK_SIZE)) | 674 | XMALLOC_OVERRUN_CHECK_SIZE)) |
| 649 | abort (); | 675 | abort (); |
| 650 | #ifdef XMALLOC_CLEAR_FREE_MEMORY | 676 | #ifdef XMALLOC_CLEAR_FREE_MEMORY |
| 651 | val -= XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t); | 677 | val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| 652 | memset (val, 0xff, osize + XMALLOC_OVERRUN_CHECK_OVERHEAD); | 678 | memset (val, 0xff, osize + XMALLOC_OVERRUN_CHECK_OVERHEAD); |
| 653 | #else | 679 | #else |
| 654 | memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE); | 680 | memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE); |
| 655 | val -= XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t); | 681 | val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| 656 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + sizeof (size_t)); | 682 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE); |
| 657 | #endif | 683 | #endif |
| 658 | } | 684 | } |
| 659 | 685 | ||