summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorapnadkarni <apnmbx-wits@yahoo.com>2023-03-01 13:18:17 (GMT)
committerapnadkarni <apnmbx-wits@yahoo.com>2023-03-01 13:18:17 (GMT)
commit30a9b333ba194339f5e8f68575626df0701b2a50 (patch)
tree4c5588b358d57274bcb77c78979fde884c77bd73 /generic
parenta6b4ef3d29565b68fb8c7104b11b03a99e0b153e (diff)
downloadtcl-30a9b333ba194339f5e8f68575626df0701b2a50.zip
tcl-30a9b333ba194339f5e8f68575626df0701b2a50.tar.gz
tcl-30a9b333ba194339f5e8f68575626df0701b2a50.tar.bz2
Bug [9a978f8323]: crash reading large files
Diffstat (limited to 'generic')
-rw-r--r--generic/tclIO.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index ff74a99..ce0dcc8 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -191,9 +191,9 @@ static int DetachChannel(Tcl_Interp *interp, Tcl_Channel chan);
static void DiscardInputQueued(ChannelState *statePtr,
int discardSavedBuffers);
static void DiscardOutputQueued(ChannelState *chanPtr);
-static int DoRead(Channel *chanPtr, char *dst, Tcl_Size bytesToRead,
+static Tcl_Size DoRead(Channel *chanPtr, char *dst, Tcl_Size bytesToRead,
int allowShortReads);
-static int DoReadChars(Channel *chan, Tcl_Obj *objPtr, Tcl_Size toRead,
+static Tcl_Size DoReadChars(Channel *chan, Tcl_Obj *objPtr, Tcl_Size toRead,
int appendFlag);
static int FilterInputBytes(Channel *chanPtr,
GetsState *statePtr);
@@ -5946,11 +5946,11 @@ Tcl_ReadChars(
*---------------------------------------------------------------------------
*/
-static int
+static Tcl_Size
DoReadChars(
Channel *chanPtr, /* The channel to read. */
Tcl_Obj *objPtr, /* Input data is stored in this object. */
- Tcl_Size toRead, /* Maximum number of characters to store, or
+ Tcl_Size toRead, /* Maximum number of characters to store, or
* TCL_INDEX_NONE to read all available data (up to EOF or
* when channel blocks). */
int appendFlag) /* If non-zero, data read from the channel
@@ -5961,7 +5961,8 @@ DoReadChars(
ChannelState *statePtr = chanPtr->state;
/* State info for channel */
ChannelBuffer *bufPtr;
- int copied, copiedNow, result;
+ Tcl_Size copied;
+ int result;
Tcl_Encoding encoding = statePtr->encoding;
int binaryMode;
#define UTF_EXPANSION_FACTOR 1024
@@ -6046,8 +6047,8 @@ DoReadChars(
}
ResetFlag(statePtr, CHANNEL_BLOCKED|CHANNEL_EOF);
statePtr->inputEncodingFlags &= ~TCL_ENCODING_END;
- for (copied = 0; toRead > 0; ) {
- copiedNow = -1;
+ for (copied = 0; toRead > 0 || toRead == TCL_INDEX_NONE; ) {
+ int copiedNow = -1;
if (statePtr->inQueueHead != NULL) {
if (binaryMode) {
copiedNow = ReadBytes(statePtr, objPtr, toRead);
@@ -6093,7 +6094,9 @@ DoReadChars(
}
} else {
copied += copiedNow;
- toRead -= copiedNow;
+ if (toRead != TCL_INDEX_NONE) {
+ toRead -= copiedNow; /* Only decr if not reading whole file */
+ }
}
}
@@ -6269,7 +6272,7 @@ ReadChars(
size_t size;
dst = TclGetStringStorage(objPtr, &size) + numBytes;
- dstLimit = size - numBytes;
+ dstLimit = (size - numBytes) > INT_MAX ? INT_MAX : (size - numBytes);
} else {
dst = TclGetString(objPtr) + numBytes;
}
@@ -9671,9 +9674,10 @@ CopyData(
Tcl_Obj *cmdPtr, *errObj = NULL, *bufObj = NULL, *msg = NULL;
Tcl_Channel inChan, outChan;
ChannelState *inStatePtr, *outStatePtr;
- int result = TCL_OK, size;
+ int result = TCL_OK;
Tcl_Size sizeb;
Tcl_WideInt total;
+ Tcl_WideInt size; /* TODO - be careful if total and size are made unsigned */
const char *buffer;
int inBinary, outBinary, sameEncoding;
/* Encoding control */
@@ -10011,7 +10015,7 @@ CopyData(
*----------------------------------------------------------------------
*/
-static int
+static Tcl_Size
DoRead(
Channel *chanPtr, /* The channel from which to read. */
char *dst, /* Where to store input read. */