Module Name: src Committed By: rillig Date: Fri Jan 13 19:41:50 UTC 2023
Modified Files: src/usr.bin/xlint/common: externs.h mem.c src/usr.bin/xlint/lint1: externs1.h init.c lint1.h main1.c mem1.c tree.c src/usr.bin/xlint/lint2: externs2.h main2.c mem2.c Log Message: lint: remove custom memory allocator Besides adding complexity, the custom memory allocator didn't invalidate freed memory, which made it harder to find possible use-after-free bugs. To generate a diff of this commit: cvs rdiff -u -r1.24 -r1.25 src/usr.bin/xlint/common/externs.h cvs rdiff -u -r1.20 -r1.21 src/usr.bin/xlint/common/mem.c cvs rdiff -u -r1.170 -r1.171 src/usr.bin/xlint/lint1/externs1.h cvs rdiff -u -r1.237 -r1.238 src/usr.bin/xlint/lint1/init.c cvs rdiff -u -r1.158 -r1.159 src/usr.bin/xlint/lint1/lint1.h cvs rdiff -u -r1.65 -r1.66 src/usr.bin/xlint/lint1/main1.c cvs rdiff -u -r1.63 -r1.64 src/usr.bin/xlint/lint1/mem1.c cvs rdiff -u -r1.489 -r1.490 src/usr.bin/xlint/lint1/tree.c cvs rdiff -u -r1.16 -r1.17 src/usr.bin/xlint/lint2/externs2.h cvs rdiff -u -r1.24 -r1.25 src/usr.bin/xlint/lint2/main2.c cvs rdiff -u -r1.15 -r1.16 src/usr.bin/xlint/lint2/mem2.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/xlint/common/externs.h diff -u src/usr.bin/xlint/common/externs.h:1.24 src/usr.bin/xlint/common/externs.h:1.25 --- src/usr.bin/xlint/common/externs.h:1.24 Sat Sep 4 14:48:27 2021 +++ src/usr.bin/xlint/common/externs.h Fri Jan 13 19:41:50 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: externs.h,v 1.24 2021/09/04 14:48:27 rillig Exp $ */ +/* $NetBSD: externs.h,v 1.25 2023/01/13 19:41:50 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -45,7 +45,6 @@ extern const char *tspec_name(tspec_t); /* * mem.c */ -extern size_t mem_block_size(void); extern void *xmalloc(size_t); extern void *xcalloc(size_t, size_t); extern void *xrealloc(void *, size_t); Index: src/usr.bin/xlint/common/mem.c diff -u src/usr.bin/xlint/common/mem.c:1.20 src/usr.bin/xlint/common/mem.c:1.21 --- src/usr.bin/xlint/common/mem.c:1.20 Fri May 20 21:18:54 2022 +++ src/usr.bin/xlint/common/mem.c Fri Jan 13 19:41:50 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: mem.c,v 1.20 2022/05/20 21:18:54 rillig Exp $ */ +/* $NetBSD: mem.c,v 1.21 2023/01/13 19:41:50 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,27 +37,15 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: mem.c,v 1.20 2022/05/20 21:18:54 rillig Exp $"); +__RCSID("$NetBSD: mem.c,v 1.21 2023/01/13 19:41:50 rillig Exp $"); #endif #include <stdarg.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> #include "lint.h" -#if defined(IS_LINT1) || defined(IS_LINT2) -size_t -mem_block_size(void) -{ - unsigned int pagesize; - - pagesize = (unsigned int)getpagesize(); - return (MBLKSIZ + pagesize - 1) / pagesize * pagesize; -} -#endif - static void * not_null(void *ptr) { Index: src/usr.bin/xlint/lint1/externs1.h diff -u src/usr.bin/xlint/lint1/externs1.h:1.170 src/usr.bin/xlint/lint1/externs1.h:1.171 --- src/usr.bin/xlint/lint1/externs1.h:1.170 Sat Oct 1 09:59:40 2022 +++ src/usr.bin/xlint/lint1/externs1.h Fri Jan 13 19:41:50 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: externs1.h,v 1.170 2022/10/01 09:59:40 rillig Exp $ */ +/* $NetBSD: externs1.h,v 1.171 2023/01/13 19:41:50 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -99,8 +99,6 @@ extern int get_filename_id(const char *) extern void add_directory_replacement(char *); extern const char *transform_filename(const char *, size_t); -extern void initmem(void); - extern void *block_zero_alloc(size_t); extern void *level_zero_alloc(size_t, size_t); extern void level_free_all(size_t); @@ -108,8 +106,8 @@ extern void level_free_all(size_t); extern void *expr_zero_alloc(size_t); extern tnode_t *expr_alloc_tnode(void); extern void expr_free_all(void); -extern struct memory_block *expr_save_memory(void); -extern void expr_restore_memory(struct memory_block *); +extern memory_pool expr_save_memory(void); +extern void expr_restore_memory(memory_pool); /* * debug.c Index: src/usr.bin/xlint/lint1/init.c diff -u src/usr.bin/xlint/lint1/init.c:1.237 src/usr.bin/xlint/lint1/init.c:1.238 --- src/usr.bin/xlint/lint1/init.c:1.237 Sun Aug 28 12:04:47 2022 +++ src/usr.bin/xlint/lint1/init.c Fri Jan 13 19:41:50 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: init.c,v 1.237 2022/08/28 12:04:47 rillig Exp $ */ +/* $NetBSD: init.c,v 1.238 2023/01/13 19:41:50 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -38,7 +38,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: init.c,v 1.237 2022/08/28 12:04:47 rillig Exp $"); +__RCSID("$NetBSD: init.c,v 1.238 2023/01/13 19:41:50 rillig Exp $"); #endif #include <stdlib.h> @@ -309,7 +309,6 @@ check_init_expr(const type_t *ltp, sym_t tnode_t *ln; type_t *lutp; tspec_t lt, rt; - struct memory_block *tmem; lutp = expr_unqualified_type(ltp); @@ -334,9 +333,9 @@ check_init_expr(const type_t *ltp, sym_t * Preserve the tree memory. This is necessary because otherwise * expr() would free it. */ - tmem = expr_save_memory(); + memory_pool saved_mem = expr_save_memory(); expr(rn, true, false, true, false); - expr_restore_memory(tmem); + expr_restore_memory(saved_mem); check_bit_field_init(ln, lt, rt); Index: src/usr.bin/xlint/lint1/lint1.h diff -u src/usr.bin/xlint/lint1/lint1.h:1.158 src/usr.bin/xlint/lint1/lint1.h:1.159 --- src/usr.bin/xlint/lint1/lint1.h:1.158 Sat Oct 1 09:42:40 2022 +++ src/usr.bin/xlint/lint1/lint1.h Fri Jan 13 19:41:50 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: lint1.h,v 1.158 2022/10/01 09:42:40 rillig Exp $ */ +/* $NetBSD: lint1.h,v 1.159 2023/01/13 19:41:50 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -36,6 +36,18 @@ #include "err-msgs.h" #include "op.h" +/* + * A memory pool collects allocated objects that must be available until: + * - the end of a block, + * - the end of an expression, or + * - the end of the translation unit. + */ +typedef struct memory_pool { + void **items; + size_t len; + size_t cap; +} memory_pool; + /* See saved_lwarn in cgram.y. */ #define LWARN_ALL (-2) #define LWARN_NONE (-1) @@ -426,7 +438,7 @@ typedef struct control_statement { tnode_t *c_switch_expr; case_label_t *c_case_labels; /* list of case values */ - struct memory_block *c_for_expr3_mem; /* saved memory for end of loop + memory_pool c_for_expr3_mem; /* saved memory for end of loop * expression in for() */ tnode_t *c_for_expr3; /* end of loop expr in for() */ pos_t c_for_expr3_pos; /* position of end of loop expr */ Index: src/usr.bin/xlint/lint1/main1.c diff -u src/usr.bin/xlint/lint1/main1.c:1.65 src/usr.bin/xlint/lint1/main1.c:1.66 --- src/usr.bin/xlint/lint1/main1.c:1.65 Tue Jul 5 22:50:41 2022 +++ src/usr.bin/xlint/lint1/main1.c Fri Jan 13 19:41:50 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: main1.c,v 1.65 2022/07/05 22:50:41 rillig Exp $ */ +/* $NetBSD: main1.c,v 1.66 2023/01/13 19:41:50 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: main1.c,v 1.65 2022/07/05 22:50:41 rillig Exp $"); +__RCSID("$NetBSD: main1.c,v 1.66 2023/01/13 19:41:50 rillig Exp $"); #endif #include <sys/types.h> @@ -259,7 +259,6 @@ main(int argc, char *argv[]) #endif (void)signal(SIGFPE, sigfpe); - initmem(); initdecl(); initscan(); Index: src/usr.bin/xlint/lint1/mem1.c diff -u src/usr.bin/xlint/lint1/mem1.c:1.63 src/usr.bin/xlint/lint1/mem1.c:1.64 --- src/usr.bin/xlint/lint1/mem1.c:1.63 Fri May 20 21:18:55 2022 +++ src/usr.bin/xlint/lint1/mem1.c Fri Jan 13 19:41:50 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: mem1.c,v 1.63 2022/05/20 21:18:55 rillig Exp $ */ +/* $NetBSD: mem1.c,v 1.64 2023/01/13 19:41:50 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: mem1.c,v 1.63 2022/05/20 21:18:55 rillig Exp $"); +__RCSID("$NetBSD: mem1.c,v 1.64 2023/01/13 19:41:50 rillig Exp $"); #endif #include <sys/param.h> @@ -160,74 +160,60 @@ get_filename_id(const char *s) return fn->fn_id; } -/* - * Memory for declarations and other things that must be available - * until the end of a block (or the end of the translation unit) - * is associated with the corresponding mem_block_level, which may be 0. - * Because this memory is allocated in large blocks associated with - * a given level it can be freed easily at the end of a block. - */ -typedef struct memory_block { - void *start; /* beginning of memory block */ - void *first_free; /* first free byte */ - size_t nfree; /* # of free bytes */ - struct memory_block *next; -} memory_block; - +/* Array of memory pools, indexed by mem_block_level. */ +typedef struct memory_pools { + struct memory_pool *pools; + size_t cap; +} memory_pools; -static size_t mblk_size; /* size of newly allocated memory blocks */ +static memory_pools mpools; -/* Array of lists of memory blocks, indexed by mem_block_level. */ -static memory_block **mblks; -static size_t nmblks; /* number of elements in *mblks */ -#define ML_INC ((size_t)32) /* Increment for length of *mblks */ +/* The pool for the current expression is independent of any block level. */ +static memory_pool expr_pool; - -/* Allocate new memory, initialized with zero. */ -static void * -xgetblk(memory_block **mbp, size_t s) +static void +mpool_add(memory_pool *pool, void *item) { - memory_block *mb; - void *p; - - size_t worst_align = 2 * sizeof(long) - 1; - s = (s + worst_align) & ~worst_align; - if ((mb = *mbp) == NULL || mb->nfree < s) { - size_t block_size = s > mblk_size ? s : mblk_size; - mb = xmalloc(sizeof(*mb)); - mb->start = xmalloc(block_size); - mb->first_free = mb->start; - mb->nfree = block_size; - mb->next = *mbp; - *mbp = mb; + if (pool->len >= pool->cap) { + pool->cap = 2 * pool->len + 16; + pool->items = xrealloc(pool->items, + sizeof(*pool->items) * pool->cap); } - - p = mb->first_free; - mb->first_free = (char *)mb->first_free + s; - mb->nfree -= s; - (void)memset(p, 0, s); - return p; + pool->items[pool->len++] = item; } -/* Free all blocks from list *fmbp. */ static void -xfreeblk(memory_block **fmbp) +mpool_free(memory_pool *pool) { - memory_block *mb; - while ((mb = *fmbp) != NULL) { - *fmbp = mb->next; - free(mb); - } + for (; pool->len > 0; pool->len--) + free(pool->items[pool->len - 1]); } -void -initmem(void) +static void * +mpool_zero_alloc(memory_pool *pool, size_t size) +{ + + void *mem = xmalloc(size); + memset(mem, 0, size); + mpool_add(pool, mem); + return mem; +} + +static memory_pool * +mpool_at(size_t level) { - mblk_size = mem_block_size(); - mblks = xcalloc(nmblks = ML_INC, sizeof(*mblks)); + if (level >= mpools.cap) { + size_t prev_cap = mpools.cap; + mpools.cap = level + 16; + mpools.pools = xrealloc(mpools.pools, + sizeof(*mpools.pools) * mpools.cap); + for (size_t i = prev_cap; i < mpools.cap; i++) + mpools.pools[i] = (memory_pool){ NULL, 0, 0 }; + } + return mpools.pools + level; } @@ -236,12 +222,7 @@ void * level_zero_alloc(size_t l, size_t s) { - while (l >= nmblks) { - mblks = xrealloc(mblks, (nmblks + ML_INC) * sizeof(*mblks)); - (void)memset(&mblks[nmblks], 0, ML_INC * sizeof(*mblks)); - nmblks += ML_INC; - } - return xgetblk(&mblks[l], s); + return mpool_zero_alloc(mpool_at(l), s); } /* Allocate memory that is freed at the end of the current block. */ @@ -256,18 +237,15 @@ void level_free_all(size_t level) { - xfreeblk(&mblks[level]); + mpool_free(mpool_at(level)); } - -static memory_block *tmblk; - /* Allocate memory that is freed at the end of the current expression. */ void * expr_zero_alloc(size_t s) { - return xgetblk(&tmblk, s); + return mpool_zero_alloc(&expr_pool, s); } static bool @@ -307,22 +285,21 @@ void expr_free_all(void) { - xfreeblk(&tmblk); + mpool_free(&expr_pool); } /* * Save the memory which is used by the current expression. This memory - * is not freed by the next expr_free_all() call. The pointer returned can be + * is not freed by the next expr_free_all() call. The returned value can be * used to restore the memory. */ -memory_block * +memory_pool expr_save_memory(void) { - memory_block *tmem; - tmem = tmblk; - tmblk = NULL; - return tmem; + memory_pool saved_pool = expr_pool; + expr_pool = (memory_pool){ NULL, 0, 0 }; + return saved_pool; } /* @@ -331,13 +308,10 @@ expr_save_memory(void) * expr_free_all() frees the restored memory. */ void -expr_restore_memory(memory_block *tmem) +expr_restore_memory(memory_pool saved_pool) { expr_free_all(); - if (tmblk != NULL) { - free(tmblk->start); - free(tmblk); - } - tmblk = tmem; + free(expr_pool.items); + expr_pool = saved_pool; } Index: src/usr.bin/xlint/lint1/tree.c diff -u src/usr.bin/xlint/lint1/tree.c:1.489 src/usr.bin/xlint/lint1/tree.c:1.490 --- src/usr.bin/xlint/lint1/tree.c:1.489 Sun Jan 8 18:37:12 2023 +++ src/usr.bin/xlint/lint1/tree.c Fri Jan 13 19:41:50 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: tree.c,v 1.489 2023/01/08 18:37:12 rillig Exp $ */ +/* $NetBSD: tree.c,v 1.490 2023/01/13 19:41:50 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: tree.c,v 1.489 2023/01/08 18:37:12 rillig Exp $"); +__RCSID("$NetBSD: tree.c,v 1.490 2023/01/13 19:41:50 rillig Exp $"); #endif #include <float.h> @@ -4883,7 +4883,7 @@ check_precedence_confusion(tnode_t *tn) } typedef struct stmt_expr { - struct memory_block *se_mem; + memory_pool se_mem; sym_t *se_sym; struct stmt_expr *se_enclosing; } stmt_expr; Index: src/usr.bin/xlint/lint2/externs2.h diff -u src/usr.bin/xlint/lint2/externs2.h:1.16 src/usr.bin/xlint/lint2/externs2.h:1.17 --- src/usr.bin/xlint/lint2/externs2.h:1.16 Tue Nov 16 22:03:12 2021 +++ src/usr.bin/xlint/lint2/externs2.h Fri Jan 13 19:41:50 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: externs2.h,v 1.16 2021/11/16 22:03:12 rillig Exp $ */ +/* $NetBSD: externs2.h,v 1.17 2023/01/13 19:41:50 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -69,7 +69,6 @@ extern void mkstatic(hte_t *); /* * mem2.c */ -extern void initmem(void); extern void *xalloc(size_t); /* Index: src/usr.bin/xlint/lint2/main2.c diff -u src/usr.bin/xlint/lint2/main2.c:1.24 src/usr.bin/xlint/lint2/main2.c:1.25 --- src/usr.bin/xlint/lint2/main2.c:1.24 Fri May 20 21:18:55 2022 +++ src/usr.bin/xlint/lint2/main2.c Fri Jan 13 19:41:50 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: main2.c,v 1.24 2022/05/20 21:18:55 rillig Exp $ */ +/* $NetBSD: main2.c,v 1.25 2023/01/13 19:41:50 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: main2.c,v 1.24 2022/05/20 21:18:55 rillig Exp $"); +__RCSID("$NetBSD: main2.c,v 1.25 2023/01/13 19:41:50 rillig Exp $"); #endif #include <stdio.h> @@ -153,8 +153,6 @@ main(int argc, char *argv[]) if (argc == 0) usage(); - initmem(); - symtab_init(); for (i = 0; i < argc; i++) Index: src/usr.bin/xlint/lint2/mem2.c diff -u src/usr.bin/xlint/lint2/mem2.c:1.15 src/usr.bin/xlint/lint2/mem2.c:1.16 --- src/usr.bin/xlint/lint2/mem2.c:1.15 Fri May 20 21:18:55 2022 +++ src/usr.bin/xlint/lint2/mem2.c Fri Jan 13 19:41:50 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: mem2.c,v 1.15 2022/05/20 21:18:55 rillig Exp $ */ +/* $NetBSD: mem2.c,v 1.16 2023/01/13 19:41:50 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,51 +37,19 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: mem2.c,v 1.15 2022/05/20 21:18:55 rillig Exp $"); +__RCSID("$NetBSD: mem2.c,v 1.16 2023/01/13 19:41:50 rillig Exp $"); #endif -#include <sys/param.h> #include <string.h> #include "lint2.h" -/* length of new allocated memory blocks */ -static size_t mblklen; - -/* offset of next free byte in mbuf */ -static size_t nxtfree; - -/* current buffer to server memory requests from */ -static void *mbuf; - -void -initmem(void) -{ - - mblklen = mem_block_size(); - nxtfree = mblklen; -} - -/* - * Allocate memory in large chunks to avoid space and time overhead of - * malloc(). This is possible because memory allocated by xalloc() - * need never to be freed. - */ +/* Allocate zero-initialized memory that doesn't need to be freed. */ void * xalloc(size_t sz) { - void *ptr; - - /* Align to at least 8 bytes. */ - sz = (sz + 7) & ~7L; - if (nxtfree + sz > mblklen) { - mbuf = xmalloc(mblklen); - (void)memset(mbuf, 0, mblklen); - nxtfree = 0; - } - - ptr = (char *)mbuf + nxtfree; - nxtfree += sz; + void *ptr = xmalloc(sz); + (void)memset(ptr, 0, sz); return ptr; }