Skip to content

Commit 77c0b6c

Browse files
afrindmeta-codesync[bot]
authored andcommitted
Fix for codec cursor invalidation
Summary: For zero-length objects we were not updating the cursor propertly after trim. Reviewed By: sandarsh Differential Revision: D89077848 fbshipit-source-id: bca05b290b4342783fbc1ad15192cbff128a17e9
1 parent 32c9bc9 commit 77c0b6c

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

moxygen/MoQCodec.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,10 @@ MoQCodec::ParseResult MoQObjectStreamCodec::onIngress(
164164
payload = ingress_.move();
165165
cursor = folly::io::Cursor(&empty);
166166
} else {
167-
payload = ingress_.split(size);
168-
XCHECK(!ingress_.empty());
167+
if (size > 0) {
168+
payload = ingress_.split(size);
169+
}
170+
// Reset cursor after split (or after trimStart if size == 0)
169171
cursor = folly::io::Cursor(ingress_.front());
170172
}
171173
return payload;
@@ -286,9 +288,7 @@ MoQCodec::ParseResult MoQObjectStreamCodec::onIngress(
286288

287289
std::unique_ptr<folly::IOBuf> payload;
288290
auto chunkLen = availableForObject(*curObjectHeader_.length);
289-
if (chunkLen > 0) {
290-
payload = splitAndResetCursor(chunkLen);
291-
}
291+
payload = splitAndResetCursor(chunkLen);
292292
auto endOfObject = chunkLen == *curObjectHeader_.length;
293293
if (endOfStream && !endOfObject) {
294294
XLOG(ERR) << "End of stream before end of object";
@@ -365,9 +365,7 @@ MoQCodec::ParseResult MoQObjectStreamCodec::onIngress(
365365
XLOG(DBG2) << "Parsing object with length, need="
366366
<< *curObjectHeader_.length;
367367
auto chunkLen = availableForObject(*curObjectHeader_.length);
368-
if (chunkLen > 0) {
369-
payload = splitAndResetCursor(chunkLen);
370-
}
368+
payload = splitAndResetCursor(chunkLen);
371369
*curObjectHeader_.length -= chunkLen;
372370
if (endOfStream && *curObjectHeader_.length != 0) {
373371
XLOG(ERR) << "End of stream before end of object remaining length="

moxygen/test/MoQCodecTest.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,61 @@ TEST_P(MoQCodecTest, CallbackReturnsContinue) {
742742
EXPECT_EQ(result, MoQCodec::ParseResult::CONTINUE);
743743
}
744744

745+
// Test zero-length status object followed by normal object
746+
// This exposes a cursor invalidation bug where trimStart() invalidates the
747+
// cursor, but when chunkLen == 0, splitAndResetCursor() isn't called,
748+
// leaving the cursor stale for the next object parse.
749+
TEST_P(MoQCodecTest, ZeroLengthObjectFollowedByNormalObject) {
750+
folly::IOBufQueue writeBuf{folly::IOBufQueue::cacheChainLength()};
751+
auto res = moqFrameWriter_.writeSubgroupHeader(
752+
writeBuf,
753+
TrackAlias(1),
754+
ObjectHeader(2, 3, 0, 5),
755+
SubgroupIDFormat::Present,
756+
false);
757+
758+
// Write a zero-length status object (valid zero-length case)
759+
ObjectHeader statusObj(0, 0, 4, 0);
760+
statusObj.status = ObjectStatus::OBJECT_NOT_EXIST;
761+
statusObj.length = 0;
762+
res = moqFrameWriter_.writeStreamObject(
763+
writeBuf, StreamType::SUBGROUP_HEADER_SG, statusObj, nullptr);
764+
765+
// Write another object with non-zero length
766+
ObjectHeader normalObj(0, 0, 5, 0, 5);
767+
res = moqFrameWriter_.writeStreamObject(
768+
writeBuf,
769+
StreamType::SUBGROUP_HEADER_SG,
770+
normalObj,
771+
folly::IOBuf::copyBuffer("hello"));
772+
773+
EXPECT_CALL(
774+
objectStreamCodecCallback_,
775+
onSubgroup(TrackAlias(1), 2, 3, folly::Optional<uint8_t>(5), testing::_));
776+
777+
// Expect onObjectStatus for the zero-length status object
778+
EXPECT_CALL(
779+
objectStreamCodecCallback_,
780+
onObjectStatus(
781+
2,
782+
3,
783+
4,
784+
folly::Optional<uint8_t>(5),
785+
ObjectStatus::OBJECT_NOT_EXIST,
786+
testing::_))
787+
.WillOnce(testing::Return(MoQCodec::ParseResult::CONTINUE));
788+
789+
// Expect onObjectBegin for the normal object (this would crash without the
790+
// fix)
791+
EXPECT_CALL(
792+
objectStreamCodecCallback_,
793+
onObjectBegin(2, 3, 5, testing::_, 5, testing::_, true, false))
794+
.WillOnce(testing::Return(MoQCodec::ParseResult::CONTINUE));
795+
796+
auto result = objectStreamCodec_.onIngress(writeBuf.move(), false);
797+
EXPECT_EQ(result, MoQCodec::ParseResult::CONTINUE);
798+
}
799+
745800
INSTANTIATE_TEST_SUITE_P(
746801
MoQCodecTest,
747802
MoQCodecTest,

0 commit comments

Comments
 (0)