diff options
| -rw-r--r-- | libs/androidfw/Android.bp | 18 | ||||
| -rw-r--r-- | libs/androidfw/CursorWindow.cpp | 21 | ||||
| -rw-r--r-- | libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp | 31 | ||||
| -rw-r--r-- | libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.bin | bin | 0 -> 292 bytes | |||
| -rw-r--r-- | libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp | 78 | ||||
| -rw-r--r-- | libs/androidfw/include/androidfw/CursorWindow.h | 3 | 
6 files changed, 141 insertions, 10 deletions
| diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index 45ad94fdb75a..903ca2aa0783 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -193,3 +193,21 @@ cc_benchmark {      shared_libs: common_test_libs,      data: ["tests/data/**/*.apk"],  } + +cc_library { +    name: "libandroidfw_fuzzer_lib", +    defaults: ["libandroidfw_defaults"], +    host_supported: true, +    srcs: [ +        "CursorWindow.cpp", +    ], +    export_include_dirs: ["include"], +    target: { +        android: { +            shared_libs: common_test_libs + ["libbinder", "liblog"], +        }, +        host: { +            static_libs: common_test_libs + ["libbinder", "liblog"], +        }, +    }, +} diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp index 1e6de67a40ba..915c0d75a280 100644 --- a/libs/androidfw/CursorWindow.cpp +++ b/libs/androidfw/CursorWindow.cpp @@ -251,7 +251,8 @@ status_t CursorWindow::clear() {  }  void CursorWindow::updateSlotsData() { -    mSlotsData = static_cast<uint8_t*>(mData) + mSize - kSlotSizeBytes; +    mSlotsStart = static_cast<uint8_t*>(mData) + mSize - kSlotSizeBytes; +    mSlotsEnd = static_cast<uint8_t*>(mData) + mSlotsOffset;  }  void* CursorWindow::offsetToPtr(uint32_t offset, uint32_t bufferSize = 0) { @@ -300,6 +301,7 @@ status_t CursorWindow::allocRow() {      }      memset(offsetToPtr(newOffset), 0, size);      mSlotsOffset = newOffset; +    updateSlotsData();      mNumRows++;      return OK;  } @@ -314,6 +316,7 @@ status_t CursorWindow::freeLastRow() {          return NO_MEMORY;      }      mSlotsOffset = newOffset; +    updateSlotsData();      mNumRows--;      return OK;  } @@ -337,18 +340,18 @@ status_t CursorWindow::alloc(size_t size, uint32_t* outOffset) {  }  CursorWindow::FieldSlot* CursorWindow::getFieldSlot(uint32_t row, uint32_t column) { -    if (row >= mNumRows || column >= mNumColumns) { -        LOG(ERROR) << "Failed to read row " << row << ", column " << column -                << " from a window with " << mNumRows << " rows, " << mNumColumns << " columns"; -        return nullptr; -    } -      // This is carefully tuned to use as few cycles as      // possible, since this is an extremely hot code path;      // see CursorWindow_bench.cpp for more details -    void *result = static_cast<uint8_t*>(mSlotsData) +    void *result = static_cast<uint8_t*>(mSlotsStart)              - (((row * mNumColumns) + column) << kSlotShift); -    return static_cast<FieldSlot*>(result); +    if (result < mSlotsEnd || column >= mNumColumns) { +        LOG(ERROR) << "Failed to read row " << row << ", column " << column +                << " from a window with " << mNumRows << " rows, " << mNumColumns << " columns"; +        return nullptr; +    } else { +        return static_cast<FieldSlot*>(result); +    }  }  status_t CursorWindow::putBlob(uint32_t row, uint32_t column, const void* value, size_t size) { diff --git a/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp b/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp new file mode 100644 index 000000000000..2dac47b0dac6 --- /dev/null +++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp @@ -0,0 +1,31 @@ +cc_fuzz { +    name: "cursorwindow_fuzzer", +    srcs: [ +        "cursorwindow_fuzzer.cpp", +    ], +    host_supported: true, +    corpus: ["corpus/*"], +    static_libs: ["libgmock"], +    target: { +        android: { +            shared_libs: [ +                "libandroidfw_fuzzer_lib", +                "libbase", +                "libbinder", +                "libcutils", +                "liblog", +                "libutils", +            ], +        }, +        host: { +            static_libs: [ +                "libandroidfw_fuzzer_lib", +                "libbase", +                "libbinder", +                "libcutils", +                "liblog", +                "libutils", +            ], +        }, +    }, +} diff --git a/libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.bin b/libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.binBinary files differ new file mode 100644 index 000000000000..c7e22dd26ea7 --- /dev/null +++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.bin diff --git a/libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp b/libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp new file mode 100644 index 000000000000..8dce21220199 --- /dev/null +++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2020 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. + */ + +#include <stddef.h> +#include <stdint.h> +#include <string.h> +#include <string> +#include <memory> + +#include "android-base/logging.h" +#include "androidfw/CursorWindow.h" +#include "binder/Parcel.h" + +#include <fuzzer/FuzzedDataProvider.h> + +using android::CursorWindow; +using android::Parcel; + +extern "C" int LLVMFuzzerInitialize(int *, char ***) { +    setenv("ANDROID_LOG_TAGS", "*:s", 1); +    android::base::InitLogging(nullptr, &android::base::StderrLogger); +    return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { +    Parcel p; +    p.setData(data, size); + +    CursorWindow* w = nullptr; +    if (!CursorWindow::createFromParcel(&p, &w)) { +        LOG(WARNING) << "Valid cursor with " << w->getNumRows() << " rows, " +                << w->getNumColumns() << " cols"; + +        // Try obtaining heap allocations for most items; we trim the +        // search space to speed things up +        auto rows = std::min(w->getNumRows(), static_cast<uint32_t>(128)); +        auto cols = std::min(w->getNumColumns(), static_cast<uint32_t>(128)); +        for (auto row = 0; row < rows; row++) { +            for (auto col = 0; col < cols; col++) { +                auto field = w->getFieldSlot(row, col); +                if (!field) continue; +                switch (w->getFieldSlotType(field)) { +                case CursorWindow::FIELD_TYPE_STRING: { +                    size_t size; +                    w->getFieldSlotValueString(field, &size); +                    break; +                } +                case CursorWindow::FIELD_TYPE_BLOB: { +                    size_t size; +                    w->getFieldSlotValueBlob(field, &size); +                    break; +                } +                } +            } +        } + +        // Finally, try obtaining the furthest valid field +        if (rows > 0 && cols > 0) { +            w->getFieldSlot(w->getNumRows() - 1, w->getNumColumns() - 1); +        } +    } +    delete w; + +    return 0; +} diff --git a/libs/androidfw/include/androidfw/CursorWindow.h b/libs/androidfw/include/androidfw/CursorWindow.h index 4c4f7335008d..6e55a9a0eb8b 100644 --- a/libs/androidfw/include/androidfw/CursorWindow.h +++ b/libs/androidfw/include/androidfw/CursorWindow.h @@ -150,7 +150,8 @@ private:       * Pointer to the first FieldSlot, used to optimize the extremely       * hot code path of getFieldSlot().       */ -    void* mSlotsData = nullptr; +    void* mSlotsStart = nullptr; +    void* mSlotsEnd = nullptr;      uint32_t mSize = 0;      /**       * When a window starts as lightweight inline allocation, this value |