Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 206fab30 authored by Lee Shombert's avatar Lee Shombert Committed by Android (Google) Code Review
Browse files

Merge "Correct JNI exception handling" into main

parents 4c218880 d65cc9c6
Loading
Loading
Loading
Loading
+32 −11
Original line number Original line Diff line number Diff line
@@ -72,14 +72,17 @@ static void throwInvalidParameter(JNIEnv *env, jlong stmtPtr, jint index) {




// This throws a SQLiteBindOrColumnIndexOutOfRangeException if the column index is out
// This throws a SQLiteBindOrColumnIndexOutOfRangeException if the column index is out
// of bounds.
// of bounds.  It returns true if an exception was thrown.
static void throwIfInvalidColumn(JNIEnv *env, jlong stmtPtr, jint col) {
static bool throwIfInvalidColumn(JNIEnv *env, jlong stmtPtr, jint col) {
    if (col < 0 || col >= sqlite3_data_count(stmt(stmtPtr))) {
    if (col < 0 || col >= sqlite3_data_count(stmt(stmtPtr))) {
        int count = sqlite3_data_count(stmt(stmtPtr));
        int count = sqlite3_data_count(stmt(stmtPtr));
        std::string message = android::base::StringPrintf(
        std::string message = android::base::StringPrintf(
            "column index %d out of bounds [0,%d]", col, count - 1);
            "column index %d out of bounds [0,%d]", col, count - 1);
        char const * errmsg = sqlite3_errstr(SQLITE_RANGE);
        char const * errmsg = sqlite3_errstr(SQLITE_RANGE);
        throw_sqlite3_exception(env, SQLITE_RANGE, errmsg, message.c_str());
        throw_sqlite3_exception(env, SQLITE_RANGE, errmsg, message.c_str());
        return true;
    } else {
        return false;
    }
    }
}
}


@@ -216,12 +219,16 @@ static void bindText(JNIEnv* env, jclass, jlong stmtPtr, jint index, jstring val




static jint columnType(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
static jint columnType(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
    throwIfInvalidColumn(env, stmtPtr, col);
    if (throwIfInvalidColumn(env, stmtPtr, col)) {
        return 0;
    }
    return sqlite3_column_type(stmt(stmtPtr), col);
    return sqlite3_column_type(stmt(stmtPtr), col);
}
}


static jstring columnName(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
static jstring columnName(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
    throwIfInvalidColumn(env, stmtPtr, col);
    if (throwIfInvalidColumn(env, stmtPtr, col)) {
        return nullptr;
    }
    const jchar* name = static_cast<const jchar*>(sqlite3_column_name16(stmt(stmtPtr), col));
    const jchar* name = static_cast<const jchar*>(sqlite3_column_name16(stmt(stmtPtr), col));
    if (name == nullptr) {
    if (name == nullptr) {
        throw_sqlite3_exception(env, db(stmtPtr), "error fetching columnName()");
        throw_sqlite3_exception(env, db(stmtPtr), "error fetching columnName()");
@@ -232,14 +239,18 @@ static jstring columnName(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
}
}


static jint columnBytes(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
static jint columnBytes(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
    throwIfInvalidColumn(env, stmtPtr, col);
    if (throwIfInvalidColumn(env, stmtPtr, col)) {
        return 0;
    }
    int r = sqlite3_column_bytes16(stmt(stmtPtr), col);
    int r = sqlite3_column_bytes16(stmt(stmtPtr), col);
    throwIfError(env, stmtPtr);
    throwIfError(env, stmtPtr);
    return r;
    return r;
}
}


static jbyteArray columnBlob(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
static jbyteArray columnBlob(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
    throwIfInvalidColumn(env, stmtPtr, col);
    if (throwIfInvalidColumn(env, stmtPtr, col)) {
        return nullptr;
    }
    const void* blob = sqlite3_column_blob(stmt(stmtPtr), col);
    const void* blob = sqlite3_column_blob(stmt(stmtPtr), col);
    if (blob == nullptr) {
    if (blob == nullptr) {
        if (throwIfError(env, stmtPtr)) {
        if (throwIfError(env, stmtPtr)) {
@@ -262,7 +273,9 @@ static jbyteArray columnBlob(JNIEnv* env, jclass, jlong stmtPtr, jint col) {


static int columnBuffer(JNIEnv* env, jclass, jlong stmtPtr, jint col,
static int columnBuffer(JNIEnv* env, jclass, jlong stmtPtr, jint col,
        jbyteArray buffer, jint offset, jint length, jint srcOffset) {
        jbyteArray buffer, jint offset, jint length, jint srcOffset) {
    throwIfInvalidColumn(env, stmtPtr, col);
    if (throwIfInvalidColumn(env, stmtPtr, col)) {
        return 0;
    }
    const void* blob = sqlite3_column_blob(stmt(stmtPtr), col);
    const void* blob = sqlite3_column_blob(stmt(stmtPtr), col);
    if (blob == nullptr) {
    if (blob == nullptr) {
        throwIfError(env, stmtPtr);
        throwIfError(env, stmtPtr);
@@ -281,22 +294,30 @@ static int columnBuffer(JNIEnv* env, jclass, jlong stmtPtr, jint col,
}
}


static jdouble columnDouble(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
static jdouble columnDouble(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
    throwIfInvalidColumn(env, stmtPtr, col);
    if (throwIfInvalidColumn(env, stmtPtr, col)) {
        return 0;
    }
    return sqlite3_column_double(stmt(stmtPtr), col);
    return sqlite3_column_double(stmt(stmtPtr), col);
}
}


static jint columnInt(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
static jint columnInt(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
    throwIfInvalidColumn(env, stmtPtr, col);
    if (throwIfInvalidColumn(env, stmtPtr, col)) {
        return 0;
    }
    return sqlite3_column_int(stmt(stmtPtr), col);
    return sqlite3_column_int(stmt(stmtPtr), col);
}
}


static jlong columnLong(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
static jlong columnLong(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
    throwIfInvalidColumn(env, stmtPtr, col);
    if (throwIfInvalidColumn(env, stmtPtr, col)) {
        return 0;
    }
    return sqlite3_column_int64(stmt(stmtPtr), col);
    return sqlite3_column_int64(stmt(stmtPtr), col);
}
}


static jstring columnText(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
static jstring columnText(JNIEnv* env, jclass, jlong stmtPtr, jint col) {
    throwIfInvalidColumn(env, stmtPtr, col);
    if (throwIfInvalidColumn(env, stmtPtr, col)) {
        return nullptr;
    }
    const jchar* text = static_cast<const jchar*>(sqlite3_column_text16(stmt(stmtPtr), col));
    const jchar* text = static_cast<const jchar*>(sqlite3_column_text16(stmt(stmtPtr), col));
    if (text == nullptr) {
    if (text == nullptr) {
        throwIfError(env, stmtPtr);
        throwIfError(env, stmtPtr);
+27 −0
Original line number Original line Diff line number Diff line
@@ -999,4 +999,31 @@ public class SQLiteRawStatementTest {
            mDatabase.endTransaction();
            mDatabase.endTransaction();
        }
        }
    }
    }

    /**
     * This test verifies that the JNI exception thrown because of a bad column is actually thrown
     * and does not crash the VM.
     */
    @Test
    public void testJniExceptions() {
        // Create the t1 table.
        mDatabase.beginTransaction();
        try {
            mDatabase.execSQL("CREATE TABLE t1 (i int, j int);");
            mDatabase.setTransactionSuccessful();
        } finally {
            mDatabase.endTransaction();
        }

        mDatabase.beginTransactionReadOnly();
        try (SQLiteRawStatement s = mDatabase.createRawStatement("SELECT * from t1")) {
            s.step();
            s.getColumnText(5); // out-of-range column
            fail("JNI exception not thrown");
        } catch (SQLiteBindOrColumnIndexOutOfRangeException e) {
            // Passing case.
        } finally {
            mDatabase.endTransaction();
        }
    }
}
}