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