From 7ad9ba94f77eba7345aaf7872f5f40681d7e16a4 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 28 Sep 2009 21:20:50 +0000 Subject: * generic/tclAlloc.c: Cleaned up various routines in the * generic/tclCkalloc.c: call stacks for memory allocation to * generic/tclParse.c: guarantee that any size values computed * generic/tclThreadAlloc.c: are within the domains of the routines they get passed to. [Bugs 2557696 and 2557796]. --- ChangeLog | 8 ++++++++ generic/tclAlloc.c | 12 +++++++----- generic/tclCkalloc.c | 21 ++++++++++++++------- generic/tclParse.c | 10 +++++++++- generic/tclThreadAlloc.c | 30 +++++++++++++++++++++++++++--- 5 files changed, 65 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index b3f8050..7bd1f8e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-09-28 Don Porter + + * generic/tclAlloc.c: Cleaned up various routines in the + * generic/tclCkalloc.c: call stacks for memory allocation to + * generic/tclParse.c: guarantee that any size values computed + * generic/tclThreadAlloc.c: are within the domains of the routines + they get passed to. [Bugs 2557696 and 2557796]. + 2009-09-18 Don Porter * generic/tclCmdMZ.c (Tcl_SubstObj): Pass 'length' values to diff --git a/generic/tclAlloc.c b/generic/tclAlloc.c index 12c0201..7decf22 100644 --- a/generic/tclAlloc.c +++ b/generic/tclAlloc.c @@ -15,7 +15,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclAlloc.c,v 1.16.2.3 2007/09/22 15:46:45 das Exp $ + * RCS: @(#) $Id: tclAlloc.c,v 1.16.2.4 2009/09/28 21:20:50 dgp Exp $ */ /* @@ -272,7 +272,7 @@ TclpAlloc(nbytes) register union overhead *op; register long bucket; register unsigned amt; - struct block *bigBlockPtr; + struct block *bigBlockPtr = NULL; if (!allocInit) { /* @@ -286,9 +286,11 @@ TclpAlloc(nbytes) /* * First the simple case: we simple allocate big blocks directly */ - if (nbytes + OVERHEAD >= MAXMALLOC) { - bigBlockPtr = (struct block *) TclpSysAlloc((unsigned) - (sizeof(struct block) + OVERHEAD + nbytes), 0); + if (nbytes >= MAXMALLOC - OVERHEAD) { + if (nbytes <= UINT_MAX - OVERHEAD - sizeof(struct block)) { + bigBlockPtr = (struct block *) TclpSysAlloc((unsigned) + (sizeof(struct block) + OVERHEAD + nbytes), 0); + } if (bigBlockPtr == NULL) { Tcl_MutexUnlock(allocMutexPtr); return NULL; diff --git a/generic/tclCkalloc.c b/generic/tclCkalloc.c index 98e8c5b..ab51f85 100644 --- a/generic/tclCkalloc.c +++ b/generic/tclCkalloc.c @@ -13,7 +13,7 @@ * * This code contributed by Karl Lehenbauer and Mark Diekhans * - * RCS: @(#) $Id: tclCkalloc.c,v 1.19 2003/01/19 07:21:18 hobbs Exp $ + * RCS: @(#) $Id: tclCkalloc.c,v 1.19.2.1 2009/09/28 21:20:51 dgp Exp $ */ #include "tclInt.h" @@ -368,13 +368,17 @@ Tcl_DbCkalloc(size, file, line) CONST char *file; int line; { - struct mem_header *result; + struct mem_header *result = NULL; if (validate_memory) Tcl_ValidateAllMemory (file, line); - result = (struct mem_header *) TclpAlloc((unsigned)size + - sizeof(struct mem_header) + HIGH_GUARD_SIZE); + + /* Don't let size argument to TclpAlloc overflow */ + if (size <= UINT_MAX - HIGH_GUARD_SIZE - sizeof(struct mem_header)) { + result = (struct mem_header *) TclpAlloc((unsigned)size + + sizeof(struct mem_header) + HIGH_GUARD_SIZE); + } if (result == NULL) { fflush(stdout); TclDumpMemoryInfo(stderr); @@ -453,13 +457,16 @@ Tcl_AttemptDbCkalloc(size, file, line) CONST char *file; int line; { - struct mem_header *result; + struct mem_header *result = NULL; if (validate_memory) Tcl_ValidateAllMemory (file, line); - result = (struct mem_header *) TclpAlloc((unsigned)size + - sizeof(struct mem_header) + HIGH_GUARD_SIZE); + /* Don't let size argument to TclpAlloc overflow */ + if (size <= UINT_MAX - HIGH_GUARD_SIZE - sizeof(struct mem_header)) { + result = (struct mem_header *) TclpAlloc((unsigned)size + + sizeof(struct mem_header) + HIGH_GUARD_SIZE); + } if (result == NULL) { fflush(stdout); TclDumpMemoryInfo(stderr); diff --git a/generic/tclParse.c b/generic/tclParse.c index e939ef3..93d1741 100644 --- a/generic/tclParse.c +++ b/generic/tclParse.c @@ -13,7 +13,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclParse.c,v 1.25.2.3 2007/10/15 13:29:19 msofer Exp $ + * RCS: @(#) $Id: tclParse.c,v 1.25.2.4 2009/09/28 21:20:51 dgp Exp $ */ #include "tclInt.h" @@ -1019,7 +1019,15 @@ TclExpandTokenArray(parsePtr) int newCount; Tcl_Token *newPtr; +#define MAX_TOKENS (int)(UINT_MAX / sizeof(Tcl_Token)) + + if (parsePtr->tokensAvailable == MAX_TOKENS) { + Tcl_Panic("max # of tokens for a Tcl parse (%d) exceeded", MAX_TOKENS); + } newCount = parsePtr->tokensAvailable*2; + if (newCount > MAX_TOKENS) { + newCount = MAX_TOKENS; + } newPtr = (Tcl_Token *) ckalloc((unsigned) (newCount * sizeof(Tcl_Token))); memcpy((VOID *) newPtr, (VOID *) parsePtr->tokenPtr, (size_t) (parsePtr->tokensAvailable * sizeof(Tcl_Token))); diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c index 9ff31db..f4c1e63 100755 --- a/generic/tclThreadAlloc.c +++ b/generic/tclThreadAlloc.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclThreadAlloc.c,v 1.4.2.8 2007/06/29 03:17:33 das Exp $ + * RCS: @(#) $Id: tclThreadAlloc.c,v 1.4.2.9 2009/09/28 21:20:51 dgp Exp $ */ #include "tclInt.h" @@ -306,11 +306,23 @@ TclFreeAllocCache(void *arg) char * TclpAlloc(unsigned int reqsize) { - Cache *cachePtr = TclpGetAllocCache(); + Cache *cachePtr; Block *blockPtr; register int bucket; size_t size; + if (sizeof(int) >= sizeof(size_t)) { + /* An unsigned int overflow can also be a size_t overflow */ + const size_t zero = 0; + const size_t max = ~zero; + + if (((size_t) reqSize) > max - sizeof(Block) - RCHECK) { + /* Requested allocation exceeds memory */ + return NULL; + } + } + + cachePtr = TclpGetAllocCache(); if (cachePtr == NULL) { cachePtr = GetCache(); } @@ -429,7 +441,7 @@ TclpFree(char *ptr) char * TclpRealloc(char *ptr, unsigned int reqsize) { - Cache *cachePtr = TclpGetAllocCache(); + Cache *cachePtr; Block *blockPtr; void *new; size_t size, min; @@ -439,6 +451,18 @@ TclpRealloc(char *ptr, unsigned int reqsize) return TclpAlloc(reqsize); } + if (sizeof(int) >= sizeof(size_t)) { + /* An unsigned int overflow can also be a size_t overflow */ + const size_t zero = 0; + const size_t max = ~zero; + + if (((size_t) reqSize) > max - sizeof(Block) - RCHECK) { + /* Requested allocation exceeds memory */ + return NULL; + } + } + + cachePtr = TclpGetAllocCache(); if (cachePtr == NULL) { cachePtr = GetCache(); } -- cgit v0.12