Subject: Stop the segfaults in [close] during [gets] tests. Not sure this is the right behavior, but it's better than crashing.

From: dgp <[email-masked]>
Date: Wed, 30 Apr 2014 19:54:51 +0000

---
 generic/tclIO.c  | 23 ++++++++++++++---------
 tests/ioCmd.test | 21 +++++++++++++++++++--
 2 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/generic/tclIO.c b/generic/tclIO.c
index 0c9db67..cd28a0e 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -4163,12 +4163,12 @@ Tcl_GetsObj(
 
   restore:
     bufPtr = statePtr->inQueueHead;
-    if (bufPtr == NULL) {
-	Tcl_Panic("Tcl_GetsObj: restore reached with bufPtr==NULL");
+    if (bufPtr != NULL) {
+	bufPtr->nextRemoved = oldRemoved;
+	bufPtr = bufPtr->nextPtr;
     }
-    bufPtr->nextRemoved = oldRemoved;
 
-    for (bufPtr = bufPtr->nextPtr; bufPtr != NULL; bufPtr = bufPtr->nextPtr) {
+    for ( ; bufPtr != NULL; bufPtr = bufPtr->nextPtr) {
 	bufPtr->nextRemoved = BUFFER_PADDING;
     }
     CommonGetsCleanup(chanPtr);
@@ -4298,6 +4298,9 @@ TclGetsObjBinary(
 		goto restore;
 	    }
 	    bufPtr = statePtr->inQueueTail;
+	    if (bufPtr == NULL) {
+		goto restore;
+	    }
 	}
 
 	dst = (unsigned char *) RemovePoint(bufPtr);
@@ -4410,12 +4413,12 @@ TclGetsObjBinary(
 
   restore:
     bufPtr = statePtr->inQueueHead;
-    if (bufPtr == NULL) {
-	Tcl_Panic("TclGetsObjBinary: restore reached with bufPtr==NULL");
+    if (bufPtr) {
+	bufPtr->nextRemoved = oldRemoved;
+	bufPtr = bufPtr->nextPtr;
     }
-    bufPtr->nextRemoved = oldRemoved;
 
-    for (bufPtr = bufPtr->nextPtr; bufPtr != NULL; bufPtr = bufPtr->nextPtr) {
+    for ( ; bufPtr != NULL; bufPtr = bufPtr->nextPtr) {
 	bufPtr->nextRemoved = BUFFER_PADDING;
     }
     CommonGetsCleanup(chanPtr);
@@ -4571,7 +4574,9 @@ FilterInputBytes(
 	bufPtr = statePtr->inQueueTail;
 	gsPtr->bufPtr = bufPtr;
 	if (bufPtr == NULL) {
-	    Tcl_Panic("GetInput nuked buffers!");
+	    gsPtr->charsWrote = 0;
+	    gsPtr->rawRead = 0;
+	    return -1;
 	}
     }
 
diff --git a/tests/ioCmd.test b/tests/ioCmd.test
index d2c0173..bb133f9 100644
--- a/tests/ioCmd.test
+++ b/tests/ioCmd.test
@@ -818,10 +818,27 @@ test iocmd-21.23 {[close] in [gets] segfaults} -setup {
     set ch [chan create read foo]
 } -body {
     gets $ch
-} -returnCodes error -cleanup {
+} -cleanup {
     catch {close $ch}
     rename foo {}
-} -match glob -result {*invalid argument*}
+} -result {}
+test iocmd-21.24 {[close] in binary [gets] segfaults} -setup {
+    proc foo {method chan args} {
+	switch -- $method initialize {
+	    return {initialize finalize watch read}
+	} finalize {} watch {} read {
+	    catch {close $chan}
+	    return \n
+	}
+    }
+    set ch [chan create read foo]
+} -body {
+    chan configure $ch -translation binary
+    gets $ch
+} -cleanup {
+    catch {close $ch}
+    rename foo {}
+} -result {}
 
 # --- --- --- --------- --------- ---------
 # Helper commands to record the arguments to handler methods.
-- 
cgit v0.12