Merge "stagefright: avoid buffer overflow in base64 decoder" into klp-dev
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index d571f17..c825970 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -428,6 +428,10 @@
             return -EINVAL;
         }
         effect_param_t *cmd = (effect_param_t *) pCmdData;
+        if (cmd->psize != sizeof(int32_t)) {
+            android_errorWriteLog(0x534e4554, "63662938");
+            return -EINVAL;
+        }
         *(int *)pReplyData = Downmix_setParameter(pDownmixer, *(int32_t *)cmd->data,
                 cmd->vsize, cmd->data + sizeof(int32_t));
         break;
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 7ab16a1..5c62e86 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -178,12 +178,13 @@
 void Reverb_free            (ReverbContext *pContext);
 int  Reverb_setConfig       (ReverbContext *pContext, effect_config_t *pConfig);
 void Reverb_getConfig       (ReverbContext *pContext, effect_config_t *pConfig);
-int  Reverb_setParameter    (ReverbContext *pContext, void *pParam, void *pValue);
+int  Reverb_setParameter    (ReverbContext *pContext, void *pParam, void *pValue, int vsize);
 int  Reverb_getParameter    (ReverbContext *pContext,
                              void          *pParam,
                              size_t        *pValueSize,
                              void          *pValue);
 int Reverb_LoadPreset       (ReverbContext   *pContext);
+int Reverb_paramValueSize   (int32_t param);
 
 /* Effect Library Interface Implementation */
 
@@ -1744,12 +1745,13 @@
 //  pContext         - handle to instance data
 //  pParam           - pointer to parameter
 //  pValue           - pointer to value
+//  vsize            - value size
 //
 // Outputs:
 //
 //----------------------------------------------------------------------------
 
-int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue){
+int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue, int vsize){
     int status = 0;
     int16_t level;
     int16_t ratio;
@@ -1773,6 +1775,11 @@
         return 0;
     }
 
+    if (vsize < Reverb_paramValueSize(param)) {
+        android_errorWriteLog(0x534e4554, "63526567");
+        return -EINVAL;
+    }
+
     switch (param){
         case REVERB_PARAM_PROPERTIES:
             ALOGV("\tReverb_setParameter() REVERB_PARAM_PROPERTIES");
@@ -1848,6 +1855,31 @@
     return status;
 } /* end Reverb_setParameter */
 
+
+/**
+ * returns the size in bytes of the value of each environmental reverb parameter
+ */
+int Reverb_paramValueSize(int32_t param) {
+    switch (param) {
+    case REVERB_PARAM_ROOM_LEVEL:
+    case REVERB_PARAM_ROOM_HF_LEVEL:
+    case REVERB_PARAM_REFLECTIONS_LEVEL:
+    case REVERB_PARAM_REVERB_LEVEL:
+        return sizeof(int16_t); // millibel
+    case REVERB_PARAM_DECAY_TIME:
+    case REVERB_PARAM_REFLECTIONS_DELAY:
+    case REVERB_PARAM_REVERB_DELAY:
+        return sizeof(uint32_t); // milliseconds
+    case REVERB_PARAM_DECAY_HF_RATIO:
+    case REVERB_PARAM_DIFFUSION:
+    case REVERB_PARAM_DENSITY:
+        return sizeof(int16_t); // permille
+    case REVERB_PARAM_PROPERTIES:
+        return sizeof(s_reverb_settings); // struct of all reverb properties
+    }
+    return sizeof(int32_t);
+}
+
 } // namespace
 } // namespace
 
@@ -2019,7 +2051,8 @@
 
             *(int *)pReplyData = android::Reverb_setParameter(pContext,
                                                              (void *)p->data,
-                                                              p->data + p->psize);
+                                                              p->data + p->psize,
+                                                              p->vsize);
         } break;
 
         case EFFECT_CMD_ENABLE:
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index c3dbc1b..cf59717 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -79,6 +79,9 @@
 #include "HTTPBase.h"
 #include "RemoteDisplay.h"
 
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleepUs = 20000;
+
 namespace {
 using android::media::Metadata;
 using android::status_t;
@@ -366,12 +369,32 @@
     snprintf(buffer, 255, "  pid(%d), connId(%d), status(%d), looping(%s)\n",
             mPid, mConnId, mStatus, mLoop?"true": "false");
     result.append(buffer);
-    write(fd, result.string(), result.size());
-    if (mPlayer != NULL) {
-        mPlayer->dump(fd, args);
+
+    sp<MediaPlayerBase> p;
+    sp<AudioOutput> audioOutput;
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mLock.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleepUs);
     }
