Merge "Fix a couple of OOB read bugs found by the fuzzer." into tm-qpr-dev
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 4b4f65f..4df79ef 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -340,6 +340,14 @@
     return mCropBottom - mCropTop + 1;
 }
 
+bool ColorConverter::BitmapParams::isValid() const {
+    if (!((mStride & 1) == 0  // stride must be even
+        && mStride >= mBpp * cropWidth())) {
+            return false;
+    }
+    return true;
+}
+
 status_t ColorConverter::convert(
         const void *srcBits,
         size_t srcWidth, size_t srcHeight, size_t srcStride,
@@ -359,9 +367,11 @@
             dstWidth, dstHeight, dstStride,
             dstCropLeft, dstCropTop, dstCropRight, dstCropBottom, mDstFormat);
 
-    if (!((src.mCropLeft & 1) == 0
-        && src.cropWidth() == dst.cropWidth()
-        && src.cropHeight() == dst.cropHeight())) {
+    if (!(src.isValid()
+            && dst.isValid()
+            && (src.mCropLeft & 1) == 0
+            && src.cropWidth() == dst.cropWidth()
+            && src.cropHeight() == dst.cropHeight())) {
         return ERROR_UNSUPPORTED;
     }
 
@@ -463,6 +473,7 @@
     }
 }
 
+// Interleaved YUV 422 CbYCrY to RGB565
 status_t ColorConverter::convertCbYCrY(
         const BitmapParams &src, const BitmapParams &dst) {
     // XXX Untested
@@ -485,10 +496,10 @@
         + dst.mCropTop * dst.mWidth + dst.mCropLeft;
 
     const uint8_t *src_ptr = (const uint8_t *)src.mBits
-        + (src.mCropTop * dst.mWidth + src.mCropLeft) * 2;
+        + (src.mCropTop * src.mWidth + src.mCropLeft) * 2;
 
     for (size_t y = 0; y < src.cropHeight(); ++y) {
-        for (size_t x = 0; x < src.cropWidth(); x += 2) {
+        for (size_t x = 0; x < src.cropWidth() - 1; x += 2) {
             signed y1 = (signed)src_ptr[2 * x + 1] - _c16;
             signed y2 = (signed)src_ptr[2 * x + 3] - _c16;
             signed u = (signed)src_ptr[2 * x] - 128;
@@ -658,13 +669,15 @@
             *u = ((uint8_t*)src_u)[x / 2] - 128;
             *v = ((uint8_t*)src_v)[x / 2] - 128;
         };
+    // this format stores 10 bits content with 16 bits
+    // converting it to 8 bits src
     case OMX_COLOR_FormatYUV420Planar16:
         return [](void *src_y, void *src_u, void *src_v, size_t x,
                 signed *y1, signed *y2, signed *u, signed *v) {
-            *y1 = (signed)(((uint16_t*)src_y)[x] >> 2);
-            *y2 = (signed)(((uint16_t*)src_y)[x + 1] >> 2);
-            *u = (signed)(((uint16_t*)src_u)[x / 2] >> 2) - 128;
-            *v = (signed)(((uint16_t*)src_v)[x / 2] >> 2) - 128;
+            *y1 = (uint8_t)(((uint16_t*)src_y)[x] >> 2);
+            *y2 = (uint8_t)(((uint16_t*)src_y)[x + 1] >> 2);
+            *u = (uint8_t)(((uint16_t*)src_u)[x / 2] >> 2) - 128;
+            *v = (uint8_t)(((uint16_t*)src_v)[x / 2] >> 2) - 128;
         };
     default:
         TRESPASS();
@@ -1122,46 +1135,25 @@
 
 status_t ColorConverter::convertQCOMYUV420SemiPlanar(
         const BitmapParams &src, const BitmapParams &dst) {
-    const uint8_t *src_y =
-        (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
-
-    const uint8_t *src_u =
-        (const uint8_t *)src_y + src.mWidth * src.mHeight
-        + src.mCropTop * src.mWidth + src.mCropLeft;
-
     /* QCOMYUV420SemiPlanar is NV21, while MediaCodec uses NV12 */
     return convertYUV420SemiPlanarBase(
-            src, dst, src_y, src_u, src.mWidth /* row_inc */, true /* isNV21 */);
+            src, dst, src.mWidth /* row_inc */, true /* isNV21 */);
 }
 
 status_t ColorConverter::convertTIYUV420PackedSemiPlanar(
         const BitmapParams &src, const BitmapParams &dst) {
-    const uint8_t *src_y =
-        (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
-
-    const uint8_t *src_u =
-        (const uint8_t *)src_y + src.mWidth * (src.mHeight - src.mCropTop / 2);
-
     return convertYUV420SemiPlanarBase(
-            src, dst, src_y, src_u, src.mWidth /* row_inc */);
+            src, dst, src.mWidth /* row_inc */);
 }
 
 status_t ColorConverter::convertYUV420SemiPlanar(
         const BitmapParams &src, const BitmapParams &dst) {
-    const uint8_t *src_y =
-        (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft;
-
-    const uint8_t *src_u =
-        (const uint8_t *)src.mBits + src.mHeight * src.mStride +
-        (src.mCropTop / 2) * src.mStride + src.mCropLeft;
-
     return convertYUV420SemiPlanarBase(
-            src, dst, src_y, src_u, src.mStride /* row_inc */);
+            src, dst, src.mStride /* row_inc */);
 }
 
-status_t ColorConverter::convertYUV420SemiPlanarBase(
-        const BitmapParams &src, const BitmapParams &dst,
-        const uint8_t *src_y, const uint8_t *src_u, size_t row_inc, bool isNV21) {
+status_t ColorConverter::convertYUV420SemiPlanarBase(const BitmapParams &src,
+        const BitmapParams &dst, size_t row_inc, bool isNV21) {
     const struct Coeffs *matrix = getMatrix();
     if (!matrix) {
         return ERROR_UNSUPPORTED;
@@ -1179,6 +1171,12 @@
     uint16_t *dst_ptr = (uint16_t *)((uint8_t *)
             dst.mBits + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp);
 
+    const uint8_t *src_y =
+        (const uint8_t *)src.mBits + src.mCropTop * row_inc + src.mCropLeft;
+
+    const uint8_t *src_u = (const uint8_t *)src.mBits + src.mHeight * row_inc +
+        (src.mCropTop / 2) * row_inc + src.mCropLeft;
+
     for (size_t y = 0; y < src.cropHeight(); ++y) {
         for (size_t x = 0; x < src.cropWidth(); x += 2) {
             signed y1 = (signed)src_y[x] - _c16;
diff --git a/media/libstagefright/include/media/stagefright/ColorConverter.h b/media/libstagefright/include/media/stagefright/ColorConverter.h
index 7a05f00..da3267e 100644
--- a/media/libstagefright/include/media/stagefright/ColorConverter.h
+++ b/media/libstagefright/include/media/stagefright/ColorConverter.h
@@ -74,6 +74,8 @@
         size_t cropWidth() const;
         size_t cropHeight() const;
 
+        bool isValid() const;
+
         void *mBits;
         OMX_COLOR_FORMATTYPE mColorFormat;
         size_t mWidth, mHeight;
@@ -121,7 +123,7 @@
 
     status_t convertYUV420SemiPlanarBase(
             const BitmapParams &src, const BitmapParams &dst,
-            const uint8_t *src_y, const uint8_t *src_u, size_t row_inc, bool isNV21 = false);
+            size_t row_inc, bool isNV21 = false);
 
     status_t convertTIYUV420PackedSemiPlanar(
             const BitmapParams &src, const BitmapParams &dst);