summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--[-rwxr-xr-x]compat/zlib/win32/zdll.libbin17152 -> 17152 bytes
-rw-r--r--[-rwxr-xr-x]compat/zlib/zlib2ansi0
-rw-r--r--generic/tclBinary.c152
-rw-r--r--generic/tclCmdAH.c5
-rw-r--r--generic/tclDictObj.c3
-rw-r--r--generic/tclIO.c20
-rw-r--r--generic/tclIOGT.c27
-rw-r--r--generic/tclIORChan.c11
-rw-r--r--generic/tclInt.h2
-rw-r--r--generic/tclObj.c1
-rw-r--r--generic/tclTest.c4
-rw-r--r--tests/execute.test2
-rw-r--r--tests/obj.test5
-rw-r--r--tests/utf.test4
14 files changed, 164 insertions, 72 deletions
diff --git a/compat/zlib/win32/zdll.lib b/compat/zlib/win32/zdll.lib
index a3e9a39..a3e9a39 100755..100644
--- a/compat/zlib/win32/zdll.lib
+++ b/compat/zlib/win32/zdll.lib
Binary files differ
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