Skip to content

Commit

Permalink
[TLS]: Fix #23792.
Browse files Browse the repository at this point in the history
What happens here is the following:

When using chunked encoding, the ChunkStream sometimes mixes async and sync requests
on the underlying stream.  The async calls work great - just the sync ones create
problems.

In this particular bug, the server returns two ApplicationData records - one big one
and then a smaller one.  The chunk parser requests a sync read of 1024 bytes which
then result in a series of sync reads on the underlying network stream.  The first
two or three network reads don't return enough data to fill the huge ApplicationData
record - the last one then returns so much data that it fills both the remainder of
the first record and the entire second one.

If the caller issued a second sync read, then the implementation would catch this -
but the async code path does not.
  • Loading branch information
Martin Baulig committed May 20, 2015
1 parent c7bf3e8 commit bc19662
Showing 1 changed file with 23 additions and 2 deletions.
Expand Up @@ -601,6 +601,9 @@ private void InternalBeginRead(InternalAsyncResult asyncResult)
{
asyncResult.SetComplete(preReadSize);
}
else if (recordStream.Position < recordStream.Length) {
InternalReadCallback_inner (asyncResult, recbuf, new object[] { recbuf, asyncResult }, false, 0);
}
else if (!this.context.ReceivedConnectionEnd)
{
// this will read data from the network until we have (at least) one
Expand Down Expand Up @@ -650,6 +653,24 @@ private void InternalReadCallback(IAsyncResult result)
return;
}

InternalReadCallback_inner(internalResult, recbuf, state, true, n);
}
catch (Exception ex)
{
internalResult.SetComplete(ex);
}

}

// read encrypted data until we have enough to decrypt (at least) one
// record and return are the records (may be more than one) we have
private void InternalReadCallback_inner(InternalAsyncResult internalResult, byte[] recbuf, object[] state, bool didRead, int n)
{
if (this.disposed)
return;

try
{
bool dataToReturn = false;
long pos = recordStream.Position;

Expand Down Expand Up @@ -713,7 +734,7 @@ record = this.protocol.ReceiveRecord(recordStream);
pos = 0;
}

if (!dataToReturn && (n > 0))
if (!dataToReturn && (!didRead || (n > 0)))
{
if (context.ReceivedConnectionEnd) {
internalResult.SetComplete (0);
Expand Down Expand Up @@ -744,7 +765,6 @@ record = this.protocol.ReceiveRecord(recordStream);
{
internalResult.SetComplete(ex);
}

}

private void InternalBeginWrite(InternalAsyncResult asyncResult)
Expand Down Expand Up @@ -1022,6 +1042,7 @@ record = null;

if (remainder > 0) {
recordStream.Write (outofrecord, 0, outofrecord.Length);
recordStream.Position = 0;
}

if (dataToReturn) {
Expand Down

0 comments on commit bc19662

Please sign in to comment.