diff options
author | Lajos Molnar <lajos@google.com> | 2015-04-01 19:32:25 -0700 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2015-10-18 13:50:57 +0200 |
commit | ee7eef0a2de22470127dba659b34bbb6b318dcd2 (patch) | |
tree | b5dae606e075105b0312b7579dd28f0481891d53 | |
parent | 09618087da140c4d4943682f3fda2c774f5f7a33 (diff) | |
download | frameworks_av-ee7eef0a2de22470127dba659b34bbb6b318dcd2.zip frameworks_av-ee7eef0a2de22470127dba659b34bbb6b318dcd2.tar.gz frameworks_av-ee7eef0a2de22470127dba659b34bbb6b318dcd2.tar.bz2 |
DO NOT MERGE: Add AUtils::isInRange, and use it to detect malformed MPEG4 nal sizes
Bug: 19641538
Change-Id: I5aae3f100846c125decc61eec7cd6563e3f33777
Conflicts:
media/libstagefright/MPEG4Extractor.cpp
-rw-r--r-- | include/media/stagefright/foundation/AUtils.h | 45 | ||||
-rw-r--r-- | media/libstagefright/MPEG4Extractor.cpp | 8 | ||||
-rw-r--r-- | media/libstagefright/tests/Utils_test.cpp | 118 |
3 files changed, 167 insertions, 4 deletions
diff --git a/include/media/stagefright/foundation/AUtils.h b/include/media/stagefright/foundation/AUtils.h new file mode 100644 index 0000000..60cb41d --- /dev/null +++ b/include/media/stagefright/foundation/AUtils.h @@ -0,0 +1,45 @@ +/* + * Copyright 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef A_UTILS_H_ + +#define A_UTILS_H_ + +/* ============================ math templates ============================ */ + +template<class T> +void ENSURE_UNSIGNED_TYPE() { + T TYPE_MUST_BE_UNSIGNED[(T)-1 < 0 ? -1 : 0]; +} + +// needle is in range [hayStart, hayStart + haySize) +template<class T, class U> +inline static bool isInRange(const T &hayStart, const U &haySize, const T &needle) { + ENSURE_UNSIGNED_TYPE<U>(); + return (T)(hayStart + haySize) >= hayStart && needle >= hayStart && (U)(needle - hayStart) < haySize; +} + +// [needleStart, needleStart + needleSize) is in range [hayStart, hayStart + haySize) +template<class T, class U> +inline static bool isInRange( + const T &hayStart, const U &haySize, const T &needleStart, const U &needleSize) { + ENSURE_UNSIGNED_TYPE<U>(); + return isInRange(hayStart, haySize, needleStart) + && (T)(needleStart + needleSize) >= needleStart + && (U)(needleStart + needleSize - hayStart) <= haySize; +} + +#endif // A_UTILS_H_ diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 167fd01..16ff80b 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -33,6 +33,7 @@ #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/DataSource.h> +#include <media/stagefright/foundation/AUtils.h> #include <media/stagefright/MediaBuffer.h> #include <media/stagefright/MediaBufferGroup.h> #include <media/stagefright/MediaDefs.h> @@ -156,8 +157,7 @@ status_t MPEG4DataSource::initCheck() const { ssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) { Mutex::Autolock autoLock(mLock); - if (offset >= mCachedOffset - && offset + size <= mCachedOffset + mCachedSize) { + if (isInRange(mCachedOffset, mCachedSize, offset, size)) { memcpy(data, &mCache[offset - mCachedOffset], size); return size; } @@ -2382,12 +2382,12 @@ status_t MPEG4Source::read( size_t dstOffset = 0; while (srcOffset < size) { - bool isMalFormed = (srcOffset + mNALLengthSize > size); + bool isMalFormed = !isInRange(0u, size, srcOffset, mNALLengthSize); size_t nalLength = 0; if (!isMalFormed) { nalLength = parseNALSize(&mSrcBuffer[srcOffset]); srcOffset += mNALLengthSize; - isMalFormed = srcOffset + nalLength > size; + isMalFormed = !isInRange(0u, size, srcOffset, nalLength); } if (isMalFormed) { diff --git a/media/libstagefright/tests/Utils_test.cpp b/media/libstagefright/tests/Utils_test.cpp new file mode 100644 index 0000000..22c4a73 --- /dev/null +++ b/media/libstagefright/tests/Utils_test.cpp @@ -0,0 +1,118 @@ +/* + * Copyright 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#define LOG_TAG "Utils_test" + +#include <gtest/gtest.h> +#include <utils/String8.h> +#include <utils/Errors.h> +#include <fcntl.h> +#include <unistd.h> + +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AUtils.h> +#include <media/stagefright/Utils.h> + +namespace android { + +class UtilsTest : public ::testing::Test { +}; + +TEST_F(UtilsTest, TestMathTemplates) { + ASSERT_FALSE(isInRange(-43, 86u, -44)); + ASSERT_TRUE(isInRange(-43, 87u, -43)); + ASSERT_TRUE(isInRange(-43, 88u, -1)); + ASSERT_TRUE(isInRange(-43, 89u, 0)); + ASSERT_TRUE(isInRange(-43, 90u, 46)); + ASSERT_FALSE(isInRange(-43, 91u, 48)); + ASSERT_FALSE(isInRange(-43, 92u, 50)); + + ASSERT_FALSE(isInRange(43, 86u, 42)); + ASSERT_TRUE(isInRange(43, 87u, 43)); + ASSERT_TRUE(isInRange(43, 88u, 44)); + ASSERT_TRUE(isInRange(43, 89u, 131)); + ASSERT_FALSE(isInRange(43, 90u, 133)); + ASSERT_FALSE(isInRange(43, 91u, 135)); + + ASSERT_FALSE(isInRange(43u, 86u, 42u)); + ASSERT_TRUE(isInRange(43u, 85u, 43u)); + ASSERT_TRUE(isInRange(43u, 84u, 44u)); + ASSERT_TRUE(isInRange(43u, 83u, 125u)); + ASSERT_FALSE(isInRange(43u, 82u, 125u)); + ASSERT_FALSE(isInRange(43u, 81u, 125u)); + + ASSERT_FALSE(isInRange(-43, ~0u, 43)); + ASSERT_FALSE(isInRange(-43, ~0u, 44)); + ASSERT_FALSE(isInRange(-43, ~0u, ~0)); + ASSERT_FALSE(isInRange(-43, ~0u, 41)); + ASSERT_FALSE(isInRange(-43, ~0u, 40)); + + ASSERT_FALSE(isInRange(43u, ~0u, 43u)); + ASSERT_FALSE(isInRange(43u, ~0u, 41u)); + ASSERT_FALSE(isInRange(43u, ~0u, 40u)); + ASSERT_FALSE(isInRange(43u, ~0u, ~0u)); + + ASSERT_FALSE(isInRange(-43, 86u, -44, 0u)); + ASSERT_FALSE(isInRange(-43, 86u, -44, 1u)); + ASSERT_FALSE(isInRange(-43, 86u, -44, 2u)); + ASSERT_FALSE(isInRange(-43, 86u, -44, ~0u)); + ASSERT_TRUE(isInRange(-43, 87u, -43, 0u)); + ASSERT_TRUE(isInRange(-43, 87u, -43, 1u)); + ASSERT_TRUE(isInRange(-43, 87u, -43, 86u)); + ASSERT_TRUE(isInRange(-43, 87u, -43, 87u)); + ASSERT_FALSE(isInRange(-43, 87u, -43, 88u)); + ASSERT_FALSE(isInRange(-43, 87u, -43, ~0u)); + ASSERT_TRUE(isInRange(-43, 88u, -1, 0u)); + ASSERT_TRUE(isInRange(-43, 88u, -1, 45u)); + ASSERT_TRUE(isInRange(-43, 88u, -1, 46u)); + ASSERT_FALSE(isInRange(-43, 88u, -1, 47u)); + ASSERT_FALSE(isInRange(-43, 88u, -1, ~3u)); + ASSERT_TRUE(isInRange(-43, 90u, 46, 0u)); + ASSERT_TRUE(isInRange(-43, 90u, 46, 1u)); + ASSERT_FALSE(isInRange(-43, 90u, 46, 2u)); + ASSERT_FALSE(isInRange(-43, 91u, 48, 0u)); + ASSERT_FALSE(isInRange(-43, 91u, 48, 2u)); + ASSERT_FALSE(isInRange(-43, 91u, 48, ~6u)); + ASSERT_FALSE(isInRange(-43, 92u, 50, 0u)); + ASSERT_FALSE(isInRange(-43, 92u, 50, 1u)); + + ASSERT_FALSE(isInRange(43u, 86u, 42u, 0u)); + ASSERT_FALSE(isInRange(43u, 86u, 42u, 1u)); + ASSERT_FALSE(isInRange(43u, 86u, 42u, 2u)); + ASSERT_FALSE(isInRange(43u, 86u, 42u, ~0u)); + ASSERT_TRUE(isInRange(43u, 87u, 43u, 0u)); + ASSERT_TRUE(isInRange(43u, 87u, 43u, 1u)); + ASSERT_TRUE(isInRange(43u, 87u, 43u, 86u)); + ASSERT_TRUE(isInRange(43u, 87u, 43u, 87u)); + ASSERT_FALSE(isInRange(43u, 87u, 43u, 88u)); + ASSERT_FALSE(isInRange(43u, 87u, 43u, ~0u)); + ASSERT_TRUE(isInRange(43u, 88u, 60u, 0u)); + ASSERT_TRUE(isInRange(43u, 88u, 60u, 70u)); + ASSERT_TRUE(isInRange(43u, 88u, 60u, 71u)); + ASSERT_FALSE(isInRange(43u, 88u, 60u, 72u)); + ASSERT_FALSE(isInRange(43u, 88u, 60u, ~3u)); + ASSERT_TRUE(isInRange(43u, 90u, 132u, 0u)); + ASSERT_TRUE(isInRange(43u, 90u, 132u, 1u)); + ASSERT_FALSE(isInRange(43u, 90u, 132u, 2u)); + ASSERT_FALSE(isInRange(43u, 91u, 134u, 0u)); + ASSERT_FALSE(isInRange(43u, 91u, 134u, 2u)); + ASSERT_FALSE(isInRange(43u, 91u, 134u, ~6u)); + ASSERT_FALSE(isInRange(43u, 92u, 136u, 0u)); + ASSERT_FALSE(isInRange(43u, 92u, 136u, 1u)); +} + +} // namespace android |