| Index: webrtc/modules/rtp_rtcp/source/forward_error_correction.cc
|
| diff --git a/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc b/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc
|
| index a9e88a5bca197f460fbea1263b9807ace128f434..48126cec55796f71e1f6a03ef8d0241783848bbd 100644
|
| --- a/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc
|
| +++ b/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc
|
| @@ -634,23 +634,35 @@ void ForwardErrorCorrection::InsertPackets(
|
| DiscardOldPackets(recovered_packet_list);
|
| }
|
|
|
| -void ForwardErrorCorrection::InitRecovery(const FecPacket* fec_packet,
|
| +bool ForwardErrorCorrection::InitRecovery(const FecPacket* fec_packet,
|
| RecoveredPacket* recovered) {
|
| // This is the first packet which we try to recover with.
|
| const uint16_t ulp_header_size =
|
| fec_packet->pkt->data[0] & 0x40 ? kUlpHeaderSizeLBitSet
|
| : kUlpHeaderSizeLBitClear; // L bit set?
|
| + if (fec_packet->pkt->length <
|
| + static_cast<size_t>(kFecHeaderSize + ulp_header_size)) {
|
| + LOG(LS_WARNING)
|
| + << "Truncated FEC packet doesn't contain room for ULP header.";
|
| + return false;
|
| + }
|
| recovered->pkt = new Packet;
|
| memset(recovered->pkt->data, 0, IP_PACKET_SIZE);
|
| recovered->returned = false;
|
| recovered->was_recovered = true;
|
| - uint8_t protection_length[2];
|
| - // Copy the protection length from the ULP header.
|
| - memcpy(protection_length, &fec_packet->pkt->data[10], 2);
|
| + uint16_t protection_length =
|
| + ByteReader<uint16_t>::ReadBigEndian(&fec_packet->pkt->data[10]);
|
| + if (protection_length >
|
| + std::min(
|
| + sizeof(recovered->pkt->data) - kRtpHeaderSize,
|
| + sizeof(fec_packet->pkt->data) - kFecHeaderSize - ulp_header_size)) {
|
| + LOG(LS_WARNING) << "Incorrect FEC protection length, dropping.";
|
| + return false;
|
| + }
|
| // Copy FEC payload, skipping the ULP header.
|
| memcpy(&recovered->pkt->data[kRtpHeaderSize],
|
| &fec_packet->pkt->data[kFecHeaderSize + ulp_header_size],
|
| - ByteReader<uint16_t>::ReadBigEndian(protection_length));
|
| + protection_length);
|
| // Copy the length recovery field.
|
| memcpy(recovered->length_recovery, &fec_packet->pkt->data[8], 2);
|
| // Copy the first 2 bytes of the FEC header.
|
| @@ -660,9 +672,10 @@ void ForwardErrorCorrection::InitRecovery(const FecPacket* fec_packet,
|
| // Set the SSRC field.
|
| ByteWriter<uint32_t>::WriteBigEndian(&recovered->pkt->data[8],
|
| fec_packet->ssrc);
|
| + return true;
|
| }
|
|
|
| -void ForwardErrorCorrection::FinishRecovery(RecoveredPacket* recovered) {
|
| +bool ForwardErrorCorrection::FinishRecovery(RecoveredPacket* recovered) {
|
| // Set the RTP version to 2.
|
| recovered->pkt->data[0] |= 0x80; // Set the 1st bit.
|
| recovered->pkt->data[0] &= 0xbf; // Clear the 2nd bit.
|
| @@ -674,6 +687,10 @@ void ForwardErrorCorrection::FinishRecovery(RecoveredPacket* recovered) {
|
| recovered->pkt->length =
|
| ByteReader<uint16_t>::ReadBigEndian(recovered->length_recovery) +
|
| kRtpHeaderSize;
|
| + if (recovered->pkt->length > sizeof(recovered->pkt->data) - kRtpHeaderSize)
|
| + return false;
|
| +
|
| + return true;
|
| }
|
|
|
| void ForwardErrorCorrection::XorPackets(const Packet* src_packet,
|
| @@ -700,9 +717,11 @@ void ForwardErrorCorrection::XorPackets(const Packet* src_packet,
|
| }
|
| }
|
|
|
| -void ForwardErrorCorrection::RecoverPacket(
|
| - const FecPacket* fec_packet, RecoveredPacket* rec_packet_to_insert) {
|
| - InitRecovery(fec_packet, rec_packet_to_insert);
|
| +bool ForwardErrorCorrection::RecoverPacket(
|
| + const FecPacket* fec_packet,
|
| + RecoveredPacket* rec_packet_to_insert) {
|
| + if (!InitRecovery(fec_packet, rec_packet_to_insert))
|
| + return false;
|
| ProtectedPacketList::const_iterator protected_it =
|
| fec_packet->protected_pkt_list.begin();
|
| while (protected_it != fec_packet->protected_pkt_list.end()) {
|
| @@ -714,7 +733,9 @@ void ForwardErrorCorrection::RecoverPacket(
|
| }
|
| ++protected_it;
|
| }
|
| - FinishRecovery(rec_packet_to_insert);
|
| + if (!FinishRecovery(rec_packet_to_insert))
|
| + return false;
|
| + return true;
|
| }
|
|
|
| void ForwardErrorCorrection::AttemptRecover(
|
| @@ -729,7 +750,13 @@ void ForwardErrorCorrection::AttemptRecover(
|
| // Recovery possible.
|
| RecoveredPacket* packet_to_insert = new RecoveredPacket;
|
| packet_to_insert->pkt = NULL;
|
| - RecoverPacket(*fec_packet_list_it, packet_to_insert);
|
| + if (!RecoverPacket(*fec_packet_list_it, packet_to_insert)) {
|
| + // Can't recover using this packet, drop it.
|
| + DiscardFECPacket(*fec_packet_list_it);
|
| + fec_packet_list_it = fec_packet_list_.erase(fec_packet_list_it);
|
| + delete packet_to_insert;
|
| + continue;
|
| + }
|
|
|
| // Add recovered packet to the list of recovered packets and update any
|
| // FEC packets covering this packet with a pointer to the data.
|
|
|