summaryrefslogtreecommitdiffstats
path: root/generic/tclZlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclZlib.c')
-rw-r--r--generic/tclZlib.c197
1 files changed, 129 insertions, 68 deletions
diff --git a/generic/tclZlib.c b/generic/tclZlib.c
index 63a25fa..6a9a38a 100644
--- a/generic/tclZlib.c
+++ b/generic/tclZlib.c
@@ -3,9 +3,9 @@
*
* This file provides the interface to the Zlib library.
*
- * Copyright (C) 2004-2005 Pascal Scheffers <pascal@scheffers.net>
- * Copyright (C) 2005 Unitas Software B.V.
- * Copyright (c) 2008-2012 Donal K. Fellows
+ * Copyright © 2004-2005 Pascal Scheffers <pascal@scheffers.net>
+ * Copyright © 2005 Unitas Software B.V.
+ * Copyright © 2008-2012 Donal K. Fellows
*
* Parts written by Jean-Claude Wippler, as part of Tclkit, placed in the
* public domain March 2003.
@@ -110,14 +110,14 @@ typedef struct {
int format; /* What format of data is going on the wire.
* Needed so that the correct [fconfigure]
* options can be enabled. */
- int readAheadLimit; /* The maximum number of bytes to read from
+ unsigned int readAheadLimit;/* The maximum number of bytes to read from
* the underlying stream in one go. */
z_stream inStream; /* Structure used by zlib for decompression of
* input. */
z_stream outStream; /* Structure used by zlib for compression of
* output. */
char *inBuffer, *outBuffer; /* Working buffers. */
- int inAllocated, outAllocated;
+ size_t inAllocated, outAllocated;
/* Sizes of working buffers. */
GzipHeader inHeader; /* Header read from input stream, when
* decompressing a gzip stream. */
@@ -163,7 +163,7 @@ typedef struct {
static Tcl_CmdDeleteProc ZlibStreamCmdDelete;
static Tcl_DriverBlockModeProc ZlibTransformBlockMode;
-static Tcl_DriverCloseProc ZlibTransformClose;
+static Tcl_DriverClose2Proc ZlibTransformClose;
static Tcl_DriverGetHandleProc ZlibTransformGetHandle;
static Tcl_DriverGetOptionProc ZlibTransformGetOption;
static Tcl_DriverHandlerProc ZlibTransformEventHandler;
@@ -197,7 +197,7 @@ static void ZlibStreamCleanup(ZlibStreamHandle *zshPtr);
static int ZlibStreamSubcmd(Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
static inline void ZlibTransformEventTimerKill(ZlibChannelData *cd);
-static void ZlibTransformTimerRun(ClientData clientData);
+static void ZlibTransformTimerRun(void *clientData);
/*
* Type of zlib-based compressing and decompressing channels.
@@ -206,7 +206,7 @@ static void ZlibTransformTimerRun(ClientData clientData);
static const Tcl_ChannelType zlibChannelType = {
"zlib",
TCL_CHANNEL_VERSION_5,
- ZlibTransformClose,
+ TCL_CLOSE2PROC,
ZlibTransformInput,
ZlibTransformOutput,
NULL, /* seekProc */
@@ -214,7 +214,7 @@ static const Tcl_ChannelType zlibChannelType = {
ZlibTransformGetOption,
ZlibTransformWatch,
ZlibTransformGetHandle,
- NULL, /* close2Proc */
+ ZlibTransformClose, /* close2Proc */
ZlibTransformBlockMode,
NULL, /* flushProc */
ZlibTransformEventHandler,
@@ -354,7 +354,7 @@ ConvertErrorToList(
return Tcl_NewListObj(4, objv);
case Z_NEED_DICT:
TclNewLiteralStringObj(objv[2], "NEED_DICT");
- objv[3] = Tcl_NewWideIntObj((Tcl_WideInt) adler);
+ TclNewIntObj(objv[3], (Tcl_WideInt)adler);
return Tcl_NewListObj(4, objv);
/*
@@ -423,6 +423,7 @@ GenerateHeader(
{
Tcl_Obj *value;
int len, result = TCL_ERROR;
+ Tcl_WideInt wideValue = 0;
const char *valueStr;
Tcl_Encoding latin1enc;
static const char *const types[] = {
@@ -441,7 +442,7 @@ GenerateHeader(
if (GetValue(interp, dictObj, "comment", &value) != TCL_OK) {
goto error;
} else if (value != NULL) {
- valueStr = Tcl_GetStringFromObj(value, &len);
+ valueStr = TclGetStringFromObj(value, &len);
Tcl_UtfToExternal(NULL, latin1enc, valueStr, len, 0, NULL,
headerPtr->nativeCommentBuf, MAX_COMMENT_LEN-1, NULL, &len,
NULL);
@@ -462,7 +463,7 @@ GenerateHeader(
if (GetValue(interp, dictObj, "filename", &value) != TCL_OK) {
goto error;
} else if (value != NULL) {
- valueStr = Tcl_GetStringFromObj(value, &len);
+ valueStr = TclGetStringFromObj(value, &len);
Tcl_UtfToExternal(NULL, latin1enc, valueStr, len, 0, NULL,
headerPtr->nativeFilenameBuf, MAXPATHLEN-1, NULL, &len, NULL);
headerPtr->nativeFilenameBuf[len] = '\0';
@@ -486,10 +487,11 @@ GenerateHeader(
if (GetValue(interp, dictObj, "time", &value) != TCL_OK) {
goto error;
- } else if (value != NULL && Tcl_GetLongFromObj(interp, value,
- (long *) &headerPtr->header.time) != TCL_OK) {
+ } else if (value != NULL && Tcl_GetWideIntFromObj(interp, value,
+ &wideValue) != TCL_OK) {
goto error;
}
+ headerPtr->header.time = wideValue;
if (GetValue(interp, dictObj, "type", &value) != TCL_OK) {
goto error;
@@ -566,10 +568,10 @@ ExtractHeader(
SetValue(dictObj, "filename", TclDStringToObj(&tmp));
}
if (headerPtr->os != 255) {
- SetValue(dictObj, "os", Tcl_NewIntObj(headerPtr->os));
+ SetValue(dictObj, "os", Tcl_NewWideIntObj(headerPtr->os));
}
if (headerPtr->time != 0 /* magic - no time */) {
- SetValue(dictObj, "time", Tcl_NewLongObj((long) headerPtr->time));
+ SetValue(dictObj, "time", Tcl_NewWideIntObj(headerPtr->time));
}
if (headerPtr->text != Z_UNKNOWN) {
SetValue(dictObj, "type",
@@ -883,7 +885,7 @@ Tcl_ZlibStreamInit(
static void
ZlibStreamCmdDelete(
- ClientData cd)
+ void *cd)
{
ZlibStreamHandle *zshPtr = (ZlibStreamHandle *)cd;
@@ -1151,6 +1153,11 @@ Tcl_ZlibStreamSetCompressionDictionary(
{
ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;
+ if (compressionDictionaryObj && (NULL == TclGetBytesFromObj(NULL,
+ compressionDictionaryObj, (int *)NULL))) {
+ /* Missing or invalid compression dictionary */
+ compressionDictionaryObj = NULL;
+ }
if (compressionDictionaryObj != NULL) {
if (Tcl_IsShared(compressionDictionaryObj)) {
compressionDictionaryObj =
@@ -1190,6 +1197,7 @@ Tcl_ZlibStreamPut(
ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;
char *dataTmp = NULL;
int e, size, outSize, toStore;
+ unsigned char *bytes;
if (zshPtr->streamEnd) {
if (zshPtr->interp) {
@@ -1200,8 +1208,13 @@ Tcl_ZlibStreamPut(
return TCL_ERROR;
}
+ bytes = TclGetBytesFromObj(zshPtr->interp, data, &size);
+ if (bytes == NULL) {
+ return TCL_ERROR;
+ }
+
if (zshPtr->mode == TCL_ZLIB_STREAM_DEFLATE) {
- zshPtr->stream.next_in = Tcl_GetByteArrayFromObj(data, &size);
+ zshPtr->stream.next_in = bytes;
zshPtr->stream.avail_in = size;
/*
@@ -1325,7 +1338,9 @@ Tcl_ZlibStreamGet(
return TCL_OK;
}
- (void) Tcl_GetByteArrayFromObj(data, &existing);
+ if (NULL == TclGetBytesFromObj(zshPtr->interp, data, &existing)) {
+ return TCL_ERROR;
+ }
if (zshPtr->mode == TCL_ZLIB_STREAM_INFLATE) {
if (count == -1) {
@@ -1516,7 +1531,7 @@ Tcl_ZlibStreamGet(
Tcl_ListObjIndex(NULL, zshPtr->outData, 0, &itemObj);
itemPtr = Tcl_GetByteArrayFromObj(itemObj, &itemLen);
if (itemLen-zshPtr->outPos >= count-dataPos) {
- unsigned len = count - dataPos;
+ size_t len = count - dataPos;
memcpy(dataPtr + dataPos, itemPtr + zshPtr->outPos, len);
zshPtr->outPos += len;
@@ -1525,7 +1540,7 @@ Tcl_ZlibStreamGet(
zshPtr->outPos = 0;
}
} else {
- unsigned len = itemLen - zshPtr->outPos;
+ size_t len = itemLen - zshPtr->outPos;
memcpy(dataPtr + dataPos, itemPtr + zshPtr->outPos, len);
dataPos += len;
@@ -1573,6 +1588,16 @@ Tcl_ZlibDeflate(
}
/*
+ * Obtain the pointer to the byte array, we'll pass this pointer straight
+ * to the deflate command.
+ */
+
+ inData = TclGetBytesFromObj(interp, data, &inLen);
+ if (inData == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
* Compressed format is specified by the wbits parameter. See zlib.h for
* details.
*/
@@ -1616,12 +1641,6 @@ Tcl_ZlibDeflate(
TclNewObj(obj);
- /*
- * Obtain the pointer to the byte array, we'll pass this pointer straight
- * to the deflate command.
- */
-
- inData = Tcl_GetByteArrayFromObj(data, &inLen);
memset(&stream, 0, sizeof(z_stream));
stream.avail_in = (uInt) inLen;
stream.next_in = inData;
@@ -1722,6 +1741,11 @@ Tcl_ZlibInflate(
return TCL_ERROR;
}
+ inData = TclGetBytesFromObj(interp, data, &inLen);
+ if (inData == NULL) {
+ return TCL_ERROR;
+ }
+
/*
* Compressed format is specified by the wbits parameter. See zlib.h for
* details.
@@ -1759,7 +1783,6 @@ Tcl_ZlibInflate(
header.comm_max = MAX_COMMENT_LEN - 1;
}
- inData = Tcl_GetByteArrayFromObj(data, &inLen);
if (bufferSize < 1) {
/*
* Start with a buffer (up to) 3 times the size of the input data.
@@ -1859,7 +1882,7 @@ Tcl_ZlibInflate(
if (headerPtr != NULL) {
ExtractHeader(&header, gzipHeaderDictObj);
SetValue(gzipHeaderDictObj, "size",
- Tcl_NewLongObj(stream.total_out));
+ Tcl_NewWideIntObj(stream.total_out));
ckfree(nameBuf);
ckfree(commentBuf);
}
@@ -1919,7 +1942,7 @@ Tcl_ZlibAdler32(
static int
ZlibCmd(
- ClientData notUsed,
+ TCL_UNUSED(void *),
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
@@ -1955,6 +1978,10 @@ ZlibCmd(
Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?");
return TCL_ERROR;
}
+ data = TclGetBytesFromObj(interp, objv[2], &dlen);
+ if (data == NULL) {
+ return TCL_ERROR;
+ }
if (objc>3 && Tcl_GetIntFromObj(interp, objv[3],
(int *) &start) != TCL_OK) {
return TCL_ERROR;
@@ -1962,7 +1989,6 @@ ZlibCmd(
if (objc < 4) {
start = Tcl_ZlibAdler32(0, NULL, 0);
}
- data = Tcl_GetByteArrayFromObj(objv[2], &dlen);
Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)
(uLong) Tcl_ZlibAdler32(start, data, dlen)));
return TCL_OK;
@@ -1972,6 +1998,10 @@ ZlibCmd(
Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?");
return TCL_ERROR;
}
+ data = TclGetBytesFromObj(interp, objv[2], &dlen);
+ if (data == NULL) {
+ return TCL_ERROR;
+ }
if (objc>3 && Tcl_GetIntFromObj(interp, objv[3],
(int *) &start) != TCL_OK) {
return TCL_ERROR;
@@ -1979,7 +2009,6 @@ ZlibCmd(
if (objc < 4) {
start = Tcl_ZlibCRC32(0, NULL, 0);
}
- data = Tcl_GetByteArrayFromObj(objv[2], &dlen);
Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)
(uLong) Tcl_ZlibCRC32(start, data, dlen)));
return TCL_OK;
@@ -2312,6 +2341,12 @@ ZlibStreamSubcmd(
return TCL_ERROR;
}
+ if (compDictObj) {
+ if (NULL == TclGetBytesFromObj(interp, compDictObj, NULL)) {
+ return TCL_ERROR;
+ }
+ }
+
/*
* Construct the stream now we know its configuration.
*/
@@ -2363,7 +2398,7 @@ ZlibPushSubcmd(
"-dictionary", "-header", "-level", "-limit", NULL
};
const char *const *pushOptions = pushDecompressOptions;
- enum pushOptions {poDictionary, poHeader, poLevel, poLimit};
+ enum pushOptionsEnum {poDictionary, poHeader, poLevel, poLimit};
Tcl_Obj *headerObj = NULL, *compDictObj = NULL;
int limit = DEFAULT_BUFFER_SIZE, dummy;
@@ -2445,7 +2480,7 @@ ZlibPushSubcmd(
Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", NULL);
return TCL_ERROR;
}
- switch ((enum pushOptions) option) {
+ switch ((enum pushOptionsEnum) option) {
case poHeader:
headerObj = objv[i];
if (Tcl_DictObjSize(interp, headerObj, &dummy) != TCL_OK) {
@@ -2489,6 +2524,10 @@ ZlibPushSubcmd(
}
}
+ if (compDictObj && (NULL == TclGetBytesFromObj(interp, compDictObj, NULL))) {
+ return TCL_ERROR;
+ }
+
if (ZlibStackChannelTransform(interp, mode, format, level, limit, chan,
headerObj, compDictObj) == NULL) {
return TCL_ERROR;
@@ -2515,7 +2554,7 @@ ZlibPushSubcmd(
static int
ZlibStreamCmd(
- ClientData cd,
+ void *cd,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
@@ -2618,7 +2657,7 @@ ZlibStreamCmd(
Tcl_WrongNumArgs(interp, 2, objv, NULL);
return TCL_ERROR;
}
- Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_ZlibStreamEof(zstream)));
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_ZlibStreamEof(zstream)));
return TCL_OK;
case zs_checksum: /* $strm checksum */
if (objc != 2) {
@@ -2641,7 +2680,7 @@ ZlibStreamCmd(
static int
ZlibStreamAddCmd(
- ClientData cd,
+ void *cd,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
@@ -2734,7 +2773,10 @@ ZlibStreamAddCmd(
if (compDictObj != NULL) {
int len;
- (void) Tcl_GetByteArrayFromObj(compDictObj, &len);
+ if (NULL == TclGetBytesFromObj(interp, compDictObj, &len)) {
+ return TCL_ERROR;
+ }
+
if (len == 0) {
compDictObj = NULL;
}
@@ -2765,7 +2807,7 @@ ZlibStreamAddCmd(
static int
ZlibStreamPutCmd(
- ClientData cd,
+ void *cd,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
@@ -2838,7 +2880,9 @@ ZlibStreamPutCmd(
if (compDictObj != NULL) {
int len;
- (void) Tcl_GetByteArrayFromObj(compDictObj, &len);
+ if (NULL == TclGetBytesFromObj(interp, compDictObj, &len)) {
+ return TCL_ERROR;
+ }
if (len == 0) {
compDictObj = NULL;
}
@@ -2854,7 +2898,7 @@ ZlibStreamPutCmd(
static int
ZlibStreamHeaderCmd(
- ClientData cd,
+ void *cd,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
@@ -2893,12 +2937,17 @@ ZlibStreamHeaderCmd(
static int
ZlibTransformClose(
- ClientData instanceData,
- Tcl_Interp *interp)
+ void *instanceData,
+ Tcl_Interp *interp,
+ int flags)
{
ZlibChannelData *cd = (ZlibChannelData *)instanceData;
int e, written, result = TCL_OK;
+ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
+ return EINVAL;
+ }
+
/*
* Delete the support timer.
*/
@@ -2932,7 +2981,7 @@ ZlibTransformClose(
result = TCL_ERROR;
break;
}
- if (written && Tcl_WriteRaw(cd->parent, cd->outBuffer, written) < 0) {
+ if (written && Tcl_WriteRaw(cd->parent, cd->outBuffer, written) == TCL_IO_FAILURE) {
/* TODO: is this the right way to do errors on close?
* Note: when close is called from FinalizeIOSubsystem then
* interp may be NULL */
@@ -2992,7 +3041,7 @@ ZlibTransformClose(
static int
ZlibTransformInput(
- ClientData instanceData,
+ void *instanceData,
char *buf,
int toRead,
int *errorCodePtr)
@@ -3010,7 +3059,7 @@ ZlibTransformInput(
gotBytes = 0;
readBytes = cd->inStream.avail_in; /* how many bytes in buffer now */
while (!(cd->flags & STREAM_DONE) && toRead > 0) {
- int n, decBytes;
+ unsigned int n; int decBytes;
/* if starting from scratch or continuation after full decompression */
if (!cd->inStream.avail_in) {
@@ -3127,7 +3176,7 @@ copyDecompressed:
static int
ZlibTransformOutput(
- ClientData instanceData,
+ void *instanceData,
const char *buf,
int toWrite,
int *errorCodePtr)
@@ -3160,7 +3209,7 @@ ZlibTransformOutput(
break;
}
- if (Tcl_WriteRaw(cd->parent, cd->outBuffer, produced) < 0) {
+ if (Tcl_WriteRaw(cd->parent, cd->outBuffer, produced) == TCL_IO_FAILURE) {
*errorCodePtr = Tcl_GetErrno();
return -1;
}
@@ -3216,7 +3265,7 @@ ZlibTransformFlush(
* Write the bytes we've received to the next layer.
*/
- if (len > 0 && Tcl_WriteRaw(cd->parent, cd->outBuffer, len) < 0) {
+ if (len > 0 && Tcl_WriteRaw(cd->parent, cd->outBuffer, len) == TCL_IO_FAILURE) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"problem flushing channel: %s",
Tcl_PosixError(interp)));
@@ -3248,7 +3297,7 @@ ZlibTransformFlush(
static int
ZlibTransformSetOption( /* not used */
- ClientData instanceData,
+ void *instanceData,
Tcl_Interp *interp,
const char *optionName,
const char *value)
@@ -3269,7 +3318,10 @@ ZlibTransformSetOption( /* not used */
TclNewStringObj(compDictObj, value, strlen(value));
Tcl_IncrRefCount(compDictObj);
- (void) Tcl_GetByteArrayFromObj(compDictObj, NULL);
+ if (NULL == TclGetBytesFromObj(interp, compDictObj, NULL)) {
+ Tcl_DecrRefCount(compDictObj);
+ return TCL_ERROR;
+ }
if (cd->compDictObj) {
TclDecrRefCount(cd->compDictObj);
}
@@ -3361,7 +3413,7 @@ ZlibTransformSetOption( /* not used */
static int
ZlibTransformGetOption(
- ClientData instanceData,
+ void *instanceData,
Tcl_Interp *interp,
const char *optionName,
Tcl_DString *dsPtr)
@@ -3417,7 +3469,7 @@ ZlibTransformGetOption(
} else {
if (cd->compDictObj) {
int len;
- const char *str = Tcl_GetStringFromObj(cd->compDictObj, &len);
+ const char *str = TclGetStringFromObj(cd->compDictObj, &len);
Tcl_DStringAppend(dsPtr, str, len);
}
@@ -3482,7 +3534,7 @@ ZlibTransformGetOption(
static void
ZlibTransformWatch(
- ClientData instanceData,
+ void *instanceData,
int mask)
{
ZlibChannelData *cd = (ZlibChannelData *)instanceData;
@@ -3505,7 +3557,7 @@ ZlibTransformWatch(
static int
ZlibTransformEventHandler(
- ClientData instanceData,
+ void *instanceData,
int interestMask)
{
ZlibChannelData *cd = (ZlibChannelData *)instanceData;
@@ -3526,7 +3578,7 @@ ZlibTransformEventTimerKill(
static void
ZlibTransformTimerRun(
- ClientData clientData)
+ void *clientData)
{
ZlibChannelData *cd = (ZlibChannelData *)clientData;
@@ -3547,9 +3599,9 @@ ZlibTransformTimerRun(
static int
ZlibTransformGetHandle(
- ClientData instanceData,
+ void *instanceData,
int direction,
- ClientData *handlePtr)
+ void **handlePtr)
{
ZlibChannelData *cd = (ZlibChannelData *)instanceData;
@@ -3568,7 +3620,7 @@ ZlibTransformGetHandle(
static int
ZlibTransformBlockMode(
- ClientData instanceData,
+ void *instanceData,
int mode)
{
ZlibChannelData *cd = (ZlibChannelData *)instanceData;
@@ -3657,7 +3709,7 @@ ZlibStackChannelTransform(
if (compDictObj != NULL) {
cd->compDictObj = Tcl_DuplicateObj(compDictObj);
Tcl_IncrRefCount(cd->compDictObj);
- Tcl_GetByteArrayFromObj(cd->compDictObj, NULL);
+ TclGetByteArrayFromObj(cd->compDictObj, NULL);
}
if (format == TCL_ZLIB_FORMAT_RAW) {
@@ -3893,13 +3945,22 @@ TclZlibInit(
cfg[0].key = "zlibVersion";
cfg[0].value = zlibVersion();
cfg[1].key = NULL;
- Tcl_RegisterConfig(interp, "zlib", cfg, "iso8859-1");
+ Tcl_RegisterConfig(interp, "zlib", cfg, "utf-8");
+
+ /*
+ * Allow command type introspection to do something sensible with streams.
+ */
+
+ TclRegisterCommandTypeName(ZlibStreamCmd, "zlibStream");
/*
* Formally provide the package as a Tcl built-in.
*/
- return Tcl_PkgProvide(interp, "zlib", TCL_ZLIB_VERSION);
+#if !defined(TCL_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9)
+ Tcl_PkgProvide(interp, "zlib", TCL_ZLIB_VERSION);
+#endif
+ return Tcl_PkgProvide(interp, "tcl::zlib", TCL_ZLIB_VERSION);
}
/*
@@ -4011,18 +4072,18 @@ Tcl_ZlibInflate(
unsigned int
Tcl_ZlibCRC32(
- unsigned int crc,
- const char *buf,
- int len)
+ TCL_UNUSED(unsigned int),
+ TCL_UNUSED(const unsigned char *),
+ TCL_UNUSED(int))
{
return 0;
}
unsigned int
Tcl_ZlibAdler32(
- unsigned int adler,
- const char *buf,
- int len)
+ TCL_UNUSED(unsigned int),
+ TCL_UNUSED(const unsigned char *),
+ TCL_UNUSED(int))
{
return 0;
}