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);
}
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)
#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)
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 ){
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;
}
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
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);
}
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);
}
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
){
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 ){
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);
S3JniDb ** ps){
int rc = 0;
jobject jDb = 0;
+
*jc = S3JniEnv_get();
if( !*jc ){
rc = SQLITE_NOMEM;
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,
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);
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
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)(
-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
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
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
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
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
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.
-2e968114fd0e60eebcc088dec02684e10b06ac1ec42d6bedb5287362f5cbf032
\ No newline at end of file
+8c25c4b18ad07861bf0e47f99f3db04b569b9b859ad0690602f748ddf3576939
\ No newline at end of file
** 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;
*/
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 };
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 ){
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 ){
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 ){
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;
){
int rc = SQLITE_OK;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
+#endif
sqlite3_mutex_enter(db->mutex);
enterMutex();
** 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 ){
** 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 */
** 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 */
** 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
** 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;