Bug 1187067 - Null-check mLastTrack before dereferencing it - r=rillian, a=sylvestre
authorGerald Squelart <gsquelart@mozilla.com>
Thu, 22 Oct 2015 01:06:00 +0200
changeset 289609 1721db97f72e
parent 289608 f2ec86a8b1a8
child 289610 6b8a2f0f4e2e
push id5218
push usercbook@mozilla.com
push date2015-10-22 08:14 +0000
treeherdermozilla-beta@1721db97f72e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrillian, sylvestre
bugs1187067
milestone42.0
Bug 1187067 - Null-check mLastTrack before dereferencing it - r=rillian, a=sylvestre
media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
--- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
@@ -850,16 +850,19 @@ status_t MPEG4Extractor::parseChunk(off6
                     sp<MPEG4DataSource> cachedSource =
                         new MPEG4DataSource(mDataSource);
 
                     if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
                         mDataSource = cachedSource;
                     }
                 }
 
+                if (!mLastTrack) {
+                  return ERROR_MALFORMED;
+                }
                 mLastTrack->sampleTable = new SampleTable(mDataSource);
             }
 
             bool isTrack = false;
             if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
                 isTrack = true;
 
                 Track *track = new Track;
@@ -975,39 +978,48 @@ status_t MPEG4Extractor::parseChunk(off6
                     return ERROR_IO;
                 }
                 entriesoffset += 4; // ignore media_rate_integer and media_rate_fraction.
                 if (media_time == -1 && i) {
                     ALOGW("ignoring invalid empty edit", i);
                     break;
                 } else if (media_time == -1) {
                     // Starting offsets for tracks (streams) are represented by an initial empty edit.
+                    if (!mLastTrack) {
+                      return ERROR_MALFORMED;
+                    }
                     mLastTrack->empty_duration = segment_duration;
                     continue;
                 } else if (i > 1) {
                     // we only support a single non-empty entry at the moment, for gapless playback
                     ALOGW("multiple edit list entries, A/V sync will be wrong");
                     break;
                 }
+                if (!mLastTrack) {
+                  return ERROR_MALFORMED;
+                }
                 mLastTrack->segment_duration = segment_duration;
                 mLastTrack->media_time = media_time;
             }
             storeEditList();
             *offset += chunk_size;
             break;
         }
 
         case FOURCC('f', 'r', 'm', 'a'):
         {
             uint32_t original_fourcc;
             if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
                 return ERROR_IO;
             }
             original_fourcc = ntohl(original_fourcc);
             ALOGV("read original format: %d", original_fourcc);
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
             uint32_t num_channels = 0;
             uint32_t sample_rate = 0;
             if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
                 mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
                 mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
             }
             *offset += chunk_size;
@@ -1062,16 +1074,19 @@ status_t MPEG4Extractor::parseChunk(off6
             }
 
             uint8_t defaultKeyId[16];
 
             if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
                 return ERROR_IO;
             }
 
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
             mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
             mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
             *offset += chunk_size;
             break;
         }
 
         case FOURCC('t', 'r', 'e', 'x'):
