From 2c04db5191597787a9dd16c98a1fa33ec46d1405 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 30 Jun 2008 02:55:00 +0000 Subject: merge updates from 8.5 branch --- ChangeLog | 20 ++++++++++ doc/IntObj.3 | 8 ++-- doc/Object.3 | 6 +-- doc/ObjectType.3 | 110 ++++++++++++++++++++++++++++++++++----------------- generic/tclPathObj.c | 19 ++++++--- unix/Makefile.in | 4 +- 6 files changed, 117 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index 503dcba..77d92b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2008-06-29 Don Porter + + * doc/ObjectType.3: Updated documentation of the Tcl_ObjType + struct to match expectations of Tcl 8.5 [Bug 1917650]. + + * generic/tclPathObj.c: Plug memory leak in [Bug 1999176] fix. Thanks + Rolf Ade for detecting. + +2008-06-28 Don Porter + + * generic/tclPathObj.c: Plug memory leak in [Bug 1972879] fix. Thanks + Rolf Ade for detecting and Dan Steffen for the fix [Bug 2004654]. + +2008-06-26 Andreas Kupries + + * unix/Makefile.in: Followup to my change of 2008-06-25, make code + generated by the Makefile and put into the installd tm.tcl + conditional on interpreter safeness as well. Thanks to Daniel + Steffen for reminding me of that code. + 2008-06-25 Don Porter *** 8.5.3 TAGGED FOR RELEASE *** diff --git a/doc/IntObj.3 b/doc/IntObj.3 index 0a34ea4..5d69303 100644 --- a/doc/IntObj.3 +++ b/doc/IntObj.3 @@ -4,7 +4,7 @@ '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" RCS: @(#) $Id: IntObj.3,v 1.11.6.1 2007/12/13 06:24:10 dgp Exp $ +'\" RCS: @(#) $Id: IntObj.3,v 1.11.6.2 2008/06/30 02:55:00 dgp Exp $ '\" .so man.macros .TH Tcl_IntObj 3 8.5 Tcl "Tcl Library Procedures" @@ -137,15 +137,15 @@ then \fBTCL_ERROR\fR is returned, and if \fIinterp\fR is non-NULL, an error message is left in \fIinterp\fR. The \fBTcl_ObjType\fR of \fIobjPtr\fR may be changed to make subsequent calls to the same routine more efficient. Unlike the other functions, -\fBTcl_TakeGetBignumFromObj\fR may set the content of the Tcl object +\fBTcl_TakeBignumFromObj\fR may set the content of the Tcl object \fIobjPtr\fR to an empty string in the process of retrieving the multiple-precision integer value. .PP The choice between \fBTcl_GetBignumFromObj\fR and -\fBTcl_TakeGetBignumFromObj\fR is governed by how the caller will +\fBTcl_TakeBignumFromObj\fR is governed by how the caller will continue to use \fIobjPtr\fR. If after the \fBmp_int\fR value is retrieved from \fIobjPtr\fR, the caller will make no more -use of \fIobjPtr\fR, then using \fBTcl_TakeGetBignumFromObj\fR +use of \fIobjPtr\fR, then using \fBTcl_TakeBignumFromObj\fR permits Tcl to detect when an unshared \fIobjPtr\fR permits the value to be moved instead of copied, which should be more efficient. If anything later in the caller requires diff --git a/doc/Object.3 b/doc/Object.3 index 8d5da1a..55678bd 100644 --- a/doc/Object.3 +++ b/doc/Object.3 @@ -4,7 +4,7 @@ '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" RCS: @(#) $Id: Object.3,v 1.15.6.2 2007/11/01 16:25:46 dgp Exp $ +'\" RCS: @(#) $Id: Object.3,v 1.15.6.3 2008/06/30 02:55:00 dgp Exp $ '\" .so man.macros .TH Tcl_Obj 3 8.5 Tcl "Tcl Library Procedures" @@ -102,10 +102,10 @@ reclaim an object's storage. .PP Tcl objects are typed. An object's internal representation is controlled by its type. -Seven types are predefined in the Tcl core +Several types are predefined in the Tcl core including integer, double, list, and bytecode. Extension writers can extend the set of types -by using the procedure \fBTcl_RegisterObjType\fR . +by defining their own \fBTcl_ObjType\fR structs. .SH "THE TCL_OBJ STRUCTURE" .PP Each Tcl object is represented by a \fBTcl_Obj\fR structure diff --git a/doc/ObjectType.3 b/doc/ObjectType.3 index 0e81777..835383e 100644 --- a/doc/ObjectType.3 +++ b/doc/ObjectType.3 @@ -4,7 +4,7 @@ '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" RCS: @(#) $Id: ObjectType.3,v 1.13.6.2 2007/11/01 16:25:46 dgp Exp $ +'\" RCS: @(#) $Id: ObjectType.3,v 1.13.6.3 2008/06/30 02:55:00 dgp Exp $ '\" .so man.macros .TH Tcl_ObjType 3 8.0 Tcl "Tcl Library Procedures" @@ -49,7 +49,10 @@ They are used to register new object types, look up types, and force conversions from one type to another. .PP \fBTcl_RegisterObjType\fR registers a new Tcl object type -in the table of all object types supported by Tcl. +in the table of all object types that \fBTcl_GetObjType\fR +can look up by name. There are other object types supported by Tcl +as well, which Tcl chooses not to register. Extensions can likewise +choose to register the object types they create or not. The argument \fItypePtr\fR points to a Tcl_ObjType structure that describes the new type by giving its name and by supplying pointers to four procedures @@ -60,11 +63,11 @@ it is replaced with the new type. The Tcl_ObjType structure is described in the section \fBTHE TCL_OBJTYPE STRUCTURE\fR below. .PP -\fBTcl_GetObjType\fR returns a pointer to the Tcl_ObjType +\fBTcl_GetObjType\fR returns a pointer to the registered Tcl_ObjType with name \fItypeName\fR. It returns NULL if no type with that name is registered. .PP -\fBTcl_AppendAllObjTypes\fR appends the name of each object type +\fBTcl_AppendAllObjTypes\fR appends the name of each registered object type as a list element onto the Tcl object referenced by \fIobjPtr\fR. The return value is \fBTCL_OK\fR unless there was an error converting \fIobjPtr\fR to a list object; @@ -74,7 +77,8 @@ in that case \fBTCL_ERROR\fR is returned. if possible. It creates a new internal representation for \fIobjPtr\fR appropriate for the target type \fItypePtr\fR -and sets its \fItypePtr\fR member to that type. +and sets its \fItypePtr\fR member as determined by calling the +\fItypePtr->setFromAnyProc\fR routine. Any internal representation for \fIobjPtr\fR's old type is freed. If an error occurs during conversion, it returns \fBTCL_ERROR\fR and leaves an error message in the result object for \fIinterp\fR @@ -82,12 +86,23 @@ unless \fIinterp\fR is NULL. Otherwise, it returns \fBTCL_OK\fR. Passing a NULL \fIinterp\fR allows this procedure to be used as a test whether the conversion can be done (and in fact was done). +.VS 8.5 +.PP +In many cases, the \fItypePtt->setFromAnyProc\fR routine will +set \fIobjPtr->typePtr\fR to the argument value \fItypePtr\fR, +but that is no longer guaranteed. The \fIsetFromAnyProc\fR is +free to set the internal representation for \fIobjPtr\fR to make +use of another related Tcl_ObjType, if it sees fit. +.VE 8.5 .SH "THE TCL_OBJTYPE STRUCTURE" .PP Extension writers can define new object types by defining four -procedures, -initializing a Tcl_ObjType structure to describe the type, -and calling \fBTcl_RegisterObjType\fR. +procedures and +initializing a Tcl_ObjType structure to describe the type. +Extension writers may also pass a pointer to their Tcl_ObjType +structire to \fBTcl_RegisterObjType\fR if they wish to permit +other extensions to look up their Tcl_ObjType by name with +the \fBTcl_GetObjType\fR routine. The \fBTcl_ObjType\fR structure is defined as follows: .PP .CS @@ -102,8 +117,9 @@ typedef struct Tcl_ObjType { .SS "THE NAME FIELD" .PP The \fIname\fR member describes the name of the type, e.g. \fBint\fR. -Extension writers can look up an object type using its name -with the \fBTcl_GetObjType\fR procedure. +When a type is registered, this is the name used by callers +of \fBTcl_GetObjType\fR to lookup the type. For unregistered +types, the \fIname\fR field is primarily of value for debugging. The remaining four members are pointers to procedures called by the generic Tcl object code: .SS "THE SETFROMANYPROC FIELD" @@ -124,22 +140,32 @@ unless \fIinterp\fR is NULL. If \fIsetFromAnyProc\fR is successful, it stores the new internal representation, sets \fIobjPtr\fR's \fItypePtr\fR member to point to -\fIsetFromAnyProc\fR's \fBTcl_ObjType\fR, and returns \fBTCL_OK\fR. +the \fBTcl_ObjType\fR struct corresponding to the new +internal representation, and returns \fBTCL_OK\fR. Before setting the new internal representation, the \fIsetFromAnyProc\fR must free any internal representation of \fIobjPtr\fR's old type; it does this by calling the old type's \fIfreeIntRepProc\fR if it is not NULL. -As an example, the \fIsetFromAnyProc\fR for the built-in Tcl integer type +.PP +As an example, the \fIsetFromAnyProc\fR for the built-in Tcl list type gets an up-to-date string representation for \fIobjPtr\fR by calling \fBTcl_GetStringFromObj\fR. -It parses the string to obtain an integer and, -if this succeeds, -stores the integer in \fIobjPtr\fR's internal representation -and sets \fIobjPtr\fR's \fItypePtr\fR member to point to the integer type's +It parses the string to verify it is in a valid list format and +to obtain each element value in the list, and, if this succeeds, +stores the list elements in \fIobjPtr\fR's internal representation +and sets \fIobjPtr\fR's \fItypePtr\fR member to point to the list type's Tcl_ObjType structure. +.PP Do not release \fIobjPtr\fR's old internal representation unless you replace it with a new one or reset the \fItypePtr\fR member to NULL. +.PP +The \fIsetFromAnyProc\fR member may be set to NULL, if the routines +making use of the internal representation have no need to derive that +internal representation from an arbitrary string value. However, in +this case, passing a pointer to the type to Tcl_ConvertToType() will +lead to a panic, so to avoid this possibility, the type +should \fInot\fR be registered. .SS "THE UPDATESTRINGPROC FIELD" .PP The \fIupdateStringProc\fR member contains the address of a function @@ -153,17 +179,27 @@ typedef void (Tcl_UpdateStringProc) (Tcl_Obj *\fIobjPtr\fR); \fIobjPtr\fR's \fIbytes\fR member is always NULL when it is called. It must always set \fIbytes\fR non-NULL before returning. We require the string representation's byte array -to have a null after the last byte, at offset \fIlength\fR; -this allows string representations that do not contain null bytes +to have a null after the last byte, at offset \fIlength\fR, +and to have no null bytes before that; this allows string representations to be treated as conventional null character-terminated C strings. +These restrictions are easily met by using Tcl's internal UTF encoding +for the string representation, same as one would do for other +Tcl routines accepting string values as arguments. Storage for the byte array must be allocated in the heap by \fBTcl_Alloc\fR or \fBckalloc\fR. Note that \fIupdateStringProc\fRs must allocate enough storage for the string's bytes and the terminating null byte. -The \fIupdateStringProc\fR for Tcl's built-in list type, for example, -builds an array of strings for each element object -and then calls \fBTcl_Merge\fR -to construct a string with proper Tcl list structure. -It stores this string as the list object's string representation. +.PP +The \fIupdateStringProc\fR for Tcl's built-in double type, for example, +calls Tcl_PrintDouble to write to a buffer of size TCL_DOUBLE_SPACE, +then allocates and copies the string representation to just enough +space to hold it. A pointer to the allocated space is stored in +the \fIbytes\fR member. +.PP +The \fIupdateStringProc\fR member may be set to NULL, if the routines +making use of the internal representation are written so that the +string representation is never invalidated. Failure to meet this +obligation will lead to panics or crashes when \fBTcl_GetStringFromObj\fR +or other similar routines ask for the string representation. .SS "THE DUPINTREPPROC FIELD" .PP The \fIdupIntRepProc\fR member contains the address of a function @@ -180,12 +216,12 @@ Before the call, \fIsrcPtr\fR's internal representation is valid and \fIdupPtr\fR's is not. \fIsrcPtr\fR's object type determines what copying its internal representation means. +.PP For example, the \fIdupIntRepProc\fR for the Tcl integer type simply copies an integer. -The built-in list type's \fIdupIntRepProc\fR -allocates a new array that points at the original element objects; -the elements are shared between the two lists -(and their reference counts are incremented to reflect the new references). +The built-in list type's \fIdupIntRepProc\fR uses a far more +sophisticated scheme to continue sharing storage as much as it +reasonably can. .SS "THE FREEINTREPPROC FIELD" .PP The \fIfreeIntRepProc\fR member contains the address of a function @@ -198,17 +234,19 @@ typedef void (Tcl_FreeInternalRepProc) (Tcl_Obj *\fIobjPtr\fR); The \fIfreeIntRepProc\fR function can deallocate the storage for the object's internal representation and do other type-specific processing necessary when an object is freed. -For example, Tcl list objects have an \fIinternalRep.otherValuePtr\fR -that points to an array of pointers to each element in the list. -The list type's \fIfreeIntRepProc\fR decrements -the reference count for each element object -(since the list will no longer refer to those objects), -then deallocates the storage for the array of pointers. +.PP +For example, the list type's \fIfreeIntRepProc\fR respects +the storage sharing scheme established by the \fIdupIntRepProc\fR +so that it only frees storage when the last object sharing it +is being freed. +.PP The \fIfreeIntRepProc\fR member can be set to NULL to indicate that the internal representation does not require freeing. -The \fIfreeIntRepProc\fR implementation should not access the -\fIbytes\fR member of the object, as this may potentially have already -been deleted. +The \fIfreeIntRepProc\fR implementation must not access the +\fIbytes\fR member of the object, since Tcl makes its own internal +uses of that field during object deletion. The defined tasks for +the \fIfreeIntRepProc\fR have no need to consult the \fIbytes\fR +member. .SH "SEE ALSO" Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount .SH KEYWORDS diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c index 59ccfbe..ca4ba5c 100644 --- a/generic/tclPathObj.c +++ b/generic/tclPathObj.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclPathObj.c,v 1.63.2.2 2008/06/25 15:56:13 dgp Exp $ + * RCS: @(#) $Id: tclPathObj.c,v 1.63.2.3 2008/06/30 02:55:00 dgp Exp $ */ #include "tclInt.h" @@ -1602,10 +1602,15 @@ Tcl_FSGetTranslatedPath( * translated version of cwdPtr to normPathPtr, we'll get the * translated result we need, and can store it for future use. */ - retObj = Tcl_FSJoinToPath(Tcl_FSGetTranslatedPath(interp, - srcFsPathPtr->cwdPtr), 1, &(srcFsPathPtr->normPathPtr)); + + Tcl_Obj *translatedCwdPtr = Tcl_FSGetTranslatedPath(interp, + srcFsPathPtr->cwdPtr); + + retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1, + &(srcFsPathPtr->normPathPtr)); srcFsPathPtr->translatedPathPtr = retObj; Tcl_IncrRefCount(retObj); + Tcl_DecrRefCount(translatedCwdPtr); } else { /* * It is a pure absolute, normalized path object. This is @@ -1874,6 +1879,7 @@ Tcl_FSGetNormalizedPath( if (fsPathPtr->normPathPtr == NULL) { ClientData clientData = NULL; Tcl_Obj *useThisCwd = NULL; + int pureNormalized = 1; /* * Since normPathPtr is NULL, but this is a valid path object, we know @@ -1922,6 +1928,7 @@ Tcl_FSGetNormalizedPath( return NULL; } + pureNormalized = 0; Tcl_DecrRefCount(absolutePath); absolutePath = Tcl_FSJoinToPath(useThisCwd, 1, &absolutePath); Tcl_IncrRefCount(absolutePath); @@ -1941,6 +1948,7 @@ Tcl_FSGetNormalizedPath( if (absolutePath == NULL) { return NULL; } + pureNormalized = 0; #endif /* __WIN32__ */ } } @@ -1962,7 +1970,7 @@ Tcl_FSGetNormalizedPath( * is an absolute path). */ - if (useThisCwd == NULL) { + if (pureNormalized) { if (!strcmp(TclGetString(fsPathPtr->normPathPtr), TclGetString(pathPtr))) { /* @@ -1978,7 +1986,8 @@ Tcl_FSGetNormalizedPath( fsPathPtr->normPathPtr = pathPtr; } - } else { + } + if (useThisCwd != NULL) { /* * We just need to free an object we allocated above for relative * paths (this was returned by Tcl_FSJoinToPath above), and then diff --git a/unix/Makefile.in b/unix/Makefile.in index d96c8c0..fc6bf1b 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -4,7 +4,7 @@ # "./configure", which is a configuration script generated by the "autoconf" # program (constructs like "@foo@" will get replaced in the actual Makefile. # -# RCS: @(#) $Id: Makefile.in,v 1.207.2.16 2008/06/25 15:56:20 dgp Exp $ +# RCS: @(#) $Id: Makefile.in,v 1.207.2.17 2008/06/30 02:55:00 dgp Exp $ VERSION = @TCL_VERSION@ MAJOR_VERSION = @TCL_MAJOR_VERSION@ @@ -805,7 +805,7 @@ install-libraries: libraries $(INSTALL_TZDATA) install-msgs done; @if [ -n "$(TCL_MODULE_PATH)" -a -f $(TOP_DIR)/library/tm.tcl ]; then \ echo "Customizing tcl module path"; \ - echo "::tcl::tm::roots {$(TCL_MODULE_PATH)}" >> \ + echo "if {![interp issafe]} { ::tcl::tm::roots {$(TCL_MODULE_PATH)} }" >> \ "$(SCRIPT_INSTALL_DIR)"/tm.tcl; \ fi -- cgit v0.12