summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2016-02-09 18:08:14 (GMT)
committerdgp <dgp@users.sourceforge.net>2016-02-09 18:08:14 (GMT)
commita8c2e6382e1ddf54dc238d00199ca6de99607bc5 (patch)
treed8e09608ef62d395350357422937f370d48c173d
parentd8d1e6bbf527a1eb861879704f7779b5ac36781a (diff)
parentb1598dbddda53d7d5886bc8ae50a5b2f8901a1d8 (diff)
downloadtcl-a8c2e6382e1ddf54dc238d00199ca6de99607bc5.zip
tcl-a8c2e6382e1ddf54dc238d00199ca6de99607bc5.tar.gz
tcl-a8c2e6382e1ddf54dc238d00199ca6de99607bc5.tar.bz2
merge trunk
-rw-r--r--generic/tclOO.c62
-rw-r--r--generic/tclZlib.c118
-rw-r--r--tests/zlib.test6
3 files changed, 120 insertions, 66 deletions
diff --git a/generic/tclOO.c b/generic/tclOO.c
index 34eb5ad..9df5029 100644
--- a/generic/tclOO.c
+++ b/generic/tclOO.c
@@ -898,10 +898,10 @@ ObjectRenamedTrace(
/*
* ----------------------------------------------------------------------
*
- * ReleaseClassContents --
+ * ClearMixins, ClearSuperclasses --
*
- * Tear down the special class data structure, including deleting all
- * dependent classes and objects.
+ * Utility functions for correctly clearing the list of mixins or
+ * superclasses of a class. Will ckfree() the list storage.
*
* ----------------------------------------------------------------------
*/
@@ -913,10 +913,15 @@ ClearMixins(
int i;
Class *mixinPtr;
+ if (clsPtr->mixins.num == 0) {
+ return;
+ }
+
FOREACH(mixinPtr, clsPtr->mixins) {
TclOORemoveFromMixinSubs(clsPtr, mixinPtr);
}
ckfree(clsPtr->mixins.list);
+ clsPtr->mixins.list = NULL;
clsPtr->mixins.num = 0;
}
@@ -927,12 +932,28 @@ ClearSuperclasses(
int i;
Class *superPtr;
+ if (clsPtr->superclasses.num == 0) {
+ return;
+ }
+
FOREACH(superPtr, clsPtr->superclasses) {
TclOORemoveFromSubclasses(clsPtr, superPtr);
}
ckfree(clsPtr->superclasses.list);
+ clsPtr->superclasses.list = NULL;
clsPtr->superclasses.num = 0;
}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * ReleaseClassContents --
+ *
+ * Tear down the special class data structure, including deleting all
+ * dependent classes and objects.
+ *
+ * ----------------------------------------------------------------------
+ */
static void
ReleaseClassContents(
@@ -1002,16 +1023,11 @@ ReleaseClassContents(
*/
FOREACH(mixinSubclassPtr, clsPtr->mixinSubs) {
- if (mixinSubclassPtr == NULL) {
- continue;
- }
if (!Deleted(mixinSubclassPtr->thisPtr)) {
Tcl_DeleteCommandFromToken(interp,
mixinSubclassPtr->thisPtr->command);
}
- if (mixinSubclassPtr->mixins.num) {
- ClearMixins(mixinSubclassPtr);
- }
+ ClearMixins(mixinSubclassPtr);
DelRef(mixinSubclassPtr->thisPtr);
DelRef(mixinSubclassPtr);
}
@@ -1026,15 +1042,13 @@ ReleaseClassContents(
*/
FOREACH(subclassPtr, clsPtr->subclasses) {
- if (subclassPtr == NULL || IsRoot(subclassPtr)) {
+ if (IsRoot(subclassPtr)) {
continue;
}
if (!Deleted(subclassPtr->thisPtr)) {
Tcl_DeleteCommandFromToken(interp, subclassPtr->thisPtr->command);
}
- if (subclassPtr->superclasses.num) {
- ClearSuperclasses(subclassPtr);
- }
+ ClearSuperclasses(subclassPtr);
DelRef(subclassPtr->thisPtr);
DelRef(subclassPtr);
}
@@ -1230,6 +1244,10 @@ ObjectNamespaceDeleted(
oPtr->metadataPtr = NULL;
}
+ /*
+ * If this was a class, there's additional deletion work to do.
+ */
+
if (clsPtr != NULL) {
Tcl_ObjectMetadataType *metadataTypePtr;
ClientData value;
@@ -1251,12 +1269,10 @@ ObjectNamespaceDeleted(
clsPtr->filters.num = 0;
}
- if (clsPtr->mixins.num) {
- ClearMixins(clsPtr);
- }
- if (clsPtr->superclasses.num) {
- ClearSuperclasses(clsPtr);
- }
+ ClearMixins(clsPtr);
+
+ ClearSuperclasses(clsPtr);
+
if (clsPtr->subclasses.list) {
ckfree(clsPtr->subclasses.list);
clsPtr->subclasses.num = 0;
@@ -1398,9 +1414,7 @@ TclOORemoveFromSubclasses(
return;
removeSubclass:
- if (Deleted(superPtr->thisPtr)) {
- superPtr->subclasses.list[i] = NULL;
- } else {
+ if (!Deleted(superPtr->thisPtr)) {
superPtr->subclasses.num--;
if (i < superPtr->subclasses.num) {
superPtr->subclasses.list[i] =
@@ -1471,9 +1485,7 @@ TclOORemoveFromMixinSubs(
return;
removeSubclass:
- if (Deleted(superPtr->thisPtr)) {
- superPtr->mixinSubs.list[i] = NULL;
- } else {
+ if (!Deleted(superPtr->thisPtr)) {
superPtr->mixinSubs.num--;
if (i < superPtr->mixinSubs.num) {
superPtr->mixinSubs.list[i] =
diff --git a/generic/tclZlib.c b/generic/tclZlib.c
index ba3e9cb..50d9a30 100644
--- a/generic/tclZlib.c
+++ b/generic/tclZlib.c
@@ -1164,6 +1164,14 @@ Tcl_ZlibStreamPut(
zshPtr->stream.next_in = Tcl_GetByteArrayFromObj(data, &size);
zshPtr->stream.avail_in = size;
+ /*
+ * Must not do a zero-length compress. [Bug 25842c161]
+ */
+
+ if (size == 0) {
+ return TCL_OK;
+ }
+
if (HaveDictToSet(zshPtr)) {
e = SetDeflateDictionary(&zshPtr->stream, zshPtr->compDictObj);
if (e != Z_OK) {
@@ -1186,32 +1194,27 @@ Tcl_ZlibStreamPut(
zshPtr->stream.next_out = (Bytef *) dataTmp;
e = deflate(&zshPtr->stream, flush);
- if ((e==Z_OK || e==Z_BUF_ERROR) && (zshPtr->stream.avail_out == 0)) {
- if (outSize - zshPtr->stream.avail_out > 0) {
- /*
- * Output buffer too small.
- */
-
- obj = Tcl_NewByteArrayObj((unsigned char *) dataTmp,
- outSize - zshPtr->stream.avail_out);
+ while (e == Z_BUF_ERROR) {
+ /*
+ * Output buffer too small to hold the data being generated; so
+ * put a new buffer into place after saving the old generated
+ * data to the outData list.
+ */
- /*
- * Now append the compressed data to the outData list.
- */
+ obj = Tcl_NewByteArrayObj((unsigned char *) dataTmp, outSize);
+ Tcl_ListObjAppendElement(NULL, zshPtr->outData, obj);
- Tcl_ListObjAppendElement(NULL, zshPtr->outData, obj);
- }
if (outSize < 0xFFFF) {
outSize = 0xFFFF; /* There may be *lots* of data left to
* output... */
- ckfree(dataTmp);
- dataTmp = ckalloc(outSize);
+ dataTmp = ckrealloc(dataTmp, outSize);
}
zshPtr->stream.avail_out = outSize;
zshPtr->stream.next_out = (Bytef *) dataTmp;
e = deflate(&zshPtr->stream, flush);
}
+
if (e != Z_OK && !(flush==Z_FINISH && e==Z_STREAM_END)) {
if (zshPtr->interp) {
ConvertError(zshPtr->interp, e, zshPtr->stream.adler);
@@ -3106,6 +3109,64 @@ ZlibTransformOutput(
/*
*----------------------------------------------------------------------
*
+ * ZlibTransformFlush --
+ *
+ * How to perform a flush of a compressing transform.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ZlibTransformFlush(
+ Tcl_Interp *interp,
+ ZlibChannelData *cd,
+ int flushType)
+{
+ int e, len;
+
+ cd->outStream.avail_in = 0;
+ do {
+ /*
+ * Get the bytes to go out of the compression engine.
+ */
+
+ cd->outStream.next_out = (Bytef *) cd->outBuffer;
+ cd->outStream.avail_out = cd->outAllocated;
+
+ e = deflate(&cd->outStream, flushType);
+ if (e != Z_OK && e != Z_BUF_ERROR) {
+ ConvertError(interp, e, cd->outStream.adler);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Write the bytes we've received to the next layer.
+ */
+
+ len = cd->outStream.next_out - (Bytef *) cd->outBuffer;
+ if (len > 0 && Tcl_WriteRaw(cd->parent, cd->outBuffer, len) < 0) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "problem flushing channel: %s",
+ Tcl_PosixError(interp)));
+ return TCL_ERROR;
+ }
+
+ /*
+ * If we get to this point, either we're in the Z_OK or the
+ * Z_BUF_ERROR state. In the former case, we're done. In the latter
+ * case, it's because there's more bytes to go than would fit in the
+ * buffer we provided, and we need to go round again to get some more.
+ *
+ * We also stop the loop if we would have done a zero-length write.
+ * Those can cause problems at the OS level.
+ */
+ } while (len > 0 && e == Z_BUF_ERROR);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* ZlibTransformSetOption --
*
* Writing side of [fconfigure] on our channel.
@@ -3178,32 +3239,7 @@ ZlibTransformSetOption( /* not used */
* Try to actually do the flush now.
*/
- cd->outStream.avail_in = 0;
- while (1) {
- int e;
-
- cd->outStream.next_out = (Bytef *) cd->outBuffer;
- cd->outStream.avail_out = cd->outAllocated;
-
- e = deflate(&cd->outStream, flushType);
- if (e == Z_BUF_ERROR) {
- break;
- } else if (e != Z_OK) {
- ConvertError(interp, e, cd->outStream.adler);
- return TCL_ERROR;
- } else if (cd->outStream.avail_out == 0) {
- break;
- }
-
- if (Tcl_WriteRaw(cd->parent, cd->outBuffer,
- cd->outStream.next_out - (Bytef *) cd->outBuffer)<0) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "problem flushing channel: %s",
- Tcl_PosixError(interp)));
- return TCL_ERROR;
- }
- }
- return TCL_OK;
+ return ZlibTransformFlush(interp, cd, flushType);
}
} else {
if (optionName && strcmp(optionName, "-limit") == 0) {
diff --git a/tests/zlib.test b/tests/zlib.test
index b1d43fb..7a486ba 100644
--- a/tests/zlib.test
+++ b/tests/zlib.test
@@ -132,6 +132,12 @@ test zlib-7.6 {zlib stream} zlib {
$s close
lappend result $data
} {{} 69f34b6a abcdeEDCBA..}
+test zlib-7.7 {zlib stream: Bug 25842c161} -constraints zlib -body {
+ set s [zlib stream deflate]
+ $s put {}
+} -cleanup {
+ catch {$s close}
+} -result ""
test zlib-8.1 {zlib transformation} -constraints zlib -setup {
set file [makeFile {} test.gz]