diff options
author | dgp <dgp@users.sourceforge.net> | 2009-03-30 17:47:08 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2009-03-30 17:47:08 (GMT) |
commit | f92b558829c3d72d1ec0edd0e41477c9357cf8c8 (patch) | |
tree | c6772d718863ab5f2fcd7ed6a98641fec120511b /generic | |
parent | 3af212fe560067545be57a91ec8cd1065ec77eff (diff) | |
download | tcl-f92b558829c3d72d1ec0edd0e41477c9357cf8c8.zip tcl-f92b558829c3d72d1ec0edd0e41477c9357cf8c8.tar.gz tcl-f92b558829c3d72d1ec0edd0e41477c9357cf8c8.tar.bz2 |
* generic/tclStringObj.c: Added protections from invalid memory
* generic/tclTestObj.c: accesses when we append (some part of)
* tests/stringObj.test: a Tcl_Obj to itself. Added the
appendself and appendself2 subcommands to the [teststringobj] testing
command and added tests to the test suite. [Bug 2603158]
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclStringObj.c | 33 | ||||
-rw-r--r-- | generic/tclTestObj.c | 67 |
2 files changed, 97 insertions, 3 deletions
diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 32197a7..6490bc6 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -33,7 +33,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclStringObj.c,v 1.32.2.7 2009/03/21 02:53:18 dgp Exp $ */ + * RCS: @(#) $Id: tclStringObj.c,v 1.32.2.8 2009/03/30 17:47:09 dgp Exp $ */ #include "tclInt.h" @@ -1242,6 +1242,17 @@ AppendUnicodeToUnicodeRep(objPtr, unicode, appendNumChars) numChars = stringPtr->numChars + appendNumChars; if (STRING_UALLOC(numChars) >= stringPtr->uallocated) { + /* + * Protect against case where unicode points into the existing + * stringPtr->unicode array. Force it to follow any relocations + * due to the reallocs below. + */ + int offset = -1; + if (unicode >= stringPtr->unicode && unicode <= stringPtr->unicode + + 1 + stringPtr->uallocated / sizeof(Tcl_UniChar)) { + offset = unicode - stringPtr->unicode; + } + stringPtr->uallocated = STRING_UALLOC(2 * numChars); tmpString = (String *) attemptckrealloc((char *)stringPtr, STRING_SIZE(stringPtr->uallocated)); @@ -1254,6 +1265,11 @@ AppendUnicodeToUnicodeRep(objPtr, unicode, appendNumChars) } stringPtr = tmpString; SET_STRING(objPtr, stringPtr); + + /* Relocate unicode if needed; see above. */ + if (offset >= 0) { + unicode = stringPtr->unicode + offset; + } } /* @@ -1399,6 +1415,16 @@ AppendUtfToUtfRep(objPtr, bytes, numBytes) stringPtr = GET_STRING(objPtr); if (newLength > (int) stringPtr->allocated) { + /* + * Protect against case where unicode points into the existing + * stringPtr->unicode array. Force it to follow any relocations + * due to the reallocs below. + */ + int offset = -1; + if (bytes >= objPtr->bytes + && bytes <= objPtr->bytes + objPtr->length) { + offset = bytes - objPtr->bytes; + } /* * There isn't currently enough space in the string representation @@ -1419,6 +1445,11 @@ AppendUtfToUtfRep(objPtr, bytes, numBytes) Tcl_SetObjLength(objPtr, newLength + growth); } + + /* Relocate bytes if needed; see above. */ + if (offset >=0) { + bytes = objPtr->bytes + offset; + } } /* diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index 5c45d70..f9181a9 100644 --- a/generic/tclTestObj.c +++ b/generic/tclTestObj.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclTestObj.c,v 1.12 2002/12/04 13:09:24 vincentdarley Exp $ + * RCS: @(#) $Id: tclTestObj.c,v 1.12.2.1 2009/03/30 17:47:09 dgp Exp $ */ #include "tclInt.h" @@ -906,13 +906,14 @@ TeststringobjCmd(clientData, interp, objc, objv) Tcl_Obj *CONST objv[]; /* Argument objects. */ { int varIndex, option, i, length; + Tcl_UniChar *unicode; #define MAX_STRINGS 11 char *index, *string, *strings[MAX_STRINGS+1]; TestString *strPtr; static CONST char *options[] = { "append", "appendstrings", "get", "get2", "length", "length2", "set", "set2", "setlength", "ualloc", "getunicode", - (char *) NULL + "appendself", "appendself2", (char *) NULL }; if (objc < 3) { @@ -1080,6 +1081,68 @@ TeststringobjCmd(clientData, interp, objc, objv) } Tcl_GetUnicodeFromObj(varPtr[varIndex], NULL); break; + case 11: /* appendself */ + if (objc != 4) { + goto wrongNumArgs; + } + if (varPtr[varIndex] == NULL) { + SetVarToObj(varIndex, Tcl_NewObj()); + } + + /* + * If the object bound to variable "varIndex" is shared, we must + * "copy on write" and append to a copy of the object. + */ + + if (Tcl_IsShared(varPtr[varIndex])) { + SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); + } + + string = Tcl_GetStringFromObj(varPtr[varIndex], &length); + + if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) { + return TCL_ERROR; + } + if ((i < 0) || (i > length)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "index value out of range", -1)); + return TCL_ERROR; + } + + Tcl_AppendToObj(varPtr[varIndex], string + i, length - i); + Tcl_SetObjResult(interp, varPtr[varIndex]); + break; + case 12: /* appendself2 */ + if (objc != 4) { + goto wrongNumArgs; + } + if (varPtr[varIndex] == NULL) { + SetVarToObj(varIndex, Tcl_NewObj()); + } + + /* + * If the object bound to variable "varIndex" is shared, we must + * "copy on write" and append to a copy of the object. + */ + + if (Tcl_IsShared(varPtr[varIndex])) { + SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); + } + + unicode = Tcl_GetUnicodeFromObj(varPtr[varIndex], &length); + + if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) { + return TCL_ERROR; + } + if ((i < 0) || (i > length)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "index value out of range", -1)); + return TCL_ERROR; + } + + Tcl_AppendUnicodeToObj(varPtr[varIndex], unicode + i, length - i); + Tcl_SetObjResult(interp, varPtr[varIndex]); + break; } return TCL_OK; |