Merge "Fix offset check in Parcel::hasFileDescriptorsInRange()" am: bc584178da am: 41952d83fd am: 055f45264b am: f809408176 am: 69e6689420

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1859393

Change-Id: Ia08d3ae421760c17ba1f39ce2ae43e3b22abf4c0
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 805e576..181f405 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -548,21 +548,17 @@
     return mHasFds;
 }
 
-status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool& result) const {
+status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool* result) const {
     if (len > INT32_MAX || offset > INT32_MAX) {
         // Don't accept size_t values which may have come from an inadvertent conversion from a
         // negative int.
         return BAD_VALUE;
     }
-    size_t limit = offset + len;
-    if (offset > mDataSize || len > mDataSize || limit > mDataSize || offset > limit) {
+    size_t limit;
+    if (__builtin_add_overflow(offset, len, &limit) || limit > mDataSize) {
         return BAD_VALUE;
     }
-    result = hasFileDescriptorsInRangeUnchecked(offset, len);
-    return NO_ERROR;
-}
-
-bool Parcel::hasFileDescriptorsInRangeUnchecked(size_t offset, size_t len) const {
+    *result = false;
     for (size_t i = 0; i < mObjectsSize; i++) {
         size_t pos = mObjects[i];
         if (pos < offset) continue;
@@ -572,10 +568,11 @@
         }
         const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + pos);
         if (flat->hdr.type == BINDER_TYPE_FD) {
-            return true;
+            *result = true;
+            break;
         }
     }
-    return false;
+    return NO_ERROR;
 }
 
 void Parcel::markSensitive() const
@@ -2568,9 +2565,9 @@
     }
 }
 
-void Parcel::scanForFds() const
-{
-    mHasFds = hasFileDescriptorsInRangeUnchecked(0, dataSize());
+void Parcel::scanForFds() const {
+    status_t status = hasFileDescriptorsInRange(0, dataSize(), &mHasFds);
+    ALOGE_IF(status != NO_ERROR, "Error %d calling hasFileDescriptorsInRange()", status);
     mFdsKnown = true;
 }
 
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 32056d9..d90e803 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -87,7 +87,7 @@
     void                restoreAllowFds(bool lastValue);
 
     bool                hasFileDescriptors() const;
-    status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool& result) const;
+    status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool* result) const;
 
     // Zeros data when reallocating. Other mitigations may be added
     // in the future.
@@ -576,7 +576,6 @@
 
     status_t            writeRawNullableParcelable(const Parcelable*
                                                    parcelable);
-    bool hasFileDescriptorsInRangeUnchecked(size_t offset, size_t length) const;
 
     //-----------------------------------------------------------------------------
     // Generic type read and write methods for Parcel:
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 8e8994b..e4f57b0 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -305,7 +305,7 @@
         size_t offset = p.readUint32();
         size_t length = p.readUint32();
         bool result;
-        status_t status = p.hasFileDescriptorsInRange(offset, length, result);
+        status_t status = p.hasFileDescriptorsInRange(offset, length, &result);
         FUZZ_LOG() << " status: " << status  << " result: " << result;
     },
 };