Round one of an audit for SQLITE_ENABLE_API_ARMOR for functions exposed by JNI and those functions missing armor, as [forum:5e3fc453a69b49ca|reported in several forum posts].

FossilOrigin-Name: 8c25c4b18ad07861bf0e47f99f3db04b569b9b859ad0690602f748ddf3576939
This commit is contained in:
stephan 2023-10-13 12:48:35 +00:00
parent 99d43979d3
commit 7dc0cc45f3
7 changed files with 114 additions and 50 deletions

View File

@ -972,6 +972,7 @@ static jstring s3jni__utf8_to_jstring(JNIEnv * const env,
hypothetically do this for any strings where n<4 and z is
NUL-terminated and none of z[0..3] are NUL bytes. */
rv = (*env)->NewStringUTF(env, "");
s3jni_oom_check( rv );
}else if( z ){
jbyteArray jba;
if( n<0 ) n = sqlite3Strlen30(z);
@ -985,8 +986,8 @@ static jstring s3jni__utf8_to_jstring(JNIEnv * const env,
}
S3JniUnrefLocal(jba);
}
s3jni_oom_check( rv );
}
s3jni_oom_check( rv );
return rv;
}
#define s3jni_utf8_to_jstring(CStr,n) s3jni__utf8_to_jstring(env, CStr, n)
@ -1468,12 +1469,14 @@ static void * NativePointerHolder__get(JNIEnv * env, jobject jNph,
#define PtrGet_sqlite3_stmt(OBJ) PtrGet_T(sqlite3_stmt, OBJ)
#define PtrGet_sqlite3_value(OBJ) PtrGet_T(sqlite3_value, OBJ)
/*
** S3JniLongPtr_T(X,Y) expects X to be an unqualified sqlite3
** struct type name and Y to be a native pointer to such an object in
** the form of a jlong value. The jlong is simply cast to (X*). This
** S3JniLongPtr_T(X,Y) expects X to be an unqualified sqlite3 struct
** type name and Y to be a native pointer to such an object in the
** form of a jlong value. The jlong is simply cast to (X*). This
** approach is, as of 2023-09-27, supplanting the former approach. We
** now do the native pointer extraction in the Java side, rather than
** the C side, because it's reportedly significantly faster.
** the C side, because it's reportedly significantly faster. The
** intptr_t part here is necessary for compatibility with (at least)
** ARM32.
*/
#define S3JniLongPtr_T(T,JLongAsPtr) (T*)((intptr_t)(JLongAsPtr))
#define S3JniLongPtr_sqlite3(JLongAsPtr) S3JniLongPtr_T(sqlite3,JLongAsPtr)
@ -2616,6 +2619,10 @@ S3JniApi(sqlite3_cancel_auto_extension(),jboolean,1cancel_1auto_1extension)(
S3JniAutoExtension * ax;
jboolean rc = JNI_FALSE;
int i;
if( !jAutoExt ){
return rc;
}
S3JniAutoExt_mutex_enter;
/* This algo corresponds to the one in the core. */
for( i = SJG.autoExt.nExt-1; i >= 0; --i ){
@ -2778,8 +2785,8 @@ S3JniApi(sqlite3_column_text(),jbyteArray,1column_1text)(
JniArgsEnvClass, jobject jpStmt, jint ndx
){
sqlite3_stmt * const stmt = PtrGet_sqlite3_stmt(jpStmt);
const unsigned char * const p = sqlite3_column_text(stmt, (int)ndx);
const int n = sqlite3_column_bytes(stmt, (int)ndx);
const unsigned char * const p = stmt ? sqlite3_column_text(stmt, (int)ndx) : 0;
const int n = p ? sqlite3_column_bytes(stmt, (int)ndx) : 0;
return p ? s3jni_new_jbyteArray(p, n) : NULL;
}
@ -2789,8 +2796,8 @@ S3JniApi(sqlite3_column_text(),jstring,1column_1text)(
JniArgsEnvClass, jobject jpStmt, jint ndx
){
sqlite3_stmt * const stmt = PtrGet_sqlite3_stmt(jpStmt);
const unsigned char * const p = sqlite3_column_text(stmt, (int)ndx);
const int n = sqlite3_column_bytes(stmt, (int)ndx);
const unsigned char * const p = stmt ? sqlite3_column_text(stmt, (int)ndx) : 0;
const int n = p ? sqlite3_column_bytes(stmt, (int)ndx) : 0;
return p ? s3jni_utf8_to_jstring( (const char *)p, n) : 0;
}
#endif
@ -2799,8 +2806,8 @@ S3JniApi(sqlite3_column_text16(),jstring,1column_1text16)(
JniArgsEnvClass, jobject jpStmt, jint ndx
){
sqlite3_stmt * const stmt = PtrGet_sqlite3_stmt(jpStmt);
const void * const p = sqlite3_column_text16(stmt, (int)ndx);
const int n = sqlite3_column_bytes16(stmt, (int)ndx);
const void * const p = stmt ? sqlite3_column_text16(stmt, (int)ndx) : 0;
const int n = p ? sqlite3_column_bytes16(stmt, (int)ndx) : 0;
return s3jni_text16_to_jstring(env, p, n);
}
@ -2808,7 +2815,8 @@ S3JniApi(sqlite3_column_value(),jobject,1column_1value)(
JniArgsEnvClass, jobject jpStmt, jint ndx
){
sqlite3_value * const sv =
sqlite3_column_value(PtrGet_sqlite3_stmt(jpStmt), (int)ndx);
sqlite3_column_value(PtrGet_sqlite3_stmt(jpStmt), (int)ndx)
/* reminder: returns an SQL NULL if jpStmt==NULL */;
return new_java_sqlite3_value(env, sv);
}
@ -2919,6 +2927,18 @@ S3JniApi(sqlite3_compileoption_get(),jstring,1compileoption_1get)(
return rv;
}
S3JniApi(sqlite3_compileoption_used(),jboolean,1compileoption_1used)(
JniArgsEnvClass, jstring name
){
const char *zUtf8 = s3jni_jstring_to_mutf8(name)
/* We know these to be ASCII, so MUTF-8 is fine (and
hypothetically faster to convert). */;
const jboolean rc =
0==sqlite3_compileoption_used(zUtf8) ? JNI_FALSE : JNI_TRUE;
s3jni_mutf8_release(name, zUtf8);
return rc;
}
S3JniApi(sqlite3_complete(),int,1complete)(
JniArgsEnvClass, jbyteArray jSql
){
@ -2935,18 +2955,6 @@ S3JniApi(sqlite3_complete(),int,1complete)(
return rc;
}
S3JniApi(sqlite3_compileoption_used(),jboolean,1compileoption_1used)(
JniArgsEnvClass, jstring name
){
const char *zUtf8 = s3jni_jstring_to_mutf8(name)
/* We know these to be ASCII, so MUTF-8 is fine (and
hypothetically faster to convert). */;
const jboolean rc =
0==sqlite3_compileoption_used(zUtf8) ? JNI_FALSE : JNI_TRUE;
s3jni_mutf8_release(name, zUtf8);
return rc;
}
S3JniApi(sqlite3_config() /*for a small subset of options.*/,
jint,1config__I)(JniArgsEnvClass, jint n){
switch( n ){
@ -3151,6 +3159,9 @@ S3JniApi(sqlite3_create_collation() sqlite3_create_collation_v2(),
int rc;
S3JniDb * ps;
if( !jDb || !name || !encodingTypeIsValid(eTextRep) ){
return (jint)SQLITE_MISUSE;
}
S3JniDb_mutex_enter;
ps = S3JniDb_from_java(jDb);
jclass const klazz = (*env)->GetObjectClass(env, oCollation);
@ -3574,6 +3585,7 @@ static int s3jni_open_pre(JNIEnv * const env, S3JniEnv **jc,
S3JniDb ** ps){
int rc = 0;
jobject jDb = 0;
*jc = S3JniEnv_get();
if( !*jc ){
rc = SQLITE_NOMEM;
@ -3650,6 +3662,8 @@ S3JniApi(sqlite3_open(),jint,1open)(
S3JniDb * ps = 0;
S3JniEnv * jc = 0;
int rc;
if( 0==jOut ) return SQLITE_MISUSE;
rc = s3jni_open_pre(env, &jc, strName, &zName, &ps);
if( 0==rc ){
rc = s3jni_open_post(env, jc, ps, &pOut, jOut,
@ -3662,14 +3676,17 @@ S3JniApi(sqlite3_open(),jint,1open)(
S3JniApi(sqlite3_open_v2(),jint,1open_1v2)(
JniArgsEnvClass, jstring strName,
jobject jOut, jint flags, jstring strVfs
jobject jOut, jint flags, jstring strVfs
){
sqlite3 * pOut = 0;
char *zName = 0;
S3JniDb * ps = 0;
S3JniEnv * jc = 0;
char *zVfs = 0;
int rc = s3jni_open_pre(env, &jc, strName, &zName, &ps);
int rc;
if( 0==jOut ) return SQLITE_MISUSE;
rc = s3jni_open_pre(env, &jc, strName, &zName, &ps);
if( 0==rc ){
if( strVfs ){
zVfs = s3jni_jstring_to_utf8( strVfs, 0);
@ -4469,7 +4486,6 @@ static int s3jni_strlike_glob(int isLike, JNIEnv *const env,
jbyte * const pG = s3jni_jbyteArray_bytes(baG);
jbyte * const pT = pG ? s3jni_jbyteArray_bytes(baT) : 0;
s3jni_oom_fatal(pT);
/* Note that we're relying on the byte arrays having been
NUL-terminated on the Java side. */
rc = isLike
@ -4509,12 +4525,8 @@ S3JniApi(sqlite3_sql(),jstring,1sql)(
S3JniApi(sqlite3_step(),jint,1step)(
JniArgsEnvClass,jobject jStmt
){
int rc = SQLITE_MISUSE;
sqlite3_stmt * const pStmt = PtrGet_sqlite3_stmt(jStmt);
if( pStmt ){
rc = sqlite3_step(pStmt);
}
return rc;
return pStmt ? (jint)sqlite3_step(pStmt) : (jint)SQLITE_MISUSE;
}
S3JniApi(sqlite3_table_column_metadata(),int,1table_1column_1metadata)(

View File

@ -1,5 +1,5 @@
C Avoid\spotential\soverflow\sin\shex().\s[forum:/forumpost/7ac0c9c5ea|See\sforum\spost\s7ac0c9c5ea.]
D 2023-10-13T01:39:47.068
C Round\sone\sof\san\saudit\sfor\sSQLITE_ENABLE_API_ARMOR\sfor\sfunctions\sexposed\sby\sJNI\sand\sthose\sfunctions\smissing\sarmor,\sas\s[forum:5e3fc453a69b49ca|reported\sin\sseveral\sforum\sposts].
D 2023-10-13T12:48:35.298
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -238,7 +238,7 @@ F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a3
F ext/jni/GNUmakefile 6da240c9a11701f3ed569384cd15ef611e8b3c5e3897d265923b14bf0e1eb272
F ext/jni/README.md ef9ac115e97704ea995d743b4a8334e23c659e5534c3b64065a5405256d5f2f4
F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa
F ext/jni/src/c/sqlite3-jni.c bf432771fbc84da2b5f4037e0bcf20757548aac2fa782b272c4894a9c279964a
F ext/jni/src/c/sqlite3-jni.c eabd48ced29954fb4f6173c4f350f7f1fce218ce19f48a75367cb560cf2da77e
F ext/jni/src/c/sqlite3-jni.h be1fdff7ab3a2bb357197271c8ac5d2bf6ff59380c106dde3a13be88724bad22
F ext/jni/src/org/sqlite/jni/AbstractCollationCallback.java 95e88ba04f4aac51ffec65693e878e234088b2f21b387f4e4285c8b72b33e436
F ext/jni/src/org/sqlite/jni/AggregateFunction.java 7312486bc65fecdb91753c0a4515799194e031f45edbe16a6373cea18f404dc4
@ -676,8 +676,8 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
F src/json.c 799430345d16fed21713416318e6ca616f1264224f708555f387bfa2ab2496c7
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 98cfba10989b3da6f1807ad42444017742db7f100a54f1032af7a8b1295912c0
F src/main.c 618aeb399e993cf561864f4b0cf6a331ee4f355cf663635f8d9da3193a46aa40
F src/loadext.c 7d56c6f28aaf9b42e2772289e0d0a12a77b57c2baed021dbfd1fcafec69c156a
F src/main.c 7a91b372dd1bada07c5b5e36082dc0d695161c3807efe2386f563a5b32446ae6
F src/malloc.c f016922435dc7d1f1f5083a03338a3e91f8c67ce2c5bdcfa4cdef62e612f5fcc
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@ -692,7 +692,7 @@ F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c bd52ec50e44a41fe1e3deb5a6e3fe98edb6f2059da3e46d196363d0fa3192cda
F src/mutex_w32.c 38b56d0bc8d54c17c20cbaaad3719b0c36b92fd07a7e34360d0c6a18d5589912
F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6
F src/notify.c 57c2d1a2805d6dee32acd5d250d928ab94e02d76369ae057dee7d445fd64e878
F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d
F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
@ -787,7 +787,7 @@ F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
F src/vdbe.c cd112eb00d20fc5cc44f631d0e713838602637328b0f127c2f3c2aa8cea3cc91
F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
F src/vdbeapi.c 4184402246172220418c0ef49ff4cf1a19ced9a4ac6c843c2f0773fb5c543f37
F src/vdbeapi.c be7d88a05df51cb3940304f74e4b0534817b51213b3406143a67eecd6f82fe21
F src/vdbeaux.c 5b415e09b5b9d5be6c0f4fcbf18ea9d7d16f6a29ced2f14a3b2041020f63e9c1
F src/vdbeblob.c 4cf5aa130e96e3b52ba3fb54b7f9606c942ab988dbb32cb19cff4db24e06aeec
F src/vdbemem.c 317b9f48708139db6239ade40c7980b4bc8233168383690d588dad6d8437f722
@ -2128,8 +2128,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 4a4eccb681741917c6771101d4e329f91eae9b035f4d345218e522bb55fff6da
R b8db52c4af481f11a25564ae1b4169f0
U larrybr
Z e40ad0deba084d2d357f307fa10fdd72
P 2e968114fd0e60eebcc088dec02684e10b06ac1ec42d6bedb5287362f5cbf032
R 64d7e862f198f312cf375ff0e1b4824a
T *branch * api-armor-audit
T *sym-api-armor-audit *
T -sym-trunk * Cancelled\sby\sbranch.
U stephan
Z fb0f8b82a9c86be7bcd5823447ca13df
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
2e968114fd0e60eebcc088dec02684e10b06ac1ec42d6bedb5287362f5cbf032
8c25c4b18ad07861bf0e47f99f3db04b569b9b859ad0690602f748ddf3576939

View File

@ -730,6 +730,9 @@ void sqlite3CloseExtensions(sqlite3 *db){
** default so as not to open security holes in older applications.
*/
int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
sqlite3_mutex_enter(db->mutex);
if( onoff ){
db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc;
@ -751,7 +754,7 @@ int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
*/
typedef struct sqlite3AutoExtList sqlite3AutoExtList;
static SQLITE_WSD struct sqlite3AutoExtList {
u32 nExt; /* Number of entries in aExt[] */
u32 nExt; /* Number of entries in aExt[] */
void (**aExt)(void); /* Pointers to the extension init functions */
} sqlite3Autoext = { 0, 0 };
@ -779,6 +782,9 @@ int sqlite3_auto_extension(
void (*xInit)(void)
){
int rc = SQLITE_OK;
#ifdef SQLITE_ENABLE_API_ARMOR
if( xInit==0 ) return SQLITE_MISUSE_BKPT;
#endif
#ifndef SQLITE_OMIT_AUTOINIT
rc = sqlite3_initialize();
if( rc ){
@ -831,6 +837,9 @@ int sqlite3_cancel_auto_extension(
int i;
int n = 0;
wsdAutoextInit;
#ifdef SQLITE_ENABLE_API_ARMOR
if( xInit==0 ) return 0;
#endif
sqlite3_mutex_enter(mutex);
for(i=(int)wsdAutoext.nExt-1; i>=0; i--){
if( wsdAutoext.aExt[i]==xInit ){

View File

@ -954,6 +954,10 @@ int sqlite3_db_cacheflush(sqlite3 *db){
int sqlite3_db_config(sqlite3 *db, int op, ...){
va_list ap;
int rc;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
sqlite3_mutex_enter(db->mutex);
va_start(ap, op);
switch( op ){
@ -2365,6 +2369,12 @@ void *sqlite3_preupdate_hook(
void *pArg /* First callback argument */
){
void *pRet;
#ifdef SQLITE_ENABLE_API_ARMOR
if( db==0 || xCallback==0 ){
return;
}
#endif
sqlite3_mutex_enter(db->mutex);
pRet = db->pPreUpdateArg;
db->xPreUpdateCallback = xCallback;

View File

@ -152,6 +152,9 @@ int sqlite3_unlock_notify(
){
int rc = SQLITE_OK;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
sqlite3_mutex_enter(db->mutex);
enterMutex();

View File

@ -2029,10 +2029,16 @@ static UnpackedRecord *vdbeUnpackRecord(
** a field of the row currently being updated or deleted.
*/
int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
PreUpdate *p = db->pPreUpdate;
PreUpdate *p;
Mem *pMem;
int rc = SQLITE_OK;
#ifdef SQLITE_ENABLE_API_ARMOR
if( db==0 || ppValue==0 ){
return SQLITE_MISUSE_BKPT;
}
#endif
p = db->pPreUpdate;
/* Test that this call is being made from within an SQLITE_DELETE or
** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */
if( !p || p->op==SQLITE_INSERT ){
@ -2093,7 +2099,12 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
** the number of columns in the row being updated, deleted or inserted.
*/
int sqlite3_preupdate_count(sqlite3 *db){
PreUpdate *p = db->pPreUpdate;
PreUpdate *p;
#ifdef SQLITE_ENABLE_API_ARMOR
p = db!=0 ? db->pPreUpdate : 0;
#else
p = db->pPreUpdate;
#endif
return (p ? p->keyinfo.nKeyField : 0);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@ -2111,7 +2122,12 @@ int sqlite3_preupdate_count(sqlite3 *db){
** or SET DEFAULT action is considered a trigger.
*/
int sqlite3_preupdate_depth(sqlite3 *db){
PreUpdate *p = db->pPreUpdate;
PreUpdate *p;
#ifdef SQLITE_ENABLE_API_ARMOR
p = db!=0 ? db->pPreUpdate : 0;
#else
p = db->pPreUpdate;
#endif
return (p ? p->v->nFrame : 0);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@ -2122,7 +2138,12 @@ int sqlite3_preupdate_depth(sqlite3 *db){
** only.
*/
int sqlite3_preupdate_blobwrite(sqlite3 *db){
PreUpdate *p = db->pPreUpdate;
PreUpdate *p;
#ifdef SQLITE_ENABLE_API_ARMOR
p = db!=0 ? db->pPreUpdate : 0;
#else
p = db->pPreUpdate;
#endif
return (p ? p->iBlobWrite : -1);
}
#endif
@ -2133,10 +2154,16 @@ int sqlite3_preupdate_blobwrite(sqlite3 *db){
** a field of the row currently being updated or inserted.
*/
int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
PreUpdate *p = db->pPreUpdate;
PreUpdate *p;
int rc = SQLITE_OK;
Mem *pMem;
#ifdef SQLITE_ENABLE_API_ARMOR
if( db==0 || ppValue==0 ){
return SQLITE_MISUSE_BKPT;
}
#endif
p = db->pPreUpdate;
if( !p || p->op==SQLITE_DELETE ){
rc = SQLITE_MISUSE_BKPT;
goto preupdate_new_out;