aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorKim F. Storm2004-11-30 00:30:56 +0000
committerKim F. Storm2004-11-30 00:30:56 +0000
commit212f33f185f9d93562aec9ab01625557c8003ee0 (patch)
tree6f446fb9b00a1171f88800cc63f97bf5f3b18e53 /src/alloc.c
parentfc36888973845984731c651411f43b039ec39be3 (diff)
downloademacs-212f33f185f9d93562aec9ab01625557c8003ee0.tar.gz
emacs-212f33f185f9d93562aec9ab01625557c8003ee0.zip
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.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c161
1 files changed, 152 insertions, 9 deletions
diff --git a/src/alloc.c b/src/alloc.c
index be2a4fa1bbc..223a49ee567 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -518,6 +518,101 @@ buffer_memory_full ()
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
524static 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
529static 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
535POINTER_TYPE *
536overrun_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
552POINTER_TYPE *
553overrun_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
585void
586overrun_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
521POINTER_TYPE * 616POINTER_TYPE *
522xmalloc (size) 617xmalloc (size)
523 size_t size; 618 size_t size;
@@ -602,7 +697,9 @@ safe_alloca_unwind (arg)
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
605static void *lisp_malloc_loser; 701static void *lisp_malloc_loser;
702#endif
606 703
607static POINTER_TYPE * 704static POINTER_TYPE *
608lisp_malloc (nbytes, type) 705lisp_malloc (nbytes, type)
@@ -1428,6 +1525,14 @@ static int total_string_size;
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
1531static 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. */
@@ -1515,7 +1620,7 @@ check_sblock (b)
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
@@ -1548,6 +1653,25 @@ check_string_bytes (all_p)
1548 1653
1549#endif /* GC_CHECK_STRING_BYTES */ 1654#endif /* GC_CHECK_STRING_BYTES */
1550 1655
1656#ifdef GC_CHECK_STRING_FREE_LIST
1657
1658static void
1659check_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
@@ -1579,6 +1703,8 @@ allocate_string ()
1579 total_free_strings += STRING_BLOCK_SIZE; 1703 total_free_strings += STRING_BLOCK_SIZE;
1580 } 1704 }
1581 1705
1706 check_string_free_list();
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);
@@ -1648,7 +1774,7 @@ allocate_string_data (s, nchars, nbytes)
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. */
@@ -1663,7 +1789,7 @@ allocate_string_data (s, nchars, nbytes)
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);
@@ -1692,7 +1818,10 @@ allocate_string_data (s, nchars, nbytes)
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
@@ -1797,9 +1926,13 @@ sweep_strings ()
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
@@ -1871,28 +2004,38 @@ compact_small_strings ()
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
@@ -2402,9 +2545,9 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2402void 2545void
2403check_cons_list () 2546check_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