aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c68
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
507static char const xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE] = 533static 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
522xmalloc_put_size (unsigned char *ptr, size_t size) 548xmalloc_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