Mercurial > emacs
comparison src/alloc.c @ 58631:7c469d30a12d
Add more checks for buffer overruns.
(XMALLOC_OVERRUN_CHECK_SIZE, xmalloc_overrun_check_header)
xmalloc_overrun_check_trailer, overrun_check_malloc)
overrun_check_realloc, overrun_check_free): Add.
(GC_STRING_EXTRA, string_overrun_pattern): Add.
(check_sblock, allocate_string_data, compact_small_strings):
Set and check string_overrun_pattern if GC_CHECK_STRING_OVERRUN.
(check_cons_list): Condition on GC_CHECK_CONS_LIST.
(check_string_free_list): Add.
(allocate_string, sweep_strings): Call check_string_free_list.
author | Kim F. Storm <storm@cua.dk> |
---|---|
date | Tue, 30 Nov 2004 00:30:56 +0000 |
parents | ff0c144203a1 |
children | 57741ce4cd6b |
comparison
equal
deleted
inserted
replaced
58630:8494a8d7029e | 58631:7c469d30a12d |
---|---|
516 } | 516 } |
517 | 517 |
518 | 518 |
519 /* Like malloc but check for no memory and block interrupt input.. */ | 519 /* Like malloc but check for no memory and block interrupt input.. */ |
520 | 520 |
521 #ifdef XMALLOC_OVERRUN_CHECK | |
522 | |
523 #define XMALLOC_OVERRUN_CHECK_SIZE 16 | |
524 static char xmalloc_overrun_check_header[XMALLOC_OVERRUN_CHECK_SIZE-4] = | |
525 { 0x9a, 0x9b, 0xae, 0xaf, | |
526 0xbf, 0xbe, 0xce, 0xcf, | |
527 0xea, 0xeb, 0xec, 0xed }; | |
528 | |
529 static char xmalloc_overrun_check_trailer[XMALLOC_OVERRUN_CHECK_SIZE] = | |
530 { 0xaa, 0xab, 0xac, 0xad, | |
531 0xba, 0xbb, 0xbc, 0xbd, | |
532 0xca, 0xcb, 0xcc, 0xcd, | |
533 0xda, 0xdb, 0xdc, 0xdd }; | |
534 | |
535 POINTER_TYPE * | |
536 overrun_check_malloc (size) | |
537 size_t size; | |
538 { | |
539 register char *val; | |
540 | |
541 val = (char *) malloc (size + XMALLOC_OVERRUN_CHECK_SIZE*2); | |
542 if (val) | |
543 { | |
544 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; | |
547 bcopy (xmalloc_overrun_check_trailer, val + size, XMALLOC_OVERRUN_CHECK_SIZE); | |
548 } | |
549 return (POINTER_TYPE *)val; | |
550 } | |
551 | |
552 POINTER_TYPE * | |
553 overrun_check_realloc (block, size) | |
554 POINTER_TYPE *block; | |
555 size_t size; | |
556 { | |
557 register char *val = (char *)block; | |
558 | |
559 if (val | |
560 && bcmp (xmalloc_overrun_check_header, | |
561 val - XMALLOC_OVERRUN_CHECK_SIZE, | |
562 XMALLOC_OVERRUN_CHECK_SIZE - 4) == 0) | |
563 { | |
564 size_t osize; | |
565 bcopy (val - 4, &osize, sizeof (osize)); | |
566 if (bcmp (xmalloc_overrun_check_trailer, | |
567 val + osize, | |
568 XMALLOC_OVERRUN_CHECK_SIZE)) | |
569 abort (); | |
570 val -= XMALLOC_OVERRUN_CHECK_SIZE; | |
571 } | |
572 | |
573 val = (char *) realloc ((POINTER_TYPE *)val, size + XMALLOC_OVERRUN_CHECK_SIZE*2); | |
574 | |
575 if (val) | |
576 { | |
577 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; | |
580 bcopy (xmalloc_overrun_check_trailer, val + size, XMALLOC_OVERRUN_CHECK_SIZE); | |
581 } | |
582 return (POINTER_TYPE *)val; | |
583 } | |
584 | |
585 void | |
586 overrun_check_free (block) | |
587 POINTER_TYPE *block; | |
588 { | |
589 char *val = (char *)block; | |
590 | |
591 if (val | |
592 && bcmp (xmalloc_overrun_check_header, | |
593 val - XMALLOC_OVERRUN_CHECK_SIZE, | |
594 XMALLOC_OVERRUN_CHECK_SIZE - 4) == 0) | |
595 { | |
596 size_t osize; | |
597 bcopy (val - 4, &osize, sizeof (osize)); | |
598 if (bcmp (xmalloc_overrun_check_trailer, | |
599 val + osize, | |
600 XMALLOC_OVERRUN_CHECK_SIZE)) | |
601 abort (); | |
602 val -= XMALLOC_OVERRUN_CHECK_SIZE; | |
603 } | |
604 | |
605 free (val); | |
606 } | |
607 | |
608 #undef malloc | |
609 #undef realloc | |
610 #undef free | |
611 #define malloc overrun_check_malloc | |
612 #define realloc overrun_check_realloc | |
613 #define free overrun_check_free | |
614 #endif | |
615 | |
521 POINTER_TYPE * | 616 POINTER_TYPE * |
522 xmalloc (size) | 617 xmalloc (size) |
523 size_t size; | 618 size_t size; |
524 { | 619 { |
525 register POINTER_TYPE *val; | 620 register POINTER_TYPE *val; |
600 | 695 |
601 /* Like malloc but used for allocating Lisp data. NBYTES is the | 696 /* Like malloc but used for allocating Lisp data. NBYTES is the |
602 number of bytes to allocate, TYPE describes the intended use of the | 697 number of bytes to allocate, TYPE describes the intended use of the |
603 allcated memory block (for strings, for conses, ...). */ | 698 allcated memory block (for strings, for conses, ...). */ |
604 | 699 |
700 #ifndef USE_LSB_TAG | |
605 static void *lisp_malloc_loser; | 701 static void *lisp_malloc_loser; |
702 #endif | |
606 | 703 |
607 static POINTER_TYPE * | 704 static POINTER_TYPE * |
608 lisp_malloc (nbytes, type) | 705 lisp_malloc (nbytes, type) |
609 size_t nbytes; | 706 size_t nbytes; |
610 enum mem_type type; | 707 enum mem_type type; |
1426 #define SDATA_OF_STRING(S) \ | 1523 #define SDATA_OF_STRING(S) \ |
1427 ((struct sdata *) ((S)->data - sizeof (struct Lisp_String *))) | 1524 ((struct sdata *) ((S)->data - sizeof (struct Lisp_String *))) |
1428 | 1525 |
1429 #endif /* not GC_CHECK_STRING_BYTES */ | 1526 #endif /* not GC_CHECK_STRING_BYTES */ |
1430 | 1527 |
1528 | |
1529 #ifdef GC_CHECK_STRING_OVERRUN | |
1530 #define GC_STRING_EXTRA 4 | |
1531 static char string_overrun_pattern[GC_STRING_EXTRA] = { 0xde, 0xad, 0xbe, 0xef }; | |
1532 #else | |
1533 #define GC_STRING_EXTRA 0 | |
1534 #endif | |
1535 | |
1431 /* Value is the size of an sdata structure large enough to hold NBYTES | 1536 /* Value is the size of an sdata structure large enough to hold NBYTES |
1432 bytes of string data. The value returned includes a terminating | 1537 bytes of string data. The value returned includes a terminating |
1433 NUL byte, the size of the sdata structure, and padding. */ | 1538 NUL byte, the size of the sdata structure, and padding. */ |
1434 | 1539 |
1435 #ifdef GC_CHECK_STRING_BYTES | 1540 #ifdef GC_CHECK_STRING_BYTES |
1513 nbytes = GC_STRING_BYTES (from->string); | 1618 nbytes = GC_STRING_BYTES (from->string); |
1514 else | 1619 else |
1515 nbytes = SDATA_NBYTES (from); | 1620 nbytes = SDATA_NBYTES (from); |
1516 | 1621 |
1517 nbytes = SDATA_SIZE (nbytes); | 1622 nbytes = SDATA_SIZE (nbytes); |
1518 from_end = (struct sdata *) ((char *) from + nbytes); | 1623 from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
1519 } | 1624 } |
1520 } | 1625 } |
1521 | 1626 |
1522 | 1627 |
1523 /* Check validity of Lisp strings' string_bytes member. ALL_P | 1628 /* Check validity of Lisp strings' string_bytes member. ALL_P |
1546 check_sblock (current_sblock); | 1651 check_sblock (current_sblock); |
1547 } | 1652 } |
1548 | 1653 |
1549 #endif /* GC_CHECK_STRING_BYTES */ | 1654 #endif /* GC_CHECK_STRING_BYTES */ |
1550 | 1655 |
1656 #ifdef GC_CHECK_STRING_FREE_LIST | |
1657 | |
1658 static void | |
1659 check_string_free_list () | |
1660 { | |
1661 struct Lisp_String *s; | |
1662 | |
1663 /* Pop a Lisp_String off the free-list. */ | |
1664 s = string_free_list; | |
1665 while (s != NULL) | |
1666 { | |
1667 if ((unsigned)s < 1024) | |
1668 abort(); | |
1669 s = NEXT_FREE_LISP_STRING (s); | |
1670 } | |
1671 } | |
1672 #else | |
1673 #define check_string_free_list() | |
1674 #endif | |
1551 | 1675 |
1552 /* Return a new Lisp_String. */ | 1676 /* Return a new Lisp_String. */ |
1553 | 1677 |
1554 static struct Lisp_String * | 1678 static struct Lisp_String * |
1555 allocate_string () | 1679 allocate_string () |
1576 string_free_list = s; | 1700 string_free_list = s; |
1577 } | 1701 } |
1578 | 1702 |
1579 total_free_strings += STRING_BLOCK_SIZE; | 1703 total_free_strings += STRING_BLOCK_SIZE; |
1580 } | 1704 } |
1705 | |
1706 check_string_free_list(); | |
1581 | 1707 |
1582 /* Pop a Lisp_String off the free-list. */ | 1708 /* Pop a Lisp_String off the free-list. */ |
1583 s = string_free_list; | 1709 s = string_free_list; |
1584 string_free_list = NEXT_FREE_LISP_STRING (s); | 1710 string_free_list = NEXT_FREE_LISP_STRING (s); |
1585 | 1711 |
1646 address space, which won't fit into an EMACS_INT (at least on | 1772 address space, which won't fit into an EMACS_INT (at least on |
1647 32-bit systems with the current tagging scheme). --fx */ | 1773 32-bit systems with the current tagging scheme). --fx */ |
1648 mallopt (M_MMAP_MAX, 0); | 1774 mallopt (M_MMAP_MAX, 0); |
1649 #endif | 1775 #endif |
1650 | 1776 |
1651 b = (struct sblock *) lisp_malloc (size, MEM_TYPE_NON_LISP); | 1777 b = (struct sblock *) lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP); |
1652 | 1778 |
1653 #ifdef DOUG_LEA_MALLOC | 1779 #ifdef DOUG_LEA_MALLOC |
1654 /* Back to a reasonable maximum of mmap'ed areas. */ | 1780 /* Back to a reasonable maximum of mmap'ed areas. */ |
1655 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); | 1781 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); |
1656 #endif | 1782 #endif |
1661 large_sblocks = b; | 1787 large_sblocks = b; |
1662 } | 1788 } |
1663 else if (current_sblock == NULL | 1789 else if (current_sblock == NULL |
1664 || (((char *) current_sblock + SBLOCK_SIZE | 1790 || (((char *) current_sblock + SBLOCK_SIZE |
1665 - (char *) current_sblock->next_free) | 1791 - (char *) current_sblock->next_free) |
1666 < needed)) | 1792 < (needed + GC_STRING_EXTRA))) |
1667 { | 1793 { |
1668 /* Not enough room in the current sblock. */ | 1794 /* Not enough room in the current sblock. */ |
1669 b = (struct sblock *) lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); | 1795 b = (struct sblock *) lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); |
1670 b->next_free = &b->first_data; | 1796 b->next_free = &b->first_data; |
1671 b->first_data.string = NULL; | 1797 b->first_data.string = NULL; |
1690 SDATA_NBYTES (data) = nbytes; | 1816 SDATA_NBYTES (data) = nbytes; |
1691 #endif | 1817 #endif |
1692 s->size = nchars; | 1818 s->size = nchars; |
1693 s->size_byte = nbytes; | 1819 s->size_byte = nbytes; |
1694 s->data[nbytes] = '\0'; | 1820 s->data[nbytes] = '\0'; |
1695 b->next_free = (struct sdata *) ((char *) data + needed); | 1821 #ifdef GC_CHECK_STRING_OVERRUN |
1822 bcopy(string_overrun_pattern, (char *) data + needed, GC_STRING_EXTRA); | |
1823 #endif | |
1824 b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA); | |
1696 | 1825 |
1697 /* If S had already data assigned, mark that as free by setting its | 1826 /* If S had already data assigned, mark that as free by setting its |
1698 string back-pointer to null, and recording the size of the data | 1827 string back-pointer to null, and recording the size of the data |
1699 in it. */ | 1828 in it. */ |
1700 if (old_data) | 1829 if (old_data) |
1795 b->next = live_blocks; | 1924 b->next = live_blocks; |
1796 live_blocks = b; | 1925 live_blocks = b; |
1797 } | 1926 } |
1798 } | 1927 } |
1799 | 1928 |
1929 check_string_free_list(); | |
1930 | |
1800 string_blocks = live_blocks; | 1931 string_blocks = live_blocks; |
1801 free_large_strings (); | 1932 free_large_strings (); |
1802 compact_small_strings (); | 1933 compact_small_strings (); |
1934 | |
1935 check_string_free_list(); | |
1803 } | 1936 } |
1804 | 1937 |
1805 | 1938 |
1806 /* Free dead large strings. */ | 1939 /* Free dead large strings. */ |
1807 | 1940 |
1869 if (from->string) | 2002 if (from->string) |
1870 nbytes = GC_STRING_BYTES (from->string); | 2003 nbytes = GC_STRING_BYTES (from->string); |
1871 else | 2004 else |
1872 nbytes = SDATA_NBYTES (from); | 2005 nbytes = SDATA_NBYTES (from); |
1873 | 2006 |
2007 #ifdef GC_CHECK_STRING_BYTES | |
2008 if (nbytes > LARGE_STRING_BYTES) | |
2009 abort (); | |
2010 #endif | |
2011 | |
1874 nbytes = SDATA_SIZE (nbytes); | 2012 nbytes = SDATA_SIZE (nbytes); |
1875 from_end = (struct sdata *) ((char *) from + nbytes); | 2013 from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
2014 | |
2015 #ifdef GC_CHECK_STRING_OVERRUN | |
2016 if (bcmp(string_overrun_pattern, ((char *) from_end) - GC_STRING_EXTRA, GC_STRING_EXTRA)) | |
2017 abort (); | |
2018 #endif | |
1876 | 2019 |
1877 /* FROM->string non-null means it's alive. Copy its data. */ | 2020 /* FROM->string non-null means it's alive. Copy its data. */ |
1878 if (from->string) | 2021 if (from->string) |
1879 { | 2022 { |
1880 /* If TB is full, proceed with the next sblock. */ | 2023 /* If TB is full, proceed with the next sblock. */ |
1881 to_end = (struct sdata *) ((char *) to + nbytes); | 2024 to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
1882 if (to_end > tb_end) | 2025 if (to_end > tb_end) |
1883 { | 2026 { |
1884 tb->next_free = to; | 2027 tb->next_free = to; |
1885 tb = tb->next; | 2028 tb = tb->next; |
1886 tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); | 2029 tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); |
1887 to = &tb->first_data; | 2030 to = &tb->first_data; |
1888 to_end = (struct sdata *) ((char *) to + nbytes); | 2031 to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
1889 } | 2032 } |
1890 | 2033 |
1891 /* Copy, and update the string's `data' pointer. */ | 2034 /* Copy, and update the string's `data' pointer. */ |
1892 if (from != to) | 2035 if (from != to) |
1893 { | 2036 { |
1894 xassert (tb != b || to <= from); | 2037 xassert (tb != b || to <= from); |
1895 safe_bcopy ((char *) from, (char *) to, nbytes); | 2038 safe_bcopy ((char *) from, (char *) to, nbytes + GC_STRING_EXTRA); |
1896 to->string->data = SDATA_DATA (to); | 2039 to->string->data = SDATA_DATA (to); |
1897 } | 2040 } |
1898 | 2041 |
1899 /* Advance past the sdata we copied to. */ | 2042 /* Advance past the sdata we copied to. */ |
1900 to = to_end; | 2043 to = to_end; |
2400 | 2543 |
2401 /* Get an error now if there's any junk in the cons free list. */ | 2544 /* Get an error now if there's any junk in the cons free list. */ |
2402 void | 2545 void |
2403 check_cons_list () | 2546 check_cons_list () |
2404 { | 2547 { |
2548 #ifdef GC_CHECK_CONS_LIST | |
2405 struct Lisp_Cons *tail = cons_free_list; | 2549 struct Lisp_Cons *tail = cons_free_list; |
2406 | 2550 |
2407 #if 0 | |
2408 while (tail) | 2551 while (tail) |
2409 tail = *(struct Lisp_Cons **)&tail->cdr; | 2552 tail = *(struct Lisp_Cons **)&tail->cdr; |
2410 #endif | 2553 #endif |
2411 } | 2554 } |
2412 | 2555 |