diff options
Diffstat (limited to 'generic/tclBinary.c')
-rw-r--r-- | generic/tclBinary.c | 167 |
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 }; |