summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/androidfw/Android.bp18
-rw-r--r--libs/androidfw/CursorWindow.cpp21
-rw-r--r--libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp31
-rw-r--r--libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.binbin0 -> 292 bytes
-rw-r--r--libs/androidfw/fuzz/cursorwindow_fuzzer/cursorwindow_fuzzer.cpp78
-rw-r--r--libs/androidfw/include/androidfw/CursorWindow.h3
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.bin
new file mode 100644
index 000000000000..c7e22dd26ea7
--- /dev/null
+++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/corpus/typical.bin
Binary files differ
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