From ed156a09fa82ac8d6ffed202a727a06aa1b4bd66 Mon Sep 17 00:00:00 2001 From: ferrieux Date: Sat, 22 Dec 2012 19:05:34 +0000 Subject: Stop leaking allocated space when objifying a zero-length DString. [Bug 3598150] spotted by afredd. --- ChangeLog | 5 +++++ generic/tclUtil.c | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 336da37..49da827 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-12-22 Alexandre Ferrieux + + * generic/tclUtil.c: Stop leaking allocated space when objifying a + zero-length DString. [Bug 3598150] spotted by afredd. + 2012-12-21 Jan Nijtmans * unix/dltest/pkgb.c: Inline compat Tcl_GetDefaultEncodingDir. diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 13e54ec..ddf067b 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -2927,14 +2927,16 @@ TclDStringToObj( { Tcl_Obj *result; - if (dsPtr->length == 0) { - TclNewObj(result); - } else if (dsPtr->string == dsPtr->staticSpace) { - /* - * Static buffer, so must copy. - */ - - TclNewStringObj(result, dsPtr->string, dsPtr->length); + if (dsPtr->string == dsPtr->staticSpace) { + if (dsPtr->length == 0) { + TclNewObj(result); + } else { + /* + * Static buffer, so must copy. + */ + + TclNewStringObj(result, dsPtr->string, dsPtr->length); + } } else { /* * Dynamic buffer, so transfer ownership and reset. -- cgit v0.12 From e2e451e2e550c7bff922e4a3966c2b4c2b90d158 Mon Sep 17 00:00:00 2001 From: dkf Date: Sun, 23 Dec 2012 08:17:17 +0000 Subject: Change back to using an isDigit function. We simply don't need to make any (formally non-portable) assumptions about what happens when an unsigned zero is decremented, and the code isn't in a performance-critical area. Remark by jan.nijtmans: The macro is perfectly portable! Not portable is the exact result of the substraction ('\xB0' - '0' might give 0x80 on some platforms and 0xffffff80 on others), but comparing <= 9 always gives the correct result. We are only checking for digits here! The macro correctly inlines with any compiler, so it's better anyway. Remark by dkf: But it's less clear. In this code, that's more important than a teeny bit of speed from inlining in a non-critical location. --- generic/tclStubLib.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index f61e0ca..859cbf9 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -24,10 +24,13 @@ const TclIntStubs *tclIntStubsPtr = NULL; const TclIntPlatStubs *tclIntPlatStubsPtr = NULL; /* - * Use our own ISDIGIT to avoid linking to libc on windows + * Use our own isDigit to avoid linking to libc on windows */ -#define ISDIGIT(c) (((unsigned)((c)-'0')) <= 9) +static int isDigit(const int c) +{ + return (c >= '0' && c <= '9'); +} /* *---------------------------------------------------------------------- @@ -79,7 +82,7 @@ Tcl_InitStubs( int count = 0; while (*p) { - count += !ISDIGIT(*p++); + count += !isDigit(*p++); } if (count == 1) { const char *q = actualVersion; @@ -88,7 +91,7 @@ Tcl_InitStubs( while (*p && (*p == *q)) { p++; q++; } - if (*p || ISDIGIT(*q)) { + if (*p || isDigit(*q)) { /* Construct error message */ stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); return NULL; -- cgit v0.12 From 4b67a9506ba46713d3d2c88962ec1efef7325576 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 26 Dec 2012 09:55:45 +0000 Subject: eliminate dependancy of compat/*.h on tcl.h --- compat/dirent2.h | 10 ++--- compat/dlfcn.h | 19 ++++------ compat/stdlib.h | 51 +++++++++++-------------- compat/string.h | 74 +++++++++++++++--------------------- compat/unistd.h | 112 ++++++++++++++++++++++++++----------------------------- 5 files changed, 115 insertions(+), 151 deletions(-) diff --git a/compat/dirent2.h b/compat/dirent2.h index c00d2f4..5be08ba 100644 --- a/compat/dirent2.h +++ b/compat/dirent2.h @@ -14,10 +14,6 @@ #ifndef _DIRENT #define _DIRENT -#ifndef _TCL -#include -#endif - /* * Dirent structure, which holds information about a single * directory entry. @@ -50,8 +46,8 @@ typedef struct _dirdesc { * Procedures defined for reading directories: */ -extern void closedir _ANSI_ARGS_((DIR *dirp)); -extern DIR * opendir _ANSI_ARGS_((char *name)); -extern struct dirent * readdir _ANSI_ARGS_((DIR *dirp)); +extern void closedir (DIR *dirp); +extern DIR * opendir (char *name); +extern struct dirent * readdir (DIR *dirp); #endif /* _DIRENT */ diff --git a/compat/dlfcn.h b/compat/dlfcn.h index 1a6a118..fb27ea0 100644 --- a/compat/dlfcn.h +++ b/compat/dlfcn.h @@ -1,4 +1,4 @@ -/* +/* * dlfcn.h -- * * This file provides a replacement for the header file "dlfcn.h" @@ -19,7 +19,6 @@ */ /* - * @(#)dlfcn.h 1.4 revision of 95/04/25 09:36:52 * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH * 30159 Hannover, Germany */ @@ -27,10 +26,6 @@ #ifndef __dlfcn_h__ #define __dlfcn_h__ -#ifndef _TCL -#include -#endif - #ifdef __cplusplus extern "C" { #endif @@ -47,14 +42,14 @@ extern "C" { * that contains functions to be called to initialize and terminate. */ struct dl_info { - void (*init) _ANSI_ARGS_((void)); - void (*fini) _ANSI_ARGS_((void)); + void (*init) (void); + void (*fini) (void); }; -VOID *dlopen _ANSI_ARGS_((const char *path, int mode)); -VOID *dlsym _ANSI_ARGS_((void *handle, const char *symbol)); -char *dlerror _ANSI_ARGS_((void)); -int dlclose _ANSI_ARGS_((void *handle)); +void *dlopen (const char *path, int mode); +void *dlsym (void *handle, const char *symbol); +char *dlerror (void); +int dlclose (void *handle); #ifdef __cplusplus } diff --git a/compat/stdlib.h b/compat/stdlib.h index 4d1a386..0ad4c1d 100644 --- a/compat/stdlib.h +++ b/compat/stdlib.h @@ -1,43 +1,36 @@ /* * stdlib.h -- * - * Declares facilities exported by the "stdlib" portion of - * the C library. This file isn't complete in the ANSI-C - * sense; it only declares things that are needed by Tcl. - * This file is needed even on many systems with their own - * stdlib.h (e.g. SunOS) because not all stdlib.h files - * declare all the procedures needed here (such as strtod). + * Declares facilities exported by the "stdlib" portion of the C library. + * This file isn't complete in the ANSI-C sense; it only declares things + * that are needed by Tcl. This file is needed even on many systems with + * their own stdlib.h (e.g. SunOS) because not all stdlib.h files declare + * all the procedures needed here (such as strtod). * * Copyright (c) 1991 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _STDLIB #define _STDLIB -#include - -extern void abort _ANSI_ARGS_((void)); -extern double atof _ANSI_ARGS_((CONST char *string)); -extern int atoi _ANSI_ARGS_((CONST char *string)); -extern long atol _ANSI_ARGS_((CONST char *string)); -extern char * calloc _ANSI_ARGS_((unsigned int numElements, - unsigned int size)); -extern void exit _ANSI_ARGS_((int status)); -extern int free _ANSI_ARGS_((char *blockPtr)); -extern char * getenv _ANSI_ARGS_((CONST char *name)); -extern char * malloc _ANSI_ARGS_((unsigned int numBytes)); -extern void qsort _ANSI_ARGS_((VOID *base, int n, int size, - int (*compar)(CONST VOID *element1, CONST VOID - *element2))); -extern char * realloc _ANSI_ARGS_((char *ptr, unsigned int numBytes)); -extern double strtod _ANSI_ARGS_((CONST char *string, char **endPtr)); -extern long strtol _ANSI_ARGS_((CONST char *string, char **endPtr, - int base)); -extern unsigned long strtoul _ANSI_ARGS_((CONST char *string, - char **endPtr, int base)); +extern void abort(void); +extern double atof(const char *string); +extern int atoi(const char *string); +extern long atol(const char *string); +extern char * calloc(unsigned int numElements, unsigned int size); +extern void exit(int status); +extern int free(char *blockPtr); +extern char * getenv(const char *name); +extern char * malloc(unsigned int numBytes); +extern void qsort(void *base, int n, int size, int (*compar)( + const void *element1, const void *element2)); +extern char * realloc(char *ptr, unsigned int numBytes); +extern double strtod(const char *string, char **endPtr); +extern long strtol(const char *string, char **endPtr, int base); +extern unsigned long strtoul(const char *string, char **endPtr, int base); #endif /* _STDLIB */ diff --git a/compat/string.h b/compat/string.h index 4eb2b86..42be10c 100644 --- a/compat/string.h +++ b/compat/string.h @@ -6,66 +6,52 @@ * Copyright (c) 1991-1993 The Regents of the University of California. * Copyright (c) 1994-1996 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _STRING #define _STRING -#include - /* - * The following #include is needed to define size_t. (This used to - * include sys/stdtypes.h but that doesn't exist on older versions - * of SunOS, e.g. 4.0.2, so I'm trying sys/types.h now.... hopefully - * it exists everywhere) + * The following #include is needed to define size_t. (This used to include + * sys/stdtypes.h but that doesn't exist on older versions of SunOS, e.g. + * 4.0.2, so I'm trying sys/types.h now.... hopefully it exists everywhere) */ #include #ifdef __APPLE__ -extern VOID * memchr _ANSI_ARGS_((CONST VOID *s, int c, size_t n)); +extern void * memchr(const void *s, int c, size_t n); #else -extern char * memchr _ANSI_ARGS_((CONST VOID *s, int c, size_t n)); +extern char * memchr(const void *s, int c, size_t n); #endif -extern int memcmp _ANSI_ARGS_((CONST VOID *s1, CONST VOID *s2, - size_t n)); -extern char * memcpy _ANSI_ARGS_((VOID *t, CONST VOID *f, size_t n)); +extern int memcmp(const void *s1, const void *s2, size_t n); +extern char * memcpy(void *t, const void *f, size_t n); #ifdef NO_MEMMOVE -#define memmove(d, s, n) bcopy ((s), (d), (n)) +#define memmove(d,s,n) (bcopy((s), (d), (n))) #else -extern char * memmove _ANSI_ARGS_((VOID *t, CONST VOID *f, - size_t n)); +extern char * memmove(void *t, const void *f, size_t n); #endif -extern char * memset _ANSI_ARGS_((VOID *s, int c, size_t n)); +extern char * memset(void *s, int c, size_t n); -extern int strcasecmp _ANSI_ARGS_((CONST char *s1, - CONST char *s2)); -extern char * strcat _ANSI_ARGS_((char *dst, CONST char *src)); -extern char * strchr _ANSI_ARGS_((CONST char *string, int c)); -extern int strcmp _ANSI_ARGS_((CONST char *s1, CONST char *s2)); -extern char * strcpy _ANSI_ARGS_((char *dst, CONST char *src)); -extern size_t strcspn _ANSI_ARGS_((CONST char *string, - CONST char *chars)); -extern char * strdup _ANSI_ARGS_((CONST char *string)); -extern char * strerror _ANSI_ARGS_((int error)); -extern size_t strlen _ANSI_ARGS_((CONST char *string)); -extern int strncasecmp _ANSI_ARGS_((CONST char *s1, - CONST char *s2, size_t n)); -extern char * strncat _ANSI_ARGS_((char *dst, CONST char *src, - size_t numChars)); -extern int strncmp _ANSI_ARGS_((CONST char *s1, CONST char *s2, - size_t nChars)); -extern char * strncpy _ANSI_ARGS_((char *dst, CONST char *src, - size_t numChars)); -extern char * strpbrk _ANSI_ARGS_((CONST char *string, - CONST char *chars)); -extern char * strrchr _ANSI_ARGS_((CONST char *string, int c)); -extern size_t strspn _ANSI_ARGS_((CONST char *string, - CONST char *chars)); -extern char * strstr _ANSI_ARGS_((CONST char *string, - CONST char *substring)); -extern char * strtok _ANSI_ARGS_((char *s, CONST char *delim)); +extern int strcasecmp(const char *s1, const char *s2); +extern char * strcat(char *dst, const char *src); +extern char * strchr(const char *string, int c); +extern int strcmp(const char *s1, const char *s2); +extern char * strcpy(char *dst, const char *src); +extern size_t strcspn(const char *string, const char *chars); +extern char * strdup(const char *string); +extern char * strerror(int error); +extern size_t strlen(const char *string); +extern int strncasecmp(const char *s1, const char *s2, size_t n); +extern char * strncat(char *dst, const char *src, size_t numChars); +extern int strncmp(const char *s1, const char *s2, size_t nChars); +extern char * strncpy(char *dst, const char *src, size_t numChars); +extern char * strpbrk(const char *string, const char *chars); +extern char * strrchr(const char *string, int c); +extern size_t strspn(const char *string, const char *chars); +extern char * strstr(const char *string, const char *substring); +extern char * strtok(char *s, const char *delim); #endif /* _STRING */ diff --git a/compat/unistd.h b/compat/unistd.h index 1a40e90..2de5bd0 100644 --- a/compat/unistd.h +++ b/compat/unistd.h @@ -1,82 +1,76 @@ /* * unistd.h -- * - * Macros, CONSTants and prototypes for Posix conformance. + * Macros, constants and prototypes for Posix conformance. * - * Copyright 1989 Regents of the University of California - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without - * fee is hereby granted, provided that the above copyright - * notice appear in all copies. The University of California - * makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without - * express or implied warranty. + * Copyright 1989 Regents of the University of California Permission to use, + * copy, modify, and distribute this software and its documentation for any + * purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies. The University of California makes + * no representations about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. */ #ifndef _UNISTD #define _UNISTD #include -#ifndef _TCL -# include "tcl.h" -#endif #ifndef NULL #define NULL 0 #endif /* - * Strict POSIX stuff goes here. Extensions go down below, in the - * ifndef _POSIX_SOURCE section. + * Strict POSIX stuff goes here. Extensions go down below, in the ifndef + * _POSIX_SOURCE section. */ -extern void _exit _ANSI_ARGS_((int status)); -extern int access _ANSI_ARGS_((CONST char *path, int mode)); -extern int chdir _ANSI_ARGS_((CONST char *path)); -extern int chown _ANSI_ARGS_((CONST char *path, uid_t owner, gid_t group)); -extern int close _ANSI_ARGS_((int fd)); -extern int dup _ANSI_ARGS_((int oldfd)); -extern int dup2 _ANSI_ARGS_((int oldfd, int newfd)); -extern int execl _ANSI_ARGS_((CONST char *path, ...)); -extern int execle _ANSI_ARGS_((CONST char *path, ...)); -extern int execlp _ANSI_ARGS_((CONST char *file, ...)); -extern int execv _ANSI_ARGS_((CONST char *path, char **argv)); -extern int execve _ANSI_ARGS_((CONST char *path, char **argv, char **envp)); -extern int execvp _ANSI_ARGS_((CONST char *file, char **argv)); -extern pid_t fork _ANSI_ARGS_((void)); -extern char *getcwd _ANSI_ARGS_((char *buf, size_t size)); -extern gid_t getegid _ANSI_ARGS_((void)); -extern uid_t geteuid _ANSI_ARGS_((void)); -extern gid_t getgid _ANSI_ARGS_((void)); -extern int getgroups _ANSI_ARGS_((int bufSize, int *buffer)); -extern pid_t getpid _ANSI_ARGS_((void)); -extern uid_t getuid _ANSI_ARGS_((void)); -extern int isatty _ANSI_ARGS_((int fd)); -extern long lseek _ANSI_ARGS_((int fd, long offset, int whence)); -extern int pipe _ANSI_ARGS_((int *fildes)); -extern int read _ANSI_ARGS_((int fd, char *buf, size_t size)); -extern int setgid _ANSI_ARGS_((gid_t group)); -extern int setuid _ANSI_ARGS_((uid_t user)); -extern unsigned sleep _ANSI_ARGS_ ((unsigned seconds)); -extern char *ttyname _ANSI_ARGS_((int fd)); -extern int unlink _ANSI_ARGS_((CONST char *path)); -extern int write _ANSI_ARGS_((int fd, CONST char *buf, size_t size)); +extern void _exit(int status); +extern int access(const char *path, int mode); +extern int chdir(const char *path); +extern int chown(const char *path, uid_t owner, gid_t group); +extern int close(int fd); +extern int dup(int oldfd); +extern int dup2(int oldfd, int newfd); +extern int execl(const char *path, ...); +extern int execle(const char *path, ...); +extern int execlp(const char *file, ...); +extern int execv(const char *path, char **argv); +extern int execve(const char *path, char **argv, char **envp); +extern int execvpw(const char *file, char **argv); +extern pid_t fork(void); +extern char * getcwd(char *buf, size_t size); +extern gid_t getegid(void); +extern uid_t geteuid(void); +extern gid_t getgid(void); +extern int getgroups(int bufSize, int *buffer); +extern pid_t getpid(void); +extern uid_t getuid(void); +extern int isatty(int fd); +extern long lseek(int fd, long offset, int whence); +extern int pipe(int *fildes); +extern int read(int fd, char *buf, size_t size); +extern int setgid(gid_t group); +extern int setuid(uid_t user); +extern unsigned sleep(unsigned seconds); +extern char * ttyname(int fd); +extern int unlink(const char *path); +extern int write(int fd, const char *buf, size_t size); #ifndef _POSIX_SOURCE -extern char *crypt _ANSI_ARGS_((CONST char *, CONST char *)); -extern int fchown _ANSI_ARGS_((int fd, uid_t owner, gid_t group)); -extern int flock _ANSI_ARGS_((int fd, int operation)); -extern int ftruncate _ANSI_ARGS_((int fd, unsigned long length)); -extern int ioctl _ANSI_ARGS_((int fd, int request, ...)); -extern int readlink _ANSI_ARGS_((CONST char *path, char *buf, int bufsize)); -extern int setegid _ANSI_ARGS_((gid_t group)); -extern int seteuid _ANSI_ARGS_((uid_t user)); -extern int setreuid _ANSI_ARGS_((int ruid, int euid)); -extern int symlink _ANSI_ARGS_((CONST char *, CONST char *)); -extern int ttyslot _ANSI_ARGS_((void)); -extern int truncate _ANSI_ARGS_((CONST char *path, unsigned long length)); -extern int vfork _ANSI_ARGS_((void)); +extern char * crypt(const char *, const char *); +extern int fchown(int fd, uid_t owner, gid_t group); +extern int flock(int fd, int operation); +extern int ftruncate(int fd, unsigned long length); +extern int ioctl(int fd, int request, ...); +extern int readlink(const char *path, char *buf, int bufsize); +extern int setegid(gid_t group); +extern int seteuidw(uid_t user); +extern int setreuid(int ruid, int euid); +extern int symlink(const char *, const char *); +extern int ttyslot(void); +extern int truncate(const char *path, unsigned long length); +extern int vfork(void); #endif /* _POSIX_SOURCE */ #endif /* _UNISTD */ - -- cgit v0.12 From 66c29096944ef5a69468c0fd188382deadcb0e03 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 27 Dec 2012 14:41:15 +0000 Subject: [Bug 3598580]: Tcl_ListObjReplace may release deleted elements too early Tests!? Where are the tests!?! They are in test listobj-11.1 --- ChangeLog | 5 +++++ generic/tclListObj.c | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 204275f..728b677 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-12-27 Jan Nijtmans + + * generic/tclListObj.c: [Bug 3598580]: Tcl_ListObjReplace may release + deleted elements too early + 2012-12-21 Jan Nijtmans * unix/dltest/pkgb.c: Turn pkgb.so into a Tcl9 interoperability test diff --git a/generic/tclListObj.c b/generic/tclListObj.c index fffe6a2..b4af98a 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -655,6 +655,10 @@ Tcl_ListObjReplace(interp, listPtr, first, count, objc, objv) count = 0; } + for (i = 0; i < objc; i++) { + Tcl_IncrRefCount(objv[i]); + } + numRequired = (numElems - count + objc); if (numRequired <= listRepPtr->maxElemCount) { /* @@ -689,7 +693,6 @@ Tcl_ListObjReplace(interp, listPtr, first, count, objc, objv) for (i = 0, j = first; i < objc; i++, j++) { elemPtrs[j] = objv[i]; - Tcl_IncrRefCount(objv[i]); } /* @@ -745,7 +748,6 @@ Tcl_ListObjReplace(interp, listPtr, first, count, objc, objv) for (i = 0, j = first; i < objc; i++, j++) { newPtrs[j] = objv[i]; - Tcl_IncrRefCount(objv[i]); } listRepPtr->elemCount = numRequired; -- cgit v0.12