aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorKim F. Storm2004-12-01 14:10:23 +0000
committerKim F. Storm2004-12-01 14:10:23 +0000
commitbdbed949970b828b02ef8746543337968d89f83b (patch)
treed4a0f480a3057479e21ddd6d8fa2cf395a10ae5d /src/alloc.c
parent1cae6d39e6c10cc785dff977039294a8971d7de9 (diff)
downloademacs-bdbed949970b828b02ef8746543337968d89f83b.tar.gz
emacs-bdbed949970b828b02ef8746543337968d89f83b.zip
Add commentary for last change.
(XMALLOC_PUT_SIZE, XMALLOC_GET_SIZE): New macros to handle sizeof(size_t) != 4. (overrun_check_malloc, overrun_check_realloc, overrun_check_free): Use them. Also clear header and trailer of freed memory. (GC_STRING_OVERRUN_COOKIE_SIZE): Rename from GC_STRING_EXTRA. (string_overrun_cookie): Rename from string_overrun_pattern. (GC_STRING_EXTRA): Define from GC_STRING_OVERRUN_COOKIE_SIZE.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c100
1 files changed, 77 insertions, 23 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 223a49ee567..e0c14e8bb9c 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -516,11 +516,22 @@ buffer_memory_full ()
516} 516}
517 517
518 518
519/* Like malloc but check for no memory and block interrupt input.. */
520
521#ifdef XMALLOC_OVERRUN_CHECK 519#ifdef XMALLOC_OVERRUN_CHECK
522 520
521/* Check for overrun in malloc'ed buffers by wrapping a 16 byte header
522 and a 16 byte trailer around each block.
523
524 The header consists of 12 fixed bytes + a 4 byte integer contaning the
525 original block size, while the trailer consists of 16 fixed bytes.
526
527 The header is used to detect whether this block has been allocated
528 through these functions -- as it seems that some low-level libc
529 functions may bypass the malloc hooks.
530*/
531
532
523#define XMALLOC_OVERRUN_CHECK_SIZE 16 533#define XMALLOC_OVERRUN_CHECK_SIZE 16
534
524static char xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE-4] = 535static char xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE-4] =
525 { 0x9a, 0x9b, 0xae, 0xaf, 536 { 0x9a, 0x9b, 0xae, 0xaf,
526 0xbf, 0xbe, 0xce, 0xcf, 537 0xbf, 0xbe, 0xce, 0xcf,
@@ -532,74 +543,99 @@ static char xmalloc_overrun_check_trailer[XMALLOC_OVERRUN_CHECK_SIZE] =
532 0xca, 0xcb, 0xcc, 0xcd, 543 0xca, 0xcb, 0xcc, 0xcd,
533 0xda, 0xdb, 0xdc, 0xdd }; 544 0xda, 0xdb, 0xdc, 0xdd };
534 545
546/* Macros to insert and extract the block size in the header. */
547
548#define XMALLOC_PUT_SIZE(ptr, size) \
549 (ptr[-1] = (size & 0xff), \
550 ptr[-2] = ((size >> 8) & 0xff), \
551 ptr[-3] = ((size >> 16) & 0xff), \
552 ptr[-4] = ((size >> 24) & 0xff))
553
554#define XMALLOC_GET_SIZE(ptr) \
555 (size_t)((unsigned)(ptr[-1]) | \
556 ((unsigned)(ptr[-2]) << 8) | \
557 ((unsigned)(ptr[-3]) << 16) | \
558 ((unsigned)(ptr[-4]) << 24))
559
560
561/* Like malloc, but wraps allocated block with header and trailer. */
562
535POINTER_TYPE * 563POINTER_TYPE *
536overrun_check_malloc (size) 564overrun_check_malloc (size)
537 size_t size; 565 size_t size;
538{ 566{
539 register char *val; 567 register unsigned char *val;
540 568
541 val = (char *) malloc (size + XMALLOC_OVERRUN_CHECK_SIZE*2); 569 val = (unsigned char *) malloc (size + XMALLOC_OVERRUN_CHECK_SIZE*2);
542 if (val) 570 if (val)
543 { 571 {
544 bcopy (xmalloc_overrun_check_header, val, XMALLOC_OVERRUN_CHECK_SIZE - 4); 572 bcopy (xmalloc_overrun_check_header, val, XMALLOC_OVERRUN_CHECK_SIZE - 4);
545 bcopy (&size, val + XMALLOC_OVERRUN_CHECK_SIZE - 4, sizeof (size));
546 val += XMALLOC_OVERRUN_CHECK_SIZE; 573 val += XMALLOC_OVERRUN_CHECK_SIZE;
574 XMALLOC_PUT_SIZE(val, size);
547 bcopy (xmalloc_overrun_check_trailer, val + size, XMALLOC_OVERRUN_CHECK_SIZE); 575 bcopy (xmalloc_overrun_check_trailer, val + size, XMALLOC_OVERRUN_CHECK_SIZE);
548 } 576 }
549 return (POINTER_TYPE *)val; 577 return (POINTER_TYPE *)val;
550} 578}
551 579
580
581/* Like realloc, but checks old block for overrun, and wraps new block
582 with header and trailer. */
583
552POINTER_TYPE * 584POINTER_TYPE *
553overrun_check_realloc (block, size) 585overrun_check_realloc (block, size)
554 POINTER_TYPE *block; 586 POINTER_TYPE *block;
555 size_t size; 587 size_t size;
556{ 588{
557 register char *val = (char *)block; 589 register unsigned char *val = (unsigned char *)block;
558 590
559 if (val 591 if (val
560 && bcmp (xmalloc_overrun_check_header, 592 && bcmp (xmalloc_overrun_check_header,
561 val - XMALLOC_OVERRUN_CHECK_SIZE, 593 val - XMALLOC_OVERRUN_CHECK_SIZE,
562 XMALLOC_OVERRUN_CHECK_SIZE - 4) == 0) 594 XMALLOC_OVERRUN_CHECK_SIZE - 4) == 0)
563 { 595 {
564 size_t osize; 596 size_t osize = XMALLOC_GET_SIZE (val);
565 bcopy (val - 4, &osize, sizeof (osize));
566 if (bcmp (xmalloc_overrun_check_trailer, 597 if (bcmp (xmalloc_overrun_check_trailer,
567 val + osize, 598 val + osize,
568 XMALLOC_OVERRUN_CHECK_SIZE)) 599 XMALLOC_OVERRUN_CHECK_SIZE))
569 abort (); 600 abort ();
601 bzero (val + osize, XMALLOC_OVERRUN_CHECK_SIZE);
570 val -= XMALLOC_OVERRUN_CHECK_SIZE; 602 val -= XMALLOC_OVERRUN_CHECK_SIZE;
603 bzero (val, XMALLOC_OVERRUN_CHECK_SIZE);
571 } 604 }
572 605
573 val = (char *) realloc ((POINTER_TYPE *)val, size + XMALLOC_OVERRUN_CHECK_SIZE*2); 606 val = (unsigned char *) realloc ((POINTER_TYPE *)val, size + XMALLOC_OVERRUN_CHECK_SIZE*2);
574 607
575 if (val) 608 if (val)
576 { 609 {
577 bcopy (xmalloc_overrun_check_header, val, XMALLOC_OVERRUN_CHECK_SIZE - 4); 610 bcopy (xmalloc_overrun_check_header, val, XMALLOC_OVERRUN_CHECK_SIZE - 4);
578 bcopy (&size, val + XMALLOC_OVERRUN_CHECK_SIZE - 4, sizeof (size));
579 val += XMALLOC_OVERRUN_CHECK_SIZE; 611 val += XMALLOC_OVERRUN_CHECK_SIZE;
612 XMALLOC_PUT_SIZE(val, size);
580 bcopy (xmalloc_overrun_check_trailer, val + size, XMALLOC_OVERRUN_CHECK_SIZE); 613 bcopy (xmalloc_overrun_check_trailer, val + size, XMALLOC_OVERRUN_CHECK_SIZE);
581 } 614 }
582 return (POINTER_TYPE *)val; 615 return (POINTER_TYPE *)val;
583} 616}
584 617
618/* Like free, but checks block for overrun. */
619
585void 620void
586overrun_check_free (block) 621overrun_check_free (block)
587 POINTER_TYPE *block; 622 POINTER_TYPE *block;
588{ 623{
589 char *val = (char *)block; 624 unsigned char *val = (unsigned char *)block;
590 625
591 if (val 626 if (val
592 && bcmp (xmalloc_overrun_check_header, 627 && bcmp (xmalloc_overrun_check_header,
593 val - XMALLOC_OVERRUN_CHECK_SIZE, 628 val - XMALLOC_OVERRUN_CHECK_SIZE,
594 XMALLOC_OVERRUN_CHECK_SIZE - 4) == 0) 629 XMALLOC_OVERRUN_CHECK_SIZE - 4) == 0)
595 { 630 {
596 size_t osize; 631 size_t osize = XMALLOC_GET_SIZE (val);
597 bcopy (val - 4, &osize, sizeof (osize));
598 if (bcmp (xmalloc_overrun_check_trailer, 632 if (bcmp (xmalloc_overrun_check_trailer,
599 val + osize, 633 val + osize,
600 XMALLOC_OVERRUN_CHECK_SIZE)) 634 XMALLOC_OVERRUN_CHECK_SIZE))
601 abort (); 635 abort ();
636 bzero (val + osize, XMALLOC_OVERRUN_CHECK_SIZE);
602 val -= XMALLOC_OVERRUN_CHECK_SIZE; 637 val -= XMALLOC_OVERRUN_CHECK_SIZE;
638 bzero (val, XMALLOC_OVERRUN_CHECK_SIZE);
603 } 639 }
604 640
605 free (val); 641 free (val);
@@ -613,6 +649,9 @@ overrun_check_free (block)
613#define free overrun_check_free 649#define free overrun_check_free
614#endif 650#endif
615 651
652
653/* Like malloc but check for no memory and block interrupt input.. */
654
616POINTER_TYPE * 655POINTER_TYPE *
617xmalloc (size) 656xmalloc (size)
618 size_t size; 657 size_t size;
@@ -1527,10 +1566,17 @@ static int total_string_size;
1527 1566
1528 1567
1529#ifdef GC_CHECK_STRING_OVERRUN 1568#ifdef GC_CHECK_STRING_OVERRUN
1530#define GC_STRING_EXTRA 4 1569
1531static char string_overrun_pattern[GC_STRING_EXTRA] = { 0xde, 0xad, 0xbe, 0xef }; 1570/* We check for overrun in string data blocks by appending a small
1571 "cookie" after each allocated string data block, and check for the
1572 presense of this cookie during GC. */
1573
1574#define GC_STRING_OVERRUN_COOKIE_SIZE 4
1575static char string_overrun_cookie[GC_STRING_OVERRUN_COOKIE_SIZE] =
1576 { 0xde, 0xad, 0xbe, 0xef };
1577
1532#else 1578#else
1533#define GC_STRING_EXTRA 0 1579#define GC_STRING_OVERRUN_COOKIE_SIZE 0
1534#endif 1580#endif
1535 1581
1536/* Value is the size of an sdata structure large enough to hold NBYTES 1582/* Value is the size of an sdata structure large enough to hold NBYTES
@@ -1556,6 +1602,10 @@ static char string_overrun_pattern[GC_STRING_EXTRA] = { 0xde, 0xad, 0xbe, 0xef }
1556 1602
1557#endif /* not GC_CHECK_STRING_BYTES */ 1603#endif /* not GC_CHECK_STRING_BYTES */
1558 1604
1605/* Extra bytes to allocate for each string. */
1606
1607#define GC_STRING_EXTRA (GC_STRING_OVERRUN_COOKIE_SIZE)
1608
1559/* Initialize string allocation. Called from init_alloc_once. */ 1609/* Initialize string allocation. Called from init_alloc_once. */
1560 1610
1561void 1611void
@@ -1655,6 +1705,9 @@ check_string_bytes (all_p)
1655 1705
1656#ifdef GC_CHECK_STRING_FREE_LIST 1706#ifdef GC_CHECK_STRING_FREE_LIST
1657 1707
1708/* Walk through the string free list looking for bogus next pointers.
1709 This may catch buffer overrun from a previous string. */
1710
1658static void 1711static void
1659check_string_free_list () 1712check_string_free_list ()
1660{ 1713{
@@ -1703,7 +1756,7 @@ allocate_string ()
1703 total_free_strings += STRING_BLOCK_SIZE; 1756 total_free_strings += STRING_BLOCK_SIZE;
1704 } 1757 }
1705 1758
1706 check_string_free_list(); 1759 check_string_free_list ();
1707 1760
1708 /* Pop a Lisp_String off the free-list. */ 1761 /* Pop a Lisp_String off the free-list. */
1709 s = string_free_list; 1762 s = string_free_list;
@@ -1819,7 +1872,8 @@ allocate_string_data (s, nchars, nbytes)
1819 s->size_byte = nbytes; 1872 s->size_byte = nbytes;
1820 s->data[nbytes] = '\0'; 1873 s->data[nbytes] = '\0';
1821#ifdef GC_CHECK_STRING_OVERRUN 1874#ifdef GC_CHECK_STRING_OVERRUN
1822 bcopy(string_overrun_pattern, (char *) data + needed, GC_STRING_EXTRA); 1875 bcopy (string_overrun_cookie, (char *) data + needed,
1876 GC_STRING_OVERRUN_COOKIE_SIZE);
1823#endif 1877#endif
1824 b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA); 1878 b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA);
1825 1879
@@ -1926,13 +1980,13 @@ sweep_strings ()
1926 } 1980 }
1927 } 1981 }
1928 1982
1929 check_string_free_list(); 1983 check_string_free_list ();
1930 1984
1931 string_blocks = live_blocks; 1985 string_blocks = live_blocks;
1932 free_large_strings (); 1986 free_large_strings ();
1933 compact_small_strings (); 1987 compact_small_strings ();
1934 1988
1935 check_string_free_list(); 1989 check_string_free_list ();
1936} 1990}
1937 1991
1938 1992
@@ -2004,16 +2058,16 @@ compact_small_strings ()
2004 else 2058 else
2005 nbytes = SDATA_NBYTES (from); 2059 nbytes = SDATA_NBYTES (from);
2006 2060
2007#ifdef GC_CHECK_STRING_BYTES
2008 if (nbytes > LARGE_STRING_BYTES) 2061 if (nbytes > LARGE_STRING_BYTES)
2009 abort (); 2062 abort ();
2010#endif
2011 2063
2012 nbytes = SDATA_SIZE (nbytes); 2064 nbytes = SDATA_SIZE (nbytes);
2013 from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); 2065 from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA);
2014 2066
2015#ifdef GC_CHECK_STRING_OVERRUN 2067#ifdef GC_CHECK_STRING_OVERRUN
2016 if (bcmp(string_overrun_pattern, ((char *) from_end) - GC_STRING_EXTRA, GC_STRING_EXTRA)) 2068 if (bcmp (string_overrun_cookie,
2069 ((char *) from_end) - GC_STRING_OVERRUN_COOKIE_SIZE,
2070 GC_STRING_OVERRUN_COOKIE_SIZE))
2017 abort (); 2071 abort ();
2018#endif 2072#endif
2019 2073