webrtc/net/dcsctp/packet/chunk/forward_tsn_chunk_test.cc
Victor Boivie 584b4df92d dcsctp: Don't deliver skipped messages
If a FORWARD-TSN contains an ordered skipped stream with a large TSN
but with a too small SSN, it can result in messages being assembled
that should've been skipped. Typically:

Receive DATA, ordered, complete, TSN=10, SID=1, SSN=0
  - will be delivered.
Receive DATA, ordered, complete, TSN=43, SID=1, SSN=7
  - will stay in queue, due to missing SSN=1,2,3,4,5,6.
Receive FORWARD-TSN, TSN=44, SSN=6
  - is invalid, as the SSN should've been 7 or higher.

However, as the TSN isn't used for removing messages in ordered streams,
but just the SSN, the SSN=7 isn't removed but instead will be delivered
as it's the next following SSN after 6. This will trigger internal
consistency checks as a chunk with TSN=43 will be delivered when the
current cumulative TSN is set to 44, which is greater.

This was found when fuzzing, and can only be provoked by a client that
is intentionally misbehaving. Before this fix, there was no harm done,
but it failed consistency checks which fuzzers have enabled. When
bug 13799 was fixed (in a previous commit), this allowed the fuzzers to
find it faster.

Bug: webrtc:13799
Change-Id: I830ef189476e227e1dbe08157d34f96ad6453e30
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/254240
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36157}
2022-03-09 11:22:15 +00:00

64 lines
2 KiB
C++

/*
* Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
#include <stdint.h>
#include <type_traits>
#include <vector>
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/forward_tsn_common.h"
#include "net/dcsctp/testing/testing_macros.h"
#include "rtc_base/gunit.h"
#include "test/gmock.h"
namespace dcsctp {
namespace {
using ::testing::ElementsAre;
TEST(ForwardTsnChunkTest, FromCapture) {
/*
FORWARD_TSN chunk(Cumulative TSN: 1905748778)
Chunk type: FORWARD_TSN (192)
Chunk flags: 0x00
Chunk length: 8
New cumulative TSN: 1905748778
*/
uint8_t data[] = {0xc0, 0x00, 0x00, 0x08, 0x71, 0x97, 0x6b, 0x2a};
ASSERT_HAS_VALUE_AND_ASSIGN(ForwardTsnChunk chunk,
ForwardTsnChunk::Parse(data));
EXPECT_EQ(*chunk.new_cumulative_tsn(), 1905748778u);
}
TEST(ForwardTsnChunkTest, SerializeAndDeserialize) {
ForwardTsnChunk chunk(
TSN(123), {ForwardTsnChunk::SkippedStream(StreamID(1), SSN(23)),
ForwardTsnChunk::SkippedStream(StreamID(42), SSN(99))});
std::vector<uint8_t> serialized;
chunk.SerializeTo(serialized);
ASSERT_HAS_VALUE_AND_ASSIGN(ForwardTsnChunk deserialized,
ForwardTsnChunk::Parse(serialized));
EXPECT_EQ(*deserialized.new_cumulative_tsn(), 123u);
EXPECT_THAT(
deserialized.skipped_streams(),
ElementsAre(ForwardTsnChunk::SkippedStream(StreamID(1), SSN(23)),
ForwardTsnChunk::SkippedStream(StreamID(42), SSN(99))));
EXPECT_EQ(deserialized.ToString(),
"FORWARD-TSN, new_cumulative_tsn=123, skip 1:23, skip 42:99");
}
} // namespace
} // namespace dcsctp