summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2009-09-28 21:20:50 (GMT)
committerdgp <dgp@users.sourceforge.net>2009-09-28 21:20:50 (GMT)
commit7ad9ba94f77eba7345aaf7872f5f40681d7e16a4 (patch)
tree4bbcc35d2c98ef432ee08599ec2bd541b906a6ba
parentcd55adb09ee0d5e492e024cac7a43350933b9dd3 (diff)
downloadtcl-7ad9ba94f77eba7345aaf7872f5f40681d7e16a4.zip
tcl-7ad9ba94f77eba7345aaf7872f5f40681d7e16a4.tar.gz
tcl-7ad9ba94f77eba7345aaf7872f5f40681d7e16a4.tar.bz2
* 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].
-rw-r--r--ChangeLog8
-rw-r--r--generic/tclAlloc.c12
-rw-r--r--generic/tclCkalloc.c21
-rw-r--r--generic/tclParse.c10
-rwxr-xr-xgeneric/tclThreadAlloc.c30
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 <dgp@users.sourceforge.net>
+
+ * 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 <dgp@users.sourceforge.net>
* 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();
}