-    if (mAudioOutput != 0) {
-        mAudioOutput->dump(fd, args);
+
+    if (locked) {
+        p = mPlayer;
+        audioOutput = mAudioOutput;
+        mLock.unlock();
+    } else {
+        result.append("  lock is taken, no dump from player and audio output\n");
+    }
+    write(fd, result.string(), result.size());
+
+    if (p != NULL) {
+        p->dump(fd, args);
+    }
+    if (audioOutput != 0) {
+        audioOutput->dump(fd, args);
     }
     write(fd, "\n", 1);
     return NO_ERROR;
@@ -528,7 +551,10 @@
 MediaPlayerService::Client::~Client()
 {
     ALOGV("Client(%d) destructor pid = %d", mConnId, mPid);
-    mAudioOutput.clear();
+    {
+        Mutex::Autolock l(mLock);
+        mAudioOutput.clear();
+    }
     wp<Client> client(this);
     disconnect();
     mService->removeClient(client);
@@ -544,10 +570,9 @@
         Mutex::Autolock l(mLock);
         p = mPlayer;
         mClient.clear();
+        mPlayer.clear();
     }
 
-    mPlayer.clear();
-
     // clear the notification to prevent callbacks to dead client
     // and reset the player. We assume the player will serialize
     // access to itself if necessary.
@@ -568,7 +593,7 @@
 sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
 {
     // determine if we have the right player type
-    sp<MediaPlayerBase> p = mPlayer;
+    sp<MediaPlayerBase> p = getPlayer();
     if ((p != NULL) && (p->playerType() != playerType)) {
         ALOGV("delete player");
         p.clear();
@@ -623,6 +648,7 @@
     }
 
     if (mStatus == OK) {
+        Mutex::Autolock l(mLock);
         mPlayer = p;
     }
 }
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 4f76b0a..7552323 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -62,6 +62,7 @@
                 const sp<SampleTable> &sampleTable,
                 Vector<SidxEntry> &sidx,
                 off64_t firstMoofOffset);
+    virtual status_t init();
 
     virtual status_t start(MetaData *params = NULL);
     virtual status_t stop();
@@ -852,6 +853,12 @@
                 ALOGE("moov: depth %d", depth);
                 return ERROR_MALFORMED;
             }
+
+            if (chunk_type == FOURCC('m', 'o', 'o', 'v') && mInitCheck == OK) {
+                ALOGE("duplicate moov");
+                return ERROR_MALFORMED;
+            }
+
             if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
                 ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
 
@@ -919,6 +926,12 @@
                 if (!mLastTrack->meta->findInt32(kKeyTrackID, &trackId)) {
                     mLastTrack->skipTrack = true;
                 }
+
+                status_t err = verifyTrack(mLastTrack);
+                if (err != OK) {
+                    mLastTrack->skipTrack = true;
+                }
+
                 if (mLastTrack->skipTrack) {
                     Track *cur = mFirstTrack;
 
@@ -936,12 +949,6 @@
 
                     return OK;
                 }
-
-                status_t err = verifyTrack(mLastTrack);
-
-                if (err != OK) {
-                    return err;
-                }
             } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
                 mInitCheck = OK;
 
@@ -1924,7 +1931,10 @@
             if (mLastTrack == NULL) {
                 return ERROR_MALFORMED;
             }
-            parseSegmentIndex(data_offset, chunk_data_size);
+            status_t err = parseSegmentIndex(data_offset, chunk_data_size);
+            if (err != OK) {
+                return err;
+            }
             *offset += chunk_size;
             return UNKNOWN_ERROR; // stop parsing after sidx
         }
@@ -2369,9 +2379,13 @@
 
     ALOGV("getTrack called, pssh: %d", mPssh.size());
 
-    return new MPEG4Source(
+    sp<MPEG4Source> source =  new MPEG4Source(
             track->meta, mDataSource, track->timescale, track->sampleTable,
             mSidxEntries, mMoofOffset);
+    if (source->init() != OK) {
+        return NULL;
+    }
+    return source;
 }
 
 // static
@@ -2548,6 +2562,7 @@
       mSegments(sidx),
       mFirstMoofOffset(firstMoofOffset),
       mCurrentMoofOffset(firstMoofOffset),
