Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(352)

Side by Side Diff: webrtc/modules/video_coding/main/source/session_info.cc

Issue 1238033003: Prevent OOB reads for truncated H264 STAP-A packets. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 size_t length = 0; 109 size_t length = 0;
110 for (PacketIteratorConst it = packets_.begin(); it != packets_.end(); ++it) 110 for (PacketIteratorConst it = packets_.begin(); it != packets_.end(); ++it)
111 length += (*it).sizeBytes; 111 length += (*it).sizeBytes;
112 return length; 112 return length;
113 } 113 }
114 114
115 int VCMSessionInfo::NumPackets() const { 115 int VCMSessionInfo::NumPackets() const {
116 return packets_.size(); 116 return packets_.size();
117 } 117 }
118 118
119 size_t VCMSessionInfo::InsertBuffer(uint8_t* frame_buffer, 119 bool VCMSessionInfo::InsertBuffer(uint8_t* frame_buffer,
120 PacketIterator packet_it) { 120 size_t* inserted_length,
121 VCMPacket& packet = *packet_it; 121 PacketIterator packet_it) {
122 VCMPacket* packet = &(*packet_it);
122 PacketIterator it; 123 PacketIterator it;
123 124
124 // Calculate the offset into the frame buffer for this packet. 125 // Calculate the offset into the frame buffer for this packet.
125 size_t offset = 0; 126 size_t offset = 0;
126 for (it = packets_.begin(); it != packet_it; ++it) 127 for (it = packets_.begin(); it != packet_it; ++it)
127 offset += (*it).sizeBytes; 128 offset += (*it).sizeBytes;
128 129
129 // Set the data pointer to pointing to the start of this packet in the 130 // Set the data pointer to pointing to the start of this packet in the
130 // frame buffer. 131 // frame buffer.
131 const uint8_t* packet_buffer = packet.dataPtr; 132 const uint8_t* packet_buffer = packet->dataPtr;
132 packet.dataPtr = frame_buffer + offset; 133 packet->dataPtr = frame_buffer + offset;
133 134
134 // We handle H.264 STAP-A packets in a special way as we need to remove the 135 // We handle H.264 STAP-A packets in a special way as we need to remove the
135 // two length bytes between each NAL unit, and potentially add start codes. 136 // two length bytes between each NAL unit, and potentially add start codes.
136 const size_t kH264NALHeaderLengthInBytes = 1; 137 const size_t kH264NALHeaderLengthInBytes = 1;
137 const size_t kLengthFieldLength = 2; 138 const size_t kLengthFieldLength = 2;
138 if (packet.codecSpecificHeader.codec == kRtpVideoH264 && 139 if (packet->codecSpecificHeader.codec == kRtpVideoH264 &&
139 packet.codecSpecificHeader.codecHeader.H264.packetization_type == 140 packet->codecSpecificHeader.codecHeader.H264.packetization_type ==
140 kH264StapA) { 141 kH264StapA) {
141 size_t required_length = 0; 142 size_t required_length = kH264NALHeaderLengthInBytes;
142 const uint8_t* nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes; 143 const uint8_t* nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes;
143 while (nalu_ptr < packet_buffer + packet.sizeBytes) { 144 while (nalu_ptr < packet_buffer + packet->sizeBytes) {
144 size_t length = BufferToUWord16(nalu_ptr); 145 size_t length = BufferToUWord16(nalu_ptr);
145 required_length += 146 required_length +=
146 length + (packet.insertStartCode ? kH264StartCodeLengthBytes : 0); 147 length + (packet->insertStartCode ? kH264StartCodeLengthBytes : 0);
stefan-webrtc 2015/07/23 12:36:04 As discussed, the problem is that this start code
147 nalu_ptr += kLengthFieldLength + length; 148 nalu_ptr += kLengthFieldLength + length;
148 } 149 }
149 ShiftSubsequentPackets(packet_it, required_length); 150 if (required_length > packet->sizeBytes)
151 return false;
152 ShiftSubsequentPackets(packet_it,
153 required_length - kH264NALHeaderLengthInBytes);
150 nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes; 154 nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes;
151 uint8_t* frame_buffer_ptr = frame_buffer + offset; 155 uint8_t* frame_buffer_ptr = frame_buffer + offset;
152 while (nalu_ptr < packet_buffer + packet.sizeBytes) { 156 while (nalu_ptr < packet_buffer + packet->sizeBytes) {
153 size_t length = BufferToUWord16(nalu_ptr); 157 size_t length = BufferToUWord16(nalu_ptr);
154 nalu_ptr += kLengthFieldLength; 158 nalu_ptr += kLengthFieldLength;
155 frame_buffer_ptr += Insert(nalu_ptr, 159 frame_buffer_ptr +=
156 length, 160 Insert(nalu_ptr, length, packet->insertStartCode, frame_buffer_ptr);
157 packet.insertStartCode,
158 const_cast<uint8_t*>(frame_buffer_ptr));
159 nalu_ptr += length; 161 nalu_ptr += length;
160 } 162 }
161 packet.sizeBytes = required_length; 163 packet->sizeBytes = required_length - kH264NALHeaderLengthInBytes;
pbos-webrtc 2015/07/17 14:08:53 Was this part (not including kH264NALHeaderLengthI
162 return packet.sizeBytes; 164 *inserted_length = packet->sizeBytes;
165 return true;
163 } 166 }
164 ShiftSubsequentPackets( 167 ShiftSubsequentPackets(
165 packet_it, 168 packet_it,
166 packet.sizeBytes + 169 packet->sizeBytes +
167 (packet.insertStartCode ? kH264StartCodeLengthBytes : 0)); 170 (packet->insertStartCode ? kH264StartCodeLengthBytes : 0));
168 171
169 packet.sizeBytes = Insert(packet_buffer, 172 packet->sizeBytes = Insert(packet_buffer,
170 packet.sizeBytes, 173 packet->sizeBytes,
171 packet.insertStartCode, 174 packet->insertStartCode,
172 const_cast<uint8_t*>(packet.dataPtr)); 175 const_cast<uint8_t*>(packet->dataPtr));
173 return packet.sizeBytes; 176 *inserted_length = packet->sizeBytes;
177 return true;
174 } 178 }
175 179
176 size_t VCMSessionInfo::Insert(const uint8_t* buffer, 180 size_t VCMSessionInfo::Insert(const uint8_t* buffer,
177 size_t length, 181 size_t length,
178 bool insert_start_code, 182 bool insert_start_code,
179 uint8_t* frame_buffer) { 183 uint8_t* frame_buffer) {
180 if (insert_start_code) { 184 if (insert_start_code) {
181 const unsigned char startCode[] = {0, 0, 0, 1}; 185 const unsigned char startCode[] = {0, 0, 0, 1};
182 memcpy(frame_buffer, startCode, kH264StartCodeLengthBytes); 186 memcpy(frame_buffer, startCode, kH264StartCodeLengthBytes);
183 } 187 }
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_)) { 510 IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_)) {
507 LOG(LS_WARNING) << "Received packet with a sequence number which is out " 511 LOG(LS_WARNING) << "Received packet with a sequence number which is out "
508 "of frame boundaries"; 512 "of frame boundaries";
509 return -3; 513 return -3;
510 } 514 }
511 } 515 }
512 516
513 // The insert operation invalidates the iterator |rit|. 517 // The insert operation invalidates the iterator |rit|.
514 PacketIterator packet_list_it = packets_.insert(rit.base(), packet); 518 PacketIterator packet_list_it = packets_.insert(rit.base(), packet);
515 519
516 size_t returnLength = InsertBuffer(frame_buffer, packet_list_it); 520 size_t returnLength;
521 if (!InsertBuffer(frame_buffer, &returnLength, packet_list_it))
522 return kSizeError;
517 UpdateCompleteSession(); 523 UpdateCompleteSession();
518 if (decode_error_mode == kWithErrors) 524 if (decode_error_mode == kWithErrors) {
519 decodable_ = true; 525 decodable_ = true;
520 else if (decode_error_mode == kSelectiveErrors) 526 } else if (decode_error_mode == kSelectiveErrors) {
521 UpdateDecodableSession(frame_data); 527 UpdateDecodableSession(frame_data);
528 }
522 return static_cast<int>(returnLength); 529 return static_cast<int>(returnLength);
523 } 530 }
524 531
525 void VCMSessionInfo::InformOfEmptyPacket(uint16_t seq_num) { 532 void VCMSessionInfo::InformOfEmptyPacket(uint16_t seq_num) {
526 // Empty packets may be FEC or filler packets. They are sequential and 533 // Empty packets may be FEC or filler packets. They are sequential and
527 // follow the data packets, therefore, we should only keep track of the high 534 // follow the data packets, therefore, we should only keep track of the high
528 // and low sequence numbers and may assume that the packets in between are 535 // and low sequence numbers and may assume that the packets in between are
529 // empty packets belonging to the same frame (timestamp). 536 // empty packets belonging to the same frame (timestamp).
530 if (empty_seq_num_high_ == -1) 537 if (empty_seq_num_high_ == -1)
531 empty_seq_num_high_ = seq_num; 538 empty_seq_num_high_ = seq_num;
532 else 539 else
533 empty_seq_num_high_ = LatestSequenceNumber(seq_num, empty_seq_num_high_); 540 empty_seq_num_high_ = LatestSequenceNumber(seq_num, empty_seq_num_high_);
534 if (empty_seq_num_low_ == -1 || IsNewerSequenceNumber(empty_seq_num_low_, 541 if (empty_seq_num_low_ == -1 || IsNewerSequenceNumber(empty_seq_num_low_,
535 seq_num)) 542 seq_num))
536 empty_seq_num_low_ = seq_num; 543 empty_seq_num_low_ = seq_num;
537 } 544 }
538 545
539 } // namespace webrtc 546 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698