@@ -1151,16 +1166,19 @@ status_t MPEG4Extractor::parseChunk(off6
 
             uint32_t timescale;
             if (mDataSource->readAt(
                         timescale_offset, &timescale, sizeof(timescale))
                     < (ssize_t)sizeof(timescale)) {
                 return ERROR_IO;
             }
 
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             mLastTrack->timescale = ntohl(timescale);
 
             // Now that we've parsed the media timescale, we can interpret
             // the edit list data.
             storeEditList();
 
             int64_t duration = 0;
             if (version == 1) {
@@ -1243,16 +1261,19 @@ status_t MPEG4Extractor::parseChunk(off6
             uint32_t entry_count = U32_AT(&buffer[4]);
 
             if (entry_count > 1) {
                 // For 3GPP timed text, there could be multiple tx3g boxes contain
                 // multiple text display formats. These formats will be used to
                 // display the timed text.
                 // For encrypted files, there may also be more than one entry.
                 const char *mime;
+                if (!mLastTrack) {
+                  return ERROR_MALFORMED;
+                }
                 CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
                 if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
                         strcasecmp(mime, "application/octet-stream")) {
                     // For now we only support a single type of media per track.
                     mLastTrack->skipTrack = true;
                     *offset += chunk_size;
                     break;
                 }
@@ -1297,16 +1318,19 @@ status_t MPEG4Extractor::parseChunk(off6
 
             uint16_t data_ref_index = U16_AT(&buffer[6]);
             uint16_t qt_version = U16_AT(&buffer[8]);
             uint32_t num_channels = U16_AT(&buffer[16]);
 
             uint16_t sample_size = U16_AT(&buffer[18]);
             uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
 
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
                 // if the chunk type is enca, we'll get the type from the sinf/frma box later
                 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
                 AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
             }
 
             uint64_t skip = 0;
             if (qt_version == 1) {
@@ -1412,16 +1436,19 @@ status_t MPEG4Extractor::parseChunk(off6
             // let the decoder figure out the actual width and height (and thus
             // be prepared for INFO_FOMRAT_CHANGED event).
             if (width == 0)  width  = 352;
             if (height == 0) height = 288;
 
             // printf("*** coding='%s' width=%d height=%d\n",
             //        chunk, width, height);
 
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
                 // if the chunk type is encv, we'll get the type from the sinf/frma box later
                 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
             }
             mLastTrack->meta->setInt32(kKeyWidth, width);
             mLastTrack->meta->setInt32(kKeyHeight, height);
 
             off64_t stop_offset = *offset + chunk_size;
@@ -1442,45 +1469,54 @@ status_t MPEG4Extractor::parseChunk(off6
                 return ERROR_MALFORMED;
             }
             break;
         }
 
         case FOURCC('s', 't', 'c', 'o'):
         case FOURCC('c', 'o', '6', '4'):
         {
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             status_t err =
                 mLastTrack->sampleTable->setChunkOffsetParams(
                         chunk_type, data_offset, chunk_data_size);
 
             if (err != OK) {
                 return err;
             }
 
             *offset += chunk_size;
             break;
         }
 
         case FOURCC('s', 't', 's', 'c'):
         {
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             status_t err =
                 mLastTrack->sampleTable->setSampleToChunkParams(
                         data_offset, chunk_data_size);
 
             if (err != OK) {
                 return err;
             }
 
             *offset += chunk_size;
             break;
         }
 
         case FOURCC('s', 't', 's', 'z'):
         case FOURCC('s', 't', 'z', '2'):
         {
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             status_t err =
                 mLastTrack->sampleTable->setSampleSizeParams(
                         chunk_type, data_offset, chunk_data_size);
 
             if (err != OK) {
                 return err;
             }
 
@@ -1525,72 +1561,87 @@ status_t MPEG4Extractor::parseChunk(off6
                 }
             }
 
             break;
         }
 
         case FOURCC('s', 't', 't', 's'):
         {
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             status_t err =
                 mLastTrack->sampleTable->setTimeToSampleParams(
                         data_offset, chunk_data_size);
 
             if (err != OK) {
                 return err;
             }
 
             *offset += chunk_size;
             break;
         }
 
         case FOURCC('c', 't', 't', 's'):
         {
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             status_t err =
                 mLastTrack->sampleTable->setCompositionTimeToSampleParams(
                         data_offset, chunk_data_size);
 
             if (err != OK) {
                 return err;
             }
 
             *offset += chunk_size;
             break;
         }
 
         case FOURCC('s', 't', 's', 's'):
         {
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             status_t err =
                 mLastTrack->sampleTable->setSyncSampleParams(
                         data_offset, chunk_data_size);
 
             if (err != OK) {
                 return err;
             }
 
             *offset += chunk_size;
             break;
         }
 
         case FOURCC('s', 'a', 'i', 'z'):
         {
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             status_t err =
                 mLastTrack->sampleTable->setSampleAuxiliaryInformationSizeParams(
                         data_offset, chunk_data_size, mDrmScheme);
 
             if (err != OK) {
                 return err;
             }
 
             *offset += chunk_size;
             break;
         }
 
         case FOURCC('s', 'a', 'i', 'o'):
         {
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             status_t err =
                 mLastTrack->sampleTable->setSampleAuxiliaryInformationOffsetParams(
                         data_offset, chunk_data_size, mDrmScheme);
 
             if (err != OK) {
                 return err;
             }
 
@@ -1649,16 +1700,19 @@ status_t MPEG4Extractor::parseChunk(off6
                 return ERROR_IO;
             }
 
             if (U32_AT(buffer) != 0) {
                 // Should be version 0, flags 0.
                 return ERROR_MALFORMED;
             }
 
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             mLastTrack->meta->setData(
                     kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
 
             if (mPath.size() >= 2
                     && (mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a') ||
                        (mPath[mPath.size() - 2] == FOURCC('e', 'n', 'c', 'a')))) {
                 // Information from the ESDS must be relied on for proper
                 // setup of sample rate and channel count for MPEG4 Audio.
@@ -1686,16 +1740,19 @@ status_t MPEG4Extractor::parseChunk(off6
 
             sp<ABuffer> buffer = new ABuffer(chunk_data_size);
 
             if (mDataSource->readAt(
                         data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
                 return ERROR_IO;
             }
 
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             mLastTrack->meta->setData(
                     kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
 
             *offset += chunk_size;
             break;
         }
 
         case FOURCC('d', '2', '6', '3'):
@@ -1718,16 +1775,19 @@ status_t MPEG4Extractor::parseChunk(off6
                 return ERROR_MALFORMED;
             }
 
             if (mDataSource->readAt(
                     data_offset, buffer, chunk_data_size) < chunk_data_size) {
                 return ERROR_IO;
             }
 
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
 
             *offset += chunk_size;
             break;
         }
 
         case FOURCC('m', 'e', 't', 'a'):
         {
@@ -1880,25 +1940,31 @@ status_t MPEG4Extractor::parseChunk(off6
                 return ERROR_IO;
             }
 
             uint32_t type = ntohl(buffer);
             // For the 3GPP file format, the handler-type within the 'hdlr' box
             // shall be 'text'. We also want to support 'sbtl' handler type
             // for a practical reason as various MPEG4 containers use it.
             if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
+                if (!mLastTrack) {
+                  return ERROR_MALFORMED;
+                }
                 mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
             }
 
             *offset += chunk_size;
             break;
         }
 
         case FOURCC('t', 'x', '3', 'g'):
         {
+            if (!mLastTrack) {
+              return ERROR_MALFORMED;
+            }
             uint32_t type;
             const void *data;
             size_t size = 0;
             if (!mLastTrack->meta->findData(
                     kKeyTextFormatData, &type, &data, &size)) {
                 size = 0;
             }
 
@@ -1990,16 +2056,17 @@ status_t MPEG4Extractor::parseChunk(off6
     }
 
     return OK;
 }
 
 void MPEG4Extractor::storeEditList()
 {
   if (mHeaderTimescale == 0 ||
+      !mLastTrack ||
       mLastTrack->timescale == 0) {
     return;
   }
 
   uint64_t segment_duration = (mLastTrack->segment_duration * 1000000) / mHeaderTimescale;
   // media_time is measured in media time scale units.
   int64_t media_time = (mLastTrack->media_time * 1000000) / mLastTrack->timescale;
   // empty_duration is in the Movie Header Box's timescale.
@@ -2129,16 +2196,19 @@ status_t MPEG4Extractor::parseSegmentInd
         se.mSize = d1 & 0x7fffffff;
         se.mDurationUs = 1000000LL * d2 / timeScale;
         mSidxEntries.add(se);
     }
 
     mSidxDuration = total_duration * 1000000 / timeScale;
     ALOGV("duration: %lld", mSidxDuration);
 
+    if (!mLastTrack) {
+      return ERROR_MALFORMED;
+    }
     int64_t metaDuration;
     if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
         mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration);
     }
     return OK;
 }
 
 status_t MPEG4Extractor::parseTrackExtends(
@@ -2198,16 +2268,19 @@ status_t MPEG4Extractor::parseTrackHeade
         ctime = U32_AT(&buffer[4]);
         mtime = U32_AT(&buffer[8]);
         id = U32_AT(&buffer[12]);
         duration = U32_AT(&buffer[20]);
     } else {
         return ERROR_UNSUPPORTED;
     }
 
+    if (!mLastTrack) {
+      return ERROR_MALFORMED;
+    }
     mLastTrack->meta->setInt32(kKeyTrackID, id);
 
     size_t matrixOffset = dynSize + 16;
     int32_t a00 = U32_AT(&buffer[matrixOffset]);
     int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
     int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
     int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
     int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
@@ -2379,16 +2452,19 @@ status_t MPEG4Extractor::parseMetaData(o
                 (mLastCommentName.length() != 0) &&
                 (mLastCommentData.length() != 0)) {
 
                 if (mLastCommentMean == "com.apple.iTunes"
                         && mLastCommentName == "iTunSMPB") {
                     int32_t delay, padding;
                     if (sscanf(mLastCommentData,
                                " %*x %x %x %*x", &delay, &padding) == 2) {
+                        if (!mLastTrack) {
+                          return ERROR_MALFORMED;
+                        }
                         mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
                         mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
                     }
                 }
 
                 mLastCommentMean.clear();
                 mLastCommentName.clear();
                 mLastCommentData.clear();
@@ -2500,22 +2576,28 @@ status_t MPEG4Extractor::updateAudioTrac
 
     uint8_t objectTypeIndication;
     if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
         return ERROR_MALFORMED;
     }
 
     if (objectTypeIndication == 0xe1) {
         // This isn't MPEG4 audio at all, it's QCELP 14k...
+        if (!mLastTrack) {
+          return ERROR_MALFORMED;
+        }
         mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
         return OK;
     }
 
     if (objectTypeIndication  == 0x6b || objectTypeIndication  == 0x69) {
         // The media subtype is MP3 audio
+        if (!mLastTrack) {
+          return ERROR_MALFORMED;
+        }
         mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
     }
 
     const uint8_t *csd;
     size_t csd_size;
     if (esds.getCodecSpecificInfo(
                 (const void **)&csd, &csd_size) != OK) {
         return ERROR_MALFORMED;
@@ -2541,17 +2623,20 @@ status_t MPEG4Extractor::updateAudioTrac
     ABitReader br(csd, csd_size);
     uint32_t objectType = br.getBits(5);
 
     if (objectType == 31) {  // AAC-ELD => additional 6 bits
         objectType = 32 + br.getBits(6);
     }
 
     if (objectType >= 1 && objectType <= 4) {
-      mLastTrack->meta->setInt32(kKeyAACProfile, objectType);
+        if (!mLastTrack) {
+          return ERROR_MALFORMED;
+        }
+        mLastTrack->meta->setInt32(kKeyAACProfile, objectType);
     }
 
     uint32_t freqIndex = br.getBits(4);
 
     int32_t sampleRate = 0;
     int32_t numChannels = 0;
     if (freqIndex == 15) {
         if (csd_size < 5) {
@@ -2585,16 +2670,19 @@ status_t MPEG4Extractor::updateAudioTrac
             sampleRate = kSamplingRate[freqIndex];
         }
     }
 
     if (numChannels == 0) {
         return ERROR_UNSUPPORTED;
     }
 
+    if (!mLastTrack) {
+      return ERROR_MALFORMED;
+    }
     int32_t prevSampleRate;
     CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
 
     if (prevSampleRate != sampleRate) {
         ALOGV("mpeg4 audio sample rate different from previous setting. "
              "was: %d, now: %d", prevSampleRate, sampleRate);
     }