Add separate LC_ASSERT_VT() for asserts that only apply for valid traffic

This commit is contained in:
Cameron Gutman
2023-10-11 20:01:39 -05:00
parent 574ad6e676
commit 620b4be477
7 changed files with 89 additions and 74 deletions

View File

@@ -197,14 +197,14 @@ static void decodeInputData(PQUEUED_AUDIO_PACKET packet) {
(unsigned char*)(rtp + 1), dataLength,
decryptedOpusData, &dataLength)) {
Limelog("Failed to decrypt audio packet (sequence number: %u)\n", rtp->sequenceNumber);
LC_ASSERT(false);
LC_ASSERT_VT(false);
return;
}
#ifdef LC_DEBUG
if (opusHeaderByte == INVALID_OPUS_HEADER) {
opusHeaderByte = decryptedOpusData[0];
LC_ASSERT(opusHeaderByte != INVALID_OPUS_HEADER);
LC_ASSERT_VT(opusHeaderByte != INVALID_OPUS_HEADER);
}
else {
// Opus header should stay constant for the entire stream.
@@ -212,7 +212,7 @@ static void decodeInputData(PQUEUED_AUDIO_PACKET packet) {
// incorrectly recovered a data shard or the decryption
// of the audio packet failed. Sunshine violates this for
// surround sound in some cases, so just ignore it.
LC_ASSERT(decryptedOpusData[0] == opusHeaderByte || IS_SUNSHINE());
LC_ASSERT_VT(decryptedOpusData[0] == opusHeaderByte || IS_SUNSHINE());
}
#endif
@@ -222,13 +222,13 @@ static void decodeInputData(PQUEUED_AUDIO_PACKET packet) {
#ifdef LC_DEBUG
if (opusHeaderByte == INVALID_OPUS_HEADER) {
opusHeaderByte = ((uint8_t*)(rtp + 1))[0];
LC_ASSERT(opusHeaderByte != INVALID_OPUS_HEADER);
LC_ASSERT_VT(opusHeaderByte != INVALID_OPUS_HEADER);
}
else {
// Opus header should stay constant for the entire stream.
// If it doesn't, it may indicate that the RtpAudioQueue
// incorrectly recovered a data shard.
LC_ASSERT(((uint8_t*)(rtp + 1))[0] == opusHeaderByte);
LC_ASSERT_VT(((uint8_t*)(rtp + 1))[0] == opusHeaderByte);
}
#endif

View File

@@ -425,7 +425,7 @@ void connectionSendFrameFecStatus(PSS_FRAME_FEC_STATUS fecStatus) {
}
void connectionSawFrame(int frameIndex) {
LC_ASSERT(!isBefore16(frameIndex, lastSeenFrame));
LC_ASSERT_VT(!isBefore16(frameIndex, lastSeenFrame));
uint64_t now = PltGetMillis();
@@ -1123,7 +1123,7 @@ static void controlReceiveThreadFunc(void* context) {
}
else {
// What do we do here???
LC_ASSERT(false);
LC_ASSERT_VT(false);
packetLength = (int)event.packet->dataLength;
event.packet->data = NULL;
}

View File

@@ -86,6 +86,17 @@
#define LC_ASSERT(x) assert(x)
#endif
// If we're fuzzing, we don't want to enable asserts that can be affected by
// bad input from the remote host. LC_ASSERT_VT() is used for assertions that
// check data that comes from the host. These checks are enabled for normal
// debug builds, since they indicate an error in Moonlight or on the host.
// These are disabled when fuzzing, since the traffic is intentionally invalid.
#ifdef LC_FUZZING
#define LC_ASSERT_VT(x)
#else
#define LC_ASSERT_VT(x) LC_ASSERT(x)
#endif
#ifdef _MSC_VER
#pragma intrinsic(_byteswap_ushort)
#define BSWAP16(x) _byteswap_ushort(x)

View File

@@ -1,6 +1,6 @@
#include "Limelight-internal.h"
#ifdef LC_DEBUG
#if defined(LC_DEBUG) && !defined(LC_FUZZING)
// This enables FEC validation mode with a synthetic drop
// and recovered packet checks vs the original input. It
// is on by default for debug builds.
@@ -86,12 +86,12 @@ static void validateFecBlockState(PRTP_AUDIO_QUEUE queue) {
while (block != NULL) {
// Ensure the list is sorted correctly
LC_ASSERT(isBefore16(lastSeqNum, block->fecHeader.baseSequenceNumber));
LC_ASSERT(isBefore32(lastTs, block->fecHeader.baseTimestamp));
LC_ASSERT_VT(isBefore32(lastTs, block->fecHeader.baseTimestamp));
// Ensure entry invariants are satisfied
LC_ASSERT(block->blockSize == lastBlock->blockSize);
LC_ASSERT(block->fecHeader.payloadType == lastBlock->fecHeader.payloadType);
LC_ASSERT(block->fecHeader.ssrc == lastBlock->fecHeader.ssrc);
LC_ASSERT_VT(block->blockSize == lastBlock->blockSize);
LC_ASSERT_VT(block->fecHeader.payloadType == lastBlock->fecHeader.payloadType);
LC_ASSERT_VT(block->fecHeader.ssrc == lastBlock->fecHeader.ssrc);
// Ensure the list itself is consistent
LC_ASSERT(block->prev == lastBlock);
@@ -205,7 +205,7 @@ static PRTPA_FEC_BLOCK getFecBlockForRtpPacket(PRTP_AUDIO_QUEUE queue, PRTP_PACK
if (packet->packetType == RTP_PAYLOAD_TYPE_AUDIO) {
if (length < sizeof(RTP_PACKET)) {
Limelog("RTP audio data packet too small: %u\n", length);
LC_ASSERT(false);
LC_ASSERT_VT(false);
return NULL;
}
@@ -239,7 +239,7 @@ static PRTPA_FEC_BLOCK getFecBlockForRtpPacket(PRTP_AUDIO_QUEUE queue, PRTP_PACK
if (length < sizeof(RTP_PACKET) + sizeof(AUDIO_FEC_HEADER)) {
Limelog("RTP audio FEC packet too small: %u\n", length);
LC_ASSERT(false);
LC_ASSERT_VT(false);
return NULL;
}
@@ -253,7 +253,7 @@ static PRTPA_FEC_BLOCK getFecBlockForRtpPacket(PRTP_AUDIO_QUEUE queue, PRTP_PACK
// later during recovery.
if (fecHeader->fecShardIndex >= RTPA_FEC_SHARDS) {
Limelog("Too many audio FEC shards: %u\n", fecHeader->fecShardIndex);
LC_ASSERT(false);
LC_ASSERT_VT(false);
return NULL;
}
@@ -264,7 +264,7 @@ static PRTPA_FEC_BLOCK getFecBlockForRtpPacket(PRTP_AUDIO_QUEUE queue, PRTP_PACK
Limelog("Invalid FEC block base sequence number (got %u, expected %u)\n",
fecBlockBaseSeqNum, (fecBlockBaseSeqNum / RTPA_DATA_SHARDS) * RTPA_DATA_SHARDS);
Limelog("Audio FEC has been disabled due to an incompatibility with your host's old software!\n");
LC_ASSERT(fecBlockBaseSeqNum % RTPA_DATA_SHARDS == 0);
LC_ASSERT_VT(fecBlockBaseSeqNum % RTPA_DATA_SHARDS == 0);
queue->incompatibleServer = true;
return NULL;
}
@@ -273,7 +273,7 @@ static PRTPA_FEC_BLOCK getFecBlockForRtpPacket(PRTP_AUDIO_QUEUE queue, PRTP_PACK
}
else {
Limelog("Invalid RTP audio payload type: %u\n", packet->packetType);
LC_ASSERT(false);
LC_ASSERT_VT(false);
return NULL;
}
@@ -296,9 +296,9 @@ static PRTPA_FEC_BLOCK getFecBlockForRtpPacket(PRTP_AUDIO_QUEUE queue, PRTP_PACK
while (existingBlock != NULL) {
if (existingBlock->fecHeader.baseSequenceNumber == fecBlockBaseSeqNum) {
// The FEC header data should match for all packets
LC_ASSERT(existingBlock->fecHeader.payloadType == fecBlockPayloadType);
LC_ASSERT(existingBlock->fecHeader.baseTimestamp == fecBlockBaseTs);
LC_ASSERT(existingBlock->fecHeader.ssrc == fecBlockSsrc);
LC_ASSERT_VT(existingBlock->fecHeader.payloadType == fecBlockPayloadType);
LC_ASSERT_VT(existingBlock->fecHeader.baseTimestamp == fecBlockBaseTs);
LC_ASSERT_VT(existingBlock->fecHeader.ssrc == fecBlockSsrc);
// The block size must match in order to safely copy shards into it
if (existingBlock->blockSize != blockSize) {
@@ -306,7 +306,7 @@ static PRTPA_FEC_BLOCK getFecBlockForRtpPacket(PRTP_AUDIO_QUEUE queue, PRTP_PACK
// constant size for audio packets.
Limelog("Audio block size mismatch (got %u, expected %u)\n", blockSize, existingBlock->blockSize);
Limelog("Audio FEC has been disabled due to an incompatibility with your host's old software!\n");
LC_ASSERT(existingBlock->blockSize == blockSize);
LC_ASSERT_VT(existingBlock->blockSize == blockSize);
queue->incompatibleServer = true;
return NULL;
}
@@ -464,11 +464,11 @@ static bool completeFecBlock(PRTP_AUDIO_QUEUE queue, PRTPA_FEC_BLOCK block) {
#ifdef FEC_VALIDATION_MODE
// Check the RTP header values
LC_ASSERT(block->dataPackets[dropIndex]->header == droppedRtpPacket->header);
LC_ASSERT(block->dataPackets[dropIndex]->packetType == droppedRtpPacket->packetType);
LC_ASSERT(block->dataPackets[dropIndex]->sequenceNumber == droppedRtpPacket->sequenceNumber);
LC_ASSERT(block->dataPackets[dropIndex]->timestamp == droppedRtpPacket->timestamp);
LC_ASSERT(block->dataPackets[dropIndex]->ssrc == droppedRtpPacket->ssrc);
LC_ASSERT_VT(block->dataPackets[dropIndex]->header == droppedRtpPacket->header);
LC_ASSERT_VT(block->dataPackets[dropIndex]->packetType == droppedRtpPacket->packetType);
LC_ASSERT_VT(block->dataPackets[dropIndex]->sequenceNumber == droppedRtpPacket->sequenceNumber);
LC_ASSERT_VT(block->dataPackets[dropIndex]->timestamp == droppedRtpPacket->timestamp);
LC_ASSERT_VT(block->dataPackets[dropIndex]->ssrc == droppedRtpPacket->ssrc);
// Check the data itself - use memcmp() and only loop if an error is detected
if (memcmp(block->dataPackets[dropIndex] + 1, droppedRtpPacket + 1, block->blockSize)) {
@@ -484,7 +484,7 @@ static bool completeFecBlock(PRTP_AUDIO_QUEUE queue, PRTPA_FEC_BLOCK block) {
}
}
LC_ASSERT(recoveryErrors == 0);
LC_ASSERT_VT(recoveryErrors == 0);
}
free(droppedRtpPacket);
@@ -523,7 +523,7 @@ static void handleMissingPackets(PRTP_AUDIO_QUEUE queue) {
// If we reach this point, we know the next packet resides in the first FEC block we're
// currently waiting on. In that case, we want to wait at least until we have a second FEC
// block to give up on the first one. If we don't have a second block now, just keep waiting.
LC_ASSERT(isBefore16(queue->nextRtpSequenceNumber, queue->blockHead->fecHeader.baseSequenceNumber + RTPA_DATA_SHARDS));
LC_ASSERT_VT(isBefore16(queue->nextRtpSequenceNumber, queue->blockHead->fecHeader.baseSequenceNumber + RTPA_DATA_SHARDS));
if (queue->blockHead == queue->blockTail) {
return;
}

View File

@@ -1,7 +1,7 @@
#include "Limelight-internal.h"
#include "rs.h"
#ifdef LC_DEBUG
#if defined(LC_DEBUG) && !defined(LC_FUZZING)
// This enables FEC validation mode with a synthetic drop
// and recovered packet checks vs the original input. It
// is on by default for debug builds.
@@ -376,15 +376,15 @@ cleanup_packets:
int j;
int recoveryErrors = 0;
LC_ASSERT(droppedDataLength <= recoveredDataLength);
LC_ASSERT(droppedDataLength == recoveredDataLength || (nvPacket->flags & FLAG_EOF));
LC_ASSERT_VT(droppedDataLength <= recoveredDataLength);
LC_ASSERT_VT(droppedDataLength == recoveredDataLength || (nvPacket->flags & FLAG_EOF));
// Check all NV_VIDEO_PACKET fields except FEC stuff which differs in the recovered packet
LC_ASSERT(nvPacket->flags == droppedNvPacket->flags);
LC_ASSERT(nvPacket->frameIndex == droppedNvPacket->frameIndex);
LC_ASSERT(nvPacket->streamPacketIndex == droppedNvPacket->streamPacketIndex);
LC_ASSERT(nvPacket->reserved == droppedNvPacket->reserved);
LC_ASSERT(!queue->multiFecCapable || nvPacket->multiFecBlocks == droppedNvPacket->multiFecBlocks);
LC_ASSERT_VT(nvPacket->flags == droppedNvPacket->flags);
LC_ASSERT_VT(nvPacket->frameIndex == droppedNvPacket->frameIndex);
LC_ASSERT_VT(nvPacket->streamPacketIndex == droppedNvPacket->streamPacketIndex);
LC_ASSERT_VT(nvPacket->reserved == droppedNvPacket->reserved);
LC_ASSERT_VT(!queue->multiFecCapable || nvPacket->multiFecBlocks == droppedNvPacket->multiFecBlocks);
// Check the data itself - use memcmp() and only loop if an error is detected
if (memcmp(nvPacket + 1, droppedNvPacket + 1, droppedDataLength)) {
@@ -409,7 +409,7 @@ cleanup_packets:
}
}
LC_ASSERT(recoveryErrors == 0);
LC_ASSERT_VT(recoveryErrors == 0);
// This drop was fake, so we don't want to actually submit it to the depacketizer.
// It will get confused because it's already seen this packet before.
@@ -542,7 +542,7 @@ int RtpvAddPacket(PRTP_VIDEO_QUEUE queue, PRTP_PACKET packet, int length, PRTPV_
}
// FLAG_EXTENSION is required for all supported versions of GFE.
LC_ASSERT(packet->header & FLAG_EXTENSION);
LC_ASSERT_VT(packet->header & FLAG_EXTENSION);
int dataOffset = sizeof(*packet);
if (packet->header & FLAG_EXTENSION) {
@@ -567,11 +567,13 @@ int RtpvAddPacket(PRTP_VIDEO_QUEUE queue, PRTP_PACKET packet, int length, PRTPV_
nvPacket->multiFecFlags = 0x10;
nvPacket->multiFecBlocks = 0x00;
}
#ifndef LC_FUZZING
if (isBefore16(nvPacket->frameIndex, queue->currentFrameNumber)) {
// Reject frames behind our current frame number
return RTPF_RET_REJECTED;
}
#endif
uint32_t fecIndex = (nvPacket->fecInfo & 0x3FF000) >> 12;
uint8_t fecCurrentBlockNumber = (nvPacket->multiFecBlocks >> 4) & 0x3;
@@ -666,7 +668,7 @@ int RtpvAddPacket(PRTP_VIDEO_QUEUE queue, PRTP_PACKET packet, int length, PRTPV_
// The check here looks weird, but that's because we increment the frame number
// after successfully processing a frame.
if (queue->currentFrameNumber != nvPacket->frameIndex) {
LC_ASSERT(queue->currentFrameNumber < nvPacket->frameIndex);
LC_ASSERT_VT(queue->currentFrameNumber < nvPacket->frameIndex);
// If the frame immediately preceding this one was lost, we may have already
// reported it using our speculative RFI logic. Don't report it again.
@@ -707,19 +709,19 @@ int RtpvAddPacket(PRTP_VIDEO_QUEUE queue, PRTP_PACKET packet, int length, PRTPV_
return RTPF_RET_REJECTED;
}
LC_ASSERT(!queue->fecPercentage || U16(packet->sequenceNumber - fecIndex) == queue->bufferLowestSequenceNumber);
LC_ASSERT((nvPacket->fecInfo & 0xFF0) >> 4 == queue->fecPercentage);
LC_ASSERT((nvPacket->fecInfo & 0xFFC00000) >> 22 == queue->bufferDataPackets);
LC_ASSERT_VT(!queue->fecPercentage || U16(packet->sequenceNumber - fecIndex) == queue->bufferLowestSequenceNumber);
LC_ASSERT_VT((nvPacket->fecInfo & 0xFF0) >> 4 == queue->fecPercentage);
LC_ASSERT_VT((nvPacket->fecInfo & 0xFFC00000) >> 22 == queue->bufferDataPackets);
// Verify that the legacy non-multi-FEC compatibility code works
LC_ASSERT(queue->multiFecCapable || fecCurrentBlockNumber == 0);
LC_ASSERT(queue->multiFecCapable || queue->multiFecLastBlockNumber == 0);
LC_ASSERT_VT(queue->multiFecCapable || fecCurrentBlockNumber == 0);
LC_ASSERT_VT(queue->multiFecCapable || queue->multiFecLastBlockNumber == 0);
// Multi-block FEC details must remain the same within a single frame
LC_ASSERT(fecCurrentBlockNumber == queue->multiFecCurrentBlockNumber);
LC_ASSERT(((nvPacket->multiFecBlocks >> 6) & 0x3) == queue->multiFecLastBlockNumber);
LC_ASSERT_VT(fecCurrentBlockNumber == queue->multiFecCurrentBlockNumber);
LC_ASSERT_VT(((nvPacket->multiFecBlocks >> 6) & 0x3) == queue->multiFecLastBlockNumber);
LC_ASSERT((nvPacket->flags & FLAG_EOF) || length - dataOffset == StreamConfig.packetSize);
LC_ASSERT_VT((nvPacket->flags & FLAG_EOF) || length - dataOffset == StreamConfig.packetSize);
if (!queuePacket(queue, packetEntry, packet, length, !isBefore16(packet->sequenceNumber, queue->bufferFirstParitySequenceNumber), false)) {
return RTPF_RET_REJECTED;
}

View File

@@ -198,27 +198,27 @@ void validateDecodeUnitForPlayback(PDECODE_UNIT decodeUnit) {
// IDR frames always start with codec configuration data
if (NegotiatedVideoFormat & VIDEO_FORMAT_MASK_H264) {
// H.264 IDR frames should have an SPS, PPS, then picture data
LC_ASSERT(decodeUnit->bufferList->bufferType == BUFFER_TYPE_SPS);
LC_ASSERT(decodeUnit->bufferList->next != NULL);
LC_ASSERT(decodeUnit->bufferList->next->bufferType == BUFFER_TYPE_PPS);
LC_ASSERT(decodeUnit->bufferList->next->next != NULL);
LC_ASSERT(decodeUnit->bufferList->next->next->bufferType == BUFFER_TYPE_PICDATA);
LC_ASSERT_VT(decodeUnit->bufferList->bufferType == BUFFER_TYPE_SPS);
LC_ASSERT_VT(decodeUnit->bufferList->next != NULL);
LC_ASSERT_VT(decodeUnit->bufferList->next->bufferType == BUFFER_TYPE_PPS);
LC_ASSERT_VT(decodeUnit->bufferList->next->next != NULL);
LC_ASSERT_VT(decodeUnit->bufferList->next->next->bufferType == BUFFER_TYPE_PICDATA);
}
else if (NegotiatedVideoFormat & VIDEO_FORMAT_MASK_H265) {
// HEVC IDR frames should have an VPS, SPS, PPS, then picture data
LC_ASSERT(decodeUnit->bufferList->bufferType == BUFFER_TYPE_VPS);
LC_ASSERT(decodeUnit->bufferList->next != NULL);
LC_ASSERT(decodeUnit->bufferList->next->bufferType == BUFFER_TYPE_SPS);
LC_ASSERT(decodeUnit->bufferList->next->next != NULL);
LC_ASSERT(decodeUnit->bufferList->next->next->bufferType == BUFFER_TYPE_PPS);
LC_ASSERT(decodeUnit->bufferList->next->next->next != NULL);
LC_ASSERT_VT(decodeUnit->bufferList->bufferType == BUFFER_TYPE_VPS);
LC_ASSERT_VT(decodeUnit->bufferList->next != NULL);
LC_ASSERT_VT(decodeUnit->bufferList->next->bufferType == BUFFER_TYPE_SPS);
LC_ASSERT_VT(decodeUnit->bufferList->next->next != NULL);
LC_ASSERT_VT(decodeUnit->bufferList->next->next->bufferType == BUFFER_TYPE_PPS);
LC_ASSERT_VT(decodeUnit->bufferList->next->next->next != NULL);
// We get 2 sets of VPS, SPS, and PPS NALUs in HDR mode.
// FIXME: Should we normalize this or something for clients?
}
else if (NegotiatedVideoFormat & VIDEO_FORMAT_MASK_AV1) {
// We don't parse the AV1 bitstream
LC_ASSERT(decodeUnit->bufferList->bufferType == BUFFER_TYPE_PICDATA);
LC_ASSERT_VT(decodeUnit->bufferList->bufferType == BUFFER_TYPE_PICDATA);
}
else {
LC_ASSERT(false);
@@ -697,7 +697,7 @@ static void processAvcHevcRtpPayloadSlow(PBUFFER_DESC currentPos, PLENTRY_INTERN
while (currentPos->length != 0) {
// Any NALUs we encounter on the way to the end of the packet must be
// reference frame slices or filler data.
LC_ASSERT(isSeqReferenceFrameStart(currentPos) || isFillerDataNal(currentPos));
LC_ASSERT_VT(isSeqReferenceFrameStart(currentPos) || isFillerDataNal(currentPos));
skipToNextNalOrEnd(currentPos);
}
}
@@ -765,7 +765,7 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
firstPacket = isFirstPacket(flags, fecCurrentBlockNumber);
lastPacket = (flags & FLAG_EOF) && fecCurrentBlockNumber == fecLastBlockNumber;
LC_ASSERT((flags & ~(FLAG_SOF | FLAG_EOF | FLAG_CONTAINS_PIC_DATA)) == 0);
LC_ASSERT_VT((flags & ~(FLAG_SOF | FLAG_EOF | FLAG_CONTAINS_PIC_DATA)) == 0);
streamPacketIndex = videoPacket->streamPacketIndex;
@@ -843,10 +843,10 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
// If this is the first packet, skip the frame header (if one exists)
uint32_t frameHeaderSize;
LC_ASSERT(currentPos.length > 0);
LC_ASSERT_VT(currentPos.length > 0);
if (firstPacket && currentPos.length > 0) {
// Parse the frame type from the header
LC_ASSERT(currentPos.length >= 4);
LC_ASSERT_VT(currentPos.length >= 4);
if (APP_VERSION_AT_LEAST(7, 1, 350) && currentPos.length >= 4) {
switch (currentPos.data[currentPos.offset + 3]) {
case 1: // Normal P-frame
@@ -874,7 +874,7 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
break;
default:
Limelog("Unrecognized frame type: %d", currentPos.data[currentPos.offset + 3]);
LC_ASSERT(false);
LC_ASSERT_VT(false);
break;
}
}
@@ -888,7 +888,7 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
}
// Sunshine can provide host processing latency of the frame
LC_ASSERT(currentPos.length >= 3);
LC_ASSERT_VT(currentPos.length >= 3);
if (IS_SUNSHINE() && currentPos.length >= 3) {
BYTE_BUFFER bb;
BbInitializeWrappedBuffer(&bb, currentPos.data, currentPos.offset + 1, 2, BYTE_ORDER_LITTLE);
@@ -897,7 +897,7 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
// Codecs like H.264 and HEVC handle the FEC trailing zero padding just fine, but other
// codecs need the exact length encoded separately.
LC_ASSERT(currentPos.length >= 6);
LC_ASSERT_VT(currentPos.length >= 6);
if (!(NegotiatedVideoFormat & (VIDEO_FORMAT_MASK_H264 | VIDEO_FORMAT_MASK_H265)) && currentPos.length >= 6) {
BYTE_BUFFER bb;
BbInitializeWrappedBuffer(&bb, currentPos.data, currentPos.offset + 4, 2, BYTE_ORDER_LITTLE);
@@ -912,7 +912,7 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
frameHeaderSize = 8;
}
else {
LC_ASSERT(currentPos.data[0] == (char)0x81);
LC_ASSERT_VT(currentPos.data[0] == (char)0x81);
frameHeaderSize = 44;
}
}
@@ -924,7 +924,7 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
frameHeaderSize = 8;
}
else {
LC_ASSERT(currentPos.data[0] == (char)0x81);
LC_ASSERT_VT(currentPos.data[0] == (char)0x81);
frameHeaderSize = 41;
}
}
@@ -936,7 +936,7 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
frameHeaderSize = 8;
}
else {
LC_ASSERT(currentPos.data[0] == (char)0x81);
LC_ASSERT_VT(currentPos.data[0] == (char)0x81);
frameHeaderSize = 24;
}
}
@@ -957,7 +957,7 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
frameHeaderSize = 0;
}
LC_ASSERT(currentPos.length >= frameHeaderSize);
LC_ASSERT_VT(currentPos.length >= frameHeaderSize);
if (currentPos.length >= frameHeaderSize) {
// Skip past the frame header
currentPos.offset += frameHeaderSize;
@@ -969,7 +969,7 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
// The Annex B NALU start prefix must be next
if (!getAnnexBStartSequence(&currentPos, NULL)) {
// If we aren't starting on a start prefix, something went wrong.
LC_ASSERT(false);
LC_ASSERT_VT(false);
// For release builds, we will try to recover by searching for one.
// This mimics the way most decoders handle this situation.
@@ -1022,11 +1022,11 @@ static void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length,
// of trailing zero padding like H.264/HEVC Annex B bitstream parsers are.
if (lastPacket) {
// The payload length includes the frame header, so it cannot be smaller than that
LC_ASSERT(lastPacketPayloadLength > frameHeaderSize);
LC_ASSERT_VT(lastPacketPayloadLength > frameHeaderSize);
// The payload length cannot be smaller than the actual received payload
// NB: currentPos.length is already adjusted to exclude the frameHeaderSize from above
LC_ASSERT(lastPacketPayloadLength - frameHeaderSize <= currentPos.length);
LC_ASSERT_VT(lastPacketPayloadLength - frameHeaderSize <= currentPos.length);
// If the payload length is valid, truncate the packet. If not, discard this frame.
if (lastPacketPayloadLength > frameHeaderSize && lastPacketPayloadLength - frameHeaderSize <= currentPos.length) {

View File

@@ -135,6 +135,7 @@ static void VideoReceiveThreadProc(void* context) {
firstDataTimeMs = PltGetMillis();
}
#ifndef LC_FUZZING
if (!receivedFullFrame) {
uint64_t now = PltGetMillis();
@@ -144,6 +145,7 @@ static void VideoReceiveThreadProc(void* context) {
break;
}
}
#endif
if (err < (int)sizeof(RTP_PACKET)) {
// Runt packet