Merge "libbinder: support server-specific session"
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 83e6787..3722383 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -38,11 +38,6 @@
 #include "DumpPool.h"
 #include "TaskQueue.h"
 
-// Workaround for const char *args[MAX_ARGS_ARRAY_SIZE] variables until they're converted to
-// std::vector<std::string>
-// TODO: remove once not used
-#define MAX_ARGS_ARRAY_SIZE 1000
-
 // TODO: move everything under this namespace
 // TODO: and then remove explicitly android::os::dumpstate:: prefixes
 namespace android {
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/ProcessState.cpp b/libs/binder/ProcessState.cpp
index e2ab515..4f21cda 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -93,9 +93,7 @@
 [[clang::no_destroy]] static std::mutex gProcessMutex;
 
 static void verifyNotForked(bool forked) {
-    if (forked) {
-        ALOGE("libbinder does not support being forked");
-    }
+    LOG_ALWAYS_FATAL_IF(forked, "libbinder ProcessState can not be used after fork");
 }
 
 sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault)
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/ndk/include_cpp/android/binder_parcel_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
index 4a7b664..2b18a0a 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -550,8 +550,8 @@
                                                                 const void* vectorData,
                                                                 size_t index) {
     const std::optional<std::vector<P>>* vector =
-            static_cast<const std::optional<std::vector<P>*>>(vectorData);
-    return AParcel_writeNullableParcelable(parcel, vector->at(index));
+            static_cast<const std::optional<std::vector<P>>*>(vectorData);
+    return AParcel_writeNullableParcelable(parcel, (*vector)->at(index));
 }
 
 /**
@@ -561,7 +561,7 @@
 binder_status_t AParcel_readNullableStdVectorParcelableElement(const AParcel* parcel,
                                                                void* vectorData, size_t index) {
     std::optional<std::vector<P>>* vector = static_cast<std::optional<std::vector<P>>*>(vectorData);
-    return AParcel_readNullableParcelable(parcel, &vector->at(index));
+    return AParcel_readNullableParcelable(parcel, &(*vector)->at(index));
 }
 
 /**
@@ -573,11 +573,7 @@
         AParcel* parcel, const void* vectorData, size_t index) {
     const std::vector<ScopedFileDescriptor>* vector =
             static_cast<const std::vector<ScopedFileDescriptor>*>(vectorData);
-    int writeFd = vector->at(index).get();
-    if (writeFd < 0) {
-        return STATUS_UNEXPECTED_NULL;
-    }
-    return AParcel_writeParcelFileDescriptor(parcel, writeFd);
+    return AParcel_writeRequiredParcelFileDescriptor(parcel, vector->at(index));
 }
 
 /**
@@ -589,15 +585,31 @@
         const AParcel* parcel, void* vectorData, size_t index) {
     std::vector<ScopedFileDescriptor>* vector =
             static_cast<std::vector<ScopedFileDescriptor>*>(vectorData);
-    int readFd;
-    binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
-    if (status == STATUS_OK) {
-        if (readFd < 0) {
-            return STATUS_UNEXPECTED_NULL;
-        }
-        vector->at(index).set(readFd);
-    }
-    return status;
+    return AParcel_readRequiredParcelFileDescriptor(parcel, &vector->at(index));
+}
+
+/**
+ * Writes a ScopedFileDescriptor object inside a std::optional<std::vector<ScopedFileDescriptor>> at
+ * index 'index' to 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_writeNullableStdVectorParcelableElement<ScopedFileDescriptor>(
+        AParcel* parcel, const void* vectorData, size_t index) {
+    const std::optional<std::vector<ScopedFileDescriptor>>* vector =
+            static_cast<const std::optional<std::vector<ScopedFileDescriptor>>*>(vectorData);
+    return AParcel_writeNullableParcelFileDescriptor(parcel, (*vector)->at(index));
+}
+
+/**
+ * Reads a ScopedFileDescriptor object inside a std::optional<std::vector<ScopedFileDescriptor>> at
+ * index 'index' from 'parcel'.
+ */
+template <>
+inline binder_status_t AParcel_readNullableStdVectorParcelableElement<ScopedFileDescriptor>(
+        const AParcel* parcel, void* vectorData, size_t index) {
+    std::optional<std::vector<ScopedFileDescriptor>>* vector =
+            static_cast<std::optional<std::vector<ScopedFileDescriptor>>*>(vectorData);
+    return AParcel_readNullableParcelFileDescriptor(parcel, &(*vector)->at(index));
 }
 
 /**
diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs
index f71a686..8bcc5d0 100644
--- a/libs/binder/rust/src/parcel/file_descriptor.rs
+++ b/libs/binder/rust/src/parcel/file_descriptor.rs
@@ -94,8 +94,6 @@
     }
 }
 
-impl SerializeArray for Option<ParcelFileDescriptor> {}
-
 impl DeserializeOption for ParcelFileDescriptor {
     fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
         let mut fd = -1i32;
@@ -126,8 +124,6 @@
     }
 }
 
-impl DeserializeArray for Option<ParcelFileDescriptor> {}
-
 impl Deserialize for ParcelFileDescriptor {
     fn deserialize(parcel: &Parcel) -> Result<Self> {
         Deserialize::deserialize(parcel)
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 499ef09..ec00e1d 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -383,6 +383,9 @@
     };
 }
 
+impl<T: DeserializeOption> DeserializeArray for Option<T> {}
+impl<T: SerializeOption> SerializeArray for Option<T> {}
+
 parcelable_primitives! {
     impl Serialize for bool = sys::AParcel_writeBool;
     impl Deserialize for bool = sys::AParcel_readBool;
@@ -537,8 +540,6 @@
     }
 }
 
-impl SerializeArray for Option<&str> {}
-
 impl Serialize for str {
     fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
         Some(self).serialize(parcel)
@@ -561,8 +562,6 @@
     }
 }
 
-impl SerializeArray for Option<String> {}
-
 impl Deserialize for Option<String> {
     fn deserialize(parcel: &Parcel) -> Result<Self> {
         let mut vec: Option<Vec<u8>> = None;
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index 6a4af07..2c5b0a8 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -429,8 +429,6 @@
 }
 
 impl SerializeArray for SpIBinder {}
-impl SerializeArray for Option<&SpIBinder> {}
-impl SerializeArray for Option<SpIBinder> {}
 
 impl Deserialize for SpIBinder {
     fn deserialize(parcel: &Parcel) -> Result<SpIBinder> {
@@ -448,7 +446,6 @@
 }
 
 impl DeserializeArray for SpIBinder {}
-impl DeserializeArray for Option<SpIBinder> {}
 
 /// A weak reference to a Binder remote object.
 ///
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 639876f..7a2bd81 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -436,6 +436,11 @@
         };
 };
 
+TEST_F(BinderLibTest, CannotUseBinderAfterFork) {
+    // EXPECT_DEATH works by forking the process
+    EXPECT_DEATH({ ProcessState::self(); }, "libbinder ProcessState can not be used after fork");
+}
+
 TEST_F(BinderLibTest, WasParceled) {
     auto binder = sp<BBinder>::make();
     EXPECT_FALSE(binder->wasParceled());
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index bc23b15..62215bb 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1359,6 +1359,16 @@
     ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?");
 }
 
+TEST_P(BinderRpc, AidlDelegatorTest) {
+    auto proc = createRpcTestSocketServerProcess({});
+    auto myDelegator = sp<IBinderRpcTestDelegator>::make(proc.rootIface);
+    ASSERT_NE(nullptr, myDelegator);
+
+    std::string doubled;
+    EXPECT_OK(myDelegator->doubleString("cool ", &doubled));
+    EXPECT_EQ("cool cool ", doubled);
+}
+
 static bool testSupportVsockLoopback() {
     // We don't need to enable TLS to know if vsock is supported.
     unsigned int vsockPort = allocateVsockPort();
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;
     },
 };
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
index 6b783a4..c0a762d 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
@@ -95,6 +95,11 @@
         PARCEL_READ(std::vector<std::string>, ndk::AParcel_readVector),
         PARCEL_READ(std::optional<std::vector<std::optional<std::string>>>, ndk::AParcel_readVector),
         PARCEL_READ(std::vector<SomeParcelable>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<std::optional<SomeParcelable>>>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<ndk::SpAIBinder>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<ndk::SpAIBinder>>, ndk::AParcel_readVector),
+        PARCEL_READ(std::vector<ndk::ScopedFileDescriptor>, ndk::AParcel_readVector),
+        PARCEL_READ(std::optional<std::vector<ndk::ScopedFileDescriptor>>, ndk::AParcel_readVector),
         PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector),
         PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector),
         PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector),
diff --git a/libs/binder/tests/rpc_fuzzer/Android.bp b/libs/binder/tests/rpc_fuzzer/Android.bp
index c0f0a12..71e847f 100644
--- a/libs/binder/tests/rpc_fuzzer/Android.bp
+++ b/libs/binder/tests/rpc_fuzzer/Android.bp
@@ -14,6 +14,7 @@
     fuzz_config: {
         cc: ["smoreland@google.com"],
     },
+    corpus: ["corpus/*"],
     dictionary: "binder_rpc_fuzzer.dict",
 
     srcs: [
diff --git a/libs/binder/tests/rpc_fuzzer/corpus/special_transaction b/libs/binder/tests/rpc_fuzzer/corpus/special_transaction
new file mode 100644
index 0000000..37228ee
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/corpus/special_transaction
Binary files differ
diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp
index 518849a..83f2ebe 100644
--- a/libs/binder/tests/rpc_fuzzer/main.cpp
+++ b/libs/binder/tests/rpc_fuzzer/main.cpp
@@ -158,6 +158,8 @@
         }
     }
 
+    usleep(10000);
+
     if (hangupBeforeShutdown) {
         connections.clear();
         while (!server->listSessions().empty() || server->numUninitializedSessions()) {