diff options
-rw-r--r-- | libs/binder/Parcel.cpp | 11 | ||||
-rw-r--r-- | libs/binder/include/binder/Parcel.h | 7 | ||||
-rw-r--r-- | libs/binder/tests/binderParcelUnitTest.cpp | 17 | ||||
-rw-r--r-- | libs/binder/tests/parcel_fuzzer/binder.cpp | 2 |
4 files changed, 36 insertions, 1 deletions
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 7027a4b0a3..6fb189cd70 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -739,6 +739,17 @@ bool Parcel::enforceInterface(const char16_t* interface, } } +binder::Status Parcel::enforceNoDataAvail() const { + const auto n = dataAvail(); + if (n == 0) { + return binder::Status::ok(); + } + return binder::Status:: + fromExceptionCode(binder::Status::Exception::EX_BAD_PARCELABLE, + String8::format("Parcel data not fully consumed, unread size: %zu", + n)); +} + size_t Parcel::objectsCount() const { return mObjectsSize; diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index 8dbdc1d115..450e3888f1 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -54,6 +54,9 @@ class ProcessState; class RpcSession; class String8; class TextOutput; +namespace binder { +class Status; +} class Parcel { friend class IPCThreadState; @@ -131,6 +134,10 @@ public: IPCThreadState* threadState = nullptr) const; bool checkInterface(IBinder*) const; + // Verify there are no bytes left to be read on the Parcel. + // Returns Status(EX_BAD_PARCELABLE) when the Parcel is not consumed. + binder::Status enforceNoDataAvail() const; + void freeData(); size_t objectsCount() const; diff --git a/libs/binder/tests/binderParcelUnitTest.cpp b/libs/binder/tests/binderParcelUnitTest.cpp index 4950b23858..aee15d8bd9 100644 --- a/libs/binder/tests/binderParcelUnitTest.cpp +++ b/libs/binder/tests/binderParcelUnitTest.cpp @@ -16,15 +16,17 @@ #include <binder/IPCThreadState.h> #include <binder/Parcel.h> +#include <binder/Status.h> #include <cutils/ashmem.h> #include <gtest/gtest.h> using android::IPCThreadState; using android::OK; using android::Parcel; +using android::status_t; using android::String16; using android::String8; -using android::status_t; +using android::binder::Status; TEST(Parcel, NonNullTerminatedString8) { String8 kTestString = String8("test-is-good"); @@ -60,6 +62,19 @@ TEST(Parcel, NonNullTerminatedString16) { EXPECT_EQ(output.size(), 0); } +TEST(Parcel, EnforceNoDataAvail) { + const int32_t kTestInt = 42; + const String8 kTestString = String8("test-is-good"); + Parcel p; + p.writeInt32(kTestInt); + p.writeString8(kTestString); + p.setDataPosition(0); + EXPECT_EQ(kTestInt, p.readInt32()); + EXPECT_EQ(p.enforceNoDataAvail().exceptionCode(), Status::Exception::EX_BAD_PARCELABLE); + EXPECT_EQ(kTestString, p.readString8()); + EXPECT_EQ(p.enforceNoDataAvail().exceptionCode(), Status::Exception::EX_NONE); +} + // Tests a second operation results in a parcel at the same location as it // started. void parcelOpSameLength(const std::function<void(Parcel*)>& a, const std::function<void(Parcel*)>& b) { diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp index 077d915ca1..13f7195eb7 100644 --- a/libs/binder/tests/parcel_fuzzer/binder.cpp +++ b/libs/binder/tests/parcel_fuzzer/binder.cpp @@ -22,6 +22,7 @@ #include <android/os/IServiceManager.h> #include <binder/ParcelableHolder.h> #include <binder/PersistableBundle.h> +#include <binder/Status.h> using ::android::status_t; using ::android::base::HexString; @@ -100,6 +101,7 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_NO_STATUS(size_t, dataAvail), PARCEL_READ_NO_STATUS(size_t, dataPosition), PARCEL_READ_NO_STATUS(size_t, dataCapacity), + PARCEL_READ_NO_STATUS(::android::binder::Status, enforceNoDataAvail), [] (const ::android::Parcel& p, uint8_t pos) { FUZZ_LOG() << "about to setDataPosition: " << pos; p.setDataPosition(pos); |