frameworks/av
Revision | 30799e0cc79cc7bc5c18825483f6732cd53709c4 (tree) |
---|---|
Time | 2017-03-24 00:09:33 |
Author | Chih-Wei Huang <cwhuang@linu...> |
Commiter | Chih-Wei Huang |
Merge tag 'android-6.0.1_r79' into marshmallow-x86
Android 6.0.1 release 79
@@ -2354,8 +2354,12 @@ int Equalizer_getParameter(EffectContext *pContext, | ||
2354 | 2354 | |
2355 | 2355 | case EQ_PARAM_BAND_LEVEL: |
2356 | 2356 | param2 = *pParamTemp; |
2357 | - if (param2 >= FIVEBAND_NUMBANDS) { | |
2357 | + if (param2 < 0 || param2 >= FIVEBAND_NUMBANDS) { | |
2358 | 2358 | status = -EINVAL; |
2359 | + if (param2 < 0) { | |
2360 | + android_errorWriteLog(0x534e4554, "32438598"); | |
2361 | + ALOGW("\tERROR Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d", param2); | |
2362 | + } | |
2359 | 2363 | break; |
2360 | 2364 | } |
2361 | 2365 | *(int16_t *)pValue = (int16_t)EqualizerGetBandLevel(pContext, param2); |
@@ -2365,8 +2369,12 @@ int Equalizer_getParameter(EffectContext *pContext, | ||
2365 | 2369 | |
2366 | 2370 | case EQ_PARAM_CENTER_FREQ: |
2367 | 2371 | param2 = *pParamTemp; |
2368 | - if (param2 >= FIVEBAND_NUMBANDS) { | |
2372 | + if (param2 < 0 || param2 >= FIVEBAND_NUMBANDS) { | |
2369 | 2373 | status = -EINVAL; |
2374 | + if (param2 < 0) { | |
2375 | + android_errorWriteLog(0x534e4554, "32436341"); | |
2376 | + ALOGW("\tERROR Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d", param2); | |
2377 | + } | |
2370 | 2378 | break; |
2371 | 2379 | } |
2372 | 2380 | *(int32_t *)pValue = EqualizerGetCentreFrequency(pContext, param2); |
@@ -2376,8 +2384,12 @@ int Equalizer_getParameter(EffectContext *pContext, | ||
2376 | 2384 | |
2377 | 2385 | case EQ_PARAM_BAND_FREQ_RANGE: |
2378 | 2386 | param2 = *pParamTemp; |
2379 | - if (param2 >= FIVEBAND_NUMBANDS) { | |
2387 | + if (param2 < 0 || param2 >= FIVEBAND_NUMBANDS) { | |
2380 | 2388 | status = -EINVAL; |
2389 | + if (param2 < 0) { | |
2390 | + android_errorWriteLog(0x534e4554, "32247948"); | |
2391 | + ALOGW("\tERROR Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d", param2); | |
2392 | + } | |
2381 | 2393 | break; |
2382 | 2394 | } |
2383 | 2395 | EqualizerGetBandFreqRange(pContext, param2, (uint32_t *)pValue, ((uint32_t *)pValue + 1)); |
@@ -2404,9 +2416,13 @@ int Equalizer_getParameter(EffectContext *pContext, | ||
2404 | 2416 | |
2405 | 2417 | case EQ_PARAM_GET_PRESET_NAME: |
2406 | 2418 | param2 = *pParamTemp; |
2407 | - if (param2 >= EqualizerGetNumPresets()) { | |
2408 | - //if (param2 >= 20) { // AGO FIX | |
2419 | + if ((param2 < 0 && param2 != PRESET_CUSTOM) || param2 >= EqualizerGetNumPresets()) { | |
2409 | 2420 | status = -EINVAL; |
2421 | + if (param2 < 0) { | |
2422 | + android_errorWriteLog(0x534e4554, "32448258"); | |
2423 | + ALOGE("\tERROR Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d", | |
2424 | + param2); | |
2425 | + } | |
2410 | 2426 | break; |
2411 | 2427 | } |
2412 | 2428 | name = (char *)pValue; |
@@ -2476,8 +2492,12 @@ int Equalizer_setParameter (EffectContext *pContext, void *pParam, void *pValue) | ||
2476 | 2492 | band = *pParamTemp; |
2477 | 2493 | level = (int32_t)(*(int16_t *)pValue); |
2478 | 2494 | //ALOGV("\tEqualizer_setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level); |
2479 | - if (band >= FIVEBAND_NUMBANDS) { | |
2495 | + if (band < 0 || band >= FIVEBAND_NUMBANDS) { | |
2480 | 2496 | status = -EINVAL; |
2497 | + if (band < 0) { | |
2498 | + android_errorWriteLog(0x534e4554, "32095626"); | |
2499 | + ALOGE("\tERROR Equalizer_setParameter() EQ_PARAM_BAND_LEVEL band %d", band); | |
2500 | + } | |
2481 | 2501 | break; |
2482 | 2502 | } |
2483 | 2503 | EqualizerSetBandLevel(pContext, band, level); |
@@ -3091,10 +3111,6 @@ int Effect_command(effect_handle_t self, | ||
3091 | 3111 | //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_GET_PARAM start"); |
3092 | 3112 | |
3093 | 3113 | effect_param_t *p = (effect_param_t *)pCmdData; |
3094 | - if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) { | |
3095 | - android_errorWriteLog(0x534e4554, "26347509"); | |
3096 | - return -EINVAL; | |
3097 | - } | |
3098 | 3114 | if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) || |
3099 | 3115 | cmdSize < (sizeof(effect_param_t) + p->psize) || |
3100 | 3116 | pReplyData == NULL || replySize == NULL || |
@@ -3102,13 +3118,32 @@ int Effect_command(effect_handle_t self, | ||
3102 | 3118 | ALOGV("\tLVM_ERROR : EFFECT_CMD_GET_PARAM: ERROR"); |
3103 | 3119 | return -EINVAL; |
3104 | 3120 | } |
3121 | + if (EFFECT_PARAM_SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) { | |
3122 | + android_errorWriteLog(0x534e4554, "26347509"); | |
3123 | + ALOGV("\tLVM_ERROR : EFFECT_CMD_GET_PARAM: psize too big"); | |
3124 | + return -EINVAL; | |
3125 | + } | |
3126 | + uint32_t paddedParamSize = ((p->psize + sizeof(int32_t) - 1) / sizeof(int32_t)) * | |
3127 | + sizeof(int32_t); | |
3128 | + if ((EFFECT_PARAM_SIZE_MAX - sizeof(effect_param_t) < paddedParamSize) || | |
3129 | + (EFFECT_PARAM_SIZE_MAX - sizeof(effect_param_t) - paddedParamSize < | |
3130 | + p->vsize)) { | |
3131 | + ALOGV("\tLVM_ERROR : EFFECT_CMD_GET_PARAM: padded_psize or vsize too big"); | |
3132 | + return -EINVAL; | |
3133 | + } | |
3134 | + uint32_t expectedReplySize = sizeof(effect_param_t) + paddedParamSize + p->vsize; | |
3135 | + if (*replySize < expectedReplySize) { | |
3136 | + ALOGV("\tLVM_ERROR : EFFECT_CMD_GET_PARAM: min. replySize %u, got %u bytes", | |
3137 | + expectedReplySize, *replySize); | |
3138 | + android_errorWriteLog(0x534e4554, "32705438"); | |
3139 | + return -EINVAL; | |
3140 | + } | |
3105 | 3141 | |
3106 | 3142 | memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize); |
3107 | 3143 | |
3108 | 3144 | p = (effect_param_t *)pReplyData; |
3109 | 3145 | |
3110 | - int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t); | |
3111 | - | |
3146 | + uint32_t voffset = paddedParamSize; | |
3112 | 3147 | if(pContext->EffectType == LVM_BASS_BOOST){ |
3113 | 3148 | p->status = android::BassBoost_getParameter(pContext, |
3114 | 3149 | p->data, |
@@ -59,6 +59,8 @@ enum visualizer_state_e { | ||
59 | 59 | |
60 | 60 | #define DISCARD_MEASUREMENTS_TIME_MS 2000 // discard measurements older than this number of ms |
61 | 61 | |
62 | +#define MAX_LATENCY_MS 3000 // 3 seconds of latency for audio pipeline | |
63 | + | |
62 | 64 | // maximum number of buffers for which we keep track of the measurements |
63 | 65 | #define MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS 25 // note: buffer index is stored in uint8_t |
64 | 66 |
@@ -521,18 +523,29 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, | ||
521 | 523 | break; |
522 | 524 | } |
523 | 525 | switch (*(uint32_t *)p->data) { |
524 | - case VISUALIZER_PARAM_CAPTURE_SIZE: | |
525 | - pContext->mCaptureSize = *((uint32_t *)p->data + 1); | |
526 | - ALOGV("set mCaptureSize = %" PRIu32, pContext->mCaptureSize); | |
527 | - break; | |
526 | + case VISUALIZER_PARAM_CAPTURE_SIZE: { | |
527 | + const uint32_t captureSize = *((uint32_t *)p->data + 1); | |
528 | + if (captureSize > VISUALIZER_CAPTURE_SIZE_MAX) { | |
529 | + android_errorWriteLog(0x534e4554, "31781965"); | |
530 | + *(int32_t *)pReplyData = -EINVAL; | |
531 | + ALOGW("set mCaptureSize = %u > %u", captureSize, VISUALIZER_CAPTURE_SIZE_MAX); | |
532 | + } else { | |
533 | + pContext->mCaptureSize = captureSize; | |
534 | + ALOGV("set mCaptureSize = %u", captureSize); | |
535 | + } | |
536 | + } break; | |
528 | 537 | case VISUALIZER_PARAM_SCALING_MODE: |
529 | 538 | pContext->mScalingMode = *((uint32_t *)p->data + 1); |
530 | 539 | ALOGV("set mScalingMode = %" PRIu32, pContext->mScalingMode); |
531 | 540 | break; |
532 | - case VISUALIZER_PARAM_LATENCY: | |
533 | - pContext->mLatency = *((uint32_t *)p->data + 1); | |
534 | - ALOGV("set mLatency = %" PRIu32, pContext->mLatency); | |
535 | - break; | |
541 | + case VISUALIZER_PARAM_LATENCY: { | |
542 | + uint32_t latency = *((uint32_t *)p->data + 1); | |
543 | + if (latency > MAX_LATENCY_MS) { | |
544 | + latency = MAX_LATENCY_MS; // clamp latency b/31781965 | |
545 | + } | |
546 | + pContext->mLatency = latency; | |
547 | + ALOGV("set mLatency = %u", latency); | |
548 | + } break; | |
536 | 549 | case VISUALIZER_PARAM_MEASUREMENT_MODE: |
537 | 550 | pContext->mMeasurementMode = *((uint32_t *)p->data + 1); |
538 | 551 | ALOGV("set mMeasurementMode = %" PRIu32, pContext->mMeasurementMode); |
@@ -571,10 +584,18 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, | ||
571 | 584 | if (latencyMs < 0) { |
572 | 585 | latencyMs = 0; |
573 | 586 | } |
574 | - const uint32_t deltaSmpl = | |
575 | - pContext->mConfig.inputCfg.samplingRate * latencyMs / 1000; | |
576 | - int32_t capturePoint = pContext->mCaptureIdx - captureSize - deltaSmpl; | |
587 | + uint32_t deltaSmpl = captureSize | |
588 | + + pContext->mConfig.inputCfg.samplingRate * latencyMs / 1000; | |
589 | + | |
590 | + // large sample rate, latency, or capture size, could cause overflow. | |
591 | + // do not offset more than the size of buffer. | |
592 | + if (deltaSmpl > CAPTURE_BUF_SIZE) { | |
593 | + android_errorWriteLog(0x534e4554, "31781965"); | |
594 | + deltaSmpl = CAPTURE_BUF_SIZE; | |
595 | + } | |
577 | 596 | |
597 | + int32_t capturePoint = pContext->mCaptureIdx - deltaSmpl; | |
598 | + // a negative capturePoint means we wrap the buffer. | |
578 | 599 | if (capturePoint < 0) { |
579 | 600 | uint32_t size = -capturePoint; |
580 | 601 | if (size > captureSize) { |
@@ -602,9 +623,14 @@ int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, | ||
602 | 623 | case VISUALIZER_CMD_MEASURE: { |
603 | 624 | if (pReplyData == NULL || replySize == NULL || |
604 | 625 | *replySize < (sizeof(int32_t) * MEASUREMENT_COUNT)) { |
605 | - ALOGV("VISUALIZER_CMD_MEASURE() error *replySize %" PRIu32 | |
606 | - " < (sizeof(int32_t) * MEASUREMENT_COUNT) %" PRIu32, *replySize, | |
607 | - sizeof(int32_t) * MEASUREMENT_COUNT); | |
626 | + if (replySize == NULL) { | |
627 | + ALOGV("VISUALIZER_CMD_MEASURE() error replySize NULL"); | |
628 | + } else { | |
629 | + ALOGV("VISUALIZER_CMD_MEASURE() error *replySize %" PRIu32 | |
630 | + " < (sizeof(int32_t) * MEASUREMENT_COUNT) %" PRIu32, | |
631 | + *replySize, | |
632 | + uint32_t(sizeof(int32_t)) * MEASUREMENT_COUNT); | |
633 | + } | |
608 | 634 | android_errorWriteLog(0x534e4554, "30229821"); |
609 | 635 | return -EINVAL; |
610 | 636 | } |
@@ -25,6 +25,9 @@ | ||
25 | 25 | |
26 | 26 | namespace android { |
27 | 27 | |
28 | +// Maximum command/reply size expected | |
29 | +#define EFFECT_PARAM_SIZE_MAX 65536 | |
30 | + | |
28 | 31 | enum { |
29 | 32 | ENABLE = IBinder::FIRST_CALL_TRANSACTION, |
30 | 33 | DISABLE, |
@@ -156,6 +159,10 @@ status_t BnEffect::onTransact( | ||
156 | 159 | uint32_t cmdSize = data.readInt32(); |
157 | 160 | char *cmd = NULL; |
158 | 161 | if (cmdSize) { |
162 | + if (cmdSize > EFFECT_PARAM_SIZE_MAX) { | |
163 | + reply->writeInt32(NO_MEMORY); | |
164 | + return NO_ERROR; | |
165 | + } | |
159 | 166 | cmd = (char *)calloc(cmdSize, 1); |
160 | 167 | if (cmd == NULL) { |
161 | 168 | reply->writeInt32(NO_MEMORY); |
@@ -167,6 +174,11 @@ status_t BnEffect::onTransact( | ||
167 | 174 | uint32_t replySz = replySize; |
168 | 175 | char *resp = NULL; |
169 | 176 | if (replySize) { |
177 | + if (replySize > EFFECT_PARAM_SIZE_MAX) { | |
178 | + free(cmd); | |
179 | + reply->writeInt32(NO_MEMORY); | |
180 | + return NO_ERROR; | |
181 | + } | |
170 | 182 | resp = (char *)calloc(replySize, 1); |
171 | 183 | if (resp == NULL) { |
172 | 184 | free(cmd); |
@@ -472,7 +472,8 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData( | ||
472 | 472 | } else { |
473 | 473 | uint32_t sampleIndex; |
474 | 474 | uint32_t sampleTime; |
475 | - if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK | |
475 | + if (track->timescale != 0 && | |
476 | + track->sampleTable->findThumbnailSample(&sampleIndex) == OK | |
476 | 477 | && track->sampleTable->getMetaDataForSample( |
477 | 478 | sampleIndex, NULL /* offset */, NULL /* size */, |
478 | 479 | &sampleTime) == OK) { |
@@ -886,6 +887,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | ||
886 | 887 | case FOURCC('s', 'c', 'h', 'i'): |
887 | 888 | case FOURCC('e', 'd', 't', 's'): |
888 | 889 | { |
890 | + if (chunk_type == FOURCC('m', 'o', 'o', 'v') && depth != 0) { | |
891 | + ALOGE("moov: depth %d", depth); | |
892 | + return ERROR_MALFORMED; | |
893 | + } | |
889 | 894 | if (chunk_type == FOURCC('m', 'o', 'o', 'f') && !mMoofFound) { |
890 | 895 | // store the offset of the first segment |
891 | 896 | mMoofFound = true; |
@@ -914,6 +919,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | ||
914 | 919 | |
915 | 920 | bool isTrack = false; |
916 | 921 | if (chunk_type == FOURCC('t', 'r', 'a', 'k')) { |
922 | + if (depth != 1) { | |
923 | + ALOGE("trak: depth %d", depth); | |
924 | + return ERROR_MALFORMED; | |
925 | + } | |
917 | 926 | isTrack = true; |
918 | 927 | |
919 | 928 | Track *track = new Track; |
@@ -937,6 +946,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | ||
937 | 946 | while (*offset < stop_offset) { |
938 | 947 | status_t err = parseChunk(offset, depth + 1); |
939 | 948 | if (err != OK) { |
949 | + if (isTrack) { | |
950 | + mLastTrack->skipTrack = true; | |
951 | + break; | |
952 | + } | |
940 | 953 | return err; |
941 | 954 | } |
942 | 955 | } |
@@ -1282,10 +1295,6 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | ||
1282 | 1295 | |
1283 | 1296 | case FOURCC('s', 't', 's', 'd'): |
1284 | 1297 | { |
1285 | - if (chunk_data_size < 8) { | |
1286 | - return ERROR_MALFORMED; | |
1287 | - } | |
1288 | - | |
1289 | 1298 | uint8_t buffer[8]; |
1290 | 1299 | if (chunk_data_size < (off64_t)sizeof(buffer)) { |
1291 | 1300 | return ERROR_MALFORMED; |
@@ -1865,6 +1874,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { | ||
1865 | 1874 | { |
1866 | 1875 | *offset += chunk_size; |
1867 | 1876 | |
1877 | + if (depth != 1) { | |
1878 | + ALOGE("mvhd: depth %d", depth); | |
1879 | + return ERROR_MALFORMED; | |
1880 | + } | |
1868 | 1881 | if (chunk_data_size < 32) { |
1869 | 1882 | return ERROR_MALFORMED; |
1870 | 1883 | } |
@@ -83,8 +83,23 @@ sp<VBRISeeker> VBRISeeker::CreateFromSource( | ||
83 | 83 | scale, |
84 | 84 | entrySize); |
85 | 85 | |
86 | + if (entrySize > 4) { | |
87 | + ALOGE("invalid VBRI entry size: %zu", entrySize); | |
88 | + return NULL; | |
89 | + } | |
90 | + | |
91 | + sp<VBRISeeker> seeker = new (std::nothrow) VBRISeeker; | |
92 | + if (seeker == NULL) { | |
93 | + ALOGW("Couldn't allocate VBRISeeker"); | |
94 | + return NULL; | |
95 | + } | |
96 | + | |
86 | 97 | size_t totalEntrySize = numEntries * entrySize; |
87 | - uint8_t *buffer = new uint8_t[totalEntrySize]; | |
98 | + uint8_t *buffer = new (std::nothrow) uint8_t[totalEntrySize]; | |
99 | + if (!buffer) { | |
100 | + ALOGW("Couldn't allocate %zu bytes", totalEntrySize); | |
101 | + return NULL; | |
102 | + } | |
88 | 103 | |
89 | 104 | n = source->readAt(pos + sizeof(vbriHeader), buffer, totalEntrySize); |
90 | 105 | if (n < (ssize_t)totalEntrySize) { |
@@ -94,7 +109,6 @@ sp<VBRISeeker> VBRISeeker::CreateFromSource( | ||
94 | 109 | return NULL; |
95 | 110 | } |
96 | 111 | |
97 | - sp<VBRISeeker> seeker = new VBRISeeker; | |
98 | 112 | seeker->mBasePos = post_id3_pos + frameSize; |
99 | 113 | // only update mDurationUs if the calculated duration is valid (non zero) |
100 | 114 | // otherwise, leave duration at -1 so that getDuration() and getOffsetForTime() |
@@ -831,20 +831,21 @@ void ID3::Iterator::findFrame() { | ||
831 | 831 | } |
832 | 832 | } |
833 | 833 | |
834 | -static size_t StringSize(const uint8_t *start, uint8_t encoding) { | |
834 | +// return includes terminator; if unterminated, returns > limit | |
835 | +static size_t StringSize(const uint8_t *start, size_t limit, uint8_t encoding) { | |
836 | + | |
835 | 837 | if (encoding == 0x00 || encoding == 0x03) { |
836 | 838 | // ISO 8859-1 or UTF-8 |
837 | - return strlen((const char *)start) + 1; | |
839 | + return strnlen((const char *)start, limit) + 1; | |
838 | 840 | } |
839 | 841 | |
840 | 842 | // UCS-2 |
841 | 843 | size_t n = 0; |
842 | - while (start[n] != '\0' || start[n + 1] != '\0') { | |
844 | + while ((n+1 < limit) && (start[n] != '\0' || start[n + 1] != '\0')) { | |
843 | 845 | n += 2; |
844 | 846 | } |
845 | - | |
846 | - // Add size of null termination. | |
847 | - return n + 2; | |
847 | + n += 2; | |
848 | + return n; | |
848 | 849 | } |
849 | 850 | |
850 | 851 | const void * |
@@ -862,11 +863,19 @@ ID3::getAlbumArt(size_t *length, String8 *mime) const { | ||
862 | 863 | |
863 | 864 | if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) { |
864 | 865 | uint8_t encoding = data[0]; |
865 | - mime->setTo((const char *)&data[1]); | |
866 | - size_t mimeLen = strlen((const char *)&data[1]) + 1; | |
866 | + size_t consumed = 1; | |
867 | + | |
868 | + // *always* in an 8-bit encoding | |
869 | + size_t mimeLen = StringSize(&data[consumed], size - consumed, 0x00); | |
870 | + if (mimeLen > size - consumed) { | |
871 | + ALOGW("bogus album art size: mime"); | |
872 | + return NULL; | |
873 | + } | |
874 | + mime->setTo((const char *)&data[consumed]); | |
875 | + consumed += mimeLen; | |
867 | 876 | |
868 | 877 | #if 0 |
869 | - uint8_t picType = data[1 + mimeLen]; | |
878 | + uint8_t picType = data[consumed]; | |
870 | 879 | if (picType != 0x03) { |
871 | 880 | // Front Cover Art |
872 | 881 | it.next(); |
@@ -874,20 +883,30 @@ ID3::getAlbumArt(size_t *length, String8 *mime) const { | ||
874 | 883 | } |
875 | 884 | #endif |
876 | 885 | |
877 | - size_t descLen = StringSize(&data[2 + mimeLen], encoding); | |
886 | + consumed++; | |
887 | + if (consumed >= size) { | |
888 | + ALOGW("bogus album art size: pic type"); | |
889 | + return NULL; | |
890 | + } | |
891 | + | |
892 | + size_t descLen = StringSize(&data[consumed], size - consumed, encoding); | |
893 | + consumed += descLen; | |
878 | 894 | |
879 | - if (size < 2 || | |
880 | - size - 2 < mimeLen || | |
881 | - size - 2 - mimeLen < descLen) { | |
882 | - ALOGW("bogus album art sizes"); | |
895 | + if (consumed >= size) { | |
896 | + ALOGW("bogus album art size: description"); | |
883 | 897 | return NULL; |
884 | 898 | } |
885 | - *length = size - 2 - mimeLen - descLen; | |
886 | 899 | |
887 | - return &data[2 + mimeLen + descLen]; | |
900 | + *length = size - consumed; | |
901 | + | |
902 | + return &data[consumed]; | |
888 | 903 | } else { |
889 | 904 | uint8_t encoding = data[0]; |
890 | 905 | |
906 | + if (size <= 5) { | |
907 | + return NULL; | |
908 | + } | |
909 | + | |
891 | 910 | if (!memcmp(&data[1], "PNG", 3)) { |
892 | 911 | mime->setTo("image/png"); |
893 | 912 | } else if (!memcmp(&data[1], "JPG", 3)) { |
@@ -907,7 +926,10 @@ ID3::getAlbumArt(size_t *length, String8 *mime) const { | ||
907 | 926 | } |
908 | 927 | #endif |
909 | 928 | |
910 | - size_t descLen = StringSize(&data[5], encoding); | |
929 | + size_t descLen = StringSize(&data[5], size - 5, encoding); | |
930 | + if (descLen > size - 5) { | |
931 | + return NULL; | |
932 | + } | |
911 | 933 | |
912 | 934 | *length = size - 5 - descLen; |
913 | 935 |
@@ -167,8 +167,10 @@ struct BufferMeta { | ||
167 | 167 | return buf; |
168 | 168 | } |
169 | 169 | |
170 | - bool copyToOmx() const { | |
171 | - return mCopyToOmx; | |
170 | + bool copyingOrSharingToOmx(const OMX_BUFFERHEADERTYPE *header) const { | |
171 | + return mCopyToOmx | |
172 | + // sharing buffer with client | |
173 | + || (mMem != NULL && mMem->pointer() == header->pBuffer); | |
172 | 174 | } |
173 | 175 | |
174 | 176 | void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) { |
@@ -780,13 +782,6 @@ status_t OMXNodeInstance::useBuffer( | ||
780 | 782 | } |
781 | 783 | memset(data, 0, allottedSize); |
782 | 784 | |
783 | - // if we are not connecting the buffers, the sizes must match | |
784 | - if (allottedSize != params->size()) { | |
785 | - CLOG_ERROR(useBuffer, BAD_VALUE, SIMPLE_BUFFER(portIndex, (size_t)allottedSize, data)); | |
786 | - delete[] data; | |
787 | - return BAD_VALUE; | |
788 | - } | |
789 | - | |
790 | 785 | buffer_meta = new BufferMeta( |
791 | 786 | params, portIndex, false /* copyToOmx */, false /* copyFromOmx */, data); |
792 | 787 | } else { |
@@ -1279,7 +1274,7 @@ status_t OMXNodeInstance::emptyBuffer( | ||
1279 | 1274 | |
1280 | 1275 | // convert incoming ANW meta buffers if component is configured for gralloc metadata mode |
1281 | 1276 | // ignore rangeOffset in this case |
1282 | - if (buffer_meta->copyToOmx() | |
1277 | + if (buffer_meta->copyingOrSharingToOmx(header) | |
1283 | 1278 | && mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource |
1284 | 1279 | && backup->capacity() >= sizeof(VideoNativeMetadata) |
1285 | 1280 | && codec->capacity() >= sizeof(VideoGrallocMetadata) |
@@ -571,6 +571,29 @@ status_t AudioFlinger::EffectModule::command(uint32_t cmdCode, | ||
571 | 571 | android_errorWriteLog(0x534e4554, "29251553"); |
572 | 572 | return -EINVAL; |
573 | 573 | } |
574 | + if (cmdCode == EFFECT_CMD_GET_PARAM && | |
575 | + (sizeof(effect_param_t) > cmdSize || | |
576 | + ((effect_param_t *)pCmdData)->psize > cmdSize | |
577 | + - sizeof(effect_param_t))) { | |
578 | + android_errorWriteLog(0x534e4554, "32438594"); | |
579 | + return -EINVAL; | |
580 | + } | |
581 | + if (cmdCode == EFFECT_CMD_GET_PARAM && | |
582 | + (sizeof(effect_param_t) > *replySize | |
583 | + || ((effect_param_t *)pCmdData)->psize > *replySize | |
584 | + - sizeof(effect_param_t) | |
585 | + || ((effect_param_t *)pCmdData)->vsize > *replySize | |
586 | + - sizeof(effect_param_t) | |
587 | + - ((effect_param_t *)pCmdData)->psize | |
588 | + || roundUpDelta(((effect_param_t *)pCmdData)->psize, (uint32_t)sizeof(int)) > | |
589 | + *replySize | |
590 | + - sizeof(effect_param_t) | |
591 | + - ((effect_param_t *)pCmdData)->psize | |
592 | + - ((effect_param_t *)pCmdData)->vsize)) { | |
593 | + ALOGV("\tLVM_ERROR : EFFECT_CMD_GET_PARAM: reply size inconsistent"); | |
594 | + android_errorWriteLog(0x534e4554, "32705438"); | |
595 | + return -EINVAL; | |
596 | + } | |
574 | 597 | if ((cmdCode == EFFECT_CMD_SET_PARAM |
575 | 598 | || cmdCode == EFFECT_CMD_SET_PARAM_DEFERRED) && // DEFERRED not generally used |
576 | 599 | (sizeof(effect_param_t) > cmdSize |
@@ -1254,36 +1277,54 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode, | ||
1254 | 1277 | // particular client process: no risk to block the whole media server process or mixer |
1255 | 1278 | // threads if we are stuck here |
1256 | 1279 | Mutex::Autolock _l(mCblk->lock); |
1257 | - if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE || | |
1258 | - mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) { | |
1280 | + | |
1281 | + // keep local copy of index in case of client corruption b/32220769 | |
1282 | + const uint32_t clientIndex = mCblk->clientIndex; | |
1283 | + const uint32_t serverIndex = mCblk->serverIndex; | |
1284 | + if (clientIndex > EFFECT_PARAM_BUFFER_SIZE || | |
1285 | + serverIndex > EFFECT_PARAM_BUFFER_SIZE) { | |
1259 | 1286 | mCblk->serverIndex = 0; |
1260 | 1287 | mCblk->clientIndex = 0; |
1261 | 1288 | return BAD_VALUE; |
1262 | 1289 | } |
1263 | 1290 | status_t status = NO_ERROR; |
1264 | - while (mCblk->serverIndex < mCblk->clientIndex) { | |
1265 | - int reply; | |
1266 | - uint32_t rsize = sizeof(int); | |
1267 | - int *p = (int *)(mBuffer + mCblk->serverIndex); | |
1268 | - int size = *p++; | |
1269 | - if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) { | |
1291 | + effect_param_t *param = NULL; | |
1292 | + for (uint32_t index = serverIndex; index < clientIndex;) { | |
1293 | + int *p = (int *)(mBuffer + index); | |
1294 | + const int size = *p++; | |
1295 | + if (size < 0 | |
1296 | + || size > EFFECT_PARAM_BUFFER_SIZE | |
1297 | + || ((uint8_t *)p + size) > mBuffer + clientIndex) { | |
1270 | 1298 | ALOGW("command(): invalid parameter block size"); |
1299 | + status = BAD_VALUE; | |
1271 | 1300 | break; |
1272 | 1301 | } |
1273 | - effect_param_t *param = (effect_param_t *)p; | |
1274 | - if (param->psize == 0 || param->vsize == 0) { | |
1275 | - ALOGW("command(): null parameter or value size"); | |
1276 | - mCblk->serverIndex += size; | |
1277 | - continue; | |
1302 | + | |
1303 | + // copy to local memory in case of client corruption b/32220769 | |
1304 | + param = (effect_param_t *)realloc(param, size); | |
1305 | + if (param == NULL) { | |
1306 | + ALOGW("command(): out of memory"); | |
1307 | + status = NO_MEMORY; | |
1308 | + break; | |
1278 | 1309 | } |
1279 | - uint32_t psize = sizeof(effect_param_t) + | |
1280 | - ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + | |
1281 | - param->vsize; | |
1310 | + memcpy(param, p, size); | |
1311 | + | |
1312 | + int reply = 0; | |
1313 | + uint32_t rsize = sizeof(reply); | |
1282 | 1314 | status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM, |
1283 | - psize, | |
1284 | - p, | |
1315 | + size, | |
1316 | + param, | |
1285 | 1317 | &rsize, |
1286 | 1318 | &reply); |
1319 | + | |
1320 | + // verify shared memory: server index shouldn't change; client index can't go back. | |
1321 | + if (serverIndex != mCblk->serverIndex | |
1322 | + || clientIndex > mCblk->clientIndex) { | |
1323 | + android_errorWriteLog(0x534e4554, "32220769"); | |
1324 | + status = BAD_VALUE; | |
1325 | + break; | |
1326 | + } | |
1327 | + | |
1287 | 1328 | // stop at first error encountered |
1288 | 1329 | if (ret != NO_ERROR) { |
1289 | 1330 | status = ret; |
@@ -1293,8 +1334,9 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode, | ||
1293 | 1334 | *(int *)pReplyData = reply; |
1294 | 1335 | break; |
1295 | 1336 | } |
1296 | - mCblk->serverIndex += size; | |
1337 | + index += size; | |
1297 | 1338 | } |
1339 | + free(param); | |
1298 | 1340 | mCblk->serverIndex = 0; |
1299 | 1341 | mCblk->clientIndex = 0; |
1300 | 1342 | return status; |