-C Patch\sto\sthe\spage\scache\sto\savoid\sharmless\spointer\sarithmetic\sthat\sdue\sto\sbugs\nin\sthe\sSTD-C\sspec\sis\stechnically\sUB.\s\sThis\sis\sto\sfix\sa\sharmless\sUBSAN\ncomplaint\sthat\sOSSFuzz\sis\shitting.
-D 2019-12-13T21:24:46.081
+C Initial\sexploration\sof\sblocky\sAPIs,\sstarting\swith\sa\svariant\sof\ssqlite3_exec.
+D 2019-12-13T22:59:38.851
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 5de3fd62bd1a692353c8f9c7bbde658f0b579f195620ca3cde1948a53015dddd
-F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
+F src/legacy.c 70ff0890930967fa02a792d3b2c48208eb6a1c4d9f55a465a664b2ddc8b044a4
F src/loadext.c d74f5e7bd51f3c9d283442473eb65aef359664efd6513591c03f01881c4ae2da
F src/main.c 868ae7db7a54fe859bf2ca8b7a4f24e9fa03a6134abfb7c9801d08411ef5dacb
F src/malloc.c 550021fcae36f0ffe9f8563d83e6385f9df307a854d55d7d0abb7241ee8dbcc6
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
F src/select.c 0fe10579de20eb8dc04ec9ed29659fa782bee2bcc85a35734637f3e2cabc2762
F src/shell.c.in 4a3a9e1c11847b1904f2b01d087af1c052f660902755abab457cab1756817ded
-F src/sqlite.h.in 2a23e8161775253d9cf383c2c6aa559005dc787d350dcb0be67a6c4cc3bd1d19
+F src/sqlite.h.in 44a53119d3fb6e2d855d8bfd4b94151338563a2fbe28638e3a24ee8d9e661ae1
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 72af51aa4e912e14cd495fb6e7fac65f0940db80ed950d90911aff292cc47ce2
-F src/sqliteInt.h 60d92fad64da7c3e77bbc35ee306340814cdaa5df32892b0ec58d306d99b5733
+F src/sqliteInt.h 6326f05f5924e779f5c3ba422f85adfdef38dbf1012be7d5e40a2d78d4d1a648
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P c1014e80b26131200a115beb86929a8f0ded2dd65b075e47373346c0f170576a
-R b59b4afd4c4fcaeb80758977b1b63c0a
-U drh
-Z 4fa57844859159ee82f87f0f14b6814f
+P c29fc21288e37f81a1617c5e2961c575d3bca6a1d1b013b2e0a99774afb1dcdb
+R e55adf2fcddc384393004665528a6995
+T *branch * blocky-exec
+T *sym-blocky-exec *
+T -sym-trunk *
+U numist
+Z 7fe9b43d252eee701000e10996724092
-c29fc21288e37f81a1617c5e2961c575d3bca6a1d1b013b2e0a99774afb1dcdb
\ No newline at end of file
+fd849d5b6a891c57facbfbba1de855b4349577dbc7afaa7f503e23bc4ca74e8f
\ No newline at end of file
sqlite3_mutex_leave(db->mutex);
return rc;
}
+
+#if SQLITE_HAS_BLOCKS
+int sqlite3_exec_b(
+ sqlite3 *db,
+ const char *zSql,
+ int (^xCallback)(sqlite3_stmt *)
+){
+ int rc = SQLITE_OK; /* Return code */
+ const char *zLeftover; /* Tail of unprocessed SQL */
+ sqlite3_stmt *pStmt = 0; /* The current SQL statement */
+ const char **azCols = 0; /* Names of result columns */
+
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
+ if( zSql==0 ) zSql = "";
+#ifdef SQLITE_ENABLE_SQLRR
+ SRRecExec(db, zSql);
+#endif
+ sqlite3_mutex_enter(db->mutex);
+ sqlite3Error(db, SQLITE_OK);
+ while( rc==SQLITE_OK && zSql[0] ){
+ int callbackIsInit = 0;
+
+ pStmt = 0;
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
+ assert( rc==SQLITE_OK || pStmt==0 );
+ if( rc!=SQLITE_OK ){
+ continue;
+ }
+ if( !pStmt ){
+ /* this happens for a comment or white-space */
+ zSql = zLeftover;
+ continue;
+ }
+
+ while( 1 ){
+ rc = sqlite3_step(pStmt);
+
+ /* Invoke the callback function if required */
+ if( xCallback && (SQLITE_ROW==rc ||
+ (SQLITE_DONE==rc && !callbackIsInit
+ && db->flags&SQLITE_NullCallback)) ){
+ if( xCallback(pStmt) ){
+ /* EVIDENCE-OF: R-38229-40159 If the callback function to
+ ** sqlite3_exec() returns non-zero, then sqlite3_exec() will
+ ** return SQLITE_ABORT. */
+ rc = SQLITE_ABORT;
+ (void)sqlite3VdbeFinalize((Vdbe *)pStmt);
+ pStmt = 0;
+ sqlite3Error(db, rc);
+ goto exec_out;
+ }
+ }
+
+ if( rc!=SQLITE_ROW ){
+ rc = sqlite3VdbeFinalize((Vdbe *)pStmt);
+ pStmt = 0;
+ zSql = zLeftover;
+ while( sqlite3Isspace(zSql[0]) ) zSql++;
+ break;
+ }
+ }
+ }
+
+exec_out:
+ if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt);
+ sqlite3DbFree(db, azCols);
+#ifdef SQLITE_ENABLE_SQLRR
+ SRRecExecEnd(db);
+#endif
+
+ rc = sqlite3ApiExit(db, rc);
+
+ assert( (rc&db->errMask)==rc );
+ sqlite3_mutex_leave(db->mutex);
+ return rc;
+
+}
+#endif
#define SQLITE3_H
#include <stdarg.h> /* Needed for the definition of va_list */
+/* Compatibility with non-clang compilers */
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+/* Compatibility with pre-3.0 versions of clang */
+#ifndef __has_extension
+# define __has_extension __has_feature
+#endif
+
/*
** Make sure we can call this stuff from C++.
*/
#ifndef SQLITE_SYSAPI
# define SQLITE_SYSAPI
#endif
+#ifndef SQLITE_NOESCAPE
+# if __has_feature(noescape)
+# define SQLITE_NOESCAPE __attribute__((noescape))
+# else
+# define SQLITE_NOESCAPE
+# endif
+#endif
/*
** These no-op macros are used in front of interfaces to mark those
** CAPI3REF: One-Step Query Execution Interface
** METHOD: sqlite3
**
-** The sqlite3_exec() interface is a convenience wrapper around
-** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
+** The sqlite3_exec() and sqlite3_exec_b() interfaces are convenience wrappers
+** around [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
** that allows an application to run multiple statements of SQL
** without having to use a lot of C code.
**
-** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
-** semicolon-separate SQL statements passed into its 2nd argument,
-** in the context of the [database connection] passed in as its 1st
-** argument. ^If the callback function of the 3rd argument to
-** sqlite3_exec() is not NULL, then it is invoked for each result row
+** ^The sqlite3_exec() and sqlite3_exec_b() interfaces run zero or more UTF-8
+** encoded, semicolon-separate SQL statements passed into their 2nd argument,
+** in the context of the [database connection] passed in to their 1st
+** argument. ^If the callback function of the 3rd argument to sqlite3_exec()
+** or sqlite3_exec_b() is not NULL, then it is invoked for each result row
** coming out of the evaluated SQL statements. ^The 4th argument to
-** sqlite3_exec() is relayed through to the 1st argument of each
-** callback invocation. ^If the callback pointer to sqlite3_exec()
-** is NULL, then no callback is ever invoked and result rows are
-** ignored.
+** sqlite3_exec() is relayed through to the 1st argument of each callback
+** invocation. ^If the callback pointer to sqlite3_exec() or sqlite3_exec_b()
+** is NULL, then no callback is ever invoked and result rows are ignored.
**
** ^If an error occurs while evaluating the SQL statements passed into
** sqlite3_exec(), then execution of the current statement stops and
** occur, then sqlite3_exec() sets the pointer in its 5th parameter to
** NULL before returning.
**
-** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec()
+** ^If an sqlite3_exec() or sqlite3_exec_b() callback returns non-zero, the
** routine returns SQLITE_ABORT without invoking the callback again and
** without running any subsequent SQL statements.
**
** entry represents the name of corresponding result column as obtained
** from [sqlite3_column_name()].
**
-** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
-** to an empty string, or a pointer that contains only whitespace and/or
-** SQL comments, then no SQL statements are evaluated and the database
-** is not changed.
+** ^The 1st argument to the sqlite3_exec_b() callback block is a prepared
+** statement object stopped at the current result row. The
+** [column access functions] may be used to extract the row's values.
+**
+** ^If the 2nd parameter to sqlite3_exec() or sqlite3_exec_b() is a NULL
+** pointer, a pointer to an empty string, or a pointer that contains only
+** whitespace and/or SQL comments, then no SQL statements are evaluated and
+** the database is not changed.
**
** Restrictions:
**
** <ul>
** <li> The application must ensure that the 1st parameter to sqlite3_exec()
-** is a valid and open [database connection].
+** or sqlite3_exec_b() is a valid and open [database connection].
** <li> The application must not close the [database connection] specified by
-** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
+** the 1st parameter to sqlite3_exec() or sqlite3_exec_b() while the
+** routine is running.
** <li> The application must not modify the SQL statement text passed into
-** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
+** the 2nd parameter of sqlite3_exec() or sqlite3_exec_b() while the
+** routine is running.
** </ul>
*/
int sqlite3_exec(
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
+#if __has_extension(blocks)
+int sqlite3_exec_b(
+ sqlite3*, /* An open database */
+ const char *sql, /* SQL to be evaluated */
+ SQLITE_NOESCAPE int (^callback)(sqlite3_stmt*) /* Callback block */
+);
+#endif
/*
** CAPI3REF: Result Codes
*/
#include "sqlite3.h"
+/*
+** SQLITE_HAS_BLOCKS controls block API availability
+*/
+#ifndef SQLITE_HAS_BLOCKS
+# if __has_extension(blocks)
+# define SQLITE_HAS_BLOCKS 1
+# else
+# define SQLITE_HAS_BLOCKS 0
+# endif
+#endif
+
/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build