summaryrefslogtreecommitdiffstats
path: root/generic/tclBinary.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclBinary.c')
-rw-r--r--generic/tclBinary.c167
1 files changed, 88 insertions, 79 deletions
diff --git a/generic/tclBinary.c b/generic/tclBinary.c
index 45489cc..32fccd6 100644
--- a/generic/tclBinary.c
+++ b/generic/tclBinary.c
@@ -22,11 +22,11 @@
* special conditions in the parsing of a format specifier.
*/
-#define BINARY_ALL ((size_t)-1) /* Use all elements in the argument. */
-#define BINARY_NOCOUNT ((size_t)-2) /* No count was specified in format. */
+#define BINARY_ALL -1 /* Use all elements in the argument. */
+#define BINARY_NOCOUNT -2 /* No count was specified in format. */
/*
- * The following flags may be ORed together and returned by GetFormatSpec
+ * The following flags may be OR'ed together and returned by GetFormatSpec
*/
#define BINARY_SIGNED 0 /* Field to be read as signed data */
@@ -37,7 +37,7 @@
* placed in the object cache by 'binary scan' before it bails out and
* switches back to Plan A (creating a new object for each value.)
* Theoretically, it would be possible to keep the cache about for the values
- * that are already in it, but that makes the code slower in practise when
+ * that are already in it, but that makes the code slower in practice when
* overflow happens, and makes little odds the rest of the time (as measured
* on my machine.) It is also slower (on the sample I tried at least) to grow
* the cache to hold all items we might want to put in it; presumably the
@@ -61,10 +61,10 @@ static int FormatNumber(Tcl_Interp *interp, int type,
Tcl_Obj *src, unsigned char **cursorPtr);
static void FreeProperByteArrayInternalRep(Tcl_Obj *objPtr);
static int GetFormatSpec(const char **formatPtr, char *cmdPtr,
- size_t *countPtr, int *flagsPtr);
+ Tcl_Size *countPtr, int *flagsPtr);
static Tcl_Obj * ScanNumber(unsigned char *buffer, int type,
int flags, Tcl_HashTable **numberCachePtr);
-static int SetByteArrayFromAny(Tcl_Interp *interp, size_t limit,
+static int SetByteArrayFromAny(Tcl_Interp *interp, Tcl_Size limit,
Tcl_Obj *objPtr);
static void UpdateStringOfByteArray(Tcl_Obj *listPtr);
static void DeleteScanNumberCache(Tcl_HashTable *numberCachePtr);
@@ -174,18 +174,19 @@ static const Tcl_ObjType properByteArrayType = {
*/
typedef struct {
- size_t used; /* The number of bytes used in the byte
+ Tcl_Size used; /* The number of bytes used in the byte
* array. */
- size_t allocated; /* The amount of space actually allocated
+ Tcl_Size allocated; /* The amount of space actually allocated
* minus 1 byte. */
unsigned char bytes[TCLFLEXARRAY]; /* The array of bytes. The actual size of this
* field depends on the 'allocated' field
* above. */
} ByteArray;
+#define BYTEARRAY_MAX_LEN (TCL_SIZE_MAX - (Tcl_Size)offsetof(ByteArray, bytes))
#define BYTEARRAY_SIZE(len) \
- ( (offsetof(ByteArray, bytes) + (len) < offsetof(ByteArray, bytes)) \
- ? (Tcl_Panic("max size of a Tcl value exceeded"), 0) \
+ ( (len < 0 || BYTEARRAY_MAX_LEN < (len)) \
+ ? (Tcl_Panic("negative length specified or max size of a Tcl value exceeded"), 0) \
: (offsetof(ByteArray, bytes) + (len)) )
#define GET_BYTEARRAY(irPtr) ((ByteArray *) (irPtr)->twoPtrValue.ptr1)
#define SET_BYTEARRAY(irPtr, baPtr) \
@@ -222,7 +223,7 @@ Tcl_Obj *
Tcl_NewByteArrayObj(
const unsigned char *bytes, /* The array of bytes used to initialize the
* new object. */
- size_t numBytes) /* Number of bytes in the array */
+ Tcl_Size numBytes) /* Number of bytes in the array */
{
#ifdef TCL_MEM_DEBUG
return Tcl_DbNewByteArrayObj(bytes, numBytes, "unknown", 0);
@@ -265,7 +266,7 @@ Tcl_Obj *
Tcl_DbNewByteArrayObj(
const unsigned char *bytes, /* The array of bytes used to initialize the
* new object. */
- size_t numBytes, /* Number of bytes in the array */
+ Tcl_Size numBytes, /* Number of bytes in the array */
const char *file, /* The name of the source file calling this
* procedure; used for debugging. */
int line) /* Line number in the source file; used for
@@ -282,7 +283,7 @@ Tcl_Obj *
Tcl_DbNewByteArrayObj(
const unsigned char *bytes, /* The array of bytes used to initialize the
* new object. */
- size_t numBytes, /* Number of bytes in the array */
+ Tcl_Size numBytes, /* Number of bytes in the array */
TCL_UNUSED(const char *) /*file*/,
TCL_UNUSED(int) /*line*/)
{
@@ -313,7 +314,8 @@ Tcl_SetByteArrayObj(
Tcl_Obj *objPtr, /* Object to initialize as a ByteArray. */
const unsigned char *bytes, /* The array of bytes to use as the new value.
* May be NULL even if numBytes > 0. */
- size_t numBytes) /* Number of bytes in the array */
+ Tcl_Size numBytes) /* Number of bytes in the array.
+ * Must be >= 0 */
{
ByteArray *byteArrayPtr;
Tcl_ObjInternalRep ir;
@@ -323,6 +325,7 @@ Tcl_SetByteArrayObj(
}
TclInvalidateStringRep(objPtr);
+ assert(numBytes >= 0);
byteArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(numBytes));
byteArrayPtr->used = numBytes;
byteArrayPtr->allocated = numBytes;
@@ -357,7 +360,7 @@ unsigned char *
Tcl_GetBytesFromObj(
Tcl_Interp *interp, /* For error reporting */
Tcl_Obj *objPtr, /* Value to extract from */
- size_t *numBytesPtr) /* If non-NULL, write the number of bytes
+ Tcl_Size *numBytesPtr) /* If non-NULL, write the number of bytes
* in the array here */
{
ByteArray *baPtr;
@@ -378,6 +381,7 @@ Tcl_GetBytesFromObj(
return baPtr->bytes;
}
+#if !defined(TCL_NO_DEPRECATED)
unsigned char *
TclGetBytesFromObj(
Tcl_Interp *interp, /* For error reporting */
@@ -385,7 +389,7 @@ TclGetBytesFromObj(
int *numBytesPtr) /* If non-NULL, write the number of bytes
* in the array here */
{
- size_t numBytes = 0;
+ Tcl_Size numBytes = 0;
unsigned char *bytes = Tcl_GetBytesFromObj(interp, objPtr, &numBytes);
if (bytes && numBytesPtr) {
@@ -395,7 +399,7 @@ TclGetBytesFromObj(
if (interp) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "byte sequence length exceeds INT_MAX", TCL_INDEX_NONE));
+ "byte sequence length exceeds INT_MAX", -1));
Tcl_SetErrorCode(interp, "TCL", "API", "OUTDATED", NULL);
}
return NULL;
@@ -405,6 +409,7 @@ TclGetBytesFromObj(
}
return bytes;
}
+#endif
/*
*----------------------------------------------------------------------
@@ -431,11 +436,13 @@ TclGetBytesFromObj(
unsigned char *
Tcl_SetByteArrayLength(
Tcl_Obj *objPtr, /* The ByteArray object. */
- size_t numBytes) /* Number of bytes in resized array */
+ Tcl_Size numBytes) /* Number of bytes in resized array
+ * Must be >= 0 */
{
ByteArray *byteArrayPtr;
Tcl_ObjInternalRep *irPtr;
+ assert(numBytes >= 0);
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength");
}
@@ -466,8 +473,8 @@ Tcl_SetByteArrayLength(
* MakeByteArray --
*
* Generate a ByteArray internal rep from the string rep of objPtr.
- * The generated byte sequence may have no more than limit bytes. The
- * value of TCL_INDEX_NONE for limit indicates no limit imposed. If
+ * The generated byte sequence may have no more than limit bytes.
+ * A negative value for limit indicates no limit imposed. If
* boolean argument demandProper is true, then no byte sequence should
* be output to the caller (write NULL instead). When no bytes sequence
* is output and interp is not NULL, leave an error message and error
@@ -487,14 +494,13 @@ static int
MakeByteArray(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
- size_t limit,
+ Tcl_Size limit,
int demandProper,
ByteArray **byteArrayPtrPtr)
{
- size_t length;
+ Tcl_Size length;
const char *src = Tcl_GetStringFromObj(objPtr, &length);
- size_t numBytes
- = (limit != TCL_INDEX_NONE && limit < length) ? limit : length;
+ Tcl_Size numBytes = (limit >= 0 && limit < length) ? limit : length;
ByteArray *byteArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(numBytes));
unsigned char *dst = byteArrayPtr->bytes;
unsigned char *dstEnd = dst + numBytes;
@@ -569,7 +575,7 @@ TclNarrowToBytes(
static int
SetByteArrayFromAny(
Tcl_Interp *interp, /* For error reporting. */
- size_t limit, /* Create no more than this many bytes */
+ Tcl_Size limit, /* Create no more than this many bytes */
Tcl_Obj *objPtr) /* The object to convert to type ByteArray. */
{
ByteArray *byteArrayPtr;
@@ -630,7 +636,7 @@ DupProperByteArrayInternalRep(
Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
- size_t length;
+ Tcl_Size length;
ByteArray *srcArrayPtr, *copyArrayPtr;
Tcl_ObjInternalRep ir;
@@ -671,8 +677,8 @@ UpdateStringOfByteArray(
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, &properByteArrayType);
ByteArray *byteArrayPtr = GET_BYTEARRAY(irPtr);
unsigned char *src = byteArrayPtr->bytes;
- size_t i, length = byteArrayPtr->used;
- size_t size = length;
+ Tcl_Size i, length = byteArrayPtr->used;
+ Tcl_Size size = length;
/*
* How much space will string rep need?
@@ -721,16 +727,16 @@ void
TclAppendBytesToByteArray(
Tcl_Obj *objPtr,
const unsigned char *bytes,
- size_t len)
+ Tcl_Size len)
{
ByteArray *byteArrayPtr;
- size_t needed;
+ Tcl_Size needed;
Tcl_ObjInternalRep *irPtr;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object","TclAppendBytesToByteArray");
}
- if (len == TCL_INDEX_NONE) {
+ if (len < 0) {
Tcl_Panic("%s must be called with definite number of bytes to append",
"TclAppendBytesToByteArray");
}
@@ -755,11 +761,11 @@ TclAppendBytesToByteArray(
* If we need to, resize the allocated space in the byte array.
*/
- needed = byteArrayPtr->used + len;
- if (needed < byteArrayPtr->used) {
- /* Wrapped around SIZE_MAX!! */
- Tcl_Panic("max size of a Tcl value exceeded");
+ if ((BYTEARRAY_MAX_LEN - byteArrayPtr->used) < len) {
+ /* Will wrap around !! */
+ Tcl_Panic("max size of a byte array exceeded");
}
+ needed = byteArrayPtr->used + len;
if (needed > byteArrayPtr->allocated) {
ByteArray *ptr = NULL;
@@ -767,22 +773,25 @@ TclAppendBytesToByteArray(
* Try to allocate double the total space that is needed.
*/
- size_t attempt = 2 * needed;
+ Tcl_Size attempt;
- /* Protection just in case we wrapped around SIZE_MAX */
- if (attempt >= needed) {
+ /* Make sure we do not wrap when doubling */
+ if (needed <= (BYTEARRAY_MAX_LEN - needed)) {
+ attempt = 2 * needed;
ptr = (ByteArray *) Tcl_AttemptRealloc(byteArrayPtr,
BYTEARRAY_SIZE(attempt));
}
+
if (ptr == NULL) {
/*
- * Try to allocate double the increment that is needed (plus).
+ * Try to allocate double the increment that is needed.
+ * (Originally TCL_MIN_GROWTH was added as well but that would
+ * need one more separate overflow check so forget it.)
*/
-
- attempt = needed + len + TCL_MIN_GROWTH;
- if (attempt >= needed) {
- ptr = (ByteArray *) Tcl_AttemptRealloc(byteArrayPtr,
- BYTEARRAY_SIZE(attempt));
+ if (len <= (BYTEARRAY_MAX_LEN - needed)) {
+ attempt = needed + len;
+ ptr = (ByteArray *)Tcl_AttemptRealloc(byteArrayPtr,
+ BYTEARRAY_SIZE(attempt));
}
}
if (ptr == NULL) {
@@ -861,7 +870,7 @@ BinaryFormatCmd(
int value = 0; /* Current integer value to be packed.
* Initialized to avoid compiler warning. */
char cmd; /* Current format character. */
- size_t count; /* Count associated with current format
+ Tcl_Size count; /* Count associated with current format
* character. */
int flags; /* Format field flags */
const char *format; /* Pointer to current position in format
@@ -873,7 +882,7 @@ BinaryFormatCmd(
* cursor has visited.*/
const char *errorString;
const char *errorValue, *str;
- size_t offset, size, length;
+ Tcl_Size offset, size, length;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "formatString ?arg ...?");
@@ -971,7 +980,7 @@ BinaryFormatCmd(
arg++;
count = 1;
} else {
- size_t listc;
+ Tcl_Size listc;
Tcl_Obj **listv;
/*
@@ -1003,7 +1012,7 @@ BinaryFormatCmd(
case 'x':
if (count == BINARY_ALL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "cannot use \"*\" in format string with \"x\"", TCL_INDEX_NONE));
+ "cannot use \"*\" in format string with \"x\"", -1));
return TCL_ERROR;
} else if (count == BINARY_NOCOUNT) {
count = 1;
@@ -1047,7 +1056,7 @@ BinaryFormatCmd(
}
/*
- * Prepare the result object by preallocating the caclulated number of
+ * Prepare the result object by preallocating the calculated number of
* bytes and filling with nulls.
*/
@@ -1253,7 +1262,7 @@ BinaryFormatCmd(
case 'q':
case 'Q':
case 'f': {
- size_t listc, i;
+ Tcl_Size listc, i;
Tcl_Obj **listv;
if (count == BINARY_NOCOUNT) {
@@ -1294,7 +1303,7 @@ BinaryFormatCmd(
if (count == BINARY_NOCOUNT) {
count = 1;
}
- if ((count == BINARY_ALL) || (count > (size_t)(cursor - buffer))) {
+ if ((count == BINARY_ALL) || (count > (cursor - buffer))) {
cursor = buffer;
} else {
cursor -= count;
@@ -1343,7 +1352,7 @@ BinaryFormatCmd(
}
error:
- Tcl_SetObjResult(interp, Tcl_NewStringObj(errorString, TCL_INDEX_NONE));
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(errorString, -1));
return TCL_ERROR;
}
@@ -1374,7 +1383,7 @@ BinaryScanCmd(
int value = 0; /* Current integer value to be packed.
* Initialized to avoid compiler warning. */
char cmd; /* Current format character. */
- size_t count; /* Count associated with current format
+ Tcl_Size count; /* Count associated with current format
* character. */
int flags; /* Format field flags */
const char *format; /* Pointer to current position in format
@@ -1383,7 +1392,7 @@ BinaryScanCmd(
unsigned char *buffer; /* Start of result buffer. */
const char *errorString;
const char *str;
- size_t offset, size, length = 0, i;
+ Tcl_Size offset, size, length = 0, i;
Tcl_Obj *valuePtr, *elementPtr;
Tcl_HashTable numberCacheHash;
@@ -1492,7 +1501,7 @@ BinaryScanCmd(
if (count == BINARY_NOCOUNT) {
count = 1;
}
- if (count > (size_t)(length - offset) * 8) {
+ if (count > (length - offset) * 8) {
goto done;
}
}
@@ -1623,7 +1632,7 @@ BinaryScanCmd(
goto badIndex;
}
if (count == BINARY_NOCOUNT) {
- if (length < (size_t)size + offset) {
+ if (length < size + offset) {
goto done;
}
valuePtr = ScanNumber(buffer+offset, cmd, flags,
@@ -1724,7 +1733,7 @@ BinaryScanCmd(
}
error:
- Tcl_SetObjResult(interp, Tcl_NewStringObj(errorString, TCL_INDEX_NONE));
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(errorString, -1));
return TCL_ERROR;
}
@@ -1753,7 +1762,7 @@ static int
GetFormatSpec(
const char **formatPtr, /* Pointer to format string. */
char *cmdPtr, /* Pointer to location of command char. */
- size_t *countPtr, /* Pointer to repeat count value. */
+ Tcl_Size *countPtr, /* Pointer to repeat count value. */
int *flagsPtr) /* Pointer to field flags */
{
/*
@@ -1786,14 +1795,14 @@ GetFormatSpec(
(*formatPtr)++;
*countPtr = BINARY_ALL;
} else if (isdigit(UCHAR(**formatPtr))) { /* INTL: digit */
- unsigned long count;
+ unsigned long long count;
errno = 0;
- count = strtoul(*formatPtr, (char **) formatPtr, 10);
- if (errno || (count > (unsigned long) INT_MAX)) {
- *countPtr = INT_MAX;
+ count = strtoull(*formatPtr, (char **) formatPtr, 10);
+ if (errno || (count > TCL_SIZE_MAX)) {
+ *countPtr = TCL_SIZE_MAX;
} else {
- *countPtr = (int) count;
+ *countPtr = count;
}
} else {
*countPtr = BINARY_NOCOUNT;
@@ -1808,7 +1817,7 @@ GetFormatSpec(
*
* This routine determines, if bytes of a number need to be re-ordered,
* and returns a numeric code indicating the re-ordering to be done.
- * This depends on the endiannes of the machine and the desired format.
+ * This depends on the endianness of the machine and the desired format.
* It is in effect a table (whose contents depend on the endianness of
* the system) describing whether a value needs reversing or not. Anyone
* porting the code to a big-endian platform should take care to make
@@ -2457,7 +2466,7 @@ BinaryEncodeHex(
Tcl_Obj *resultObj = NULL;
unsigned char *data = NULL;
unsigned char *cursor = NULL;
- size_t offset = 0, count = 0;
+ Tcl_Size offset = 0, count = 0;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "data");
@@ -2506,7 +2515,7 @@ BinaryDecodeHex(
unsigned char *data, *datastart, *dataend;
unsigned char *begin, *cursor, c;
int i, index, value, pure = 1, strict = 0;
- size_t size, cut = 0, count = 0;
+ Tcl_Size size, cut = 0, count = 0;
int ucs4;
enum {OPT_STRICT };
static const char *const optStrings[] = { "-strict", NULL };
@@ -2629,11 +2638,11 @@ BinaryEncode64(
{
Tcl_Obj *resultObj;
unsigned char *data, *limit;
- int maxlen = 0;
+ Tcl_Size maxlen = 0;
const char *wrapchar = "\n";
- size_t wrapcharlen = 1;
- int i, index, size, outindex = 0, purewrap = 1;
- size_t offset, count = 0;
+ Tcl_Size wrapcharlen = 1;
+ int index, purewrap = 1;
+ Tcl_Size i, offset, size, outindex = 0, count = 0;
enum { OPT_MAXLEN, OPT_WRAPCHAR };
static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL };
@@ -2649,12 +2658,12 @@ BinaryEncode64(
}
switch (index) {
case OPT_MAXLEN:
- if (Tcl_GetIntFromObj(interp, objv[i + 1], &maxlen) != TCL_OK) {
+ if (Tcl_GetSizeIntFromObj(interp, objv[i + 1], &maxlen) != TCL_OK) {
return TCL_ERROR;
}
if (maxlen < 0) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "line length out of range", TCL_INDEX_NONE));
+ "line length out of range", -1));
Tcl_SetErrorCode(interp, "TCL", "BINARY", "ENCODE",
"LINE_LENGTH", NULL);
return TCL_ERROR;
@@ -2755,12 +2764,12 @@ BinaryEncodeUu(
{
Tcl_Obj *resultObj;
unsigned char *data, *start, *cursor;
- int rawLength, i, bits, index;
+ int i, bits, index;
unsigned int n;
int lineLength = 61;
const unsigned char SingleNewline[] = { UCHAR('\n') };
const unsigned char *wrapchar = SingleNewline;
- size_t j, offset, count = 0, wrapcharlen = sizeof(SingleNewline);
+ Tcl_Size j, rawLength, offset, count = 0, wrapcharlen = sizeof(SingleNewline);
enum { OPT_MAXLEN, OPT_WRAPCHAR };
static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL };
@@ -2782,7 +2791,7 @@ BinaryEncodeUu(
}
if (lineLength < 5 || lineLength > 85) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "line length out of range", TCL_INDEX_NONE));
+ "line length out of range", -1));
Tcl_SetErrorCode(interp, "TCL", "BINARY", "ENCODE",
"LINE_LENGTH", NULL);
return TCL_ERROR;
@@ -2794,7 +2803,7 @@ BinaryEncodeUu(
objv[i + 1], &wrapcharlen);
{
const unsigned char *p = wrapchar;
- size_t numBytes = wrapcharlen;
+ Tcl_Size numBytes = wrapcharlen;
while (numBytes) {
switch (*p) {
@@ -2850,7 +2859,7 @@ BinaryEncodeUu(
*/
while (offset < count) {
- int lineLen = count - offset;
+ Tcl_Size lineLen = count - offset;
if (lineLen > rawLength) {
lineLen = rawLength;
@@ -2909,7 +2918,7 @@ BinaryDecodeUu(
unsigned char *data, *datastart, *dataend;
unsigned char *begin, *cursor;
int i, index, pure = 1, strict = 0, lineLen;
- size_t size, count = 0;
+ Tcl_Size size, count = 0;
unsigned char c;
int ucs4;
enum { OPT_STRICT };
@@ -3085,7 +3094,7 @@ BinaryDecode64(
unsigned char *cursor = NULL;
int pure = 1, strict = 0;
int i, index, cut = 0;
- size_t size, count = 0;
+ Tcl_Size size, count = 0;
int ucs4;
enum { OPT_STRICT };
static const char *const optStrings[] = { "-strict", NULL };