-
Notifications
You must be signed in to change notification settings - Fork 685
Fix uint32 overflow in receive buffer growth #6226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8fa9fae
1071065
298714b
b053b33
5b5b933
0194d49
6efd483
38d7f3a
9ae9fa3
f527d14
beabe69
10c75c4
9537b63
0287dc4
524eb22
ad97fa2
3acb4fc
070a7c9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -804,8 +804,13 @@ QuicStreamOnBytesDelivered( | |
| // | ||
| // Limit stream FC window growth by the connection FC window size. | ||
| // | ||
| const uint32_t MaxVirtualBufferLength = | ||
| Stream->RecvBuffer.RecvMode == QUIC_RECV_BUF_MODE_APP_OWNED ? | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure we need this. |
||
| UINT32_MAX : | ||
| 0x80000000U; | ||
| if (Stream->RecvBuffer.VirtualBufferLength != 0 && | ||
| Stream->RecvBuffer.VirtualBufferLength < Stream->Connection->Settings.ConnFlowControlWindow) { | ||
| Stream->RecvBuffer.VirtualBufferLength < Stream->Connection->Settings.ConnFlowControlWindow && | ||
| Stream->RecvBuffer.VirtualBufferLength < MaxVirtualBufferLength) { | ||
| uint64_t TimeThreshold = | ||
| ((Stream->RecvWindowBytesDelivered * Stream->Connection->Paths[0].SmoothedRtt) / RecvBufferDrainThreshold); | ||
| if (CxPlatTimeDiff64(Stream->RecvWindowLastUpdate, TimeNow) <= TimeThreshold) { | ||
|
|
@@ -830,7 +835,7 @@ QuicStreamOnBytesDelivered( | |
| // | ||
|
|
||
| uint64_t NewLength = (uint64_t)Stream->RecvBuffer.VirtualBufferLength * 2; | ||
| NewLength = CXPLAT_MIN(NewLength, UINT32_MAX); | ||
| NewLength = CXPLAT_MIN(NewLength, MaxVirtualBufferLength); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Simply don't do the doubling (or undo it) when it would overflow rather than using a constant. This line is actually redundant with the check in the if test above. |
||
|
|
||
| QuicRecvBufferIncreaseVirtualBufferLength( | ||
| &Stream->RecvBuffer, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -547,6 +547,30 @@ TEST_P(WithMode, WriteTooMuch2) | |
| ASSERT_FALSE(RecvBuf.HasUnreadData()); | ||
| } | ||
|
|
||
| TEST(RecvBufferGrowthTest, WriteGrowthOverflow) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider having this test running with all buffer modes. |
||
| { | ||
| RecvBuffer RecvBuf; | ||
| ASSERT_EQ(QUIC_STATUS_SUCCESS, RecvBuf.Initialize(QUIC_RECV_BUF_MODE_SINGLE)); | ||
|
|
||
| RecvBuf.IncreaseVirtualBufferLength(UINT32_MAX); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Setting the virtual buffer size to something that isn't a power of 2 is not meant to happen unless in app-owned buffer mode (and even that is probably what should be fixed). |
||
|
|
||
| uint8_t WriteBuffer = 0; | ||
| uint64_t QuotaConsumed = 0; | ||
| uint64_t BufferSizeNeeded = 0; | ||
| BOOLEAN NewDataReady = FALSE; | ||
| ASSERT_EQ( | ||
| QUIC_STATUS_OUT_OF_MEMORY, | ||
| QuicRecvBufferWrite( | ||
| &RecvBuf.RecvBuf, | ||
| 0x80000000U, | ||
| sizeof(WriteBuffer), | ||
| &WriteBuffer, | ||
| UINT32_MAX, | ||
| &QuotaConsumed, | ||
| &NewDataReady, | ||
| &BufferSizeNeeded)); | ||
| } | ||
|
|
||
| TEST_P(WithMode, WriteWhilePendingRead) | ||
| { | ||
| RecvBuffer RecvBuf; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be impossible as long as the invariant of the receive buffer are respected.
This path is already not reachable when app-owned buffer are used, so the virtual length is a power of two that fit in a uint32_t, and we would not reach this line if the write was requiring an allocation larger than the virtual length.