+      mNextMoofOffset(-1),
       mCurrentTime(0),
       mCurrentSampleInfoAllocSize(0),
       mCurrentSampleInfoSizes(NULL),
@@ -2596,10 +2611,14 @@
 
     CHECK(format->findInt32(kKeyTrackID, &mTrackId));
 
+}
+
+status_t MPEG4Source::init() {
     if (mFirstMoofOffset != 0) {
         off64_t offset = mFirstMoofOffset;
-        parseChunk(&offset);
+        return parseChunk(&offset);
     }
+    return OK;
 }
 
 MPEG4Source::~MPEG4Source() {
@@ -2715,9 +2734,42 @@
                 }
             }
             if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
-                // *offset points to the mdat box following this moof
-                parseChunk(offset); // doesn't actually parse it, just updates offset
-                mNextMoofOffset = *offset;
+                // *offset points to the box following this moof. Find the next moof from there.
+
+                while (true) {
+                    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
+                        // no more box to the end of file.
+                        break;
+                    }
+                    chunk_size = ntohl(hdr[0]);
+                    chunk_type = ntohl(hdr[1]);
+                    if (chunk_size == 1) {
+                        // ISO/IEC 14496-12:2012, 8.8.4 Movie Fragment Box, moof is a Box
+                        // which is defined in 4.2 Object Structure.
+                        // When chunk_size==1, 8 bytes follows as "largesize".
+                        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
+                            return ERROR_IO;
+                        }
+                        chunk_size = ntoh64(chunk_size);
+                        if (chunk_size < 16) {
+                            // The smallest valid chunk is 16 bytes long in this case.
+                            return ERROR_MALFORMED;
+                        }
+                    } else if (chunk_size == 0) {
+                        // next box extends to end of file.
+                    } else if (chunk_size < 8) {
+                        // The smallest valid chunk is 8 bytes long in this case.
+                        return ERROR_MALFORMED;
+                    }
+
+                    if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
+                        mNextMoofOffset = *offset;
+                        break;
+                    } else if (chunk_size == 0) {
+                        break;
+                    }
+                    *offset += chunk_size;
+                }
             }
             break;
         }
@@ -3572,9 +3624,13 @@
                 totalOffset += se->mSize;
             }
         mCurrentMoofOffset = totalOffset;
+        mNextMoofOffset = -1;
         mCurrentSamples.clear();
         mCurrentSampleIndex = 0;
-        parseChunk(&totalOffset);
+        status_t err = parseChunk(&totalOffset);
+        if (err != OK) {
+            return err;
+        }
         mCurrentTime = totalTime * mTimescale / 1000000ll;
         }
 
@@ -3601,7 +3657,10 @@
             mCurrentMoofOffset = nextMoof;
             mCurrentSamples.clear();
             mCurrentSampleIndex = 0;
-            parseChunk(&nextMoof);
+            status_t err = parseChunk(&nextMoof);
+            if (err != OK) {
+                return err;
+            }
                 if (mCurrentSampleIndex >= mCurrentSamples.size()) {
                     return ERROR_END_OF_STREAM;
                 }
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 8f9c9c8..b4884e2 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -460,6 +460,11 @@
         bits.skipBits(2);
 
         unsigned aac_frame_length = bits.getBits(13);
+        if (aac_frame_length == 0){
+            ALOGE("b/62673179, Invalid AAC frame length!");
+            android_errorWriteLog(0x534e4554, "62673179");
+            return NULL;
+        }
 
         bits.skipBits(11);  // adts_buffer_fullness
 
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 9e06358..9e9116b 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1145,6 +1145,24 @@
     ALOGVV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
             cmdCode, mHasControl, mEffect.unsafe_get());
 
+    // reject commands reserved for internal use by audio framework if coming from outside
+    // of audioserver
+    switch(cmdCode) {
+        case EFFECT_CMD_ENABLE:
+        case EFFECT_CMD_DISABLE:
+        case EFFECT_CMD_SET_PARAM:
+        case EFFECT_CMD_SET_PARAM_DEFERRED:
+        case EFFECT_CMD_SET_PARAM_COMMIT:
+        case EFFECT_CMD_GET_PARAM:
+            break;
+        default:
+            if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY) {
+                break;
+            }
+            android_errorWriteLog(0x534e4554, "62019992");
+            return BAD_VALUE;
+    }
+
     if (cmdCode == EFFECT_CMD_ENABLE) {
         if (*replySize < sizeof(int)) {
             android_errorWriteLog(0x534e4554, "32095713");