diff options
-rw-r--r--[-rwxr-xr-x] | compat/zlib/win32/zdll.lib | bin | 17152 -> 17152 bytes | |||
-rw-r--r--[-rwxr-xr-x] | compat/zlib/zlib2ansi | 0 | ||||
-rw-r--r-- | generic/tclBinary.c | 152 | ||||
-rw-r--r-- | generic/tclCmdAH.c | 5 | ||||
-rw-r--r-- | generic/tclDictObj.c | 3 | ||||
-rw-r--r-- | generic/tclIO.c | 20 | ||||
-rw-r--r-- | generic/tclIOGT.c | 27 | ||||
-rw-r--r-- | generic/tclIORChan.c | 11 | ||||
-rw-r--r-- | generic/tclInt.h | 2 | ||||
-rw-r--r-- | generic/tclObj.c | 1 | ||||
-rw-r--r-- | generic/tclTest.c | 4 | ||||
-rw-r--r-- | tests/execute.test | 2 | ||||
-rw-r--r-- | tests/obj.test | 5 | ||||
-rw-r--r-- | tests/utf.test | 4 |
14 files changed, 164 insertions, 72 deletions
diff --git a/compat/zlib/win32/zdll.lib b/compat/zlib/win32/zdll.lib Binary files differindex a3e9a39..a3e9a39 100755..100644 --- a/compat/zlib/win32/zdll.lib +++ b/compat/zlib/win32/zdll.lib diff --git a/compat/zlib/zlib2ansi b/compat/zlib/zlib2ansi index 15e3e16..15e3e16 100755..100644 --- a/compat/zlib/zlib2ansi +++ b/compat/zlib/zlib2ansi diff --git a/generic/tclBinary.c b/generic/tclBinary.c index 2d170f9..8edbd0a 100644 --- a/generic/tclBinary.c +++ b/generic/tclBinary.c @@ -160,10 +160,6 @@ static const EnsembleImplMap decodeMap[] = { * without loss or damage. Such values are useful for things like * encoded strings or Tk images to name just two. * - * It's strange to have two Tcl_ObjTypes in place for this task when - * one would do, so a bit of detail and history how we got to this point - * and where we might go from here. - * * A bytearray is an ordered sequence of bytes. Each byte is an integer * value in the range [0-255]. To be a Tcl value type, we need a way to * encode each value in the value set as a Tcl string. The simplest @@ -252,14 +248,6 @@ static const Tcl_ObjType properByteArrayType = { NULL }; -const Tcl_ObjType tclByteArrayType = { - "bytearray", - FreeByteArrayInternalRep, - DupByteArrayInternalRep, - NULL, - SetByteArrayFromAny -}; - /* * The following structure is the internal rep for a ByteArray object. Keeps * track of how much memory has been used and how much has been allocated for @@ -450,9 +438,13 @@ Tcl_GetByteArrayFromObj( { ByteArray *baPtr; - if ((objPtr->typePtr != &properByteArrayType) - && (objPtr->typePtr != &tclByteArrayType)) { - SetByteArrayFromAny(NULL, objPtr); + if (objPtr->typePtr != &properByteArrayType) { + if (TCL_ERROR == SetByteArrayFromAny(NULL, objPtr)) { + if (lengthPtr != NULL) { + *lengthPtr = 0; + } + return NULL; + } } baPtr = GET_BYTEARRAY(objPtr); @@ -494,9 +486,12 @@ Tcl_SetByteArrayLength( if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength"); } - if ((objPtr->typePtr != &properByteArrayType) - && (objPtr->typePtr != &tclByteArrayType)) { - SetByteArrayFromAny(NULL, objPtr); + if (objPtr->typePtr != &properByteArrayType) { + if (length == 0) { + Tcl_SetByteArrayObj(objPtr, NULL, 0); + } else if (TCL_ERROR == SetByteArrayFromAny(NULL, objPtr)) { + return NULL; + } } byteArrayPtr = GET_BYTEARRAY(objPtr); @@ -527,40 +522,74 @@ Tcl_SetByteArrayLength( */ static int +MakeByteArray( + Tcl_Obj *objPtr, + int earlyOut, + ByteArray **byteArrayPtrPtr) +{ + int length, proper = 1; + unsigned char *dst; + const char *src = TclGetStringFromObj(objPtr, &length); + ByteArray *byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length)); + const char *srcEnd = src + length; + + for (dst = byteArrayPtr->bytes; src < srcEnd; ) { + Tcl_UniChar ch = 0; + + src += TclUtfToUniChar(src, &ch); + if (ch > 255) { + proper = 0; + if (earlyOut) { + ckfree(byteArrayPtr); + *byteArrayPtrPtr = NULL; + return proper; + } + } + *dst++ = UCHAR(ch); + } + byteArrayPtr->used = dst - byteArrayPtr->bytes; + byteArrayPtr->allocated = length; + + *byteArrayPtrPtr = byteArrayPtr; + return proper; +} + +Tcl_Obj * +TclNarrowToBytes( + Tcl_Obj *objPtr) +{ + if (objPtr->typePtr != &properByteArrayType) { + ByteArray *byteArrayPtr; + + if (0 == MakeByteArray(objPtr, 0, &byteArrayPtr)) { + objPtr = Tcl_NewObj(); + TclInvalidateStringRep(objPtr); + } + TclFreeIntRep(objPtr); + objPtr->typePtr = &properByteArrayType; + SET_BYTEARRAY(objPtr, byteArrayPtr); + } + Tcl_IncrRefCount(objPtr); + return objPtr; +} + +static int SetByteArrayFromAny( Tcl_Interp *interp, /* Not used. */ Tcl_Obj *objPtr) /* The object to convert to type ByteArray. */ { - size_t length; - int improper = 0; - const char *src, *srcEnd; - unsigned char *dst; ByteArray *byteArrayPtr; - Tcl_UniChar ch = 0; if (objPtr->typePtr == &properByteArrayType) { return TCL_OK; } - if (objPtr->typePtr == &tclByteArrayType) { - return TCL_OK; - } - - src = TclGetString(objPtr); - length = objPtr->length; - srcEnd = src + length; - byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length)); - for (dst = byteArrayPtr->bytes; src < srcEnd; ) { - src += TclUtfToUniChar(src, &ch); - improper = improper || (ch > 255); - *dst++ = UCHAR(ch); + if (0 == MakeByteArray(objPtr, 1, &byteArrayPtr)) { + return TCL_ERROR; } - byteArrayPtr->used = dst - byteArrayPtr->bytes; - byteArrayPtr->allocated = length; - TclFreeIntRep(objPtr); - objPtr->typePtr = improper ? &tclByteArrayType : &properByteArrayType; + objPtr->typePtr = &properByteArrayType; SET_BYTEARRAY(objPtr, byteArrayPtr); return TCL_OK; } @@ -731,9 +760,10 @@ TclAppendBytesToByteArray( /* Append zero bytes is a no-op. */ return; } - if ((objPtr->typePtr != &properByteArrayType) - && (objPtr->typePtr != &tclByteArrayType)) { - SetByteArrayFromAny(NULL, objPtr); + if (objPtr->typePtr != &properByteArrayType) { + if (TCL_ERROR == SetByteArrayFromAny(NULL, objPtr)) { + Tcl_Panic("attempt to append bytes to non-bytearray"); + } } byteArrayPtr = GET_BYTEARRAY(objPtr); @@ -888,7 +918,9 @@ BinaryFormatCmd( goto badIndex; } if (count == BINARY_ALL) { - Tcl_GetByteArrayFromObj(objv[arg], &count); + Tcl_Obj *copy = TclNarrowToBytes(objv[arg]); + Tcl_GetByteArrayFromObj(copy, &count); + Tcl_DecrRefCount(copy); } else if (count == BINARY_NOCOUNT) { count = 1; } @@ -1051,8 +1083,9 @@ BinaryFormatCmd( case 'A': { char pad = (char) (cmd == 'a' ? '\0' : ' '); unsigned char *bytes; + Tcl_Obj *copy = TclNarrowToBytes(objv[arg++]); - bytes = Tcl_GetByteArrayFromObj(objv[arg++], &length); + bytes = Tcl_GetByteArrayFromObj(copy, &length); if (count == BINARY_ALL) { count = length; @@ -1066,6 +1099,7 @@ BinaryFormatCmd( memset(cursor + length, pad, (size_t) (count - length)); } cursor += count; + Tcl_DecrRefCount(copy); break; } case 'b': @@ -1363,9 +1397,13 @@ BinaryScanCmd( "value formatString ?varName ...?"); return TCL_ERROR; } + buffer = Tcl_GetByteArrayFromObj(objv[1], &length); + if (buffer == NULL) { + Tcl_AppendResult(interp, "binary scan expects bytes", NULL); + return TCL_ERROR; + } numberCachePtr = &numberCacheHash; Tcl_InitHashTable(numberCachePtr, TCL_ONE_WORD_KEYS); - buffer = Tcl_GetByteArrayFromObj(objv[1], &length); format = TclGetString(objv[2]); arg = 3; offset = 0; @@ -2412,8 +2450,13 @@ BinaryEncodeHex( return TCL_ERROR; } - TclNewObj(resultObj); data = Tcl_GetByteArrayFromObj(objv[1], &count); + if (data == NULL) { + Tcl_AppendResult(interp, "binary encode expects bytes", NULL); + return TCL_ERROR; + } + + TclNewObj(resultObj); cursor = Tcl_SetByteArrayLength(resultObj, count * 2); for (offset = 0; offset < count; ++offset) { *cursor++ = HexDigits[((data[offset] >> 4) & 0x0f)]; @@ -2606,8 +2649,12 @@ BinaryEncode64( } } - resultObj = Tcl_NewObj(); data = Tcl_GetByteArrayFromObj(objv[objc-1], &count); + if (data == NULL) { + Tcl_AppendResult(interp, "binary encode expects bytes", NULL); + return TCL_ERROR; + } + resultObj = Tcl_NewObj(); if (count > 0) { size = (((count * 4) / 3) + 3) & ~3; /* ensure 4 byte chunks */ if (maxlen > 0 && size > maxlen) { @@ -2706,6 +2753,11 @@ BinaryEncodeUu( break; case OPT_WRAPCHAR: wrapchar = Tcl_GetByteArrayFromObj(objv[i+1], &wrapcharlen); + if (wrapchar == NULL) { + Tcl_AppendResult(interp, + "binary encode -wrapchar expects bytes", NULL); + return TCL_ERROR; + } break; } } @@ -2715,9 +2767,13 @@ BinaryEncodeUu( * enough". */ - resultObj = Tcl_NewObj(); offset = 0; data = Tcl_GetByteArrayFromObj(objv[objc-1], &count); + if (data == NULL) { + Tcl_AppendResult(interp, "binary encode expects bytes", NULL); + return TCL_ERROR; + } + resultObj = Tcl_NewObj(); rawLength = (lineLength - 1) * 3 / 4; start = cursor = Tcl_SetByteArrayLength(resultObj, (lineLength + wrapcharlen) * diff --git a/generic/tclCmdAH.c b/generic/tclCmdAH.c index f904d66..6f49659 100644 --- a/generic/tclCmdAH.c +++ b/generic/tclCmdAH.c @@ -616,6 +616,11 @@ EncodingConvertfromObjCmd( * Convert the string into a byte array in 'ds' */ bytesPtr = (char *) Tcl_GetByteArrayFromObj(data, &length); + if (bytesPtr == NULL) { + Tcl_AppendResult(interp, "encoding conversion expects bytes", NULL); + Tcl_FreeEncoding(encoding); + return TCL_ERROR; + } Tcl_ExternalToUtfDString(encoding, bytesPtr, length, &ds); /* diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c index d6211cd..eaee244 100644 --- a/generic/tclDictObj.c +++ b/generic/tclDictObj.c @@ -492,7 +492,8 @@ UpdateStringOfDict( Dict *dict = DICT(dictPtr); ChainEntry *cPtr; Tcl_Obj *keyPtr, *valuePtr; - size_t i, length, bytesNeeded = 0; + size_t i, length; + int bytesNeeded = 0; const char *elem; char *dst; diff --git a/generic/tclIO.c b/generic/tclIO.c index 8fb5a4a..f3d495f 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -4101,7 +4101,7 @@ Tcl_WriteChars( Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; /* State info for channel */ int result; - Tcl_Obj *objPtr; + Tcl_Obj *objPtr, *copy; if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) { return -1; @@ -4128,9 +4128,11 @@ Tcl_WriteChars( } objPtr = Tcl_NewStringObj(src, len); - src = (char *) Tcl_GetByteArrayFromObj(objPtr, &len); - result = WriteBytes(chanPtr, src, len); + copy = TclNarrowToBytes(objPtr); + src = (char *) Tcl_GetByteArrayFromObj(copy, &len); TclDecrRefCount(objPtr); + result = WriteBytes(chanPtr, src, len); + TclDecrRefCount(copy); return result; } @@ -4180,8 +4182,13 @@ Tcl_WriteObj( return -1; } if (statePtr->encoding == NULL) { - src = (char *) Tcl_GetByteArrayFromObj(objPtr, &srcLen); - return WriteBytes(chanPtr, src, srcLen); + int result; + Tcl_Obj *copy = TclNarrowToBytes(objPtr); + + src = (char *) Tcl_GetByteArrayFromObj(copy, &srcLen); + result = WriteBytes(chanPtr, src, srcLen); + Tcl_DecrRefCount(copy); + return result; } else { src = TclGetStringFromObj(objPtr, &srcLen); return WriteChars(chanPtr, src, srcLen); @@ -4539,7 +4546,8 @@ Tcl_GetsObj( if ((statePtr->encoding == NULL) && ((statePtr->inputTranslation == TCL_TRANSLATE_LF) - || (statePtr->inputTranslation == TCL_TRANSLATE_CR))) { + || (statePtr->inputTranslation == TCL_TRANSLATE_CR)) + && Tcl_GetByteArrayFromObj(objPtr, NULL) != NULL) { return TclGetsObjBinary(chan, objPtr); } diff --git a/generic/tclIOGT.c b/generic/tclIOGT.c index c1e8c44..5c40212 100644 --- a/generic/tclIOGT.c +++ b/generic/tclIOGT.c @@ -444,9 +444,12 @@ ExecuteCallback( } resObj = Tcl_GetObjResult(eval); resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen); - Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self), (char *) resBuf, - resLen); - break; + if (resBuf) { + Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self), + (char *) resBuf, resLen); + break; + } + goto nonBytes; case TRANSMIT_SELF: if (dataPtr->self == NULL) { @@ -454,14 +457,24 @@ ExecuteCallback( } resObj = Tcl_GetObjResult(eval); resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen); - Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen); - break; + if (resBuf) { + Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen); + break; + } + goto nonBytes; case TRANSMIT_IBUF: resObj = Tcl_GetObjResult(eval); resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen); - ResultAdd(&dataPtr->result, resBuf, resLen); - break; + if (resBuf) { + ResultAdd(&dataPtr->result, resBuf, resLen); + break; + } + nonBytes: + Tcl_AppendResult(interp, "chan transform callback received non-bytes", + NULL); + Tcl_Release(eval); + return TCL_ERROR; case TRANSMIT_NUM: /* diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index 8e1496d..7c293ff 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -448,6 +448,7 @@ static void MarkDead(ReflectedChannel *rcPtr); */ static const char *msg_read_toomuch = "{read delivered more than requested}"; +static const char *msg_read_nonbyte = "{read delivered nonbyte result}"; static const char *msg_write_toomuch = "{write wrote more than requested}"; static const char *msg_write_nothing = "{write wrote nothing}"; static const char *msg_seek_beforestart = "{Tried to seek before origin}"; @@ -1318,7 +1319,10 @@ ReflectInput( bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); - if (toRead < bytec) { + if (bytev == NULL) { + SetChannelErrorStr(rcPtr->chan, msg_read_nonbyte); + goto invalid; + } else if (toRead < bytec) { SetChannelErrorStr(rcPtr->chan, msg_read_toomuch); goto invalid; } @@ -3003,7 +3007,10 @@ ForwardProc( bytev = Tcl_GetByteArrayFromObj(resObj, &bytec); - if (paramPtr->input.toRead < bytec) { + if (bytev == NULL) { + ForwardSetStaticError(paramPtr, msg_read_nonbyte); + paramPtr->input.toRead = -1; + } else if (paramPtr->input.toRead < bytec) { ForwardSetStaticError(paramPtr, msg_read_toomuch); paramPtr->input.toRead = -1; } else { diff --git a/generic/tclInt.h b/generic/tclInt.h index 367c76b..c4c390f 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2644,7 +2644,6 @@ MODULE_SCOPE ClientData tclTimeClientData; MODULE_SCOPE const Tcl_ObjType tclBignumType; MODULE_SCOPE const Tcl_ObjType tclBooleanType; -MODULE_SCOPE const Tcl_ObjType tclByteArrayType; MODULE_SCOPE const Tcl_ObjType tclByteCodeType; MODULE_SCOPE const Tcl_ObjType tclDoubleType; MODULE_SCOPE const Tcl_ObjType tclEndOffsetType; @@ -2977,6 +2976,7 @@ MODULE_SCOPE int TclMaxListLength(const char *bytes, int numBytes, MODULE_SCOPE int TclMergeReturnOptions(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], Tcl_Obj **optionsPtrPtr, int *codePtr, int *levelPtr); +MODULE_SCOPE Tcl_Obj * TclNarrowToBytes(Tcl_Obj *objPtr); MODULE_SCOPE Tcl_Obj * TclNoErrorStack(Tcl_Interp *interp, Tcl_Obj *options); MODULE_SCOPE int TclNokia770Doubles(void); MODULE_SCOPE void TclNsDecrRefCount(Namespace *nsPtr); diff --git a/generic/tclObj.c b/generic/tclObj.c index ea7c078..9d44bb2 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -393,7 +393,6 @@ TclInitObjSubsystem(void) Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS); Tcl_MutexUnlock(&tableMutex); - Tcl_RegisterObjType(&tclByteArrayType); Tcl_RegisterObjType(&tclDoubleType); Tcl_RegisterObjType(&tclEndOffsetType); Tcl_RegisterObjType(&tclIntType); diff --git a/generic/tclTest.c b/generic/tclTest.c index fe68d51..c771af1 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -4914,6 +4914,10 @@ TestbytestringObjCmd( return TCL_ERROR; } p = (const char *)Tcl_GetByteArrayFromObj(objv[1], &n); + if (p == NULL) { + Tcl_AppendResult(interp, "testbytestring expects bytes", NULL); + return TCL_ERROR; + } Tcl_SetObjResult(interp, Tcl_NewStringObj(p, n)); return TCL_OK; } diff --git a/tests/execute.test b/tests/execute.test index 2480a95..2d6bda2 100644 --- a/tests/execute.test +++ b/tests/execute.test @@ -993,7 +993,7 @@ test execute-9.1 {Interp result resetting [Bug 1522803]} { } SUCCESS test execute-10.1 {TclExecuteByteCode, INST_CONCAT1, bytearrays} { - apply {s {binary scan $s c x; list $x [scan $s$s %c%c]}} \u0130 + apply {s {binary scan [binary format a $s] c x; list $x [scan $s$s %c%c]}} \u0130 } {48 {304 304}} test execute-10.2 {Bug 2802881} -setup { interp create slave diff --git a/tests/obj.test b/tests/obj.test index 4d57c08..ce1883a 100644 --- a/tests/obj.test +++ b/tests/obj.test @@ -27,7 +27,6 @@ test obj-1.1 {Tcl_AppendAllObjTypes, and InitTypeTable, Tcl_RegisterObjType} tes set r 1 foreach {t} { {array search} - bytearray bytecode cmdName dict @@ -48,10 +47,10 @@ test obj-2.2 {Tcl_GetObjType and Tcl_ConvertToType} testobj { set result "" lappend result [testobj freeallvars] lappend result [testintobj set 1 12] - lappend result [testobj convert 1 bytearray] + lappend result [testobj convert 1 string] lappend result [testobj type 1] lappend result [testobj refcount 1] -} {{} 12 12 bytearray 3} +} {{} 12 12 string 3} test obj-3.1 {Tcl_ConvertToType error} testobj { list [testdoubleobj set 1 12.34] \ diff --git a/tests/utf.test b/tests/utf.test index 422ab08..2a8d9ff 100644 --- a/tests/utf.test +++ b/tests/utf.test @@ -93,7 +93,7 @@ test utf-4.2 {Tcl_NumUtfChars: length 1} {testnumutfchars testbytestring} { testnumutfchars [testbytestring "\xC2\xA2"] } {1} test utf-4.3 {Tcl_NumUtfChars: long string} {testnumutfchars testbytestring} { - testnumutfchars [testbytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"] + testnumutfchars [testbytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e"] } {7} test utf-4.4 {Tcl_NumUtfChars: #u0000} {testnumutfchars testbytestring} { testnumutfchars [testbytestring "\xC0\x80"] @@ -105,7 +105,7 @@ test utf-4.6 {Tcl_NumUtfChars: length 1, calc len} {testnumutfchars testbytestri testnumutfchars [testbytestring "\xC2\xA2"] 2 } {1} test utf-4.7 {Tcl_NumUtfChars: long string, calc len} {testnumutfchars testbytestring} { - testnumutfchars [testbytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"] 10 + testnumutfchars [testbytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e"] 10 } {7} test utf-4.8 {Tcl_NumUtfChars: #u0000, calc len} {testnumutfchars testbytestring} { testnumutfchars [testbytestring "\xC0\x80"] 2 |