diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/.editorconfig b/libsql-ffi/bundled/SQLite3MultipleCiphers/.editorconfig new file mode 100644 index 0000000000..b259d5da6a --- /dev/null +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/.editorconfig @@ -0,0 +1,16 @@ +# This is the EditorConfig (http://editorconfig.org/) coding style file for +# SQLite3 Multiple Ciphers. + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[makefile.*] +indent_style = tab +indent_size = 8 diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/CHANGELOG.md b/libsql-ffi/bundled/SQLite3MultipleCiphers/CHANGELOG.md index 748450afae..a304d0ba85 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/CHANGELOG.md +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/CHANGELOG.md @@ -7,6 +7,70 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.9.0] - 2024-10-22 + +### Changed + +- Based on SQLite version 3.47.0 +- Changed signature of cipher scheme method `GenerateKey` (affects only developers of dynamic cipher schemes) + +### Fixed + +- Using differing KDF and HMAC algorithms resulted in databases incompatible with the original SQLCipher library. Setting the parameter `hmac_algorithm_compat` to 0 restores the (incompatible) behaviour. + +## [1.8.7] - 2024-08-14 + +### Changed + +- Based on SQLite version 3.46.1 + +## [1.8.6] - 2024-06-14 + +### Changed + +- Removed extern keyword in function declarations +- Cleaned up white space +- Added SQLITE_PRIVATE for several internal functions +- The cipher configuration parameter `legacy_page_size` now accepts only valid page sizes +- The cipher configuration parameter `plaintext_header_size` now accepts only values that are multiples of 16 + +### Fixed + +- Fixed issue [#156](../../issues/156)) - corrupted database if MMAP_SIZE > 0 was used +- Fixed issue [#158](../../issues/158)) - add check to verify compatibility of source and target database in backup operation +- Fixed issue [#160](../../issues/160)) - fix accessing memory out of array bounds +- Fixed issue [#162](../../issues/162)) - fix loading/storing misaligned data +- Fixed issue [#164](../../issues/164)) - fix return of error messages from rekey +- Fixed issue [#165](../../issues/165)) - fix rekey function by enforcing page size and number of reserved bytes per page +- Fixed issue [#166](../../issues/166)) - missing attribute SQLITE_PRIVATE for several internal functions +- Fixed issue [#167](../../issues/167)) - improve VFS error reporting +- Fixed issue [#168](../../issues/168)) - add check for encryption support + +## [1.8.5] - 2024-05-24 + +### Changed + +- Based on SQLite version 3.46.0 + +## [1.8.4] - 2024-03-14 + +### Changed + +- Based on SQLite version 3.45.2 +- Disable user authentication extension by default + +## [1.8.3] - 2024-01-31 + +### Changed + +- Based on SQLite version 3.45.1 + +## [1.8.2] - 2024-01-16 + +### Changed + +- Based on SQLite version 3.45.0 + ## [1.8.1] - 2023-12-02 ### Changed @@ -469,7 +533,15 @@ The following ciphers are supported: - AES 256 Bit CBC - SHA1/SHA256/SHA512 HMAC ([SQLCipher](https://www.zetetic.net/sqlcipher/), database versions 1, 2, 3, and 4) - RC4 - No HMAC ([System.Data.SQLite](http://system.data.sqlite.org)) -[Unreleased]: ../../compare/v1.8.0...HEAD +[Unreleased]: ../../compare/v1.9.0...HEAD +[1.9.0]: ../../compare/v1.8.7...v1.9.0 +[1.8.7]: ../../compare/v1.8.6...v1.8.7 +[1.8.6]: ../../compare/v1.8.5...v1.8.6 +[1.8.5]: ../../compare/v1.8.4...v1.8.5 +[1.8.4]: ../../compare/v1.8.3...v1.8.4 +[1.8.3]: ../../compare/v1.8.2...v1.8.3 +[1.8.2]: ../../compare/v1.8.1...v1.8.2 +[1.8.1]: ../../compare/v1.8.0...v1.8.1 [1.8.0]: ../../compare/v1.7.4...v1.8.0 [1.7.4]: ../../compare/v1.7.3...v1.7.4 [1.7.3]: ../../compare/v1.7.2...v1.7.3 diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/CMakeLists.txt b/libsql-ffi/bundled/SQLite3MultipleCiphers/CMakeLists.txt index e178589249..40fd03a36b 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/CMakeLists.txt +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/CMakeLists.txt @@ -32,7 +32,7 @@ OPTION(SQLITE_ENABLE_JSON1 "Enable extension 'json1'" ON) OPTION(SQLITE_ENABLE_RTREE "Enable extension 'rtree'" ON) OPTION(SQLITE_ENABLE_UUID "Enable extension 'uuid'" ON) OPTION(SQLITE_USE_URI "Enable the URI filename process logic" ON) -OPTION(SQLITE_USER_AUTHENTICATION "Enable extension 'user authentication'" ON) +OPTION(SQLITE_USER_AUTHENTICATION "Enable extension 'user authentication'" OFF) OPTION(SQLITE_ENABLE_PREUPDATE_HOOK "Enable preupdate hooks" OFF) OPTION(SQLITE_ENABLE_SESSION "Enable session extension" OFF) OPTION(SQLITE_SHELL_IS_UTF8 "Shell command line arguments in UTF-8 encoding" ON) @@ -64,7 +64,6 @@ OPTION(SQLITE3MC_USE_SQLCIPHER_LEGACY "Use sqlcipher legacy mode as default" OFF # Additional memory security (filling freed memory allocations with zeros or random data) OPTION(SQLITE3MC_SECURE_MEMORY "Enable pragma to secure freed memory" OFF) -OPTION(SQLITE3MC_USE_RANDOM_FILL_MEMORY "Fill freed memory with random data" OFF) # Omit AES hardware support OPTION(SQLITE3MC_OMIT_AES_HARDWARE_SUPPORT "Omit AES hardware support" OFF) @@ -182,12 +181,6 @@ if(SQLITE3MC_SECURE_MEMORY) SQLITE3MC_SECURE_MEMORY=1 ) endif() -if(SQLITE3MC_USE_RANDOM_FILL_MEMORY) - set(SQLITE3MC_BASE_DEFINITIONS - ${SQLITE3MC_BASE_DEFINITIONS} - SQLITE3MC_USE_RANDOM_FILL_MEMORY=1 - ) -endif() if(SQLITE3MC_USE_MINIZ OR _SQLITE3MC_REQUIRE_ZLIB) if(_SQLITE3MC_REQUIRE_ZLIB) diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/LICENSE b/libsql-ffi/bundled/SQLite3MultipleCiphers/LICENSE index 3317557506..074d3c71ac 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/LICENSE +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019-2020 Ulrich Telle +Copyright (c) 2019-2024 Ulrich Telle Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/Makefile.am b/libsql-ffi/bundled/SQLite3MultipleCiphers/Makefile.am index 900cac9cd6..ff4fd8251d 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/Makefile.am +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/Makefile.am @@ -24,7 +24,7 @@ ACLOCAL_AMFLAGS = -I admin/m4 AM_CXXFLAGS = -I$(top_srcdir)/src AM_CFLAGS = -I$(top_srcdir)/src -AM_CFLAGS += -std=c99 -DSQLITE_THREADSAFE=1 -DSQLITE_DQS=0 -DSQLITE_MAX_ATTACHED=10 -DSQLITE_SOUNDEX=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_SECURE_DELETE=1 -DSQLITE_ENABLE_DESERIALIZE=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 -DSQLITE_ENABLE_SESSION=1 -DSQLITE_CORE=1 -DSQLITE_ENABLE_EXTFUNC=1 -DSQLITE_ENABLE_MATH_FUNCTIONS=1 -DSQLITE_ENABLE_CSV=1 -DSQLITE_ENABLE_SHA3=1 -DSQLITE_ENABLE_CARRAY=1 -DSQLITE_ENABLE_FILEIO=1 -DSQLITE_ENABLE_SERIES=1 -DSQLITE_ENABLE_UUID=1 -DSQLITE_ENABLE_REGEXP=1 -DSQLITE_TEMP_STORE=2 -DSQLITE_USE_URI=1 -DSQLITE_USER_AUTHENTICATION=1 $(X86_FLAGS) $(ARM_FLAGS) +AM_CFLAGS += -std=c99 -DSQLITE_THREADSAFE=1 -DSQLITE_DQS=0 -DSQLITE_MAX_ATTACHED=10 -DSQLITE_SOUNDEX=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_SECURE_DELETE=1 -DSQLITE_ENABLE_DESERIALIZE=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 -DSQLITE_ENABLE_SESSION=1 -DSQLITE_CORE=1 -DSQLITE_ENABLE_EXTFUNC=1 -DSQLITE_ENABLE_MATH_FUNCTIONS=1 -DSQLITE_ENABLE_CSV=1 -DSQLITE_ENABLE_SHA3=1 -DSQLITE_ENABLE_CARRAY=1 -DSQLITE_ENABLE_FILEIO=1 -DSQLITE_ENABLE_SERIES=1 -DSQLITE_ENABLE_UUID=1 -DSQLITE_ENABLE_REGEXP=1 -DSQLITE_TEMP_STORE=2 -DSQLITE_USE_URI=1 -DSQLITE_USER_AUTHENTICATION=0 $(X86_FLAGS) $(ARM_FLAGS) if HOST_WINDOWS AM_CFLAGS += -DSQLITE_API=__declspec\(dllexport\) @@ -138,7 +138,7 @@ sqlite3shell_SOURCES = \ src/sqlite3mc.c \ src/shell.c -sqlite3shell_CFLAGS = -I$(top_srcdir)/src -std=c99 -D_GNU_SOURCE -DSQLITE_THREADSAFE=1 -DSQLITE_DQS=0 -DSQLITE_MAX_ATTACHED=10 -DSQLITE_SOUNDEX=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_SECURE_DELETE=1 -DSQLITE_ENABLE_DESERIALIZE=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 -DSQLITE_ENABLE_SESSION=1 -DSQLITE_CORE=1 -DSQLITE_ENABLE_EXTFUNC=1 -DSQLITE_ENABLE_MATH_FUNCTIONS=1 -DSQLITE_ENABLE_CSV=1 -DSQLITE_ENABLE_CARRAY=1 -DSQLITE_ENABLE_UUID=1 -DSQLITE_TEMP_STORE=2 -DSQLITE_USE_URI=1 -DSQLITE_USER_AUTHENTICATION=1 -DSQLITE_ENABLE_DBPAGE_VTAB=1 -DSQLITE_ENABLE_DBSTAT_VTAB=1 -DSQLITE_ENABLE_STMTVTAB=1 -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION=1 $(X86_FLAGS) $(ARM_FLAGS) +sqlite3shell_CFLAGS = -I$(top_srcdir)/src -std=c99 -D_GNU_SOURCE -DSQLITE_THREADSAFE=1 -DSQLITE_DQS=0 -DSQLITE_MAX_ATTACHED=10 -DSQLITE_SOUNDEX=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_SECURE_DELETE=1 -DSQLITE_ENABLE_DESERIALIZE=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_FTS4=1 -DSQLITE_ENABLE_FTS5=1 -DSQLITE_ENABLE_JSON1=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_GEOPOLY=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 -DSQLITE_ENABLE_SESSION=1 -DSQLITE_CORE=1 -DSQLITE_ENABLE_EXTFUNC=1 -DSQLITE_ENABLE_MATH_FUNCTIONS=1 -DSQLITE_ENABLE_CSV=1 -DSQLITE_ENABLE_CARRAY=1 -DSQLITE_ENABLE_UUID=1 -DSQLITE_TEMP_STORE=2 -DSQLITE_USE_URI=1 -DSQLITE_USER_AUTHENTICATION=0 -DSQLITE_ENABLE_DBPAGE_VTAB=1 -DSQLITE_ENABLE_DBSTAT_VTAB=1 -DSQLITE_ENABLE_STMTVTAB=1 -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION=1 $(X86_FLAGS) $(ARM_FLAGS) if HOST_WINDOWS sqlite3shell_LDADD = diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/configure.ac b/libsql-ffi/bundled/SQLite3MultipleCiphers/configure.ac index 355f6b5786..573979655c 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/configure.ac +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/configure.ac @@ -1,10 +1,10 @@ dnl Process this script with autoconf to create configure for sqlite3mc library dnl -dnl Copyright (C) 2019-2023 Ulrich Telle +dnl Copyright (C) 2019-2024 Ulrich Telle dnl dnl This file is covered by the same licence as the entire SQLite3 Multiple Ciphers package. -AC_INIT([sqlite3mc], [1.8.1], [ulrich@telle-online.de]) +AC_INIT([sqlite3mc], [1.9.0], [ulrich@telle-online.de]) dnl This is the version tested with, might work with earlier ones. AC_PREREQ([2.69]) diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/premake5.lua b/libsql-ffi/bundled/SQLite3MultipleCiphers/premake5.lua index b304564412..2c27a68f20 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/premake5.lua +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/premake5.lua @@ -92,10 +92,9 @@ project "sqlite3mc_lib" -- "SQLITE_ENABLE_SQLAR=1" -- "SQLITE_ENABLE_ZIPFILE=1" "SQLITE3MC_SECURE_MEMORY=$(SQLITE3MC_SECURE_MEMORY)", --- "SQLITE3MC_USE_RANDOM_FILL_MEMORY=$(SQLITE3MC_USE_RANDOM_FILL_MEMORY)", "SQLITE_TEMP_STORE=2", "SQLITE_USE_URI=1", - "SQLITE_USER_AUTHENTICATION=1", + "SQLITE_USER_AUTHENTICATION=0", -- Compatibility with official SQLite3 shell "SQLITE_ENABLE_DBPAGE_VTAB=1", "SQLITE_ENABLE_DBSTAT_VTAB=1", @@ -190,10 +189,9 @@ project "sqlite3mc_dll" -- "SQLITE_ENABLE_SQLAR=1" -- "SQLITE_ENABLE_ZIPFILE=1" "SQLITE3MC_SECURE_MEMORY=$(SQLITE3MC_SECURE_MEMORY)", --- "SQLITE3MC_USE_RANDOM_FILL_MEMORY=$(SQLITE3MC_USE_RANDOM_FILL_MEMORY)", "SQLITE_TEMP_STORE=2", "SQLITE_USE_URI=1", - "SQLITE_USER_AUTHENTICATION=1" + "SQLITE_USER_AUTHENTICATION=0" } -- Intermediate directory @@ -251,7 +249,7 @@ project "sqlite3mc_shell" "SQLITE_SHELL_IS_UTF8=1", "SQLITE_ENABLE_SESSION=1", "SQLITE_ENABLE_DBPAGE_VTAB=1", - "SQLITE_USER_AUTHENTICATION=1" + "SQLITE_USER_AUTHENTICATION=0" } -- Intermediate directory @@ -342,10 +340,9 @@ project "sqlite3mc_libicu" -- "SQLITE_ENABLE_SQLAR=1" -- "SQLITE_ENABLE_ZIPFILE=1" "SQLITE3MC_SECURE_MEMORY=$(SQLITE3MC_SECURE_MEMORY)", --- "SQLITE3MC_USE_RANDOM_FILL_MEMORY=$(SQLITE3MC_USE_RANDOM_FILL_MEMORY)", "SQLITE_TEMP_STORE=2", "SQLITE_USE_URI=1", - "SQLITE_USER_AUTHENTICATION=1", + "SQLITE_USER_AUTHENTICATION=0", -- Compatibility with official SQLite3 shell "SQLITE_ENABLE_DBPAGE_VTAB=1", "SQLITE_ENABLE_DBSTAT_VTAB=1", @@ -453,10 +450,9 @@ project "sqlite3mc_dllicu" -- "SQLITE_ENABLE_SQLAR=1" -- "SQLITE_ENABLE_ZIPFILE=1" "SQLITE3MC_SECURE_MEMORY=$(SQLITE3MC_SECURE_MEMORY)", --- "SQLITE3MC_USE_RANDOM_FILL_MEMORY=$(SQLITE3MC_USE_RANDOM_FILL_MEMORY)", "SQLITE_TEMP_STORE=2", "SQLITE_USE_URI=1", - "SQLITE_USER_AUTHENTICATION=1" + "SQLITE_USER_AUTHENTICATION=0" } -- Intermediate directory @@ -526,7 +522,7 @@ project "sqlite3mc_shellicu" "SQLITE_SHELL_IS_UTF8=1", "SQLITE_ENABLE_SESSION=1", "SQLITE_ENABLE_DBPAGE_VTAB=1", - "SQLITE_USER_AUTHENTICATION=1" + "SQLITE_USER_AUTHENTICATION=0" } -- Intermediate directory diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/readme.md b/libsql-ffi/bundled/SQLite3MultipleCiphers/readme.md index 1ab5f9d684..e525ad0cf6 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/readme.md +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/readme.md @@ -10,10 +10,10 @@ The code was mainly developed under Windows, but was tested under Linux as well. ## Version information -* 1.8.1 - *December 2023* - - Based on SQLite version 3.44.2 - - Fixed issue #133 - missing API symbols - - Applied several modifications to improve support for [SQLite3 WASM](https://sqlite.org/wasm/) +* 1.9.0 - *October 2024* + - Based on SQLite version 3.47.0 + - Changed signature of cipher scheme method `GenerateKey` (affects only developers of dynamic cipher schemes) + - Using differing KDF and HMAC algorithms resulted in databases incompatible with the original SQLCipher library. Setting the parameter `hmac_algorithm_compat` to 0 restores the (incompatible) behaviour. For further version information please consult the [CHANGELOG](CHANGELOG.md). diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/scripts/patchshell.sh b/libsql-ffi/bundled/SQLite3MultipleCiphers/scripts/patchshell.sh index 65c1873b93..56151b4886 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/scripts/patchshell.sh +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/scripts/patchshell.sh @@ -14,7 +14,10 @@ die() { exit 2 } -sed -e '/^ oputf("SQLite version/{n;N;d}' "$INPUT" \ +sed -e '/^ sputf(stdout, "SQLite version/{n;N;d}' "$INPUT" \ | sed '/#ifdef SQLITE_CUSTOM_INCLUDE/!{p;d;};n;n;n;a #if SQLITE3MC_USE_MINIZ != 0 && !defined(SQLITE_ENABLE_COMPRESS)\n#include "miniz.c"\n#ifdef SQLITE_HAVE_ZLIB\n#undef SQLITE_HAVE_ZLIB\n#endif\n#define SQLITE_HAVE_ZLIB 1\n#endif\n' \ | sed '/#include /c #include "zlibwrap.h"' \ - | sed '/^ oputf("SQLite version/c \ extern char* sqlite3mc_version();\n oputf("SQLite version \%s \%.19s%s" \/\*extra-version-info\*\/\n " (\%s)\\n" \/\*SQLite3-Multiple-Ciphers-version-info\*\/\n "Enter \\".help\\" for usage hints.\\n\",\n sqlite3_libversion(), sqlite3_sourceid(), SHELL_CIO_CHAR_SET, sqlite3mc_version());' + | sed '/^ sqlite3_fprintf(stdout,$/c \ extern char* sqlite3mc_version();\n sqlite3_fprintf(stdout,' \ + | sed '/^ "SQLite version/c \ "SQLite version \%s \%.19s%s" \/\*extra-version-info\*\/\n " (\%s)\\n" \/\*SQLite3-Multiple-Ciphers-version-info\*\/' \ + | sed '/^ sqlite3_libversion(), sqlite3_sourceid(), SHELL_CIO_CHAR_SET);/c \ sqlite3_libversion(), sqlite3_sourceid(), SHELL_CIO_CHAR_SET, sqlite3mc_version());' \ + | sed '/^ sqlite3_libversion(), sqlite3_sourceid());/a \ extern char* sqlite3mc_version();\n sqlite3_fprintf(p->out, "\%s\\n", sqlite3mc_version());' diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/scripts/patchsqlite3.sh b/libsql-ffi/bundled/SQLite3MultipleCiphers/scripts/patchsqlite3.sh index 30625482a6..5a689f596a 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/scripts/patchsqlite3.sh +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/scripts/patchsqlite3.sh @@ -17,7 +17,7 @@ die() { # 1) Intercept VFS pragma handling # 2) Add handling of KEY parameter in ATTACH statements sed 's/sqlite3_file_control\(.*SQLITE_FCNTL_PRAGMA\)/sqlite3mcFileControlPragma\1/' "$INPUT" \ - | sed '/\#endif \/\* SQLITE3\_H \*\//a \ \n\/\* Function prototypes of SQLite3 Multiple Ciphers \*\/\nSQLITE_PRIVATE int sqlite3mcCheckVfs(const char*);\nSQLITE_PRIVATE int sqlite3mcFileControlPragma(sqlite3*, const char*, int, void*);\nSQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**);\nSQLITE_PRIVATE int sqlite3mcHandleMainKey(sqlite3*, const char*);\ntypedef struct PgHdr PgHdrMC;\nSQLITE_PRIVATE void* sqlite3mcPagerCodec(PgHdrMC* pPg);\ntypedef struct Pager PagerMC;\nSQLITE_PRIVATE int sqlite3mcPagerHasCodec(PagerMC* pPager);\nSQLITE_PRIVATE void sqlite3mcInitMemoryMethods();' \ + | sed '/\#endif \/\* SQLITE3\_H \*\//a \ \n\/\* Function prototypes of SQLite3 Multiple Ciphers \*\/\nSQLITE_PRIVATE int sqlite3mcCheckVfs(const char*);\nSQLITE_PRIVATE int sqlite3mcFileControlPragma(sqlite3*, const char*, int, void*);\nSQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**);\nSQLITE_PRIVATE int sqlite3mcHandleMainKey(sqlite3*, const char*);\ntypedef struct PgHdr PgHdrMC;\nSQLITE_PRIVATE void* sqlite3mcPagerCodec(PgHdrMC* pPg);\ntypedef struct Pager PagerMC;\nSQLITE_PRIVATE int sqlite3mcPagerHasCodec(PagerMC* pPager);\nSQLITE_PRIVATE void sqlite3mcInitMemoryMethods();\nSQLITE_PRIVATE int sqlite3mcIsBackupSupported(sqlite3*, const char*, sqlite3*, const char*);' \ | sed '/\#define MAX\_PATHNAME 512/c #if SQLITE3MC\_MAX\_PATHNAME \> 512\n#define MAX_PATHNAME SQLITE3MC\_MAX\_PATHNAME\n#else\n#define MAX_PATHNAME 512\n#endif' \ | sed '/pData = pPage->pData;/c \ if( (pData = sqlite3mcPagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT;' \ | sed '/pData = p->pData;/c \ if( (pData = sqlite3mcPagerCodec(p))==0 ) return SQLITE_NOMEM;' \ @@ -26,4 +26,5 @@ sed 's/sqlite3_file_control\(.*SQLITE_FCNTL_PRAGMA\)/sqlite3mcFileControlPragma\ | sed '/sqlite3_free_filename(zOpen);/i \\n \/\* Handle encryption related URI parameters. \*\/\n if( rc==SQLITE_OK ){\n rc = sqlite3mcHandleMainKey(db, zOpen);\n }' \ | sed '/^ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;/a \ if( sqlite3mcPagerHasCodec(pPager) != 0 ) return 0;' \ | sed '/^ }else if( USEFETCH(pPager) ){/c \ }else if( USEFETCH(pPager) && sqlite3mcPagerHasCodec(pPager) == 0 ){' \ - | sed '/^ if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));/a \\n \/\* Initialize wrapper for memory management.\*\/\n if( rc==SQLITE_OK ) {\n sqlite3mcInitMemoryMethods();\n }\n' + | sed '/^ if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));/a \\n \/\* Initialize wrapper for memory management.\*\/\n if( rc==SQLITE_OK ) {\n sqlite3mcInitMemoryMethods();\n }\n' \ + | sed '/Lock the source database handle./i \ \/\* Check whether databases are compatible with backup \*\/\n if (!sqlite3mcIsBackupSupported(pSrcDb, zSrcDb, pDestDb, zDestDb)){\n sqlite3ErrorWithMsg(pDestDb, SQLITE_ERROR, \"backup is not supported with incompatible source and target databases\");\n return NULL;\n }\n' diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/aes_hardware.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/aes_hardware.c index 2787712f00..9a45b9fb90 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/aes_hardware.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/aes_hardware.c @@ -198,7 +198,7 @@ aesGenKeyEncrypt(const unsigned char* userKey, const int bits, unsigned char* ke { int numberOfRounds = (bits == 128) ? 10 : (bits == 192) ? 12 : (bits == 256) ? 14 : 0; int rc = (!userKey || !keyData) ? -1 : (numberOfRounds > 0) ? 0 : -2; - + if (rc == 0) { __m128i tempKey[_MAX_ROUNDS + 1]; @@ -347,7 +347,7 @@ aesDecryptCBC(const unsigned char* in, int offset; --numBlocks; offset = numBlocks * 16; - + /* Decrypt the last plain block. */ last_in = _mm_loadu_si128(&((__m128i*) in)[numBlocks]); data = _mm_xor_si128(last_in, key[numberOfRounds - 0]); @@ -477,7 +477,7 @@ aesGenKeyEncryptInternal(const unsigned char* userKey, const int bits, uint8x16_ int i; int j; int numberOfRounds = (bits == 128) ? 10 : (bits == 192) ? 12 : (bits == 256) ? 14 : 0; - int keyWords = bits / 32; + int keyWords = bits / 32; int schedWords = (numberOfRounds + 1) * 4; /* @@ -538,7 +538,7 @@ aesGenKeyEncrypt(const unsigned char* userKey, const int bits, unsigned char* ke { int numberOfRounds = (bits == 128) ? 10 : (bits == 192) ? 12 : (bits == 256) ? 14 : 0; int rc = (!userKey || !keyData) ? -1 : (numberOfRounds > 0) ? 0 : -2; - + if (rc == 0) { uint8x16_t tempKey[_MAX_ROUNDS + 1]; @@ -648,7 +648,7 @@ aesEncryptCBC(const unsigned char* in, } feedback = vaeseq_u8(feedback, key[numberOfRounds-1]); feedback = veorq_u8(feedback, key[numberOfRounds]); \ - + vst1q_u8(&out[(numBlocks-1)*16], feedback); memcpy(&out[numBlocks*16], lastblock, lenFrag); @@ -689,7 +689,7 @@ aesDecryptCBC(const unsigned char* in, int offset; --numBlocks; offset = numBlocks * 16; - + /* Decrypt the last plain block. */ last_in = vld1q_u8(&in[numBlocks*16]); diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/aead.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/aead.c index 1d9132e267..b65e63e360 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/aead.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/aead.c @@ -88,7 +88,7 @@ forceinline void ascon_adata(ascon_state_t* s, const uint8_t* ad, ASCON_P(s, nr); } /* domain separation */ - s->x[4] ^= 1; + s->x[4] ^= ASCON_DSEP(); ascon_printstate("domain separation", s); } @@ -197,6 +197,7 @@ forceinline void ascon_final(ascon_state_t* s, const ascon_key_t* key) { ascon_printstate("final 2nd key xor", s); } +SQLITE_PRIVATE int ascon_aead_encrypt(uint8_t* ctext, uint8_t tag[ASCON_AEAD_TAG_LEN], const uint8_t* mtext, uint64_t mlen, @@ -220,6 +221,7 @@ int ascon_aead_encrypt(uint8_t* ctext, return 0; } +SQLITE_PRIVATE int ascon_aead_decrypt(uint8_t* mtext, const uint8_t* ctext, uint64_t clen, const uint8_t* ad, uint64_t adlen, diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_aead.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_aead.h index 0955c7638e..4c205bacb4 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_aead.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_aead.h @@ -13,6 +13,10 @@ #ifndef CRYPTO_AEAD_H #define CRYPTO_AEAD_H +#ifndef SQLITE_PRIVATE +#define SQLITE_PRIVATE +#endif + #include /* @@ -27,6 +31,7 @@ ** \param nonce Buffer with nonce data ** \param k Buffer with key data */ +SQLITE_PRIVATE int ascon_aead_encrypt(uint8_t* ctext, uint8_t tag[ASCON_AEAD_TAG_LEN], const uint8_t* mtext, uint64_t mlen, const uint8_t* ad, uint64_t adlen, @@ -45,6 +50,7 @@ int ascon_aead_encrypt(uint8_t* ctext, uint8_t tag[ASCON_AEAD_TAG_LEN], ** \param nonce Buffer with nonce data ** \param k Buffer with key data */ +SQLITE_PRIVATE int ascon_aead_decrypt(uint8_t* mtext, const uint8_t* ctext, uint64_t clen, const uint8_t* ad, uint64_t adlen, const uint8_t tag[ASCON_AEAD_TAG_LEN], diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_hash.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_hash.h index af9b04e29d..4f326f1e12 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_hash.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_hash.h @@ -13,6 +13,10 @@ #ifndef CRYPTO_HASH_H #define CRYPTO_HASH_H +#ifndef SQLITE_PRIVATE +#define SQLITE_PRIVATE +#endif + #include /* @@ -22,6 +26,7 @@ ** \param in Buffer with input data ** \param passwordlen Length of input data in bytes */ +SQLITE_PRIVATE int ascon_hash(uint8_t* out, const uint8_t* in, uint64_t inlen); #endif diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_pbkdf2.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_pbkdf2.h index 95d7f9d743..d9f247b824 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_pbkdf2.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/crypto_pbkdf2.h @@ -17,6 +17,10 @@ #ifndef ASCON_PBKDF2_H #define ASCON_PBKDF2_H +#ifndef SQLITE_PRIVATE +#define SQLITE_PRIVATE +#endif + #include /* @@ -35,6 +39,7 @@ ** \param saltlen Number of bytes in the salt ** \param count Number of iterations to perform */ +SQLITE_PRIVATE void ascon_pbkdf2(uint8_t* out, uint32_t outlen, const uint8_t* password, uint32_t passwordlen, const uint8_t* salt, uint32_t saltlen, uint32_t count) diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/hash.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/hash.c index 46d17623ec..ae400f10e3 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/hash.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/hash.c @@ -89,6 +89,7 @@ forceinline void ascon_squeeze(ascon_state_t* s, uint8_t* out, ascon_printstate("squeeze output", s); } +SQLITE_PRIVATE int ascon_hash(uint8_t* out, const uint8_t* in, uint64_t inlen) { ascon_state_t s; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/pbkdf2.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/pbkdf2.c index 8db33c998d..1f84d551cf 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/pbkdf2.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/pbkdf2.c @@ -15,6 +15,7 @@ #define ASCON_HASH_SIZE 32 #define ASCON_PBKDF2_SIZE 32 +SQLITE_PRIVATE void ascon_pbkdf2_init(ascon_state_t* state, const char* functionName, const unsigned char* custom, uint32_t customlen, uint32_t outlen) { @@ -60,10 +61,11 @@ void ascon_pbkdf2_init(ascon_state_t* state, const char* functionName, * Note: Instead of HMAC like in RFC 8018, use the following PRF: * PRF(P, X) = ASCON-cXOF(X, 256, "PBKDF2", P) */ -static void ascon_pbkdf2_f(ascon_state_t* state, - uint8_t* T, /*uint8_t* U,*/ - const uint8_t* salt, uint32_t saltlen, - uint32_t count, uint32_t blocknum) +static +void ascon_pbkdf2_f(ascon_state_t* state, + uint8_t* T, /*uint8_t* U,*/ + const uint8_t* salt, uint32_t saltlen, + uint32_t count, uint32_t blocknum) { uint32_t asconSaltLen = (saltlen < ASCON_SALT_LEN) ? saltlen : ASCON_SALT_LEN; uint8_t temp[ASCON_SALT_LEN+4]; @@ -73,7 +75,7 @@ static void ascon_pbkdf2_f(ascon_state_t* state, memset(temp, 0, ASCON_SALT_LEN); memcpy(temp, salt, asconSaltLen); STORE32_BE(temp+ASCON_SALT_LEN, blocknum); - + /* Copy initial state */ for (j = 0; j < 5; ++j) state2.x[j] = state->x[j]; @@ -109,6 +111,7 @@ static void ascon_pbkdf2_f(ascon_state_t* state, sqlite3mcSecureZeroMemory(&state2, sizeof(ascon_state_t)); } +SQLITE_PRIVATE void ascon_pbkdf2(uint8_t* out, uint32_t outlen, const uint8_t* password, uint32_t passwordlen, const uint8_t* salt, uint32_t saltlen, uint32_t count) diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/prolog.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/prolog.h index 4e65e45cdd..5efe9ba0ae 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/prolog.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/prolog.h @@ -1,6 +1,6 @@ /* ** Name: prolog.h -** Purpose: Include important header files, before +** Purpose: Include important header files, before ** Based on: Public domain Ascon reference implementation ** and optimized variants for 32- and 64-bit ** (see https://github.com/ascon/ascon-c) diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/word.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/word.h index cfd960a00e..972b55d2f0 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/word.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/ascon/word.h @@ -15,6 +15,8 @@ typedef union { #define ASCON_U64TOWORD(x) ASCON_U64BIG(x) #define ASCON_WORDTOU64(x) ASCON_U64BIG(x) +#define ASCON_LOAD(b, n) ASCON_LOADBYTES(b, n) +#define ASCON_STORE(b, w, n) ASCON_STOREBYTES(b, w, n) forceinline uint64_t ASCON_ROR(uint64_t x, int n) { return x >> n | x << (-n & 63); } @@ -32,6 +34,8 @@ forceinline int ASCON_NOTZERO(uint64_t a, uint64_t b) { forceinline uint64_t ASCON_PAD(int i) { return 0x80ull << (56 - 8 * i); } +forceinline uint64_t ASCON_DSEP() { return 0x01; } + forceinline uint64_t ASCON_PRFS_MLEN(uint64_t len) { return len << 51; } forceinline uint64_t ASCON_CLEAR(uint64_t w, int n) { @@ -45,16 +49,6 @@ forceinline uint64_t ASCON_MASK(int n) { return ~0ull >> (64 - 8 * n); } -forceinline uint64_t ASCON_LOAD(const uint8_t* bytes, int n) { - uint64_t x = *(uint64_t*)bytes & ASCON_MASK(n); - return ASCON_U64TOWORD(x); -} - -forceinline void ASCON_STORE(uint8_t* bytes, uint64_t w, int n) { - *(uint64_t*)bytes &= ~ASCON_MASK(n); - *(uint64_t*)bytes |= ASCON_WORDTOU64(w); -} - forceinline uint64_t ASCON_LOADBYTES(const uint8_t* bytes, int n) { uint64_t x = 0; memcpy(&x, bytes, n); diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/carray.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/carray.c index b1caa98c3f..28806d5ea6 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/carray.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/carray.c @@ -46,7 +46,7 @@ ** ctype TEXT HIDDEN ** ); ** -** If the hidden columns "pointer" and "count" are unconstrained, then +** If the hidden columns "pointer" and "count" are unconstrained, then ** the virtual table has no rows. Otherwise, the virtual table interprets ** the integer value of "pointer" as a pointer to the array and "count" ** as the number of elements in the array. The virtual table steps through @@ -64,7 +64,7 @@ SQLITE_EXTENSION_INIT1 #else # include #endif - + /* Allowed values for the mFlags parameter to sqlite3_carray_bind(). ** Must exactly match the definitions in carray.h. */ @@ -271,7 +271,7 @@ static int carrayEof(sqlite3_vtab_cursor *cur){ ** to the first row of output. */ static int carrayFilter( - sqlite3_vtab_cursor *pVtabCursor, + sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ @@ -385,7 +385,7 @@ static int carrayBestIndex( } /* -** This following structure defines all the methods for the +** This following structure defines all the methods for the ** carray virtual table. */ static sqlite3_module carrayModule = { @@ -468,7 +468,7 @@ SQLITE_API int sqlite3_carray_bind( for(i=0; iaData = sqlite3_malloc64( sz ); if( pNew->aData==0 ){ sqlite3_free(pNew); @@ -542,8 +542,8 @@ static void inttoptrFunc( #endif /* SQLITE_OMIT_VIRTUALTABLE */ SQLITE_API int sqlite3_carray_init( - sqlite3 *db, - char **pzErrMsg, + sqlite3 *db, + char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/chacha20poly1305.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/chacha20poly1305.c index 57a96931b6..13bdad6e6a 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/chacha20poly1305.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/chacha20poly1305.c @@ -74,6 +74,7 @@ static void chacha20_block(uint32_t x[16]) #undef CC20QR } +SQLITE_PRIVATE void chacha20_xor(void* buffer, size_t n, const uint8_t key[32], const uint8_t nonce[12], uint32_t counter) { @@ -141,6 +142,7 @@ void chacha20_xor(void* buffer, size_t n, const uint8_t key[32], /* * Poly1305 authentication tags */ +SQLITE_PRIVATE void poly1305(const uint8_t* msg, size_t n, const uint8_t key[32], uint8_t tag[16]) { @@ -210,6 +212,7 @@ void poly1305(const uint8_t* msg, size_t n, const uint8_t key[32], s4 = d4; STORE32_LE(tag + 12, s4); } +SQLITE_PRIVATE int poly1305_tagcmp(const uint8_t tag1[16], const uint8_t tag2[16]) { uint8_t d = 0; @@ -286,7 +289,7 @@ static size_t entropy(void* buf, size_t n) } #else - + #include #define RtlGenRandom SystemFunction036 BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); @@ -405,6 +408,7 @@ static size_t entropy(void* buf, size_t n) /* * ChaCha20 random number generator */ +SQLITE_PRIVATE void chacha20_rng(void* out, size_t n) { static uint8_t key[32], nonce[12], buffer[64] = { 0 }; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_ascon.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_ascon.c index 89d658a621..c702104f77 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_ascon.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_ascon.c @@ -3,7 +3,7 @@ ** Purpose: Implementation of cipher Ascon ** Author: Ulrich Telle ** Created: 2023-11-13 -** Copyright: (c) 2023-2023 Ulrich Telle +** Copyright: (c) 2023-2024 Ulrich Telle ** License: MIT */ @@ -114,21 +114,18 @@ GetSaltAscon128Cipher(void* cipher) } static void -GenerateKeyAscon128Cipher(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) +GenerateKeyAscon128Cipher(void* cipher, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) { Ascon128Cipher* ascon128Cipher = (Ascon128Cipher*) cipher; int bypass = 0; - Pager *pPager = pBt->pPager; - sqlite3_file* fd = (isOpen(pPager->fd)) ? pPager->fd : NULL; - int keyOnly = 1; - if (rekey || fd == NULL || sqlite3OsRead(fd, ascon128Cipher->m_salt, SALTLENGTH_ASCON128, 0) != SQLITE_OK) + if (rekey || cipherSalt == NULL) { chacha20_rng(ascon128Cipher->m_salt, SALTLENGTH_ASCON128); keyOnly = 0; } - else if (cipherSalt != NULL) + else { memcpy(ascon128Cipher->m_salt, cipherSalt, SALTLENGTH_ASCON128); } diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_chacha20.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_chacha20.c index f93a867468..67dca9c51e 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_chacha20.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_chacha20.c @@ -3,7 +3,7 @@ ** Purpose: Implementation of cipher ChaCha20 - Poly1305 ** Author: Ulrich Telle ** Created: 2020-02-02 -** Copyright: (c) 2006-2020 Ulrich Telle +** Copyright: (c) 2006-2024 Ulrich Telle ** License: MIT */ @@ -140,21 +140,18 @@ GetSaltChaCha20Cipher(void* cipher) } static void -GenerateKeyChaCha20Cipher(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) +GenerateKeyChaCha20Cipher(void* cipher, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) { ChaCha20Cipher* chacha20Cipher = (ChaCha20Cipher*) cipher; int bypass = 0; - Pager *pPager = pBt->pPager; - sqlite3_file* fd = (isOpen(pPager->fd)) ? pPager->fd : NULL; - int keyOnly = 1; - if (rekey || fd == NULL || sqlite3OsRead(fd, chacha20Cipher->m_salt, SALTLENGTH_CHACHA20, 0) != SQLITE_OK) + if (rekey || cipherSalt == NULL) { chacha20_rng(chacha20Cipher->m_salt, SALTLENGTH_CHACHA20); keyOnly = 0; } - else if (cipherSalt != NULL) + else { memcpy(chacha20Cipher->m_salt, cipherSalt, SALTLENGTH_CHACHA20); } @@ -274,7 +271,8 @@ EncryptPageChaCha20Cipher(void* cipher, int page, unsigned char* data, int len, return rc; } -int chacha20_ismemset(const void* v, unsigned char value, int len) +static int +chacha20_ismemset(const void* v, unsigned char value, int len) { const unsigned char* a = v; int i = 0, result = 0; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_common.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_common.c index 6e4eed953d..2075a7874e 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_common.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_common.c @@ -3,7 +3,7 @@ ** Purpose: Implementation of SQLite codecs ** Author: Ulrich Telle ** Created: 2020-02-02 -** Copyright: (c) 2006-2022 Ulrich Telle +** Copyright: (c) 2006-2024 Ulrich Telle ** License: MIT */ @@ -144,7 +144,7 @@ sqlite3mcGetCipherType(sqlite3* db) { CodecParameter* codecParams = (db != NULL) ? sqlite3mcGetCodecParams(db) : globalCodecParameterTable; CipherParams* cipherParamTable = (codecParams != NULL) ? codecParams[0].m_params : commonParams; - int cipherType = CODEC_TYPE; + int cipherType = CODEC_TYPE_UNKNOWN; CipherParams* cipher = cipherParamTable; for (; cipher->m_name[0] != 0; ++cipher) { @@ -207,6 +207,7 @@ sqlite3mcCodecInit(Codec* codec) memset(codec->m_page, 0, sizeof(codec->m_page)); codec->m_pageSize = 0; codec->m_reserved = 0; + codec->m_lastError = SQLITE_OK; codec->m_hasKeySalt = 0; memset(codec->m_keySalt, 0, sizeof(codec->m_keySalt)); } @@ -245,6 +246,10 @@ sqlite3mcCodecSetup(Codec* codec, int cipherType, char* userPassword, int passwo { int rc = SQLITE_OK; CipherParams* globalParams = sqlite3mcGetCipherParams(codec->m_db, CIPHER_NAME_GLOBAL); + if (cipherType <= CODEC_TYPE_UNKNOWN) + { + return SQLITE_ERROR; + } codec->m_isEncrypted = 1; codec->m_hmacCheck = sqlite3mcGetCipherParameter(globalParams, "hmac_check"); codec->m_walLegacy = sqlite3mcGetCipherParameter(globalParams, "mc_legacy_wal"); @@ -270,6 +275,10 @@ sqlite3mcSetupWriteCipher(Codec* codec, int cipherType, char* userPassword, int { int rc = SQLITE_OK; CipherParams* globalParams = sqlite3mcGetCipherParams(codec->m_db, CIPHER_NAME_GLOBAL); + if (cipherType <= CODEC_TYPE_UNKNOWN) + { + return SQLITE_ERROR; + } if (codec->m_writeCipher != NULL) { globalCodecDescriptorTable[codec->m_writeCipherType-1].m_freeCipher(codec->m_writeCipher); @@ -414,7 +423,7 @@ sqlite3mcGetLegacyWriteCipher(Codec* codec) SQLITE_PRIVATE int sqlite3mcGetPageSizeReadCipher(Codec* codec) { - int pageSize = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType - 1].m_getPageSize(codec->m_readCipher) : 0; + int pageSize = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType - 1].m_getPageSize(codec->m_readCipher) : -1; return pageSize; } @@ -447,6 +456,21 @@ sqlite3mcReservedEqual(Codec* codec) return (readReserved == writeReserved); } +SQLITE_PRIVATE void +sqlite3mcSetCodecLastError(Codec* codec, int error) +{ + if (codec) + { + codec->m_lastError = error; + } +} + +SQLITE_PRIVATE int +sqlite3mcGetCodecLastError(Codec* codec) +{ + return codec ? codec->m_lastError : SQLITE_OK; +} + SQLITE_PRIVATE unsigned char* sqlite3mcGetSaltWriteCipher(Codec* codec) { @@ -500,6 +524,9 @@ sqlite3mcCodecCopy(Codec* codec, Codec* other) codec->m_bt = other->m_bt; #endif codec->m_btShared = other->m_btShared; + + codec->m_lastError = SQLITE_OK; + return rc; } @@ -570,16 +597,30 @@ sqlite3mcPadPassword(char* password, int pswdlen, unsigned char pswd[32]) } } +SQLITE_PRIVATE unsigned char* mcReadDatabaseHeader(Codec* codec, unsigned char* dbHeader) +{ + Pager* pPager = codec->m_btShared->pPager; + sqlite3_file* fd = (isOpen(pPager->fd)) ? pPager->fd : NULL; + if (fd == NULL || sqlite3OsRead(fd, dbHeader, KEYSALT_LENGTH, 0) != SQLITE_OK) + return NULL; + else + return dbHeader; +} + SQLITE_PRIVATE void sqlite3mcGenerateReadKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt) { - globalCodecDescriptorTable[codec->m_readCipherType-1].m_generateKey(codec->m_readCipher, codec->m_btShared, userPassword, passwordLength, 0, cipherSalt); + unsigned char dbHeader[KEYSALT_LENGTH]; + unsigned char* pDbHeader = (cipherSalt == NULL) ? mcReadDatabaseHeader(codec, dbHeader) : cipherSalt; + globalCodecDescriptorTable[codec->m_readCipherType-1].m_generateKey(codec->m_readCipher, userPassword, passwordLength, 0, pDbHeader); } SQLITE_PRIVATE void sqlite3mcGenerateWriteKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt) { - globalCodecDescriptorTable[codec->m_writeCipherType-1].m_generateKey(codec->m_writeCipher, codec->m_btShared, userPassword, passwordLength, 1, cipherSalt); + unsigned char dbHeader[KEYSALT_LENGTH]; + unsigned char* pDbHeader = (cipherSalt == NULL) ? mcReadDatabaseHeader(codec, dbHeader) : cipherSalt; + globalCodecDescriptorTable[codec->m_writeCipherType-1].m_generateKey(codec->m_writeCipher, userPassword, passwordLength, 1, pDbHeader); } SQLITE_PRIVATE int @@ -610,10 +651,10 @@ sqlite3mcConfigureSQLCipherVersion(sqlite3* db, int configDefault, int legacyVer static char* defNames[] = { "default:legacy_page_size", "default:kdf_iter", "default:hmac_use", "default:kdf_algorithm", "default:hmac_algorithm", NULL }; static int versionParams[SQLCIPHER_VERSION_MAX][5] = { - { 1024, 4000, 0, SQLCIPHER_KDF_ALGORITHM_SHA1, SQLCIPHER_HMAC_ALGORITHM_SHA1 }, - { 1024, 4000, 1, SQLCIPHER_KDF_ALGORITHM_SHA1, SQLCIPHER_HMAC_ALGORITHM_SHA1 }, - { 1024, 64000, 1, SQLCIPHER_KDF_ALGORITHM_SHA1, SQLCIPHER_HMAC_ALGORITHM_SHA1 }, - { 4096, 256000, 1, SQLCIPHER_KDF_ALGORITHM_SHA512, SQLCIPHER_HMAC_ALGORITHM_SHA512 } + { 1024, 4000, 0, SQLCIPHER_ALGORITHM_SHA1, SQLCIPHER_ALGORITHM_SHA1 }, + { 1024, 4000, 1, SQLCIPHER_ALGORITHM_SHA1, SQLCIPHER_ALGORITHM_SHA1 }, + { 1024, 64000, 1, SQLCIPHER_ALGORITHM_SHA1, SQLCIPHER_ALGORITHM_SHA1 }, + { 4096, 256000, 1, SQLCIPHER_ALGORITHM_SHA512, SQLCIPHER_ALGORITHM_SHA512 } }; if (legacyVersion > 0 && legacyVersion <= SQLCIPHER_VERSION_MAX) { diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_common.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_common.h index a1bae217c1..15bee4c5aa 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_common.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_common.h @@ -87,6 +87,7 @@ typedef struct _Codec unsigned char m_page[SQLITE_MAX_PAGE_SIZE + 24]; int m_pageSize; int m_reserved; + int m_lastError; int m_hasKeySalt; unsigned char m_keySalt[KEYSALT_LENGTH]; } Codec; @@ -158,6 +159,9 @@ SQLITE_PRIVATE int sqlite3mcGetReservedWriteCipher(Codec* codec); SQLITE_PRIVATE int sqlite3mcReservedEqual(Codec* codec); +SQLITE_PRIVATE void sqlite3mcSetCodecLastError(Codec* codec, int error); +SQLITE_PRIVATE int sqlite3mcGetCodecLastError(Codec* codec); + SQLITE_PRIVATE unsigned char* sqlite3mcGetSaltWriteCipher(Codec* codec); SQLITE_PRIVATE int sqlite3mcCodecCopy(Codec* codec, Codec* other); diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_config.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_config.c index 6937968d7b..2dd63f15c4 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_config.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_config.c @@ -3,7 +3,7 @@ ** Purpose: Configuration of SQLite codecs ** Author: Ulrich Telle ** Created: 2020-03-02 -** Copyright: (c) 2006-2023 Ulrich Telle +** Copyright: (c) 2006-2024 Ulrich Telle ** License: MIT */ @@ -188,6 +188,21 @@ sqlite3mc_cipher_name(int cipherIndex) return cipherName; } +static +int checkParameterValue(const char* paramName, int value) +{ + int ok = 1; + if (sqlite3_stricmp(paramName, "legacy_page_size") == 0 && value > 0) + { + ok = value >= 512 && value <= SQLITE_MAX_PAGE_SIZE && ((value - 1) & value) == 0; + } + if (ok && sqlite3_stricmp(paramName, "plaintext_header_size") == 0 && value > 0) + { + ok = value % 16 == 0; + } + return ok; +} + SQLITE_API int sqlite3mc_config_cipher(sqlite3* db, const char* cipherName, const char* paramName, int newValue) { @@ -294,7 +309,8 @@ sqlite3mc_config_cipher(sqlite3* db, const char* cipherName, const char* paramNa value = (hasDefaultPrefix) ? param->m_default : (hasMinPrefix) ? param->m_minValue : (hasMaxPrefix) ? param->m_maxValue : param->m_value; if (!hasMinPrefix && !hasMaxPrefix) { - if (newValue >= 0 && newValue >= param->m_minValue && newValue <= param->m_maxValue) + if (newValue >= 0 && newValue >= param->m_minValue && newValue <= param->m_maxValue && + checkParameterValue(paramName, newValue)) { if (hasDefaultPrefix) { @@ -772,11 +788,11 @@ sqlite3mcConfigureFromUri(sqlite3* db, const char *zDbName, int configDefault) if (value >= 0) { /* Configure cipher parameter if it was given in the URI */ - char* param = (configDefault) ? sqlite3_mprintf("default:%s", cipherParams[j].m_name) : cipherParams[j].m_name; + const char* param = (configDefault) ? sqlite3_mprintf("default:%s", cipherParams[j].m_name) : cipherParams[j].m_name; sqlite3mc_config_cipher(db, cipherName, param, value); if (configDefault) { - sqlite3_free(param); + sqlite3_free((char*) param); } } } diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_config.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_config.h index 5a57c70359..451b98ac54 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_config.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_config.h @@ -16,7 +16,7 @@ SQLITE_PRIVATE void sqlite3mcConfigTable(sqlite3_context* context, int argc, sql SQLITE_PRIVATE CodecParameter* sqlite3mcGetCodecParams(sqlite3* db); /* Forward declaration */ -static unsigned char* sqlite3mcGetSaltWriteCipher(Codec* codec); +SQLITE_PRIVATE unsigned char* sqlite3mcGetSaltWriteCipher(Codec* codec); SQLITE_PRIVATE void sqlite3mcCodecDataSql(sqlite3_context* context, int argc, sqlite3_value** argv); SQLITE_PRIVATE void sqlite3mcConfigParams(sqlite3_context* context, int argc, sqlite3_value** argv); diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_sds_rc4.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_sds_rc4.c index eda420f88c..2b940984b1 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_sds_rc4.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_sds_rc4.c @@ -3,7 +3,7 @@ ** Purpose: Implementation of cipher System.Data.SQLite3 RC4 ** Author: Ulrich Telle ** Created: 2020-02-02 -** Copyright: (c) 2006-2020 Ulrich Telle +** Copyright: (c) 2006-2024 Ulrich Telle ** License: MIT */ @@ -116,7 +116,7 @@ GetSaltRC4Cipher(void* cipher) } static void -GenerateKeyRC4Cipher(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) +GenerateKeyRC4Cipher(void* cipher, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) { RC4Cipher* rc4Cipher = (RC4Cipher*) cipher; unsigned char digest[SHA1_DIGEST_SIZE]; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_sqlcipher.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_sqlcipher.c index e97467ff24..f356fe0723 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_sqlcipher.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_sqlcipher.c @@ -3,7 +3,7 @@ ** Purpose: Implementation of cipher SQLCipher (version 1 to 4) ** Author: Ulrich Telle ** Created: 2020-02-02 -** Copyright: (c) 2006-2020 Ulrich Telle +** Copyright: (c) 2006-2024 Ulrich Telle ** License: MIT */ @@ -31,13 +31,11 @@ #define SQLCIPHER_HMAC_PGNO_NATIVE 0 #define SQLCIPHER_HMAC_SALT_MASK 0x3a -#define SQLCIPHER_KDF_ALGORITHM_SHA1 0 -#define SQLCIPHER_KDF_ALGORITHM_SHA256 1 -#define SQLCIPHER_KDF_ALGORITHM_SHA512 2 +#define SQLCIPHER_ALGORITHM_SHA1 0 +#define SQLCIPHER_ALGORITHM_SHA256 1 +#define SQLCIPHER_ALGORITHM_SHA512 2 -#define SQLCIPHER_HMAC_ALGORITHM_SHA1 0 -#define SQLCIPHER_HMAC_ALGORITHM_SHA256 1 -#define SQLCIPHER_HMAC_ALGORITHM_SHA512 2 +#define SQLCIPHER_HMAC_ALGO_COMPAT 1 #define SQLCIPHER_VERSION_1 1 #define SQLCIPHER_VERSION_2 2 @@ -58,13 +56,13 @@ #if SQLCIPHER_VERSION_DEFAULT < SQLCIPHER_VERSION_4 #define SQLCIPHER_KDF_ITER 64000 #define SQLCIPHER_LEGACY_PAGE_SIZE 1024 -#define SQLCIPHER_KDF_ALGORITHM SQLCIPHER_KDF_ALGORITHM_SHA1 -#define SQLCIPHER_HMAC_ALGORITHM SQLCIPHER_HMAC_ALGORITHM_SHA1 +#define SQLCIPHER_KDF_ALGORITHM SQLCIPHER_ALGORITHM_SHA1 +#define SQLCIPHER_HMAC_ALGORITHM SQLCIPHER_ALGORITHM_SHA1 #else #define SQLCIPHER_KDF_ITER 256000 #define SQLCIPHER_LEGACY_PAGE_SIZE 4096 -#define SQLCIPHER_KDF_ALGORITHM SQLCIPHER_KDF_ALGORITHM_SHA512 -#define SQLCIPHER_HMAC_ALGORITHM SQLCIPHER_HMAC_ALGORITHM_SHA512 +#define SQLCIPHER_KDF_ALGORITHM SQLCIPHER_ALGORITHM_SHA512 +#define SQLCIPHER_HMAC_ALGORITHM SQLCIPHER_ALGORITHM_SHA512 #endif SQLITE_PRIVATE CipherParams mcSQLCipherParams[] = @@ -78,6 +76,7 @@ SQLITE_PRIVATE CipherParams mcSQLCipherParams[] = { "hmac_salt_mask", SQLCIPHER_HMAC_SALT_MASK, SQLCIPHER_HMAC_SALT_MASK, 0x00, 0xff }, { "kdf_algorithm", SQLCIPHER_KDF_ALGORITHM, SQLCIPHER_KDF_ALGORITHM, 0, 2 }, { "hmac_algorithm", SQLCIPHER_HMAC_ALGORITHM, SQLCIPHER_HMAC_ALGORITHM, 0, 2 }, + { "hmac_algorithm_compat", SQLCIPHER_HMAC_ALGO_COMPAT, SQLCIPHER_HMAC_ALGO_COMPAT, 0, 1 }, { "plaintext_header_size", 0, 0, 0, 100 /* restrict to db header size */ }, CIPHER_PARAMS_SENTINEL }; @@ -98,6 +97,7 @@ typedef struct _sqlCipherCipher int m_hmacSaltMask; int m_kdfAlgorithm; int m_hmacAlgorithm; + int m_hmacAlgorithmCompat; int m_plaintextHeaderSize; int m_keyLength; uint8_t m_key[KEYLENGTH_SQLCIPHER]; @@ -139,6 +139,7 @@ AllocateSQLCipherCipher(sqlite3* db) sqlCipherCipher->m_hmacSaltMask = sqlite3mcGetCipherParameter(cipherParams, "hmac_salt_mask"); sqlCipherCipher->m_kdfAlgorithm = sqlite3mcGetCipherParameter(cipherParams, "kdf_algorithm"); sqlCipherCipher->m_hmacAlgorithm = sqlite3mcGetCipherParameter(cipherParams, "hmac_algorithm"); + sqlCipherCipher->m_hmacAlgorithmCompat = sqlite3mcGetCipherParameter(cipherParams, "hmac_algorithm_compat"); if (sqlCipherCipher->m_legacy >= SQLCIPHER_VERSION_4) { int plaintextHeaderSize = sqlite3mcGetCipherParameter(cipherParams, "plaintext_header_size"); @@ -176,6 +177,7 @@ CloneSQLCipherCipher(void* cipherTo, void* cipherFrom) sqlCipherCipherTo->m_hmacSaltMask = sqlCipherCipherFrom->m_hmacSaltMask; sqlCipherCipherTo->m_kdfAlgorithm = sqlCipherCipherFrom->m_kdfAlgorithm; sqlCipherCipherTo->m_hmacAlgorithm = sqlCipherCipherFrom->m_hmacAlgorithm; + sqlCipherCipherTo->m_hmacAlgorithmCompat = sqlCipherCipherFrom->m_hmacAlgorithmCompat; sqlCipherCipherTo->m_plaintextHeaderSize = sqlCipherCipherFrom->m_plaintextHeaderSize; sqlCipherCipherTo->m_keyLength = sqlCipherCipherFrom->m_keyLength; memcpy(sqlCipherCipherTo->m_key, sqlCipherCipherFrom->m_key, KEYLENGTH_SQLCIPHER); @@ -217,11 +219,11 @@ GetReservedSQLCipherCipher(void* cipher) { switch (sqlCipherCipher->m_hmacAlgorithm) { - case SQLCIPHER_HMAC_ALGORITHM_SHA1: - case SQLCIPHER_HMAC_ALGORITHM_SHA256: + case SQLCIPHER_ALGORITHM_SHA1: + case SQLCIPHER_ALGORITHM_SHA256: reserved += SHA256_DIGEST_SIZE; break; - case SQLCIPHER_HMAC_ALGORITHM_SHA512: + case SQLCIPHER_ALGORITHM_SHA512: default: reserved += SHA512_DIGEST_SIZE; break; @@ -238,18 +240,15 @@ GetSaltSQLCipherCipher(void* cipher) } static void -GenerateKeySQLCipherCipher(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) +GenerateKeySQLCipherCipher(void* cipher, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) { SQLCipherCipher* sqlCipherCipher = (SQLCipherCipher*) cipher; - Pager *pPager = pBt->pPager; - sqlite3_file* fd = (isOpen(pPager->fd)) ? pPager->fd : NULL; - - if (rekey || fd == NULL || sqlite3OsRead(fd, sqlCipherCipher->m_salt, SALTLENGTH_SQLCIPHER, 0) != SQLITE_OK) + if (rekey || cipherSalt == NULL) { chacha20_rng(sqlCipherCipher->m_salt, SALTLENGTH_SQLCIPHER); } - else if (cipherSalt != NULL) + else { memcpy(sqlCipherCipher->m_salt, cipherSalt, SALTLENGTH_SQLCIPHER); } @@ -271,19 +270,19 @@ GenerateKeySQLCipherCipher(void* cipher, BtShared* pBt, char* userPassword, int { switch (sqlCipherCipher->m_kdfAlgorithm) { - case SQLCIPHER_KDF_ALGORITHM_SHA1: + case SQLCIPHER_ALGORITHM_SHA1: fastpbkdf2_hmac_sha1((unsigned char*) userPassword, passwordLength, sqlCipherCipher->m_salt, SALTLENGTH_SQLCIPHER, sqlCipherCipher->m_kdfIter, sqlCipherCipher->m_key, KEYLENGTH_SQLCIPHER); break; - case SQLCIPHER_KDF_ALGORITHM_SHA256: + case SQLCIPHER_ALGORITHM_SHA256: fastpbkdf2_hmac_sha256((unsigned char*) userPassword, passwordLength, sqlCipherCipher->m_salt, SALTLENGTH_SQLCIPHER, sqlCipherCipher->m_kdfIter, sqlCipherCipher->m_key, KEYLENGTH_SQLCIPHER); break; - case SQLCIPHER_KDF_ALGORITHM_SHA512: + case SQLCIPHER_ALGORITHM_SHA512: default: fastpbkdf2_hmac_sha512((unsigned char*) userPassword, passwordLength, sqlCipherCipher->m_salt, SALTLENGTH_SQLCIPHER, @@ -296,6 +295,7 @@ GenerateKeySQLCipherCipher(void* cipher, BtShared* pBt, char* userPassword, int if (sqlCipherCipher->m_hmacUse != 0) { int j; + int algorithm = (sqlCipherCipher->m_hmacAlgorithmCompat) ? sqlCipherCipher->m_kdfAlgorithm : sqlCipherCipher->m_hmacAlgorithm; unsigned char hmacSaltMask = sqlCipherCipher->m_hmacSaltMask; unsigned char hmacSalt[SALTLENGTH_SQLCIPHER]; memcpy(hmacSalt, sqlCipherCipher->m_salt, SALTLENGTH_SQLCIPHER); @@ -303,21 +303,21 @@ GenerateKeySQLCipherCipher(void* cipher, BtShared* pBt, char* userPassword, int { hmacSalt[j] ^= hmacSaltMask; } - switch (sqlCipherCipher->m_hmacAlgorithm) + switch (algorithm) { - case SQLCIPHER_HMAC_ALGORITHM_SHA1: + case SQLCIPHER_ALGORITHM_SHA1: fastpbkdf2_hmac_sha1(sqlCipherCipher->m_key, KEYLENGTH_SQLCIPHER, hmacSalt, SALTLENGTH_SQLCIPHER, sqlCipherCipher->m_fastKdfIter, sqlCipherCipher->m_hmacKey, KEYLENGTH_SQLCIPHER); break; - case SQLCIPHER_HMAC_ALGORITHM_SHA256: + case SQLCIPHER_ALGORITHM_SHA256: fastpbkdf2_hmac_sha256(sqlCipherCipher->m_key, KEYLENGTH_SQLCIPHER, hmacSalt, SALTLENGTH_SQLCIPHER, sqlCipherCipher->m_fastKdfIter, sqlCipherCipher->m_hmacKey, KEYLENGTH_SQLCIPHER); break; - case SQLCIPHER_HMAC_ALGORITHM_SHA512: + case SQLCIPHER_ALGORITHM_SHA512: default: fastpbkdf2_hmac_sha512(sqlCipherCipher->m_key, KEYLENGTH_SQLCIPHER, hmacSalt, SALTLENGTH_SQLCIPHER, @@ -334,11 +334,13 @@ GetHmacSizeSQLCipherCipher(int algorithm) int hmacSize = SHA512_DIGEST_SIZE; switch (algorithm) { - case SQLCIPHER_HMAC_ALGORITHM_SHA1: + case SQLCIPHER_ALGORITHM_SHA1: hmacSize = SHA1_DIGEST_SIZE; break; - case SQLCIPHER_HMAC_ALGORITHM_SHA256: - case SQLCIPHER_HMAC_ALGORITHM_SHA512: + case SQLCIPHER_ALGORITHM_SHA256: + hmacSize = SHA256_DIGEST_SIZE; + break; + case SQLCIPHER_ALGORITHM_SHA512: default: hmacSize = SHA512_DIGEST_SIZE; break; @@ -356,7 +358,7 @@ EncryptPageSQLCipherCipher(void* cipher, int page, unsigned char* data, int len, int n = len - nReserved; int offset = (page == 1) ? (sqlCipherCipher->m_legacy != 0) ? 16 : 24 : 0; int blen; - unsigned char iv[64]; + unsigned char iv[128]; int usePlaintextHeader = 0; /* Check whether a plaintext header should be used */ @@ -373,10 +375,10 @@ EncryptPageSQLCipherCipher(void* cipher, int page, unsigned char* data, int len, } /* Generate nonce (64 bytes) */ - memset(iv, 0, 64); + memset(iv, 0, 128); if (nReserved > 0) { - chacha20_rng(iv, 64); + chacha20_rng(iv, 128); } else { diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_wxaes128.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_wxaes128.c index e84a88009f..67be9c21a7 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_wxaes128.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_wxaes128.c @@ -3,7 +3,7 @@ ** Purpose: Implementation of cipher wxSQLite3 AES 128-bit ** Author: Ulrich Telle ** Created: 2020-02-02 -** Copyright: (c) 2006-2020 Ulrich Telle +** Copyright: (c) 2006-2024 Ulrich Telle ** License: MIT */ @@ -130,7 +130,7 @@ GetSaltAES128Cipher(void* cipher) } static void -GenerateKeyAES128Cipher(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) +GenerateKeyAES128Cipher(void* cipher, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) { AES128Cipher* aesCipher = (AES128Cipher*) cipher; unsigned char userPad[32]; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_wxaes256.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_wxaes256.c index 906888a555..5fa8ba76b6 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_wxaes256.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/cipher_wxaes256.c @@ -3,7 +3,7 @@ ** Purpose: Implementation of cipher wxSQLite3 AES 256-bit ** Author: Ulrich Telle ** Created: 2020-02-02 -** Copyright: (c) 2006-2020 Ulrich Telle +** Copyright: (c) 2006-2024 Ulrich Telle ** License: MIT */ @@ -136,7 +136,7 @@ GetSaltAES256Cipher(void* cipher) } static void -GenerateKeyAES256Cipher(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) +GenerateKeyAES256Cipher(void* cipher, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt) { AES256Cipher* aesCipher = (AES256Cipher*) cipher; unsigned char userPad[32]; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codec_algos.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codec_algos.c index 7efa5db7c9..3c1951a2d5 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codec_algos.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codec_algos.c @@ -135,7 +135,7 @@ sqlite3mcAES128(Rijndael* aesCtx, int page, int encrypt, unsigned char encryptio { len = RijndaelBlockDecrypt(aesCtx, datain, datalen*8, dataout); } - + /* It is a good idea to check the error code */ if (len < 0) { @@ -189,7 +189,7 @@ sqlite3mcAES256(Rijndael* aesCtx, int page, int encrypt, unsigned char encryptio { len = RijndaelBlockDecrypt(aesCtx, datain, datalen*8, dataout); } - + /* It is a good idea to check the error code */ if (len < 0) { diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c index 6754109ebc..fca5b11000 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c @@ -65,7 +65,7 @@ sqlite3_activate_see(const char *info) /* ** Free the encryption data structure associated with a pager instance. -** (called from the modified code in pager.c) +** (called from the modified code in pager.c) */ SQLITE_PRIVATE void sqlite3mcCodecFree(void *pCodecArg) @@ -95,12 +95,15 @@ mcReportCodecError(BtShared* pBt, int error) { pBt->pPager->eState = PAGER_ERROR; } - setGetterMethod(pBt->pPager); if (error == SQLITE_OK) { /* Clear cache to force reread of database after a new passphrase has been set */ sqlite3PagerClearCache(pBt->pPager); + /* unlock required? + pager_unlock(pBt->pPager); + */ } + setGetterMethod(pBt->pPager); } /* @@ -119,6 +122,7 @@ sqlite3mcCodec(void* pCodecArg, void* data, Pgno nPageNum, int nMode) codec = (Codec*) pCodecArg; if (!sqlite3mcIsEncrypted(codec)) { + sqlite3mcSetCodecLastError(codec, rc); return data; } @@ -132,7 +136,11 @@ sqlite3mcCodec(void* pCodecArg, void* data, Pgno nPageNum, int nMode) if (sqlite3mcHasReadCipher(codec)) { rc = sqlite3mcDecrypt(codec, nPageNum, (unsigned char*) data, pageSize); - if (rc != SQLITE_OK) mcReportCodecError(sqlite3mcGetBtShared(codec), rc); + if (rc != SQLITE_OK) + { + mcReportCodecError(sqlite3mcGetBtShared(codec), rc); + memset(data, 0, pageSize); + } } break; @@ -166,6 +174,7 @@ sqlite3mcCodec(void* pCodecArg, void* data, Pgno nPageNum, int nMode) } break; } + sqlite3mcSetCodecLastError(codec, rc); return data; } @@ -175,6 +184,9 @@ sqlite3mcGetMainCodec(sqlite3* db); SQLITE_PRIVATE void sqlite3mcSetCodec(sqlite3* db, const char* zDbName, const char* zFileName, Codec* codec); +SQLITE_PRIVATE int +sqlite3mcIsEncryptionSupported(sqlite3* db, const char* zDbName); + static int mcAdjustBtree(Btree* pBt, int nPageSize, int nReserved, int isLegacy) { @@ -190,11 +202,12 @@ mcAdjustBtree(Btree* pBt, int nPageSize, int nReserved, int isLegacy) /* Adjust the page size and the reserved area */ if (pager->pageSize != pagesize || pager->nReserve != nReserved) { + int reserved = (nReserved >= 0) ? nReserved : 0; if (isLegacy != 0) { pBt->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; } - rc = sqlite3BtreeSetPageSize(pBt, pagesize, nReserved, 0); + rc = sqlite3BtreeSetPageSize(pBt, pagesize, reserved, 0); } return rc; } @@ -332,6 +345,11 @@ SQLITE_API int sqlite3_key_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) { int rc = SQLITE_ERROR; + if (!sqlite3mcIsEncryptionSupported(db, zDbName)) + { + sqlite3ErrorWithMsg(db, rc, "Setting key failed. Encryption is not supported by the VFS."); + return rc; + } if (zKey != NULL && nKey < 0) { /* Key is zero-terminated string */ @@ -384,7 +402,15 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) int nReserved; Pager* pPager; Codec* codec; + int codecAllocated = 0; int rc = SQLITE_ERROR; + char* err = NULL; + + if (!sqlite3mcIsEncryptionSupported(db, zDbName)) + { + sqlite3ErrorWithMsg(db, rc, "Rekeying failed. Encryption is not supported by the VFS."); + return rc; + } if (zKey != NULL && nKey < 0) { /* Key is zero-terminated string */ @@ -417,10 +443,10 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) sqlite3ErrorWithMsg(db, rc, "Rekeying is not supported in WAL journal mode."); return rc; } - + if ((zKey == NULL || nKey == 0) && (codec == NULL || !sqlite3mcIsEncrypted(codec))) { - /* Database not encrypted and key not specified, therefore do nothing */ + /* Database not encrypted and key not specified, therefore do nothing */ return SQLITE_OK; } @@ -428,9 +454,10 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) if (codec == NULL || !sqlite3mcIsEncrypted(codec)) { - /* Database not encrypted, but key specified, therefore encrypt database */ + /* Database not encrypted, but key specified, therefore encrypt database */ if (codec == NULL) { + codecAllocated = 1; codec = (Codec*) sqlite3_malloc(sizeof(Codec)); rc = (codec != NULL) ? sqlite3mcCodecInit(codec) : SQLITE_NOMEM; } @@ -454,14 +481,9 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) if (nReserved != nReservedWriteCipher) { /* Use VACUUM to change the number of reserved bytes */ - char* err = NULL; sqlite3mcSetReadReserved(codec, nReserved); sqlite3mcSetWriteReserved(codec, nReservedWriteCipher); rc = sqlite3mcRunVacuumForRekey(&err, db, dbIndex, NULL, nReservedWriteCipher); - if (rc != SQLITE_OK && err != NULL) - { - sqlite3ErrorWithMsg(db, rc, err); - } goto leave_rekey; } } @@ -469,12 +491,17 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) { /* Pagesize cannot be changed for an encrypted database */ rc = SQLITE_ERROR; - sqlite3ErrorWithMsg(db, rc, "Rekeying failed. Pagesize cannot be changed for an encrypted database."); + err = "Rekeying failed. Pagesize cannot be changed for an encrypted database."; goto leave_rekey; } } else { + sqlite3_mutex_leave(db->mutex); + if (codecAllocated) + { + sqlite3mcCodecFree(codec); + } return rc; } } @@ -490,10 +517,6 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) sqlite3mcSetReadReserved(codec, nReserved); sqlite3mcSetWriteReserved(codec, 0); rc = sqlite3mcRunVacuumForRekey(&err, db, dbIndex, NULL, 0); - if (rc != SQLITE_OK && err != NULL) - { - sqlite3ErrorWithMsg(db, rc, err); - } goto leave_rekey; } } @@ -515,10 +538,6 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) sqlite3mcSetReadReserved(codec, nReserved); sqlite3mcSetWriteReserved(codec, nReservedWriteCipher); rc = sqlite3mcRunVacuumForRekey(&err, db, dbIndex, NULL, nReservedWriteCipher); - if (rc != SQLITE_OK && err != NULL) - { - sqlite3ErrorWithMsg(db, rc, err); - } goto leave_rekey; } } @@ -526,14 +545,14 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) { /* Pagesize cannot be changed for an encrypted database */ rc = SQLITE_ERROR; - sqlite3ErrorWithMsg(db, rc, "Rekeying failed. Pagesize cannot be changed for an encrypted database."); + err = "Rekeying failed. Pagesize cannot be changed for an encrypted database."; goto leave_rekey; } } else { /* Setup of write cipher failed */ - sqlite3ErrorWithMsg(db, rc, "Rekeying failed. Setup of write cipher failed."); + err = "Rekeying failed. Setup of write cipher failed."; goto leave_rekey; } } @@ -584,8 +603,15 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) /* Set read key equal to write key if necessary */ if (sqlite3mcHasWriteCipher(codec)) { + /* Set Read cipher equal to Write cipher */ sqlite3mcCopyCipher(codec, 0); sqlite3mcSetHasReadCipher(codec, 1); + + /* Enforce page size and number of reserved bytes per page */ + int pageSize = sqlite3mcGetPageSizeWriteCipher(codec); + int reserved = sqlite3mcGetReservedWriteCipher(codec); + mcAdjustBtree(pBt, pageSize, reserved, sqlite3mcGetLegacyWriteCipher(codec)); + sqlite3mcCodecSizeChange(codec, pageSize, reserved); } else { @@ -615,6 +641,10 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey) /* Remove codec for unencrypted database */ sqlite3mcSetCodec(db, zDbName, dbFileName, NULL); } + if (rc != SQLITE_OK && err != NULL) + { + sqlite3ErrorWithMsg(db, rc, err); + } return rc; } diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/compress.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/compress.c index e6534e8a23..302fc7cfbb 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/compress.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/compress.c @@ -112,14 +112,14 @@ static void uncompressFunc( __declspec(dllexport) #endif int sqlite3_compress_init( - sqlite3 *db, - char **pzErrMsg, + sqlite3 *db, + char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused parameter */ - rc = sqlite3_create_function(db, "compress", 1, + rc = sqlite3_create_function(db, "compress", 1, SQLITE_UTF8 | SQLITE_INNOCUOUS, 0, compressFunc, 0, 0); if( rc==SQLITE_OK ){ diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/csv.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/csv.c index f980dfb028..7e54385167 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/csv.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/csv.c @@ -170,7 +170,7 @@ static int csv_getc(CsvReader *p){ return ((unsigned char*)p->zIn)[p->iIn++]; } -/* Increase the size of p->z and append character c to the end. +/* Increase the size of p->z and append character c to the end. ** Return 0 on success and non-zero if there is an OOM error */ static CSV_NOINLINE int csv_resize_and_append(CsvReader *p, char c){ char *zNew; @@ -289,9 +289,9 @@ static char *csv_read_one_field(CsvReader *p){ /* Forward references to the various virtual table methods implemented ** in this file. */ -static int csvtabCreate(sqlite3*, void*, int, const char*const*, +static int csvtabCreate(sqlite3*, void*, int, const char*const*, sqlite3_vtab**,char**); -static int csvtabConnect(sqlite3*, void*, int, const char*const*, +static int csvtabConnect(sqlite3*, void*, int, const char*const*, sqlite3_vtab**,char**); static int csvtabBestIndex(sqlite3_vtab*,sqlite3_index_info*); static int csvtabDisconnect(sqlite3_vtab*); @@ -476,7 +476,7 @@ static int csv_boolean_parameter( ** columns=N Assume the CSV file contains N columns. ** ** Only available if compiled with SQLITE_TEST: -** +** ** testflags=N Bitmask of test flags. Optional ** ** If schema= is omitted, then the columns are named "c0", "c1", "c2", @@ -503,7 +503,7 @@ static int csvtabConnect( CsvReader sRdr; /* A CSV file reader used to store an error ** message and/or to count the number of columns */ static const char *azParam[] = { - "filename", "data", "schema", + "filename", "data", "schema", }; char *azPValue[3]; /* Parameter values */ # define CSV_FILENAME (azPValue[0]) @@ -805,7 +805,7 @@ static int csvtabEof(sqlite3_vtab_cursor *cur){ ** the beginning. */ static int csvtabFilter( - sqlite3_vtab_cursor *pVtabCursor, + sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ @@ -861,7 +861,7 @@ static int csvtabBestIndex( unsigned char op; if( pIdxInfo->aConstraint[i].usable==0 ) continue; op = pIdxInfo->aConstraint[i].op; - if( op==SQLITE_INDEX_CONSTRAINT_EQ + if( op==SQLITE_INDEX_CONSTRAINT_EQ || op==SQLITE_INDEX_CONSTRAINT_LIKE || op==SQLITE_INDEX_CONSTRAINT_GLOB ){ @@ -948,14 +948,14 @@ static sqlite3_module CsvModuleFauxWrite = { #ifdef _WIN32 __declspec(dllexport) #endif -/* +/* ** This routine is called when the extension is loaded. The new ** CSV virtual table module is registered with the calling database ** connection. */ int sqlite3_csv_init( - sqlite3 *db, - char **pzErrMsg, + sqlite3 *db, + char **pzErrMsg, const sqlite3_api_routines *pApi ){ #ifndef SQLITE_OMIT_VIRTUALTABLE diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/extensionfunctions.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/extensionfunctions.c index 5dcaa10cdf..2e38d54f60 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/extensionfunctions.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/extensionfunctions.c @@ -54,7 +54,7 @@ Usage instructions for the sqlite3 program: security measure; see "Security Considerations" in http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions. If the sqlite3 program and library are built this - way, you cannot use these functions from the program, you + way, you cannot use these functions from the program, you must write your own program using the sqlite3 API, and call sqlite3_enable_load_extension as described above, or else rebuilt the sqlite3 program to allow loadable extensions. @@ -125,7 +125,7 @@ Original code 2006 June 05 by relicoder. #define HAVE_ISBLANK 1 #endif #define SQLITE_SOUNDEX 1 -#define HAVE_TRIM 1 /* LMH 2007-03-25 if sqlite has trim functions */ +#define HAVE_TRIM 1 /* LMH 2007-03-25 if sqlite has trim functions */ #ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE #include "sqlite3ext.h" @@ -139,7 +139,7 @@ SQLITE_EXTENSION_INIT1 #include #include #include -#include /* LMH 2007-03-25 */ +#include /* LMH 2007-03-25 */ #include #include @@ -319,7 +319,7 @@ static int sqlite3ReadUtf8(const unsigned char *z){ ** pZ is a UTF-8 encoded unicode string. If nByte is less than zero, ** return the number of unicode characters in pZ up to (but not including) ** the first 0x00 byte. If nByte is not less than zero, return the -** number of unicode characters in the first nByte of pZ (or up to +** number of unicode characters in the first nByte of pZ (or up to ** the first 0x00, whichever comes first). */ static int sqlite3Utf8CharLen(const char *z, int nByte){ @@ -354,7 +354,7 @@ static int sqlite3Utf8CharLen(const char *z, int nByte){ ** ** Could have been implemented using pointers to functions but this way it's inline ** and thus more efficient. Lower * ranking though... -** +** ** Parameters: ** name: function name to de defined (eg: sinFunc) ** function: function defined in math.h to wrap (eg: sin) @@ -400,7 +400,7 @@ GEN_MATH_WRAP_DOUBLE_1(atanFunc, atan) /* ** Many of systems don't have inverse hyperbolic trig functions so this will emulate -** them on those systems in terms of log and sqrt (formulas are too trivial to demand +** them on those systems in terms of log and sqrt (formulas are too trivial to demand ** written proof here) */ @@ -572,7 +572,7 @@ static void squareFunc(sqlite3_context *context, int argc, sqlite3_value **argv) ** (see sqrt just before this). Here the result is always double */ /* LMH 2007-03-25 Changed to use errno; no pre-checking for errors. Also removes - but that was present in the pre-checking that called sqlite3_result_error on + but that was present in the pre-checking that called sqlite3_result_error on a non-positive first argument, which is not always an error. */ static void powerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ double r1 = 0.0; @@ -580,9 +580,9 @@ static void powerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ double val; assert( argc==2 ); - + if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){ - sqlite3_result_null(context); + sqlite3_result_null(context); }else{ r1 = sqlite3_value_double(argv[0]); r2 = sqlite3_value_double(argv[1]); @@ -590,9 +590,9 @@ static void powerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ val = pow(r1,r2); if (errno == 0) { sqlite3_result_double(context, val); - } else { + } else { sqlite3_result_error(context, strerror(errno), errno); - } + } } } @@ -606,9 +606,9 @@ static void atn2Func(sqlite3_context *context, int argc, sqlite3_value **argv){ double r2 = 0.0; assert( argc==2 ); - + if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){ - sqlite3_result_null(context); + sqlite3_result_null(context); }else{ r1 = sqlite3_value_double(argv[0]); r2 = sqlite3_value_double(argv[1]); @@ -705,14 +705,14 @@ static void floorFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ #endif /* SQLITE_ENABLE_MATH_FUNCTIONS */ /* -** Given a string (s) in the first argument and an integer (n) in the second returns the +** Given a string (s) in the first argument and an integer (n) in the second returns the ** string that constains s contatenated n times */ static void replicateFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ unsigned char *z; /* input string */ unsigned char *zo; /* result string */ i64 iCount; /* times to repeat */ - i64 nLen; /* length of the input string (no multibyte considerations) */ + i64 nLen; /* length of the input string (no multibyte considerations) */ i64 nTLen; /* length of the result string (no multibyte considerations) */ i64 i=0; @@ -747,7 +747,7 @@ static void replicateFunc(sqlite3_context *context, int argc, sqlite3_value **ar } } -/* +/* ** Some systems (win32 among others) don't have an isblank function, this will emulate it. ** This function is not UFT-8 safe since it only analyses a byte character. */ @@ -812,9 +812,9 @@ static void padlFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ char *zt; assert( argc==2 ); - + if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ - sqlite3_result_null(context); + sqlite3_result_null(context); }else{ zi = (char *)sqlite3_value_text(argv[0]); ilen = sqlite3_value_int64(argv[1]); @@ -866,9 +866,9 @@ static void padrFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ char *zt; assert( argc==2 ); - + if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ - sqlite3_result_null(context); + sqlite3_result_null(context); }else{ zi = (char *)sqlite3_value_text(argv[0]); ilen = sqlite3_value_int64(argv[1]); @@ -921,9 +921,9 @@ static void padcFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ char *zt; assert( argc==2 ); - + if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ - sqlite3_result_null(context); + sqlite3_result_null(context); }else{ zi = (char *)sqlite3_value_text(argv[0]); ilen = sqlite3_value_int64(argv[1]); @@ -980,17 +980,17 @@ static void strfilterFunc(sqlite3_context *context, int argc, sqlite3_value **ar int c2 = 0; assert( argc==2 ); - + if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){ - sqlite3_result_null(context); + sqlite3_result_null(context); }else{ zi1 = (char *)sqlite3_value_text(argv[0]); zi2 = (char *)sqlite3_value_text(argv[1]); - /* - ** maybe I could allocate less, but that would imply 2 passes, rather waste + /* + ** maybe I could allocate less, but that would imply 2 passes, rather waste ** (possibly) some memory */ - zo = sqlite3_malloc((int) (strlen(zi1)+1)); + zo = sqlite3_malloc((int) (strlen(zi1)+1)); if (!zo){ sqlite3_result_error_nomem(context); return; @@ -1034,11 +1034,11 @@ static int _substr(const char* z1, const char* z2, int s, const char** p){ if( '\0'==*z1 ){ return -1; } - + while( (sqliteCharVal((unsigned char *)z2) != 0) && (c++) 0 ){ sqliteNextChar(zt); } @@ -1186,7 +1186,7 @@ static void rightFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ return; } strcpy((char*) rz, (char*) (zt)); - sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT); + sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT); sqlite3_free(rz); } @@ -1224,7 +1224,7 @@ static void ltrimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ return; } z = sqlite3_value_text(argv[0]); - sqlite3_result_text(context, ltrim(z), -1, SQLITE_TRANSIENT); + sqlite3_result_text(context, ltrim(z), -1, SQLITE_TRANSIENT); } /* @@ -1465,7 +1465,7 @@ static void modeStep(sqlite3_context *context, int argc, sqlite3_value **argv){ if( type == SQLITE_NULL) return; - + p = sqlite3_aggregate_context(context, sizeof(*p)); if( 0==(p->m) ){ @@ -1504,33 +1504,33 @@ static void modeIterate(void* e, i64 c, void* pp){ i64 ei; double ed; ModeCtx *p = (ModeCtx*)pp; - + if( 0==p->is_double ){ ei = *(int*)(e); - if( p->mcnt==c ){ + if( p->mcnt==c ){ ++p->mn; }else if( p->mcntriM = ei; p->mcnt = c; - p->mn=1; + p->mn=1; } }else{ ed = *(double*)(e); - if( p->mcnt==c ){ + if( p->mcnt==c ){ ++p->mn; }else if(p->mcntrdM = ed; p->mcnt = c; - p->mn=1; + p->mn=1; } } } /* ** Auxiliary function that iterates all elements in a map and finds the median -** (the value such that the number of elements smaller is equal the the number of +** (the value such that the number of elements smaller is equal the the number of ** elements larger) */ static void medianIterate(void* e, i64 c, void* pp){ @@ -1601,9 +1601,9 @@ static void _medianFinalize(sqlite3_context *context){ if( 0==p->is_double ) if( 1==p->mn ) - sqlite3_result_int64(context, p->riM); + sqlite3_result_int64(context, p->riM); else - sqlite3_result_double(context, p->riM*1.0/p->mn); + sqlite3_result_double(context, p->riM*1.0/p->mn); else sqlite3_result_double(context, p->rdM/p->mn); } @@ -1723,12 +1723,12 @@ static void differenceFunc(sqlite3_context *context, int argc, sqlite3_value **a const u8 *zIn2; assert( argc==2 ); - + if( sqlite3_value_type(argv[0])==SQLITE_NULL || sqlite3_value_type(argv[1])==SQLITE_NULL ){ sqlite3_result_null(context); return; } - + zIn1 = (u8*)sqlite3_value_text(argv[0]); zIn2 = (u8*)sqlite3_value_text(argv[1]); @@ -1865,7 +1865,7 @@ int RegisterExtensionFunctions(sqlite3 *db){ aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0); #if 0 if( aFuncs[i].needCollSeq ){ - struct FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName, + struct FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName, strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0); if( pFunc && aFuncs[i].needCollSeq ){ pFunc->needCollSeq = 1; @@ -1882,7 +1882,7 @@ int RegisterExtensionFunctions(sqlite3 *db){ } /* sqlite3CreateFunc */ /* LMH no error checking */ - sqlite3_create_function(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8, + sqlite3_create_function(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8, pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize); #if 0 if( aAggs[i].needCollSeq ){ diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fastpbkdf2.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fastpbkdf2.c index a190f7616a..7ed8e16b80 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fastpbkdf2.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fastpbkdf2.c @@ -391,6 +391,7 @@ DECL_PBKDF2(sha512, sha512_extract, sha512_xor) +SQLITE_PRIVATE void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw, const uint8_t *salt, size_t nsalt, uint32_t iterations, @@ -402,6 +403,7 @@ void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw, #endif } +SQLITE_PRIVATE void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw, const uint8_t *salt, size_t nsalt, uint32_t iterations, @@ -410,6 +412,7 @@ void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw, PBKDF2(sha256)(pw, npw, salt, nsalt, iterations, out, nout); } +SQLITE_PRIVATE void fastpbkdf2_hmac_sha512(const uint8_t *pw, size_t npw, const uint8_t *salt, size_t nsalt, uint32_t iterations, @@ -418,6 +421,7 @@ void fastpbkdf2_hmac_sha512(const uint8_t *pw, size_t npw, PBKDF2(sha512)(pw, npw, salt, nsalt, iterations, out, nout); } +SQLITE_PRIVATE void sqlcipher_hmac(int algorithm, unsigned char* key, int nkey, unsigned char* in, int in_sz, unsigned char* in2, int in2_sz, unsigned char* out) { switch (algorithm) diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fastpbkdf2.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fastpbkdf2.h index 75f7e2c742..d523314576 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fastpbkdf2.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fastpbkdf2.h @@ -15,6 +15,10 @@ #ifndef FASTPBKDF2_H #define FASTPBKDF2_H +#ifndef SQLITE_PRIVATE +#define SQLITE_PRIVATE +#endif + #include #include "mystdint.h" @@ -31,6 +35,7 @@ extern "C" { * * This function cannot fail; it does not report errors. */ +SQLITE_PRIVATE void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw, const uint8_t *salt, size_t nsalt, uint32_t iterations, @@ -45,6 +50,7 @@ void fastpbkdf2_hmac_sha1(const uint8_t *pw, size_t npw, * * This function cannot fail; it does not report errors. */ +SQLITE_PRIVATE void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw, const uint8_t *salt, size_t nsalt, uint32_t iterations, @@ -59,6 +65,7 @@ void fastpbkdf2_hmac_sha256(const uint8_t *pw, size_t npw, * * This function cannot fail; it does not report errors. */ +SQLITE_PRIVATE void fastpbkdf2_hmac_sha512(const uint8_t *pw, size_t npw, const uint8_t *salt, size_t nsalt, uint32_t iterations, @@ -68,6 +75,7 @@ void fastpbkdf2_hmac_sha512(const uint8_t *pw, size_t npw, * * This function cannot fail; it does not report errors. */ +SQLITE_PRIVATE void sqlcipher_hmac(int algorithm, unsigned char* key, int nkey, unsigned char* in, int in_sz, diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fileio.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fileio.c index ca8090ed2e..4cc4b9f6e1 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fileio.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/fileio.c @@ -40,7 +40,7 @@ ** modification-time of the target file is set to this value before ** returning. ** -** If three or more arguments are passed to this function and an +** If five or more arguments are passed to this function and an ** error is encountered, an exception is raised. ** ** READFILE(FILE): @@ -69,8 +69,8 @@ ** directory, NULL. ** ** If a non-NULL value is specified for the optional $dir parameter and -** $path is a relative path, then $path is interpreted relative to $dir. -** And the paths returned in the "name" column of the table are also +** $path is a relative path, then $path is interpreted relative to $dir. +** And the paths returned in the "name" column of the table are also ** relative to directory $dir. ** ** Notes on building this extension for Windows: @@ -110,6 +110,13 @@ SQLITE_EXTENSION_INIT1 #include #include +/* When used as part of the CLI, the sqlite3_stdio.h module will have +** been included before this one. In that case use the sqlite3_stdio.h +** #defines. If not, create our own for fopen(). +*/ +#ifndef _SQLITE3_STDIO_H_ +# define sqlite3_fopen fopen +#endif /* ** Structure of the fsdir() table-valued function @@ -125,7 +132,7 @@ SQLITE_EXTENSION_INIT1 /* -** Set the result stored by context ctx to a blob containing the +** Set the result stored by context ctx to a blob containing the ** contents of file zName. Or, leave the result unchanged (NULL) ** if the file does not exist or is unreadable. ** @@ -142,7 +149,7 @@ static void readFileContents(sqlite3_context *ctx, const char *zName){ sqlite3 *db; int mxBlob; - in = fopen(zName, "rb"); + in = sqlite3_fopen(zName, "rb"); if( in==0 ){ /* File does not exist or is unreadable. Leave the result set to NULL. */ return; @@ -358,7 +365,7 @@ static int makeDirectory( } /* -** This function does the work for the writefile() UDF. Refer to +** This function does the work for the writefile() UDF. Refer to ** header comments at the top of this file for details. */ static int writeFile( @@ -397,7 +404,7 @@ static int writeFile( sqlite3_int64 nWrite = 0; const char *z; int rc = 0; - FILE *out = fopen(zFile, "wb"); + FILE *out = sqlite3_fopen(zFile, "wb"); if( out==0 ) return 1; z = (const char*)sqlite3_value_blob(pData); if( z ){ @@ -460,10 +467,10 @@ static int writeFile( return 1; } #else - /* Legacy unix. + /* Legacy unix. ** ** Do not use utimes() on a symbolic link - it sees through the link and - ** modifies the timestamps on the target. Or fails if the target does + ** modifies the timestamps on the target. Or fails if the target does ** not exist. */ if( 0==S_ISLNK(mode) ){ struct timeval times[2]; @@ -481,7 +488,7 @@ static int writeFile( } /* -** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function. +** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function. ** Refer to header comments at the top of this file for details. */ static void writefileFunc( @@ -495,7 +502,7 @@ static void writefileFunc( sqlite3_int64 mtime = -1; if( argc<2 || argc>4 ){ - sqlite3_result_error(context, + sqlite3_result_error(context, "wrong number of arguments to function writefile()", -1 ); return; @@ -565,7 +572,7 @@ static void lsModeFunc( #ifndef SQLITE_OMIT_VIRTUALTABLE -/* +/* ** Cursor type for recursively iterating through a directory structure. */ typedef struct fsdir_cursor fsdir_cursor; @@ -713,7 +720,7 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){ } pCur->iLvl = iNew; pLvl = &pCur->aLvl[iNew]; - + pLvl->zDir = pCur->zPath; pCur->zPath = 0; pLvl->pDir = opendir(pLvl->zDir); @@ -844,7 +851,7 @@ static int fsdirEof(sqlite3_vtab_cursor *cur){ ** idxNum==2 Both PATH and DIR supplied */ static int fsdirFilter( - sqlite3_vtab_cursor *cur, + sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ @@ -933,7 +940,7 @@ static int fsdirBestIndex( } break; } - } + } } if( seenPath || seenDir ){ /* If input parameters are unusable, disallow this plan */ @@ -1005,14 +1012,14 @@ static int fsdirRegister(sqlite3 *db){ __declspec(dllexport) #endif int sqlite3_fileio_init( - sqlite3 *db, - char **pzErrMsg, + sqlite3 *db, + char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused parameter */ - rc = sqlite3_create_function(db, "readfile", 1, + rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8|SQLITE_DIRECTONLY, 0, readfileFunc, 0, 0); if( rc==SQLITE_OK ){ diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/md5.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/md5.c index 2c7c6a1345..42e9b330a8 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/md5.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/md5.c @@ -60,19 +60,19 @@ static void MD5_Final(unsigned char *result, MD5_CTX *ctx); * architectures that lack an AND-NOT instruction, just like in Colin Plumb's * implementation. */ -#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) -#define H(x, y, z) (((x) ^ (y)) ^ (z)) -#define H2(x, y, z) ((x) ^ ((y) ^ (z))) -#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) (((x) ^ (y)) ^ (z)) +#define H2(x, y, z) ((x) ^ ((y) ^ (z))) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) /* * The MD5 transformation for all four rounds. */ #define STEP(f, a, b, c, d, x, t, s) \ - (a) += f((b), (c), (d)) + (x) + (t); \ - (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ - (a) += (b); + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); /* * SET reads 4 input bytes in little-endian byte order and stores them @@ -84,18 +84,18 @@ static void MD5_Final(unsigned char *result, MD5_CTX *ctx); */ #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) #define SET(n) \ - (*(MD5_u32plus *)&ptr[(n) * 4]) + (*(MD5_u32plus *)&ptr[(n) * 4]) #define GET(n) \ - SET(n) + SET(n) #else #define SET(n) \ - (ctx->block[(n)] = \ - (MD5_u32plus)ptr[(n) * 4] | \ - ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ - ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ - ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) + (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) #define GET(n) \ - (ctx->block[(n)]) + (ctx->block[(n)]) #endif /* diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/memory_secure.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/memory_secure.c index 171e2c645a..ee82bcafdb 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/memory_secure.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/memory_secure.c @@ -44,38 +44,6 @@ static volatile int mcSecureMemoryFlag = 0; /* Map of default memory allocation methods */ static volatile sqlite3_mem_methods mcDefaultMemoryMethods; -#if SQLITE3MC_ENABLE_RANDOM_FILL_MEMORY - -/* -** Fill a buffer with pseudo-random bytes. This is used to preset -** the content of a new memory allocation to unpredictable values and -** to clear the content of a freed allocation to unpredictable values. -*/ -static void mcRandomFill(char* pBuf, int nByte) -{ - unsigned int x, y, r; - x = SQLITE_PTR_TO_INT(pBuf); - y = nByte | 1; - while( nByte >= 4 ) - { - x = (x>>1) ^ (-(int)(x&1) & 0xd0000001); - y = y*1103515245 + 12345; - r = x ^ y; - *(int*)pBuf = r; - pBuf += 4; - nByte -= 4; - } - while( nByte-- > 0 ) - { - x = (x>>1) ^ (-(int)(x&1) & 0xd0000001); - y = y*1103515245 + 12345; - r = x ^ y; - *(pBuf++) = r & 0xff; - } -} - -#endif - /* ** Return the size of an allocation */ @@ -99,13 +67,8 @@ static void mcMemoryFree(void* pPrior) { if (mcSecureMemoryFlag) { -#if SQLITE3MC_USE_RANDOM_FILL_MEMORY - int nSize = mcMemorySize(pPrior); - mcRandomFill((char*) pPrior, nSize) -#else int nSize = mcMemorySize(pPrior); sqlite3mcSecureZeroMemory(pPrior, 0, nSize); -#endif } mcDefaultMemoryMethods.xFree(pPrior); } diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/miniz.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/miniz.c index 87bdedb188..b46bc7677e 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/miniz.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/miniz.c @@ -1379,15 +1379,15 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush) #ifdef MINIZ_UNALIGNED_USE_MEMCPY static mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p) { - mz_uint16 ret; - memcpy(&ret, p, sizeof(mz_uint16)); - return ret; + mz_uint16 ret; + memcpy(&ret, p, sizeof(mz_uint16)); + return ret; } static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p) { - mz_uint16 ret; - memcpy(&ret, p, sizeof(mz_uint16)); - return ret; + mz_uint16 ret; + memcpy(&ret, p, sizeof(mz_uint16)); + return ret; } #else #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p) @@ -1495,9 +1495,9 @@ static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahe #ifdef MINIZ_UNALIGNED_USE_MEMCPY static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(const mz_uint8* p) { - mz_uint32 ret; - memcpy(&ret, p, sizeof(mz_uint32)); - return ret; + mz_uint32 ret; + memcpy(&ret, p, sizeof(mz_uint32)); + return ret; } #else #define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p) @@ -1572,7 +1572,7 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); #ifdef MINIZ_UNALIGNED_USE_MEMCPY - memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist)); + memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist)); #else *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; #endif @@ -2741,7 +2741,7 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex do { #ifdef MINIZ_UNALIGNED_USE_MEMCPY - memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2); + memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2); #else ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; @@ -2768,7 +2768,7 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex pOut_buf_cur[2] = pSrc[2]; pOut_buf_cur += 3; pSrc += 3; - counter -= 3; + counter -= 3; } if (counter > 0) { @@ -3706,47 +3706,47 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag if (extra_size_remaining) { - const mz_uint8 *pExtra_data; - void* buf = NULL; - - if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n) - { - buf = MZ_MALLOC(ext_data_size); - if(buf==NULL) - return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); - - if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size, buf, ext_data_size) != ext_data_size) - { - MZ_FREE(buf); - return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); - } - - pExtra_data = (mz_uint8*)buf; - } - else - { - pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size; - } + const mz_uint8 *pExtra_data; + void* buf = NULL; + + if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n) + { + buf = MZ_MALLOC(ext_data_size); + if(buf==NULL) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size, buf, ext_data_size) != ext_data_size) + { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + + pExtra_data = (mz_uint8*)buf; + } + else + { + pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size; + } do { mz_uint32 field_id; mz_uint32 field_data_size; - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) - { - MZ_FREE(buf); - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - } + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } field_id = MZ_READ_LE16(pExtra_data); field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); - if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) - { - MZ_FREE(buf); - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); - } + if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) + { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { @@ -3760,7 +3760,7 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; } while (extra_size_remaining); - MZ_FREE(buf); + MZ_FREE(buf); } } @@ -3965,7 +3965,7 @@ mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) { - MZ_FCLOSE(pFile); + MZ_FCLOSE(pFile); return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE); } @@ -6177,16 +6177,16 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n } #endif /* #ifndef MINIZ_NO_TIME */ - if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) - { - uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size); - uncomp_size = buf_size; - if (uncomp_size <= 3) - { - level = 0; - store_data_uncompressed = MZ_TRUE; - } - } + if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { + uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size); + uncomp_size = buf_size; + if (uncomp_size <= 3) + { + level = 0; + store_data_uncompressed = MZ_TRUE; + } + } archive_name_size = strlen(pArchive_name); if (archive_name_size > MZ_UINT16_MAX) @@ -6202,9 +6202,9 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n { /* Bail early if the archive would obviously become too large */ if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size - + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len + - pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len - + MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF) + + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len + + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len + + MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF) { pState->m_zip64 = MZ_TRUE; /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ @@ -6303,13 +6303,13 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n cur_archive_file_ofs += archive_name_size; } - if (user_extra_data_len > 0) - { - if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len) - return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); + if (user_extra_data_len > 0) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len) + return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); - cur_archive_file_ofs += user_extra_data_len; - } + cur_archive_file_ofs += user_extra_data_len; + } if (store_data_uncompressed) { @@ -6461,8 +6461,8 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA { /* Bail early if the archive would obviously become too large */ if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE - + archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024 - + MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF) + + archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024 + + MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF) { pState->m_zip64 = MZ_TRUE; /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */ @@ -6704,7 +6704,7 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), - (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : uncomp_size, + (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : uncomp_size, (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); @@ -6753,20 +6753,20 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA static size_t mz_file_read_func_stdio(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) { - MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque; - mz_int64 cur_ofs = MZ_FTELL64(pSrc_file); + MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pSrc_file); - if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET)))) - return 0; + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET)))) + return 0; - return MZ_FREAD(pBuf, 1, n, pSrc_file); + return MZ_FREAD(pBuf, 1, n, pSrc_file); } mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, - const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len) + const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len) { - return mz_zip_writer_add_read_buf_callback(pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, max_size, pFile_time, pComment, comment_size, level_and_flags, - user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len); + return mz_zip_writer_add_read_buf_callback(pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, max_size, pFile_time, pComment, comment_size, level_and_flags, + user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len); } mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) @@ -7088,11 +7088,11 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive * { /* src is zip64, dest must be zip64 */ - /* name uint32_t's */ - /* id 1 (optional in zip64?) */ - /* crc 1 */ - /* comp_size 2 */ - /* uncomp_size 2 */ + /* name uint32_t's */ + /* id 1 (optional in zip64?) */ + /* crc 1 */ + /* comp_size 2 */ + /* uncomp_size 2 */ if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/miniz.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/miniz.h index 6cc398c920..82be6580c3 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/miniz.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/miniz.h @@ -115,7 +115,7 @@ -/* Defines to completely disable specific portions of miniz.c: +/* Defines to completely disable specific portions of miniz.c: If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. */ /* Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O. */ @@ -138,7 +138,7 @@ /* Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib. */ /*#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES */ -/* Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. +/* Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. */ @@ -908,7 +908,7 @@ struct tinfl_decompressor_tag #ifdef __cplusplus } #endif - + #pragma once @@ -1226,13 +1226,13 @@ MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, c #if 0 /* TODO */ - typedef void *mz_zip_streaming_extract_state_ptr; - mz_zip_streaming_extract_state_ptr mz_zip_streaming_extract_begin(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags); - uint64_t mz_zip_streaming_extract_get_size(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); - uint64_t mz_zip_streaming_extract_get_cur_ofs(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); - mz_bool mz_zip_streaming_extract_seek(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, uint64_t new_ofs); - size_t mz_zip_streaming_extract_read(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, void *pBuf, size_t buf_size); - mz_bool mz_zip_streaming_extract_end(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); + typedef void *mz_zip_streaming_extract_state_ptr; + mz_zip_streaming_extract_state_ptr mz_zip_streaming_extract_begin(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags); + uint64_t mz_zip_streaming_extract_get_size(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); + uint64_t mz_zip_streaming_extract_get_cur_ofs(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); + mz_bool mz_zip_streaming_extract_seek(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, uint64_t new_ofs); + size_t mz_zip_streaming_extract_read(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, void *pBuf, size_t buf_size); + mz_bool mz_zip_streaming_extract_end(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState); #endif /* This function compares the archive's local headers, the optional local zip64 extended information block, and the optional descriptor following the compressed data vs. the data in the central directory. */ @@ -1294,8 +1294,8 @@ MINIZ_EXPORT mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const cha /* Adds the contents of a file to an archive. This function also records the disk file's modified time into the archive. */ /* File data is supplied via a read callback function. User mz_zip_writer_add_(c)file to add a file directly.*/ MINIZ_EXPORT mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 max_size, - const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data_local, mz_uint user_extra_data_local_len, - const char *user_extra_data_central, mz_uint user_extra_data_central_len); + const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data_local, mz_uint user_extra_data_local_len, + const char *user_extra_data_central, mz_uint user_extra_data_central_len); #ifndef MINIZ_NO_STDIO diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/mystdint.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/mystdint.h index 3648a1fee3..a6beaf8c26 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/mystdint.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/mystdint.h @@ -19,7 +19,7 @@ typedef unsigned long long uint64_t; #define UINT8_MAX 255 #define UINT16_MAX 65535 #define UINT32_MAX 0xffffffffU /* 4294967295U */ -#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ +#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ #else #include #endif diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/regexp.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/regexp.c index a50008ca35..1826649321 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/regexp.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/regexp.c @@ -169,7 +169,7 @@ static void re_add_state(ReStateSet *pSet, int newState){ /* Extract the next unicode character from *pzIn and return it. Advance ** *pzIn to the first byte past the end of the character returned. To -** be clear: this routine converts utf8 to unicode. This routine is +** be clear: this routine converts utf8 to unicode. This routine is ** optimized for the common case where the next character is a single byte. */ static unsigned re_next_char(ReInput *p){ @@ -240,7 +240,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){ /* Look for the initial prefix match, if there is one. */ if( pRe->nInit ){ unsigned char x = pRe->zInit[0]; - while( in.i+pRe->nInit<=in.mx + while( in.i+pRe->nInit<=in.mx && (zIn[in.i]!=x || strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0) ){ @@ -710,7 +710,7 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){ /* The following is a performance optimization. If the regex begins with ** ".*" (if the input regex lacks an initial "^") and afterwards there are ** one or more matching characters, enter those matching characters into - ** zInit[]. The re_match() routine can then search ahead in the input + ** zInit[]. The re_match() routine can then search ahead in the input ** string looking for the initial match without having to run the whole ** regex engine over the string. Do not worry about trying to match ** unicode characters beyond plane 0 - those are very rare and this is @@ -853,14 +853,14 @@ static void re_bytecode_func( __declspec(dllexport) #endif int sqlite3_regexp_init( - sqlite3 *db, - char **pzErrMsg, + sqlite3 *db, + char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; SQLITE_EXTENSION_INIT2(pApi); (void)pzErrMsg; /* Unused */ - rc = sqlite3_create_function(db, "regexp", 2, + rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0, re_sql_func, 0, 0); if( rc==SQLITE_OK ){ diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rekeyvacuum.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rekeyvacuum.c index d50ed97e36..557f14678f 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rekeyvacuum.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rekeyvacuum.c @@ -27,7 +27,7 @@ ** Change 4: Call sqlite3mcBtreeSetPageSize instead of sqlite3BtreeSetPageSize for main database ** (sqlite3mcBtreeSetPageSize allows to reduce the number of reserved bytes) ** -** This code is generated by the script rekeyvacuum.sh from SQLite version 3.44.2 amalgamation. +** This code is generated by the script rekeyvacuum.sh from SQLite version 3.47.0 amalgamation. */ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3mcRunVacuumForRekey( char **pzErrMsg, /* Write error message here */ @@ -50,6 +50,9 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3mcRunVacuumForRekey( const char *zDbMain; /* Schema name of database to vacuum */ const char *zOut; /* Name of output file */ u32 pgflags = PAGER_SYNCHRONOUS_OFF; /* sync flags for output db */ + u64 iRandom; /* Random value used for zDbVacuum[] */ + char zDbVacuum[42]; /* Name of the ATTACH-ed database used for vacuum */ + if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); @@ -90,27 +93,29 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3mcRunVacuumForRekey( pMain = db->aDb[iDb].pBt; isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain)); - /* Attach the temporary database as 'vacuum_db'. The synchronous pragma + /* Attach the temporary database as 'vacuum_XXXXXX'. The synchronous pragma ** can be set to 'off' for this file, as it is not recovered if a crash ** occurs anyway. The integrity of the database is maintained by a ** (possibly synchronous) transaction opened on the main database before ** sqlite3BtreeCopyFile() is called. ** ** An optimization would be to use a non-journaled pager. - ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but + ** (Later:) I tried setting "PRAGMA vacuum_XXXXXX.journal_mode=OFF" but ** that actually made the VACUUM run slower. Very little journalling ** actually occurs when doing a vacuum since the vacuum_db is initially ** empty. Only the journal header is written. Apparently it takes more ** time to parse and run the PRAGMA to turn journalling off than it does ** to write the journal header file. */ + sqlite3_randomness(sizeof(iRandom),&iRandom); + sqlite3_snprintf(sizeof(zDbVacuum), zDbVacuum, "vacuum_%016llx", iRandom); nDb = db->nDb; - rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut); + rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS %s", zOut, zDbVacuum); db->openFlags = saved_openFlags; if( rc!=SQLITE_OK ) goto end_of_vacuum; assert( (db->nDb-1)==nDb ); pDb = &db->aDb[nDb]; - assert( strcmp(pDb->zDbSName,"vacuum_db")==0 ); + assert( strcmp(pDb->zDbSName,zDbVacuum)==0 ); pTemp = pDb->pBt; if( pOut ){ sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp)); @@ -195,11 +200,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3mcRunVacuumForRekey( ** the contents to the temporary database. */ rc = execSqlF(db, pzErrMsg, - "SELECT'INSERT INTO vacuum_db.'||quote(name)" + "SELECT'INSERT INTO %s.'||quote(name)" "||' SELECT*FROM\"%w\".'||quote(name)" - "FROM vacuum_db.sqlite_schema " + "FROM %s.sqlite_schema " "WHERE type='table'AND coalesce(rootpage,1)>0", - zDbMain + zDbVacuum, zDbMain, zDbVacuum ); assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 ); db->mDbFlags &= ~DBFLAG_Vacuum; @@ -211,11 +216,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3mcRunVacuumForRekey( ** from the schema table. */ rc = execSqlF(db, pzErrMsg, - "INSERT INTO vacuum_db.sqlite_schema" + "INSERT INTO %s.sqlite_schema" " SELECT*FROM \"%w\".sqlite_schema" " WHERE type IN('view','trigger')" " OR(type='table'AND rootpage=0)", - zDbMain + zDbVacuum, zDbMain ); if( rc ) goto end_of_vacuum; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rijndael.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rijndael.c index fccca806d3..144e849088 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rijndael.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rijndael.c @@ -86,21 +86,21 @@ static UINT8 S[256]= { - 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, - 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, - 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, - 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, - 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, - 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, - 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, - 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, - 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, - 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, - 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, - 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, - 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, - 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, - 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, + 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, + 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, + 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, + 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, + 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, + 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, + 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, + 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, + 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, + 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, + 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, + 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22 }; @@ -171,7 +171,7 @@ static UINT8 T1[256][4]= {0x82,0x41,0x41,0xc3}, {0x29,0x99,0x99,0xb0}, {0x5a,0x2d,0x2d,0x77}, {0x1e,0x0f,0x0f,0x11}, {0x7b,0xb0,0xb0,0xcb}, {0xa8,0x54,0x54,0xfc}, {0x6d,0xbb,0xbb,0xd6}, {0x2c,0x16,0x16,0x3a} }; - + static UINT8 T2[256][4]= { {0xa5,0xc6,0x63,0x63}, {0x84,0xf8,0x7c,0x7c}, {0x99,0xee,0x77,0x77}, {0x8d,0xf6,0x7b,0x7b}, @@ -783,7 +783,7 @@ static UINT8 U1[256][4]= {0xa7,0x79,0xb4,0x92}, {0xa9,0x70,0xb9,0x99}, {0xbb,0x6b,0xae,0x84}, {0xb5,0x62,0xa3,0x8f}, {0x9f,0x5d,0x80,0xbe}, {0x91,0x54,0x8d,0xb5}, {0x83,0x4f,0x9a,0xa8}, {0x8d,0x46,0x97,0xa3} }; - + static UINT8 U2[256][4]= { {0x00,0x00,0x00,0x00}, {0x0b,0x0e,0x09,0x0d}, {0x16,0x1c,0x12,0x1a}, {0x1d,0x12,0x1b,0x17}, @@ -989,7 +989,7 @@ static UINT8 U4[256][4]= }; static UINT32 rcon[30]= -{ +{ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, @@ -1003,11 +1003,13 @@ static UINT32 rcon[30]= ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ +SQLITE_PRIVATE void RijndaelCreate(Rijndael* rijndael) { rijndael->m_state = RIJNDAEL_State_Invalid; } +SQLITE_PRIVATE int RijndaelInit(Rijndael* rijndael, int mode, int dir, UINT8* key, int keyLen, UINT8* initVector) { UINT32 uKeyLenInBytes; @@ -1092,7 +1094,7 @@ int RijndaelInit(Rijndael* rijndael, int mode, int dir, UINT8* key, int keyLen, #endif } } -#ifndef TEST_AES_HW +#ifndef TEST_AES_HW else #endif #endif @@ -1104,7 +1106,7 @@ int RijndaelInit(Rijndael* rijndael, int mode, int dir, UINT8* key, int keyLen, if (rijndael->m_direction == RIJNDAEL_Direction_Decrypt) RijndaelKeyEncToDec(rijndael); } -#ifdef TEST_AES_HW +#ifdef TEST_AES_HW { int cmpkeyexp = memcmp((unsigned char*) rijndael->m_expandedKey, aesKeySched, (rijndael->m_uRounds+1)*16); int datalen = (rijndael->m_uRounds + 1) * 16; @@ -1134,10 +1136,10 @@ int RijndaelBlockEncrypt(Rijndael* rijndael, UINT8* input, int inputLen, UINT8* numBlocks = inputLen/128; lenFrag = (inputLen % 128) / 8; - + switch (rijndael->m_mode) { - case RIJNDAEL_Direction_Mode_ECB: + case RIJNDAEL_Direction_Mode_ECB: for(i = numBlocks;i > 0;i--) { RijndaelEncrypt(rijndael, input, outBuffer); @@ -1149,7 +1151,7 @@ int RijndaelBlockEncrypt(Rijndael* rijndael, UINT8* input, int inputLen, UINT8* #if HAS_AES_HARDWARE if (aesHardwareAvailable()) { -#ifndef TEST_AES_HW +#ifndef TEST_AES_HW aesEncryptCBC(input, outBuffer, rijndael->m_initVector, inputLen/8, (unsigned char*) (rijndael->m_expandedKey), rijndael->m_uRounds); #else TEST_AES_HW_DEBUG_LOG("aes enc: hw enabled\n"); @@ -1195,8 +1197,8 @@ int RijndaelBlockEncrypt(Rijndael* rijndael, UINT8* input, int inputLen, UINT8* } break; case RIJNDAEL_Direction_Mode_CFB1: -#if STRICT_ALIGN - memcpy(iv,rijndael->m_initVector,16); +#if STRICT_ALIGN + memcpy(iv,rijndael->m_initVector,16); #else /* !STRICT_ALIGN */ *((UINT32*)iv[0]) = *((UINT32*)(rijndael->m_initVector )); *((UINT32*)iv[1]) = *((UINT32*)(rijndael->m_initVector + 4)); @@ -1240,7 +1242,7 @@ int RijndaelBlockEncrypt(Rijndael* rijndael, UINT8* input, int inputLen, UINT8* break; } -#ifdef TEST_AES_HW +#ifdef TEST_AES_HW { int cmpdata = memcmp((unsigned char*) outOrig, outBuffer2, inputLen/8); TEST_AES_HW_DEBUG_LOG("aes enc: cmp=%d\n", cmpdata); @@ -1248,10 +1250,11 @@ int RijndaelBlockEncrypt(Rijndael* rijndael, UINT8* input, int inputLen, UINT8* TEST_AES_HW_DEBUG_HEX("aes enc HW:", outBuffer2, 16); } #endif - + return 128 * numBlocks; } +SQLITE_PRIVATE int RijndaelPadEncrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 *outBuffer) { int i, numBlocks, padLen; @@ -1266,7 +1269,7 @@ int RijndaelPadEncrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 switch (rijndael->m_mode) { - case RIJNDAEL_Direction_Mode_ECB: + case RIJNDAEL_Direction_Mode_ECB: for(i = numBlocks; i > 0; i--) { RijndaelEncrypt(rijndael, input, outBuffer); @@ -1306,10 +1309,11 @@ int RijndaelPadEncrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 return -1; break; } - + return 16*(numBlocks + 1); } - + +SQLITE_PRIVATE int RijndaelBlockDecrypt(Rijndael* rijndael, UINT8* input, int inputLen, UINT8* outBuffer) { int i, k, numBlocks, lenFrag; @@ -1329,7 +1333,7 @@ int RijndaelBlockDecrypt(Rijndael* rijndael, UINT8* input, int inputLen, UINT8* switch (rijndael->m_mode) { - case RIJNDAEL_Direction_Mode_ECB: + case RIJNDAEL_Direction_Mode_ECB: for (i = numBlocks; i > 0; i--) { RijndaelDecrypt(rijndael, input, outBuffer); @@ -1384,8 +1388,8 @@ int RijndaelBlockDecrypt(Rijndael* rijndael, UINT8* input, int inputLen, UINT8* } } } -#if STRICT_ALIGN - memcpy(iv,rijndael->m_initVector,16); +#if STRICT_ALIGN + memcpy(iv,rijndael->m_initVector,16); #else *((UINT32*)iv[0]) = *((UINT32*)(rijndael->m_initVector )); *((UINT32*)iv[1]) = *((UINT32*)(rijndael->m_initVector+ 4)); @@ -1414,8 +1418,8 @@ int RijndaelBlockDecrypt(Rijndael* rijndael, UINT8* input, int inputLen, UINT8* } break; case RIJNDAEL_Direction_Mode_CFB1: -#if STRICT_ALIGN - memcpy(iv, rijndael->m_initVector, 16); +#if STRICT_ALIGN + memcpy(iv, rijndael->m_initVector, 16); #else *((UINT32*)iv[0]) = *((UINT32*)(rijndael->m_initVector)); *((UINT32*)iv[1]) = *((UINT32*)(rijndael->m_initVector+ 4)); @@ -1459,7 +1463,7 @@ int RijndaelBlockDecrypt(Rijndael* rijndael, UINT8* input, int inputLen, UINT8* break; } -#ifdef TEST_AES_HW +#ifdef TEST_AES_HW { int cmpdata = memcmp((unsigned char*) outOrig, outBuffer2, inputLen/8); TEST_AES_HW_DEBUG_LOG("aes dec: cmp=%d\n", cmpdata); @@ -1467,10 +1471,11 @@ int RijndaelBlockDecrypt(Rijndael* rijndael, UINT8* input, int inputLen, UINT8* TEST_AES_HW_DEBUG_HEX("aes dec HW:", outBuffer2, 16); } #endif - + return 128*numBlocks; } +SQLITE_PRIVATE int RijndaelPadDecrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 *outBuffer) { int i, numBlocks, padLen; @@ -1504,7 +1509,7 @@ int RijndaelPadDecrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 if (block[i] != padLen) return RIJNDAEL_CORRUPTED_DATA; } memcpy(outBuffer, block, 16 - padLen); - break; + break; case RIJNDAEL_Direction_Mode_CBC: memcpy(iv, rijndael->m_initVector, 16); /* all blocks but last */ @@ -1534,12 +1539,12 @@ int RijndaelPadDecrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 } memcpy(outBuffer, block, 16 - padLen); break; - + default: return -1; break; } - + return 16*numBlocks - padLen; } @@ -1549,6 +1554,7 @@ int RijndaelPadDecrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ +SQLITE_PRIVATE void RijndaelKeySched(Rijndael* rijndael, UINT8 key[_MAX_KEY_COLUMNS][4]) { int j,rconpointer = 0; @@ -1585,7 +1591,7 @@ void RijndaelKeySched(Rijndael* rijndael, UINT8 key[_MAX_KEY_COLUMNS][4]) t = 0; } } - + while(r <= rijndael->m_uRounds) { tempKey[0][0] ^= S[tempKey[uKeyColumns-1][1]]; @@ -1626,9 +1632,10 @@ void RijndaelKeySched(Rijndael* rijndael, UINT8 key[_MAX_KEY_COLUMNS][4]) t = 0; } } - } + } } +SQLITE_PRIVATE void RijndaelKeyEncToDec(Rijndael* rijndael) { UINT32 r; @@ -1645,8 +1652,9 @@ void RijndaelKeyEncToDec(Rijndael* rijndael) w = rijndael->m_expandedKey[r][3]; *((UINT32*)w) = *((UINT32*)U1[w[0]]) ^ *((UINT32*)U2[w[1]]) ^ *((UINT32*)U3[w[2]]) ^ *((UINT32*)U4[w[3]]); } -} +} +SQLITE_PRIVATE void RijndaelEncrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]) { UINT32 r; @@ -1658,19 +1666,19 @@ void RijndaelEncrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]) *((UINT32*)temp[3]) = *((UINT32*)(a+12)) ^ *((UINT32*)rijndael->m_expandedKey[0][3]); *((UINT32*)(b )) = *((UINT32*)T1[temp[0][0]]) ^ *((UINT32*)T2[temp[1][1]]) - ^ *((UINT32*)T3[temp[2][2]]) + ^ *((UINT32*)T3[temp[2][2]]) ^ *((UINT32*)T4[temp[3][3]]); *((UINT32*)(b + 4)) = *((UINT32*)T1[temp[1][0]]) ^ *((UINT32*)T2[temp[2][1]]) - ^ *((UINT32*)T3[temp[3][2]]) + ^ *((UINT32*)T3[temp[3][2]]) ^ *((UINT32*)T4[temp[0][3]]); *((UINT32*)(b + 8)) = *((UINT32*)T1[temp[2][0]]) ^ *((UINT32*)T2[temp[3][1]]) - ^ *((UINT32*)T3[temp[0][2]]) + ^ *((UINT32*)T3[temp[0][2]]) ^ *((UINT32*)T4[temp[1][3]]); *((UINT32*)(b +12)) = *((UINT32*)T1[temp[3][0]]) ^ *((UINT32*)T2[temp[0][1]]) - ^ *((UINT32*)T3[temp[1][2]]) + ^ *((UINT32*)T3[temp[1][2]]) ^ *((UINT32*)T4[temp[2][3]]); for(r = 1; r < rijndael->m_uRounds-1; r++) { @@ -1681,19 +1689,19 @@ void RijndaelEncrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]) *((UINT32*)(b )) = *((UINT32*)T1[temp[0][0]]) ^ *((UINT32*)T2[temp[1][1]]) - ^ *((UINT32*)T3[temp[2][2]]) + ^ *((UINT32*)T3[temp[2][2]]) ^ *((UINT32*)T4[temp[3][3]]); *((UINT32*)(b + 4)) = *((UINT32*)T1[temp[1][0]]) ^ *((UINT32*)T2[temp[2][1]]) - ^ *((UINT32*)T3[temp[3][2]]) + ^ *((UINT32*)T3[temp[3][2]]) ^ *((UINT32*)T4[temp[0][3]]); *((UINT32*)(b + 8)) = *((UINT32*)T1[temp[2][0]]) ^ *((UINT32*)T2[temp[3][1]]) - ^ *((UINT32*)T3[temp[0][2]]) + ^ *((UINT32*)T3[temp[0][2]]) ^ *((UINT32*)T4[temp[1][3]]); *((UINT32*)(b +12)) = *((UINT32*)T1[temp[3][0]]) ^ *((UINT32*)T2[temp[0][1]]) - ^ *((UINT32*)T3[temp[1][2]]) + ^ *((UINT32*)T3[temp[1][2]]) ^ *((UINT32*)T4[temp[2][3]]); } *((UINT32*)temp[0]) = *((UINT32*)(b )) ^ *((UINT32*)rijndael->m_expandedKey[rijndael->m_uRounds-1][0]); @@ -1722,11 +1730,12 @@ void RijndaelEncrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]) *((UINT32*)(b+12)) ^= *((UINT32*)rijndael->m_expandedKey[rijndael->m_uRounds][3]); } +SQLITE_PRIVATE void RijndaelDecrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]) { int r; UINT8 temp[4][4]; - + *((UINT32*)temp[0]) = *((UINT32*)(a )) ^ *((UINT32*)rijndael->m_expandedKey[rijndael->m_uRounds][0]); *((UINT32*)temp[1]) = *((UINT32*)(a+ 4)) ^ *((UINT32*)rijndael->m_expandedKey[rijndael->m_uRounds][1]); *((UINT32*)temp[2]) = *((UINT32*)(a+ 8)) ^ *((UINT32*)rijndael->m_expandedKey[rijndael->m_uRounds][2]); @@ -1734,19 +1743,19 @@ void RijndaelDecrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]) *((UINT32*)(b )) = *((UINT32*)T5[temp[0][0]]) ^ *((UINT32*)T6[temp[3][1]]) - ^ *((UINT32*)T7[temp[2][2]]) + ^ *((UINT32*)T7[temp[2][2]]) ^ *((UINT32*)T8[temp[1][3]]); *((UINT32*)(b+ 4)) = *((UINT32*)T5[temp[1][0]]) ^ *((UINT32*)T6[temp[0][1]]) - ^ *((UINT32*)T7[temp[3][2]]) + ^ *((UINT32*)T7[temp[3][2]]) ^ *((UINT32*)T8[temp[2][3]]); *((UINT32*)(b+ 8)) = *((UINT32*)T5[temp[2][0]]) ^ *((UINT32*)T6[temp[1][1]]) - ^ *((UINT32*)T7[temp[0][2]]) + ^ *((UINT32*)T7[temp[0][2]]) ^ *((UINT32*)T8[temp[3][3]]); *((UINT32*)(b+12)) = *((UINT32*)T5[temp[3][0]]) ^ *((UINT32*)T6[temp[2][1]]) - ^ *((UINT32*)T7[temp[1][2]]) + ^ *((UINT32*)T7[temp[1][2]]) ^ *((UINT32*)T8[temp[0][3]]); for(r = rijndael->m_uRounds-1; r > 1; r--) { @@ -1756,22 +1765,22 @@ void RijndaelDecrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]) *((UINT32*)temp[3]) = *((UINT32*)(b+12)) ^ *((UINT32*)rijndael->m_expandedKey[r][3]); *((UINT32*)(b )) = *((UINT32*)T5[temp[0][0]]) ^ *((UINT32*)T6[temp[3][1]]) - ^ *((UINT32*)T7[temp[2][2]]) + ^ *((UINT32*)T7[temp[2][2]]) ^ *((UINT32*)T8[temp[1][3]]); *((UINT32*)(b+ 4)) = *((UINT32*)T5[temp[1][0]]) ^ *((UINT32*)T6[temp[0][1]]) - ^ *((UINT32*)T7[temp[3][2]]) + ^ *((UINT32*)T7[temp[3][2]]) ^ *((UINT32*)T8[temp[2][3]]); *((UINT32*)(b+ 8)) = *((UINT32*)T5[temp[2][0]]) ^ *((UINT32*)T6[temp[1][1]]) - ^ *((UINT32*)T7[temp[0][2]]) + ^ *((UINT32*)T7[temp[0][2]]) ^ *((UINT32*)T8[temp[3][3]]); *((UINT32*)(b+12)) = *((UINT32*)T5[temp[3][0]]) ^ *((UINT32*)T6[temp[2][1]]) - ^ *((UINT32*)T7[temp[1][2]]) + ^ *((UINT32*)T7[temp[1][2]]) ^ *((UINT32*)T8[temp[0][3]]); } - + *((UINT32*)temp[0]) = *((UINT32*)(b )) ^ *((UINT32*)rijndael->m_expandedKey[1][0]); *((UINT32*)temp[1]) = *((UINT32*)(b+ 4)) ^ *((UINT32*)rijndael->m_expandedKey[1][1]); *((UINT32*)temp[2]) = *((UINT32*)(b+ 8)) ^ *((UINT32*)rijndael->m_expandedKey[1][2]); @@ -1798,6 +1807,7 @@ void RijndaelDecrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]) *((UINT32*)(b+12)) ^= *((UINT32*)rijndael->m_expandedKey[0][3]); } +SQLITE_PRIVATE void RijndaelInvalidate(Rijndael* rijndael) { rijndael->m_state = RIJNDAEL_State_Invalid; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rijndael.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rijndael.h index f383c0cbb5..837169b286 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rijndael.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/rijndael.h @@ -18,6 +18,10 @@ #ifndef _RIJNDAEL_H_ #define _RIJNDAEL_H_ +#ifndef SQLITE_PRIVATE +#define SQLITE_PRIVATE +#endif + /* // File : rijndael.h // Creation date : Sun Nov 5 2000 03:21:05 CEST @@ -116,16 +120,16 @@ typedef unsigned short UINT16; */ typedef struct _Rijndael -{ - int m_state; - int m_mode; - int m_direction; - UINT8 m_initVector[MAX_IV_SIZE]; - UINT32 m_uRounds; - UINT8 m_expandedKey[_MAX_ROUNDS+1][4][4]; +{ + int m_state; + int m_mode; + int m_direction; + UINT8 m_initVector[MAX_IV_SIZE]; + UINT32 m_uRounds; + UINT8 m_expandedKey[_MAX_ROUNDS+1][4][4]; } Rijndael; -void RijndaelCreate(Rijndael* rijndael); +SQLITE_PRIVATE void RijndaelCreate(Rijndael* rijndael); /* ////////////////////////////////////////////////////////////////////////////////////////// @@ -147,7 +151,7 @@ void RijndaelCreate(Rijndael* rijndael); // keyLen : Rijndael::Key16Bytes , Rijndael::Key24Bytes or Rijndael::Key32Bytes // initVector: initialization vector, you will usually use 0 here */ -int RijndaelInit(Rijndael* rijndael, int mode, int dir, UINT8* key, int keyLen, UINT8* initVector); +SQLITE_PRIVATE int RijndaelInit(Rijndael* rijndael, int mode, int dir, UINT8* key, int keyLen, UINT8* initVector); /* // Encrypts the input array (can be binary data) @@ -158,7 +162,7 @@ int RijndaelInit(Rijndael* rijndael, int mode, int dir, UINT8* key, int keyLen, // outBuffer must be at least inputLen / 8 bytes long. // Returns the encrypted buffer length in BITS or an error code < 0 in case of error */ -int RijndaelBlockEncrypt(Rijndael* rijndael, UINT8 *input, int inputLen, UINT8 *outBuffer); +SQLITE_PRIVATE int RijndaelBlockEncrypt(Rijndael* rijndael, UINT8 *input, int inputLen, UINT8 *outBuffer); /* // Encrypts the input array (can be binary data) @@ -167,7 +171,7 @@ int RijndaelBlockEncrypt(Rijndael* rijndael, UINT8 *input, int inputLen, UINT8 * // outBuffer must be at least (inputLen + 16) bytes long // Returns the encrypted buffer length in BYTES or an error code < 0 in case of error */ -int RijndaelPadEncrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 *outBuffer); +SQLITE_PRIVATE int RijndaelPadEncrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 *outBuffer); /* // Decrypts the input vector @@ -175,7 +179,7 @@ int RijndaelPadEncrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 // outBuffer must be at least inputLen / 8 bytes long // Returns the decrypted buffer length in BITS and an error code < 0 in case of error */ -int RijndaelBlockDecrypt(Rijndael* rijndael, UINT8 *input, int inputLen, UINT8 *outBuffer); +SQLITE_PRIVATE int RijndaelBlockDecrypt(Rijndael* rijndael, UINT8 *input, int inputLen, UINT8 *outBuffer); /* // Decrypts the input vector @@ -183,12 +187,12 @@ int RijndaelBlockDecrypt(Rijndael* rijndael, UINT8 *input, int inputLen, UINT8 * // outBuffer must be at least inputLen bytes long // Returns the decrypted buffer length in BYTES and an error code < 0 in case of error */ -int RijndaelPadDecrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 *outBuffer); - -void RijndaelInvalidate(Rijndael* rijndael); -void RijndaelKeySched(Rijndael* rijndael, UINT8 key[_MAX_KEY_COLUMNS][4]); -void RijndaelKeyEncToDec(Rijndael* rijndael); -void RijndaelEncrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]); -void RijndaelDecrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]); - +SQLITE_PRIVATE int RijndaelPadDecrypt(Rijndael* rijndael, UINT8 *input, int inputOctets, UINT8 *outBuffer); + +SQLITE_PRIVATE void RijndaelInvalidate(Rijndael* rijndael); +SQLITE_PRIVATE void RijndaelKeySched(Rijndael* rijndael, UINT8 key[_MAX_KEY_COLUMNS][4]); +SQLITE_PRIVATE void RijndaelKeyEncToDec(Rijndael* rijndael); +SQLITE_PRIVATE void RijndaelEncrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]); +SQLITE_PRIVATE void RijndaelDecrypt(Rijndael* rijndael, UINT8 a[16], UINT8 b[16]); + #endif /* _RIJNDAEL_H_ */ diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/series.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/series.c index 0dfed181f6..e0810fa6a1 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/series.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/series.c @@ -90,6 +90,26 @@ ** and a very large cost if either start or stop are unavailable. This ** encourages the query planner to order joins such that the bounds of the ** series are well-defined. +** +** Update on 2024-08-22: +** xBestIndex now also looks for equality and inequality constraints against +** the value column and uses those constraints as additional bounds against +** the sequence range. Thus, a query like this: +** +** SELECT value FROM generate_series($SA,$EA) +** WHERE value BETWEEN $SB AND $EB; +** +** Is logically the same as: +** +** SELECT value FROM generate_series(max($SA,$SB),min($EA,$EB)); +** +** Constraints on the value column can server as substitutes for constraints +** on the hidden start and stop columns. So, the following two queries +** are equivalent: +** +** SELECT value FROM generate_series($S,$E); +** SELECT value FROM generate_series WHERE value BETWEEN $S and $E; +** */ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 @@ -131,8 +151,10 @@ static sqlite3_int64 genSeqMember( typedef unsigned char u8; typedef struct SequenceSpec { - sqlite3_int64 iBase; /* Starting value ("start") */ - sqlite3_int64 iTerm; /* Given terminal value ("stop") */ + sqlite3_int64 iOBase; /* Original starting value ("start") */ + sqlite3_int64 iOTerm; /* Original terminal value ("stop") */ + sqlite3_int64 iBase; /* Starting value to actually use */ + sqlite3_int64 iTerm; /* Terminal value to actually use */ sqlite3_int64 iStep; /* Increment ("step") */ sqlite3_uint64 uSeqIndexMax; /* maximum sequence index (aka "n") */ sqlite3_uint64 uSeqIndexNow; /* Current index during generation */ @@ -325,9 +347,9 @@ static int seriesColumn( series_cursor *pCur = (series_cursor*)cur; sqlite3_int64 x = 0; switch( i ){ - case SERIES_COLUMN_START: x = pCur->ss.iBase; break; - case SERIES_COLUMN_STOP: x = pCur->ss.iTerm; break; - case SERIES_COLUMN_STEP: x = pCur->ss.iStep; break; + case SERIES_COLUMN_START: x = pCur->ss.iOBase; break; + case SERIES_COLUMN_STOP: x = pCur->ss.iOTerm; break; + case SERIES_COLUMN_STEP: x = pCur->ss.iStep; break; default: x = pCur->ss.iValueNow; break; } sqlite3_result_int64(ctx, x); @@ -335,7 +357,9 @@ static int seriesColumn( } #ifndef LARGEST_UINT64 +#define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) #define LARGEST_UINT64 (0xffffffff|(((sqlite3_uint64)0xffffffff)<<32)) +#define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) #endif /* @@ -376,13 +400,18 @@ static int seriesEof(sqlite3_vtab_cursor *cur){ ** parameter. (idxStr is not used in this implementation.) idxNum ** is a bitmask showing which constraints are available: ** -** 0x01: start=VALUE -** 0x02: stop=VALUE -** 0x04: step=VALUE -** 0x08: descending order -** 0x10: ascending order -** 0x20: LIMIT VALUE -** 0x40: OFFSET VALUE +** 0x0001: start=VALUE +** 0x0002: stop=VALUE +** 0x0004: step=VALUE +** 0x0008: descending order +** 0x0010: ascending order +** 0x0020: LIMIT VALUE +** 0x0040: OFFSET VALUE +** 0x0080: value=VALUE +** 0x0100: value>=VALUE +** 0x0200: value>VALUE +** 0x1000: value<=VALUE +** 0x2000: valuess.iBase = sqlite3_value_int64(argv[i++]); @@ -416,16 +451,98 @@ static int seriesFilter( }else{ pCur->ss.iStep = 1; } + + /* If there are constraints on the value column but there are + ** no constraints on the start, stop, and step columns, then + ** initialize the default range to be the entire range of 64-bit signed + ** integers. This range will contracted by the value column constraints + ** further below. + */ + if( (idxNum & 0x05)==0 && (idxNum & 0x0380)!=0 ){ + pCur->ss.iBase = SMALLEST_INT64; + } + if( (idxNum & 0x06)==0 && (idxNum & 0x3080)!=0 ){ + pCur->ss.iTerm = LARGEST_INT64; + } + pCur->ss.iOBase = pCur->ss.iBase; + pCur->ss.iOTerm = pCur->ss.iTerm; + + /* Extract the LIMIT and OFFSET values, but do not apply them yet. + ** The range must first be constrained by the limits on value. + */ if( idxNum & 0x20 ){ - sqlite3_int64 iLimit = sqlite3_value_int64(argv[i++]); - sqlite3_int64 iTerm; + iLimit = sqlite3_value_int64(argv[i++]); if( idxNum & 0x40 ){ - sqlite3_int64 iOffset = sqlite3_value_int64(argv[i++]); - if( iOffset>0 ){ - pCur->ss.iBase += pCur->ss.iStep*iOffset; + iOffset = sqlite3_value_int64(argv[i++]); + } + } + + if( idxNum & 0x3380 ){ + /* Extract the maximum range of output values determined by + ** constraints on the "value" column. + */ + if( idxNum & 0x0080 ){ + iMin = iMax = sqlite3_value_int64(argv[i++]); + }else{ + if( idxNum & 0x0300 ){ + iMin = sqlite3_value_int64(argv[i++]); + if( idxNum & 0x0200 ){ + if( iMin==LARGEST_INT64 ){ + returnNoRows = 1; + }else{ + iMin++; + } + } + } + if( idxNum & 0x3000 ){ + iMax = sqlite3_value_int64(argv[i++]); + if( idxNum & 0x2000 ){ + if( iMax==SMALLEST_INT64 ){ + returnNoRows = 1; + }else{ + iMax--; + } + } + } + if( iMin>iMax ){ + returnNoRows = 1; + } + } + + /* Try to reduce the range of values to be generated based on + ** constraints on the "value" column. + */ + if( pCur->ss.iStep>0 ){ + sqlite3_int64 szStep = pCur->ss.iStep; + if( pCur->ss.iBasess.iBase; + pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep; + } + if( pCur->ss.iTerm>iMax ){ + sqlite3_uint64 d = pCur->ss.iTerm - iMax; + pCur->ss.iTerm -= ((d+szStep-1)/szStep)*szStep; + } + }else{ + sqlite3_int64 szStep = -pCur->ss.iStep; + assert( szStep>0 ); + if( pCur->ss.iBase>iMax ){ + sqlite3_uint64 d = pCur->ss.iBase - iMax; + pCur->ss.iBase -= ((d+szStep-1)/szStep)*szStep; + } + if( pCur->ss.iTermss.iTerm; + pCur->ss.iTerm += ((d+szStep-1)/szStep)*szStep; } } + } + + /* Apply LIMIT and OFFSET constraints, if any */ + if( idxNum & 0x20 ){ + if( iOffset>0 ){ + pCur->ss.iBase += pCur->ss.iStep*iOffset; + } if( iLimit>=0 ){ + sqlite3_int64 iTerm; iTerm = pCur->ss.iBase + (iLimit - 1)*pCur->ss.iStep; if( pCur->ss.iStep<0 ){ if( iTerm>pCur->ss.iTerm ) pCur->ss.iTerm = iTerm; @@ -434,16 +551,21 @@ static int seriesFilter( } } } + + for(i=0; iss.iBase = 1; - pCur->ss.iTerm = 0; - pCur->ss.iStep = 1; + returnNoRows = 1; break; } } + if( returnNoRows ){ + pCur->ss.iBase = 1; + pCur->ss.iTerm = 0; + pCur->ss.iStep = 1; + } if( idxNum & 0x08 ){ pCur->ss.isReversing = pCur->ss.iStep > 0; }else{ @@ -464,13 +586,35 @@ static int seriesFilter( ** ** The query plan is represented by bits in idxNum: ** -** 0x01 start = $value -- constraint exists -** 0x02 stop = $value -- constraint exists -** 0x04 step = $value -- constraint exists -** 0x08 output is in descending order -** 0x10 output is in ascending order -** 0x20 LIMIT $value -- constraint exists -** 0x40 OFFSET $value -- constraint exists +** 0x0001 start = $num +** 0x0002 stop = $num +** 0x0004 step = $num +** 0x0008 output is in descending order +** 0x0010 output is in ascending order +** 0x0020 LIMIT $num +** 0x0040 OFFSET $num +** 0x0080 value = $num +** 0x0100 value >= $num +** 0x0200 value > $num +** 0x1000 value <= $num +** 0x2000 value < $num +** +** Only one of 0x0100 or 0x0200 will be returned. Similarly, only +** one of 0x1000 or 0x2000 will be returned. If the 0x0080 is set, then +** none of the 0xff00 bits will be set. +** +** The order of parameters passed to xFilter is as follows: +** +** * The argument to start= if bit 0x0001 is in the idxNum mask +** * The argument to stop= if bit 0x0002 is in the idxNum mask +** * The argument to step= if bit 0x0004 is in the idxNum mask +** * The argument to LIMIT if bit 0x0020 is in the idxNum mask +** * The argument to OFFSET if bit 0x0040 is in the idxNum mask +** * The argument to value=, or value>= or value> if any of +** bits 0x0380 are in the idxNum mask +** * The argument to value<= or value< if either of bits 0x3000 +** are in the mask +** */ static int seriesBestIndex( sqlite3_vtab *pVTab, @@ -483,7 +627,9 @@ static int seriesBestIndex( #endif int unusableMask = 0; /* Mask of unusable constraints */ int nArg = 0; /* Number of arguments that seriesFilter() expects */ - int aIdx[5]; /* Constraints on start, stop, step, LIMIT, OFFSET */ + int aIdx[7]; /* Constraints on start, stop, step, LIMIT, OFFSET, + ** and value. aIdx[5] covers value=, value>=, and + ** value>, aIdx[6] covers value<= and value< */ const struct sqlite3_index_constraint *pConstraint; /* This implementation assumes that the start, stop, and step columns @@ -491,7 +637,7 @@ static int seriesBestIndex( assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 ); assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 ); - aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = -1; + aIdx[0] = aIdx[1] = aIdx[2] = aIdx[3] = aIdx[4] = aIdx[5] = aIdx[6] = -1; pConstraint = pIdxInfo->aConstraint; for(i=0; inConstraint; i++, pConstraint++){ int iCol; /* 0 for start, 1 for stop, 2 for step */ @@ -512,7 +658,52 @@ static int seriesBestIndex( } continue; } - if( pConstraint->iColumniColumniColumn==SERIES_COLUMN_VALUE ){ + switch( op ){ + case SQLITE_INDEX_CONSTRAINT_EQ: + case SQLITE_INDEX_CONSTRAINT_IS: { + idxNum |= 0x0080; + idxNum &= ~0x3300; + aIdx[5] = i; + aIdx[6] = -1; + bStartSeen = 1; + break; + } + case SQLITE_INDEX_CONSTRAINT_GE: { + if( idxNum & 0x0080 ) break; + idxNum |= 0x0100; + idxNum &= ~0x0200; + aIdx[5] = i; + bStartSeen = 1; + break; + } + case SQLITE_INDEX_CONSTRAINT_GT: { + if( idxNum & 0x0080 ) break; + idxNum |= 0x0200; + idxNum &= ~0x0100; + aIdx[5] = i; + bStartSeen = 1; + break; + } + case SQLITE_INDEX_CONSTRAINT_LE: { + if( idxNum & 0x0080 ) break; + idxNum |= 0x1000; + idxNum &= ~0x2000; + aIdx[6] = i; + break; + } + case SQLITE_INDEX_CONSTRAINT_LT: { + if( idxNum & 0x0080 ) break; + idxNum |= 0x2000; + idxNum &= ~0x1000; + aIdx[6] = i; + break; + } + } + } + continue; + } iCol = pConstraint->iColumn - SERIES_COLUMN_START; assert( iCol>=0 && iCol<=2 ); iMask = 1 << iCol; @@ -534,7 +725,7 @@ static int seriesBestIndex( idxNum &= ~0x60; aIdx[4] = 0; } - for(i=0; i<5; i++){ + for(i=0; i<7; i++){ if( (j = aIdx[i])>=0 ){ pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg; pIdxInfo->aConstraintUsage[j].omit = @@ -560,7 +751,7 @@ static int seriesBestIndex( return SQLITE_CONSTRAINT; } if( (idxNum & 0x03)==0x03 ){ - /* Both start= and stop= boundaries are available. This is the + /* Both start= and stop= boundaries are available. This is the ** the preferred case */ pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0)); pIdxInfo->estimatedRows = 1000; @@ -582,11 +773,14 @@ static int seriesBestIndex( pIdxInfo->estimatedRows = 2147483647; } pIdxInfo->idxNum = idxNum; +#ifdef SQLITE_INDEX_SCAN_HEX + pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_HEX; +#endif return SQLITE_OK; } /* -** This following structure defines all the methods for the +** This following structure defines all the methods for the ** generate_series virtual table. */ static sqlite3_module seriesModule = { @@ -623,8 +817,8 @@ static sqlite3_module seriesModule = { __declspec(dllexport) #endif int sqlite3_series_init( - sqlite3 *db, - char **pzErrMsg, + sqlite3 *db, + char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha1.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha1.c index 6a562192d5..c49041cb7f 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha1.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha1.c @@ -13,10 +13,10 @@ Still 100% Public Domain Corrected a problem which generated improper hash values on 16 bit machines Routine SHA1Update changed from - void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len) to - void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned long len) The 'len' parameter was declared an int which works fine on 32 bit machines. @@ -141,6 +141,7 @@ A million repetitions of "a" z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2); /* Hash a single 512-bit block. This is the core of the algorithm. */ +SQLITE_PRIVATE void sha1_transform(sha1_ctx *context, const uint8_t buffer[64]) { uint32_t a, b, c, d, e; @@ -205,6 +206,7 @@ void sha1_transform(sha1_ctx *context, const uint8_t buffer[64]) * * @param context SHA1-Context */ +SQLITE_PRIVATE void sha1_init(sha1_ctx *context) { /* SHA1 initialization constants */ @@ -224,6 +226,7 @@ void sha1_init(sha1_ctx *context) * @param p Buffer to run SHA1 on * @param len Number of bytes */ +SQLITE_PRIVATE void sha1_update(sha1_ctx *context, const void *p, size_t len) { const uint8_t *data = p; @@ -259,6 +262,7 @@ void sha1_update(sha1_ctx *context, const void *p, size_t len) * @param digest Generated message digest * @param context SHA1-Context */ +SQLITE_PRIVATE void sha1_final(sha1_ctx *context, uint8_t digest[SHA1_DIGEST_SIZE]) { uint32_t i; diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha1.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha1.h index bf2c56aae9..844b607bb1 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha1.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha1.h @@ -4,6 +4,10 @@ #ifndef SHA1_H_ #define SHA1_H_ (1) +#ifndef SQLITE_PRIVATE +#define SQLITE_PRIVATE +#endif + /** SHA-1 Context */ typedef struct { uint32_t h[5]; @@ -17,12 +21,12 @@ typedef struct { /** SHA-1 Digest size in bytes */ #define SHA1_DIGEST_SIZE 20 -void sha1_init(sha1_ctx *context); +SQLITE_PRIVATE void sha1_init(sha1_ctx *context); -void sha1_update(sha1_ctx *context, const void *p, size_t len); +SQLITE_PRIVATE void sha1_update(sha1_ctx *context, const void *p, size_t len); -void sha1_final(sha1_ctx *context, uint8_t digest[SHA1_DIGEST_SIZE]); +SQLITE_PRIVATE void sha1_final(sha1_ctx *context, uint8_t digest[SHA1_DIGEST_SIZE]); -void sha1_transform(sha1_ctx *context, const uint8_t buffer[64]); +SQLITE_PRIVATE void sha1_transform(sha1_ctx *context, const uint8_t buffer[64]); #endif /* SHA1_H_ */ diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha2.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha2.c index 587cc39556..cf1300402f 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha2.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha2.c @@ -131,27 +131,27 @@ wv[h] = t1 + t2; \ } -uint32 sha224_h0[8] = +static uint32 sha224_h0[8] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}; -uint32 sha256_h0[8] = +static uint32 sha256_h0[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; -uint64 sha384_h0[8] = +static uint64 sha384_h0[8] = {li_64(cbbb9d5dc1059ed8), li_64(629a292a367cd507), li_64(9159015a3070dd17), li_64(152fecd8f70e5939), li_64(67332667ffc00b31), li_64(8eb44a8768581511), li_64(db0c2e0d64f98fa7), li_64(47b5481dbefa4fa4)}; -uint64 sha512_h0[8] = +static uint64 sha512_h0[8] = {li_64(6a09e667f3bcc908), li_64(bb67ae8584caa73b), li_64(3c6ef372fe94f82b), li_64(a54ff53a5f1d36f1), li_64(510e527fade682d1), li_64(9b05688c2b3e6c1f), li_64(1f83d9abfb41bd6b), li_64(5be0cd19137e2179)}; -uint32 sha256_k[64] = +static uint32 sha256_k[64] = {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, @@ -169,7 +169,7 @@ uint32 sha256_k[64] = 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; -uint64 sha512_k[80] = +static uint64 sha512_k[80] = {li_64(428a2f98d728ae22), li_64(7137449123ef65cd), li_64(b5c0fbcfec4d3b2f), li_64(e9b5dba58189dbbc), li_64(3956c25bf348b538), li_64(59f111f1b605d019), @@ -329,11 +329,13 @@ void sha256_transf(sha256_ctx *ctx, const unsigned char *message, } } +SQLITE_PRIVATE void sha256_transform(sha256_ctx *ctx, const unsigned char *message) { sha256_transf(ctx, message, 1); } +SQLITE_PRIVATE void sha256(const unsigned char *message, unsigned int len, unsigned char *digest) { sha256_ctx ctx; @@ -343,6 +345,7 @@ void sha256(const unsigned char *message, unsigned int len, unsigned char *diges sha256_final(&ctx, digest); } +SQLITE_PRIVATE void sha256_init(sha256_ctx *ctx) { #ifndef UNROLL_LOOPS @@ -361,6 +364,7 @@ void sha256_init(sha256_ctx *ctx) ctx->tot_len = 0; } +SQLITE_PRIVATE void sha256_update(sha256_ctx *ctx, const unsigned char *message, unsigned int len) { @@ -395,6 +399,7 @@ void sha256_update(sha256_ctx *ctx, const unsigned char *message, ctx->tot_len += (block_nb + 1) << 6; } +SQLITE_PRIVATE void sha256_final(sha256_ctx *ctx, unsigned char *digest) { unsigned int block_nb; @@ -531,11 +536,13 @@ void sha512_transf(sha512_ctx *ctx, const unsigned char *message, } } +SQLITE_PRIVATE void sha512_transform(sha512_ctx *ctx, const unsigned char *message) { sha512_transf(ctx, message, 1); } +SQLITE_PRIVATE void sha512(const unsigned char *message, unsigned int len, unsigned char *digest) { @@ -546,6 +553,7 @@ void sha512(const unsigned char *message, unsigned int len, sha512_final(&ctx, digest); } +SQLITE_PRIVATE void sha512_init(sha512_ctx *ctx) { #ifndef UNROLL_LOOPS @@ -564,6 +572,7 @@ void sha512_init(sha512_ctx *ctx) ctx->tot_len = 0; } +SQLITE_PRIVATE void sha512_update(sha512_ctx *ctx, const unsigned char *message, unsigned int len) { @@ -598,6 +607,7 @@ void sha512_update(sha512_ctx *ctx, const unsigned char *message, ctx->tot_len += (block_nb + 1) << 7; } +SQLITE_PRIVATE void sha512_final(sha512_ctx *ctx, unsigned char *digest) { unsigned int block_nb; @@ -638,6 +648,7 @@ void sha512_final(sha512_ctx *ctx, unsigned char *digest) /* SHA-384 functions */ +SQLITE_PRIVATE void sha384(const unsigned char *message, unsigned int len, unsigned char *digest) { @@ -648,6 +659,7 @@ void sha384(const unsigned char *message, unsigned int len, sha384_final(&ctx, digest); } +SQLITE_PRIVATE void sha384_init(sha384_ctx *ctx) { #ifndef UNROLL_LOOPS @@ -666,6 +678,7 @@ void sha384_init(sha384_ctx *ctx) ctx->tot_len = 0; } +SQLITE_PRIVATE void sha384_update(sha384_ctx *ctx, const unsigned char *message, unsigned int len) { @@ -700,6 +713,7 @@ void sha384_update(sha384_ctx *ctx, const unsigned char *message, ctx->tot_len += (block_nb + 1) << 7; } +SQLITE_PRIVATE void sha384_final(sha384_ctx *ctx, unsigned char *digest) { unsigned int block_nb; @@ -738,6 +752,7 @@ void sha384_final(sha384_ctx *ctx, unsigned char *digest) /* SHA-224 functions */ +SQLITE_PRIVATE void sha224(const unsigned char *message, unsigned int len, unsigned char *digest) { @@ -748,6 +763,7 @@ void sha224(const unsigned char *message, unsigned int len, sha224_final(&ctx, digest); } +SQLITE_PRIVATE void sha224_init(sha224_ctx *ctx) { #ifndef UNROLL_LOOPS @@ -766,6 +782,7 @@ void sha224_init(sha224_ctx *ctx) ctx->tot_len = 0; } +SQLITE_PRIVATE void sha224_update(sha224_ctx *ctx, const unsigned char *message, unsigned int len) { @@ -800,6 +817,7 @@ void sha224_update(sha224_ctx *ctx, const unsigned char *message, ctx->tot_len += (block_nb + 1) << 6; } +SQLITE_PRIVATE void sha224_final(sha224_ctx *ctx, unsigned char *digest) { unsigned int block_nb; @@ -963,4 +981,3 @@ int main() } #endif /* TEST_VECTORS */ - diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha2.h b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha2.h index 4e63b26b0b..07c12c76f4 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha2.h +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sha2.h @@ -34,6 +34,10 @@ #ifndef SHA2_H #define SHA2_H +#ifndef SQLITE_PRIVATE +#define SQLITE_PRIVATE +#endif + #define SHA224_DIGEST_SIZE ( 224 / 8) #define SHA256_DIGEST_SIZE ( 256 / 8) #define SHA384_DIGEST_SIZE ( 384 / 8) @@ -55,7 +59,7 @@ typedef sqlite3_uint64 uint64; #define li_64(h) 0x##h##ui64 #else #define li_64(h) 0x##h##ull -#endif +#endif #if 0 /* Start of original int64 defines */ @@ -127,35 +131,27 @@ typedef struct { typedef sha512_ctx sha384_ctx; typedef sha256_ctx sha224_ctx; -void sha224_init(sha224_ctx *ctx); -void sha224_update(sha224_ctx *ctx, const unsigned char *message, - unsigned int len); -void sha224_final(sha224_ctx *ctx, unsigned char *digest); -void sha224(const unsigned char *message, unsigned int len, - unsigned char *digest); - -void sha256_init(sha256_ctx * ctx); -void sha256_update(sha256_ctx *ctx, const unsigned char *message, - unsigned int len); -void sha256_final(sha256_ctx *ctx, unsigned char *digest); -void sha256_transform(sha256_ctx *ctx, const unsigned char *message); -void sha256(const unsigned char *message, unsigned int len, - unsigned char *digest); - -void sha384_init(sha384_ctx *ctx); -void sha384_update(sha384_ctx *ctx, const unsigned char *message, - unsigned int len); -void sha384_final(sha384_ctx *ctx, unsigned char *digest); -void sha384(const unsigned char *message, unsigned int len, - unsigned char *digest); - -void sha512_init(sha512_ctx *ctx); -void sha512_update(sha512_ctx *ctx, const unsigned char *message, - unsigned int len); -void sha512_final(sha512_ctx *ctx, unsigned char *digest); -void sha512_transform(sha512_ctx *ctx, const unsigned char *message); -void sha512(const unsigned char *message, unsigned int len, - unsigned char *digest); +SQLITE_PRIVATE void sha224_init(sha224_ctx *ctx); +SQLITE_PRIVATE void sha224_update(sha224_ctx *ctx, const unsigned char *message, unsigned int len); +SQLITE_PRIVATE void sha224_final(sha224_ctx *ctx, unsigned char *digest); +SQLITE_PRIVATE void sha224(const unsigned char *message, unsigned int len, unsigned char *digest); + +SQLITE_PRIVATE void sha256_init(sha256_ctx * ctx); +SQLITE_PRIVATE void sha256_update(sha256_ctx *ctx, const unsigned char *message, unsigned int len); +SQLITE_PRIVATE void sha256_final(sha256_ctx *ctx, unsigned char *digest); +SQLITE_PRIVATE void sha256_transform(sha256_ctx *ctx, const unsigned char *message); +SQLITE_PRIVATE void sha256(const unsigned char *message, unsigned int len, unsigned char *digest); + +SQLITE_PRIVATE void sha384_init(sha384_ctx *ctx); +SQLITE_PRIVATE void sha384_update(sha384_ctx *ctx, const unsigned char *message, unsigned int len); +SQLITE_PRIVATE void sha384_final(sha384_ctx *ctx, unsigned char *digest); +SQLITE_PRIVATE void sha384(const unsigned char *message, unsigned int len, unsigned char *digest); + +SQLITE_PRIVATE void sha512_init(sha512_ctx *ctx); +SQLITE_PRIVATE void sha512_update(sha512_ctx *ctx, const unsigned char *message, unsigned int len); +SQLITE_PRIVATE void sha512_final(sha512_ctx *ctx, unsigned char *digest); +SQLITE_PRIVATE void sha512_transform(sha512_ctx *ctx, const unsigned char *message); +SQLITE_PRIVATE void sha512(const unsigned char *message, unsigned int len, unsigned char *digest); #ifdef __cplusplus } diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/shathree.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/shathree.c index ba3ea581f8..b03d107d4b 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/shathree.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/shathree.c @@ -15,10 +15,20 @@ ** Two SQL functions are implemented: ** ** sha3(X,SIZE) -** sha3_query(Y,SIZE) +** sha3_agg(Y,SIZE) +** sha3_query(Z,SIZE) ** ** The sha3(X) function computes the SHA3 hash of the input X, or NULL if -** X is NULL. +** X is NULL. If inputs X is text, the UTF-8 rendering of that text is +** used to compute the hash. If X is a BLOB, then the binary data of the +** blob is used to compute the hash. If X is an integer or real number, +** then that number if converted into UTF-8 text and the hash is computed +** over the text. +** +** The sha3_agg(Y) function computes the SHA3 hash of all Y inputs. Since +** order is important for the hash, it is recommended that the Y expression +** by followed by an ORDER BY clause to guarantee that the inputs occur +** in the desired order. ** ** The sha3_query(Y) function evaluates all queries in the SQL statements of Y ** and returns a hash of their results. @@ -26,6 +36,68 @@ ** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm ** is used. If SIZE is included it must be one of the integers 224, 256, ** 384, or 512, to determine SHA3 hash variant that is computed. +** +** Because the sha3_agg() and sha3_query() functions compute a hash over +** multiple values, the values are encode to use include type information. +** +** In sha3_agg(), the sequence of bytes that gets hashed for each input +** Y depends on the datatype of Y: +** +** typeof(Y)='null' A single "N" is hashed. (One byte) +** +** typeof(Y)='integer' The data hash is the character "I" followed +** by an 8-byte big-endian binary of the +** 64-bit signed integer. (Nine bytes total.) +** +** typeof(Y)='real' The character "F" followed by an 8-byte +** big-ending binary of the double. (Nine +** bytes total.) +** +** typeof(Y)='text' The hash is over prefix "Tnnn:" followed +** by the UTF8 encoding of the text. The "nnn" +** in the prefix is the minimum-length decimal +** representation of the octet_length of the text. +** Notice the ":" at the end of the prefix, which +** is needed to separate the prefix from the +** content in cases where the content starts +** with a digit. +** +** typeof(Y)='blob' The hash is taken over prefix "Bnnn:" followed +** by the binary content of the blob. The "nnn" +** in the prefix is the mimimum-length decimal +** representation of the byte-length of the blob. +** +** According to the rules above, all of the following SELECT statements +** should return TRUE: +** +** SELECT sha3(1) = sha3('1'); +** +** SELECT sha3('hello') = sha3(x'68656c6c6f'); +** +** WITH a(x) AS (VALUES('xyzzy')) +** SELECT sha3_agg(x) = sha3('T5:xyzzy') FROM a; +** +** WITH a(x) AS (VALUES(x'010203')) +** SELECT sha3_agg(x) = sha3(x'42333a010203') FROM a; +** +** WITH a(x) AS (VALUES(0x123456)) +** SELECT sha3_agg(x) = sha3(x'490000000000123456') FROM a; +** +** WITH a(x) AS (VALUES(100.015625)) +** SELECT sha3_agg(x) = sha3(x'464059010000000000') FROM a; +** +** WITH a(x) AS (VALUES(NULL)) +** SELECT sha3_agg(x) = sha3('N') FROM a; +** +** +** In sha3_query(), individual column values are encoded as with +** sha3_agg(), but with the addition that a single "R" character is +** inserted at the start of each row. +** +** Note that sha3_agg() hashes rows for which Y is NULL. Add a FILTER +** clause if NULL rows should be excluded: +** +** SELECT sha3_agg(x ORDER BY rowid) FILTER(WHERE x NOT NULL) FROM t1; */ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 @@ -75,6 +147,7 @@ struct SHA3Context { unsigned nRate; /* Bytes of input accepted per Keccak iteration */ unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */ unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ + unsigned iSize; /* 224, 256, 358, or 512 */ }; /* @@ -404,6 +477,7 @@ static void KeccakF1600Step(SHA3Context *p){ */ static void SHA3Init(SHA3Context *p, int iSize){ memset(p, 0, sizeof(*p)); + p->iSize = iSize; if( iSize>=128 && iSize<=512 ){ p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; }else{ @@ -495,7 +569,7 @@ static unsigned char *SHA3Final(SHA3Context *p){ ** Implementation of the sha3(X,SIZE) function. ** ** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default -** size is 256. If X is a BLOB, it is hashed as is. +** size is 256. If X is a BLOB, it is hashed as is. ** For all other non-NULL types of input, X is converted into a UTF-8 string ** and the string is hashed without the trailing 0x00 terminator. The hash ** of a NULL value is NULL. @@ -547,6 +621,60 @@ static void sha3_step_vformat( SHA3Update(p, (unsigned char*)zBuf, n); } +/* +** Update a SHA3Context using a single sqlite3_value. +*/ +static void sha3UpdateFromValue(SHA3Context *p, sqlite3_value *pVal){ + switch( sqlite3_value_type(pVal) ){ + case SQLITE_NULL: { + SHA3Update(p, (const unsigned char*)"N",1); + break; + } + case SQLITE_INTEGER: { + sqlite3_uint64 u; + int j; + unsigned char x[9]; + sqlite3_int64 v = sqlite3_value_int64(pVal); + memcpy(&u, &v, 8); + for(j=8; j>=1; j--){ + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'I'; + SHA3Update(p, x, 9); + break; + } + case SQLITE_FLOAT: { + sqlite3_uint64 u; + int j; + unsigned char x[9]; + double r = sqlite3_value_double(pVal); + memcpy(&u, &r, 8); + for(j=8; j>=1; j--){ + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'F'; + SHA3Update(p,x,9); + break; + } + case SQLITE_TEXT: { + int n2 = sqlite3_value_bytes(pVal); + const unsigned char *z2 = sqlite3_value_text(pVal); + sha3_step_vformat(p,"T%d:",n2); + SHA3Update(p, z2, n2); + break; + } + case SQLITE_BLOB: { + int n2 = sqlite3_value_bytes(pVal); + const unsigned char *z2 = sqlite3_value_blob(pVal); + sha3_step_vformat(p,"B%d:",n2); + SHA3Update(p, z2, n2); + break; + } + } +} + /* ** Implementation of the sha3_query(SQL,SIZE) function. ** @@ -636,54 +764,7 @@ static void sha3QueryFunc( while( SQLITE_ROW==sqlite3_step(pStmt) ){ SHA3Update(&cx,(const unsigned char*)"R",1); for(i=0; i=1; j--){ - x[j] = u & 0xff; - u >>= 8; - } - x[0] = 'I'; - SHA3Update(&cx, x, 9); - break; - } - case SQLITE_FLOAT: { - sqlite3_uint64 u; - int j; - unsigned char x[9]; - double r = sqlite3_column_double(pStmt,i); - memcpy(&u, &r, 8); - for(j=8; j>=1; j--){ - x[j] = u & 0xff; - u >>= 8; - } - x[0] = 'F'; - SHA3Update(&cx,x,9); - break; - } - case SQLITE_TEXT: { - int n2 = sqlite3_column_bytes(pStmt, i); - const unsigned char *z2 = sqlite3_column_text(pStmt, i); - sha3_step_vformat(&cx,"T%d:",n2); - SHA3Update(&cx, z2, n2); - break; - } - case SQLITE_BLOB: { - int n2 = sqlite3_column_bytes(pStmt, i); - const unsigned char *z2 = sqlite3_column_blob(pStmt, i); - sha3_step_vformat(&cx,"B%d:",n2); - SHA3Update(&cx, z2, n2); - break; - } - } + sha3UpdateFromValue(&cx, sqlite3_column_value(pStmt,i)); } } sqlite3_finalize(pStmt); @@ -691,6 +772,44 @@ static void sha3QueryFunc( sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); } +/* +** xStep function for sha3_agg(). +*/ +static void sha3AggStep( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + SHA3Context *p; + p = (SHA3Context*)sqlite3_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + if( p->nRate==0 ){ + int sz = 256; + if( argc==2 ){ + sz = sqlite3_value_int(argv[1]); + if( sz!=224 && sz!=384 && sz!=512 ){ + sz = 256; + } + } + SHA3Init(p, sz); + } + sha3UpdateFromValue(p, argv[0]); +} + + +/* +** xFinal function for sha3_agg(). +*/ +static void sha3AggFinal(sqlite3_context *context){ + SHA3Context *p; + p = (SHA3Context*)sqlite3_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + if( p->iSize ){ + sqlite3_result_blob(context, SHA3Final(p), p->iSize/8, SQLITE_TRANSIENT); + } +} + + #ifdef _WIN32 __declspec(dllexport) @@ -711,6 +830,16 @@ int sqlite3_shathree_init( SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, 0, sha3Func, 0, 0); } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha3_agg", 1, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + 0, 0, sha3AggStep, sha3AggFinal); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha3_agg", 2, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + 0, 0, sha3AggStep, sha3AggFinal); + } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8 | SQLITE_DIRECTONLY, diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/shell.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/shell.c index dea16bdbd4..0d9c0a243e 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/shell.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/shell.c @@ -218,8 +218,6 @@ typedef unsigned char u8; # ifndef strdup # define strdup _strdup # endif -# undef popen -# define popen _popen # undef pclose # define pclose _pclose # endif @@ -263,19 +261,9 @@ extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR); extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText); #endif -/* Use console I/O package as a direct INCLUDE. */ -#define SQLITE_INTERNAL_LINKAGE static - -#ifdef SQLITE_SHELL_FIDDLE -/* Deselect most features from the console I/O package for Fiddle. */ -# define SQLITE_CIO_NO_REDIRECT -# define SQLITE_CIO_NO_CLASSIFY -# define SQLITE_CIO_NO_TRANSLATE -# define SQLITE_CIO_NO_SETMODE -#endif -/************************* Begin ../ext/consio/console_io.h ******************/ +/************************* Begin ../ext/misc/sqlite3_stdio.h ******************/ /* -** 2023 November 1 +** 2024-09-24 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -284,1081 +272,432 @@ extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText); ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** -******************************************************************************** -** This file exposes various interfaces used for console and other I/O -** by the SQLite project command-line tools. These interfaces are used -** at either source conglomeration time, compilation time, or run time. -** This source provides for either inclusion into conglomerated, -** "single-source" forms or separate compilation then linking. +************************************************************************* +** +** This header file contains definitions of interfaces that provide +** cross-platform I/O for UTF-8 content. ** -** Platform dependencies are "hidden" here by various stratagems so -** that, provided certain conditions are met, the programs using this -** source or object code compiled from it need no explicit conditional -** compilation in their source for their console and stream I/O. +** On most platforms, the interfaces definitions in this file are +** just #defines. For example sqlite3_fopen() is a macro that resolves +** to the standard fopen() in the C-library. ** -** The symbols and functionality exposed here are not a public API. -** This code may change in tandem with other project code as needed. +** But Windows does not have a standard C-library, at least not one that +** can handle UTF-8. So for windows build, the interfaces resolve to new +** C-language routines contained in the separate sqlite3_stdio.c source file. ** -** When this .h file and its companion .c are directly incorporated into -** a source conglomeration (such as shell.c), the preprocessor symbol -** CIO_WIN_WC_XLATE is defined as 0 or 1, reflecting whether console I/O -** translation for Windows is effected for the build. +** So on all non-Windows platforms, simply #include this header file and +** use the interfaces defined herein. Then to run your application on Windows, +** also link in the accompanying sqlite3_stdio.c source file when compiling +** to get compatible interfaces. */ +#ifndef _SQLITE3_STDIO_H_ +#define _SQLITE3_STDIO_H_ 1 +#ifdef _WIN32 +/**** Definitions For Windows ****/ +#include +#include -#ifndef SQLITE_INTERNAL_LINKAGE -# define SQLITE_INTERNAL_LINKAGE extern /* external to translation unit */ -# include -#else -# define SHELL_NO_SYSINC /* Better yet, modify mkshellc.tcl for this. */ -#endif +FILE *sqlite3_fopen(const char *zFilename, const char *zMode); +FILE *sqlite3_popen(const char *zCommand, const char *type); +char *sqlite3_fgets(char *s, int size, FILE *stream); +int sqlite3_fputs(const char *s, FILE *stream); +int sqlite3_fprintf(FILE *stream, const char *format, ...); +void sqlite3_fsetmode(FILE *stream, int mode); -#ifndef SQLITE3_H -/* # include "sqlite3.h" */ -#endif -#ifndef SQLITE_CIO_NO_CLASSIFY +#else +/**** Definitions For All Other Platforms ****/ +#include +#define sqlite3_fopen fopen +#define sqlite3_popen popen +#define sqlite3_fgets fgets +#define sqlite3_fputs fputs +#define sqlite3_fprintf fprintf +#define sqlite3_fsetmode(F,X) /*no-op*/ -/* Define enum for use with following function. */ -typedef enum StreamsAreConsole { - SAC_NoConsole = 0, - SAC_InConsole = 1, SAC_OutConsole = 2, SAC_ErrConsole = 4, - SAC_AnyConsole = 0x7 -} StreamsAreConsole; +#endif +#endif /* _SQLITE3_STDIO_H_ */ +/************************* End ../ext/misc/sqlite3_stdio.h ********************/ +/************************* Begin ../ext/misc/sqlite3_stdio.c ******************/ /* -** Classify the three standard I/O streams according to whether -** they are connected to a console attached to the process. +** 2024-09-24 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: ** -** Returns the bit-wise OR of SAC_{In,Out,Err}Console values, -** or SAC_NoConsole if none of the streams reaches a console. +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. ** -** This function should be called before any I/O is done with -** the given streams. As a side-effect, the given inputs are -** recorded so that later I/O operations on them may be done -** differently than the C library FILE* I/O would be done, -** iff the stream is used for the I/O functions that follow, -** and to support the ones that use an implicit stream. +************************************************************************* ** -** On some platforms, stream or console mode alteration (aka -** "Setup") may be made which is undone by consoleRestore(). +** Implementation of standard I/O interfaces for UTF-8 that are missing +** on Windows. */ -SQLITE_INTERNAL_LINKAGE StreamsAreConsole -consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ); -/* A usual call for convenience: */ -#define SQLITE_STD_CONSOLE_INIT() consoleClassifySetup(stdin,stdout,stderr) +#ifdef _WIN32 /* This file is a no-op on all platforms except Windows */ +#ifndef _SQLITE3_STDIO_H_ +/* #include "sqlite3_stdio.h" */ +#endif +#undef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +/* #include "sqlite3.h" */ +#include +#include +#include +#include /* -** After an initial call to consoleClassifySetup(...), renew -** the same setup it effected. (A call not after is an error.) -** This will restore state altered by consoleRestore(); -** -** Applications which run an inferior (child) process which -** inherits the same I/O streams may call this function after -** such a process exits to guard against console mode changes. -*/ -SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void); +** If the SQLITE_U8TEXT_ONLY option is defined, then use O_U8TEXT +** when appropriate on all output. (Sometimes use O_BINARY when +** rendering ASCII text in cases where NL-to-CRLF expansion would +** not be correct.) +** +** If the SQLITE_U8TEXT_STDIO option is defined, then use O_U8TEXT +** when appropriate when writing to stdout or stderr. Use O_BINARY +** or O_TEXT (depending on things like the .mode and the .crlf setting +** in the CLI, or other context clues in other applications) for all +** other output channels. +** +** The default behavior, if neither of the above is defined is to +** use O_U8TEXT when writing to the Windows console (or anything +** else for which _isatty() returns true) and to use O_BINARY or O_TEXT +** for all other output channels. +*/ +#if defined(SQLITE_U8TEXT_ONLY) +# define UseWtextForOutput(fd) 1 +# define UseWtextForInput(fd) 1 +# define IsConsole(fd) _isatty(_fileno(fd)) +#elif defined(SQLITE_U8TEXT_STDIO) +# define UseWtextForOutput(fd) ((fd)==stdout || (fd)==stderr) +# define UseWtextForInput(fd) ((fd)==stdin) +# define IsConsole(fd) _isatty(_fileno(fd)) +#else +# define UseWtextForOutput(fd) _isatty(_fileno(fd)) +# define UseWtextForInput(fd) _isatty(_fileno(fd)) +# define IsConsole(fd) 1 +#endif /* -** Undo any side-effects left by consoleClassifySetup(...). -** -** This should be called after consoleClassifySetup() and -** before the process terminates normally. It is suitable -** for use with the atexit() C library procedure. After -** this call, no console I/O should be done until one of -** console{Classify or Renew}Setup(...) is called again. -** -** Applications which run an inferior (child) process that -** inherits the same I/O streams might call this procedure -** before so that said process will have a console setup -** however users have configured it or come to expect. +** Global variables determine if simulated O_BINARY mode is to be +** used for stdout or other, respectively. Simulated O_BINARY mode +** means the mode is usually O_BINARY, but switches to O_U8TEXT for +** unicode characters U+0080 or greater (any character that has a +** multi-byte representation in UTF-8). This is the only way we +** have found to render Unicode characters on a Windows console while +** at the same time avoiding undesirable \n to \r\n translation. */ -SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void ); +static int simBinaryStdout = 0; +static int simBinaryOther = 0; -#else /* defined(SQLITE_CIO_NO_CLASSIFY) */ -# define consoleClassifySetup(i,o,e) -# define consoleRenewSetup() -# define consoleRestore() -#endif /* defined(SQLITE_CIO_NO_CLASSIFY) */ -#ifndef SQLITE_CIO_NO_REDIRECT /* -** Set stream to be used for the functions below which write -** to "the designated X stream", where X is Output or Error. -** Returns the previous value. -** -** Alternatively, pass the special value, invalidFileStream, -** to get the designated stream value without setting it. -** -** Before the designated streams are set, they default to -** those passed to consoleClassifySetup(...), and before -** that is called they default to stdout and stderr. -** -** It is error to close a stream so designated, then, without -** designating another, use the corresponding {o,e}Emit(...). +** Determine if simulated binary mode should be used for output to fd */ -SQLITE_INTERNAL_LINKAGE FILE *invalidFileStream; -SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf); -# ifdef CONSIO_SET_ERROR_STREAM -SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf); -# endif -#else -# define setOutputStream(pf) -# define setErrorStream(pf) -#endif /* !defined(SQLITE_CIO_NO_REDIRECT) */ +static int UseBinaryWText(FILE *fd){ + if( fd==stdout || fd==stderr ){ + return simBinaryStdout; + }else{ + return simBinaryOther; + } +} -#ifndef SQLITE_CIO_NO_TRANSLATE -/* -** Emit output like fprintf(). If the output is going to the -** console and translation from UTF-8 is necessary, perform -** the needed translation. Otherwise, write formatted output -** to the provided stream almost as-is, possibly with newline -** translation as specified by set{Binary,Text}Mode(). -*/ -SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...); -/* Like fPrintfUtf8 except stream is always the designated output. */ -SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...); -/* Like fPrintfUtf8 except stream is always the designated error. */ -SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...); /* -** Emit output like fputs(). If the output is going to the -** console and translation from UTF-8 is necessary, perform -** the needed translation. Otherwise, write given text to the -** provided stream almost as-is, possibly with newline -** translation as specified by set{Binary,Text}Mode(). +** Work-alike for the fopen() routine from the standard C library. */ -SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO); -/* Like fPutsUtf8 except stream is always the designated output. */ -SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z); -/* Like fPutsUtf8 except stream is always the designated error. */ -SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z); +FILE *sqlite3_fopen(const char *zFilename, const char *zMode){ + FILE *fp = 0; + wchar_t *b1, *b2; + int sz1, sz2; + + sz1 = (int)strlen(zFilename); + sz2 = (int)strlen(zMode); + b1 = malloc( (sz1+1)*sizeof(b1[0]) ); + b2 = malloc( (sz2+1)*sizeof(b1[0]) ); + if( b1 && b2 ){ + sz1 = MultiByteToWideChar(CP_UTF8, 0, zFilename, sz1, b1, sz1); + b1[sz1] = 0; + sz2 = MultiByteToWideChar(CP_UTF8, 0, zMode, sz2, b2, sz2); + b2[sz2] = 0; + fp = _wfopen(b1, b2); + } + free(b1); + free(b2); + simBinaryOther = 0; + return fp; +} -/* -** Emit output like fPutsUtf8(), except that the length of the -** accepted char or character sequence is limited by nAccept. -** -** Returns the number of accepted char values. -*/ -#ifdef CONSIO_SPUTB -SQLITE_INTERNAL_LINKAGE int -fPutbUtf8(FILE *pfOut, const char *cBuf, int nAccept); -#endif -/* Like fPutbUtf8 except stream is always the designated output. */ -SQLITE_INTERNAL_LINKAGE int -oPutbUtf8(const char *cBuf, int nAccept); -/* Like fPutbUtf8 except stream is always the designated error. */ -#ifdef CONSIO_EPUTB -SQLITE_INTERNAL_LINKAGE int -ePutbUtf8(const char *cBuf, int nAccept); -#endif /* -** Collect input like fgets(...) with special provisions for input -** from the console on platforms that require same. Defers to the -** C library fgets() when input is not from the console. Newline -** translation may be done as set by set{Binary,Text}Mode(). As a -** convenience, pfIn==NULL is treated as stdin. +** Work-alike for the popen() routine from the standard C library. */ -SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn); -/* Like fGetsUtf8 except stream is always the designated input. */ -/* SQLITE_INTERNAL_LINKAGE char* iGetsUtf8(char *cBuf, int ncMax); */ +FILE *sqlite3_popen(const char *zCommand, const char *zMode){ + FILE *fp = 0; + wchar_t *b1, *b2; + int sz1, sz2; -#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ + sz1 = (int)strlen(zCommand); + sz2 = (int)strlen(zMode); + b1 = malloc( (sz1+1)*sizeof(b1[0]) ); + b2 = malloc( (sz2+1)*sizeof(b1[0]) ); + if( b1 && b2 ){ + sz1 = MultiByteToWideChar(CP_UTF8, 0, zCommand, sz1, b1, sz1); + b1[sz1] = 0; + sz2 = MultiByteToWideChar(CP_UTF8, 0, zMode, sz2, b2, sz2); + b2[sz2] = 0; + fp = _wpopen(b1, b2); + } + free(b1); + free(b2); + return fp; +} -#ifndef SQLITE_CIO_NO_SETMODE /* -** Set given stream for binary mode, where newline translation is -** not done, or for text mode where, for some platforms, newlines -** are translated to the platform's conventional char sequence. -** If bFlush true, flush the stream. -** -** An additional side-effect is that if the stream is one passed -** to consoleClassifySetup() as an output, it is flushed first. -** -** Note that binary/text mode has no effect on console I/O -** translation. On all platforms, newline to the console starts -** a new line and CR,LF chars from the console become a newline. +** Work-alike for fgets() from the standard C library. */ -SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *, short bFlush); -SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *, short bFlush); -#endif - -#ifdef SQLITE_CIO_PROMPTED_IN -typedef struct Prompts { - int numPrompts; - const char **azPrompts; -} Prompts; +char *sqlite3_fgets(char *buf, int sz, FILE *in){ + if( UseWtextForInput(in) ){ + /* When reading from the command-prompt in Windows, it is necessary + ** to use _O_WTEXT input mode to read UTF-16 characters, then translate + ** that into UTF-8. Otherwise, non-ASCII characters all get translated + ** into '?'. + */ + wchar_t *b1 = malloc( sz*sizeof(wchar_t) ); + if( b1==0 ) return 0; + _setmode(_fileno(in), IsConsole(in) ? _O_WTEXT : _O_U8TEXT); + if( fgetws(b1, sz/4, in)==0 ){ + sqlite3_free(b1); + return 0; + } + WideCharToMultiByte(CP_UTF8, 0, b1, -1, buf, sz, 0, 0); + sqlite3_free(b1); + return buf; + }else{ + /* Reading from a file or other input source, just read bytes without + ** any translation. */ + return fgets(buf, sz, in); + } +} /* -** Macros for use of a line editor. -** -** The following macros define operations involving use of a -** line-editing library or simple console interaction. -** A "T" argument is a text (char *) buffer or filename. -** A "N" argument is an integer. -** -** SHELL_ADD_HISTORY(T) // Record text as line(s) of history. -** SHELL_READ_HISTORY(T) // Read history from file named by T. -** SHELL_WRITE_HISTORY(T) // Write history to file named by T. -** SHELL_STIFLE_HISTORY(N) // Limit history to N entries. -** -** A console program which does interactive console input is -** expected to call: -** SHELL_READ_HISTORY(T) before collecting such input; -** SHELL_ADD_HISTORY(T) as record-worthy input is taken; -** SHELL_STIFLE_HISTORY(N) after console input ceases; then -** SHELL_WRITE_HISTORY(T) before the program exits. +** Send ASCII text as O_BINARY. But for Unicode characters U+0080 and +** greater, switch to O_U8TEXT. */ +static void piecemealOutput(wchar_t *b1, int sz, FILE *out){ + int i; + wchar_t c; + while( sz>0 ){ + for(i=0; i=0x80; i++){} + if( i>0 ){ + c = b1[i]; + b1[i] = 0; + fflush(out); + _setmode(_fileno(out), _O_U8TEXT); + fputws(b1, out); + fflush(out); + b1 += i; + b1[0] = c; + sz -= i; + }else{ + fflush(out); + _setmode(_fileno(out), _O_TEXT); + _setmode(_fileno(out), _O_BINARY); + fwrite(&b1[0], 1, 1, out); + for(i=1; i=0 => char count, nAccept<0 => character - */ -SQLITE_INTERNAL_LINKAGE const char* -zSkipValidUtf8(const char *z, int nAccept, long ccm); - -#endif + va_start(ap, zFormat); + z = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + sqlite3_fputs(z, out); + rc = (int)strlen(z); + sqlite3_free(z); + }else{ + /* Writing to a file or other destination, just write bytes without + ** any translation. */ + va_list ap; + va_start(ap, zFormat); + rc = vfprintf(out, zFormat, ap); + va_end(ap); + } + return rc; +} -/************************* End ../ext/consio/console_io.h ********************/ -/************************* Begin ../ext/consio/console_io.c ******************/ /* -** 2023 November 4 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -******************************************************************************** -** This file implements various interfaces used for console and stream I/O -** by the SQLite project command-line tools, as explained in console_io.h . -** Functions prefixed by "SQLITE_INTERNAL_LINKAGE" behave as described there. +** Set the mode for an output stream. mode argument is typically _O_BINARY or +** _O_TEXT. */ +void sqlite3_fsetmode(FILE *fp, int mode){ + if( !UseWtextForOutput(fp) ){ + fflush(fp); + _setmode(_fileno(fp), mode); + }else if( fp==stdout || fp==stderr ){ + simBinaryStdout = (mode==_O_BINARY); + }else{ + simBinaryOther = (mode==_O_BINARY); + } +} -#ifndef SQLITE_CDECL -# define SQLITE_CDECL -#endif - -#ifndef SHELL_NO_SYSINC -# include -# include -# include -# include -# include -# include "console_io.h" -/* # include "sqlite3.h" */ -#endif +#endif /* defined(_WIN32) */ -#ifndef SQLITE_CIO_NO_TRANSLATE -# if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT -# ifndef SHELL_NO_SYSINC -# include -# include -# undef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# include -# endif -# define CIO_WIN_WC_XLATE 1 /* Use WCHAR Windows APIs for console I/O */ -# else -# ifndef SHELL_NO_SYSINC -# include -# endif -# define CIO_WIN_WC_XLATE 0 /* Use plain C library stream I/O at console */ -# endif -#else -# define CIO_WIN_WC_XLATE 0 /* Not exposing translation routines at all */ -#endif +/************************* End ../ext/misc/sqlite3_stdio.c ********************/ -#if CIO_WIN_WC_XLATE -/* Character used to represent a known-incomplete UTF-8 char group (�) */ -static WCHAR cBadGroup = 0xfffd; -#endif +/* Use console I/O package as a direct INCLUDE. */ +#define SQLITE_INTERNAL_LINKAGE static -#if CIO_WIN_WC_XLATE -static HANDLE handleOfFile(FILE *pf){ - int fileDesc = _fileno(pf); - union { intptr_t osfh; HANDLE fh; } fid = { - (fileDesc>=0)? _get_osfhandle(fileDesc) : (intptr_t)INVALID_HANDLE_VALUE - }; - return fid.fh; -} +#ifdef SQLITE_SHELL_FIDDLE +/* Deselect most features from the console I/O package for Fiddle. */ +# define SQLITE_CIO_NO_REDIRECT +# define SQLITE_CIO_NO_CLASSIFY +# define SQLITE_CIO_NO_TRANSLATE +# define SQLITE_CIO_NO_SETMODE +# define SQLITE_CIO_NO_FLUSH #endif -#ifndef SQLITE_CIO_NO_TRANSLATE -typedef struct PerStreamTags { -# if CIO_WIN_WC_XLATE - HANDLE hx; - DWORD consMode; - char acIncomplete[4]; -# else - short reachesConsole; -# endif - FILE *pf; -} PerStreamTags; - -/* Define NULL-like value for things which can validly be 0. */ -# define SHELL_INVALID_FILE_PTR ((FILE *)~0) -# if CIO_WIN_WC_XLATE -# define SHELL_INVALID_CONS_MODE 0xFFFF0000 -# endif +#define eputz(z) sqlite3_fputs(z,stderr) +#define sputz(fp,z) sqlite3_fputs(z,fp) -# if CIO_WIN_WC_XLATE -# define PST_INITIALIZER { INVALID_HANDLE_VALUE, SHELL_INVALID_CONS_MODE, \ - {0,0,0,0}, SHELL_INVALID_FILE_PTR } -# else -# define PST_INITIALIZER { 0, SHELL_INVALID_FILE_PTR } -# endif +/* True if the timer is enabled */ +static int enableTimer = 0; -/* Quickly say whether a known output is going to the console. */ -# if CIO_WIN_WC_XLATE -static short pstReachesConsole(PerStreamTags *ppst){ - return (ppst->hx != INVALID_HANDLE_VALUE); +/* A version of strcmp() that works with NULL values */ +static int cli_strcmp(const char *a, const char *b){ + if( a==0 ) a = ""; + if( b==0 ) b = ""; + return strcmp(a,b); } -# else -# define pstReachesConsole(ppst) 0 -# endif - -# if CIO_WIN_WC_XLATE -static void restoreConsoleArb(PerStreamTags *ppst){ - if( pstReachesConsole(ppst) ) SetConsoleMode(ppst->hx, ppst->consMode); +static int cli_strncmp(const char *a, const char *b, size_t n){ + if( a==0 ) a = ""; + if( b==0 ) b = ""; + return strncmp(a,b,n); } -# else -# define restoreConsoleArb(ppst) -# endif -/* Say whether FILE* appears to be a console, collect associated info. */ -static short streamOfConsole(FILE *pf, /* out */ PerStreamTags *ppst){ -# if CIO_WIN_WC_XLATE - short rv = 0; - DWORD dwCM = SHELL_INVALID_CONS_MODE; - HANDLE fh = handleOfFile(pf); - ppst->pf = pf; - if( INVALID_HANDLE_VALUE != fh ){ - rv = (GetFileType(fh) == FILE_TYPE_CHAR && GetConsoleMode(fh,&dwCM)); - } - ppst->hx = (rv)? fh : INVALID_HANDLE_VALUE; - ppst->consMode = dwCM; - return rv; -# else - ppst->pf = pf; - ppst->reachesConsole = ( (short)isatty(fileno(pf)) ); - return ppst->reachesConsole; -# endif +/* Return the current wall-clock time */ +static sqlite3_int64 timeOfDay(void){ + static sqlite3_vfs *clockVfs = 0; + sqlite3_int64 t; + if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); + if( clockVfs==0 ) return 0; /* Never actually happens */ + if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){ + clockVfs->xCurrentTimeInt64(clockVfs, &t); + }else{ + double r; + clockVfs->xCurrentTime(clockVfs, &r); + t = (sqlite3_int64)(r*86400000.0); + } + return t; } -# if CIO_WIN_WC_XLATE -/* Define console modes for use with the Windows Console API. */ -# define SHELL_CONI_MODE \ - (ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | 0x80 \ - | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT) -# define SHELL_CONO_MODE (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT \ - | ENABLE_VIRTUAL_TERMINAL_PROCESSING) -# endif - -typedef struct ConsoleInfo { - PerStreamTags pstSetup[3]; - PerStreamTags pstDesignated[3]; - StreamsAreConsole sacSetup; -} ConsoleInfo; - -static short isValidStreamInfo(PerStreamTags *ppst){ - return (ppst->pf != SHELL_INVALID_FILE_PTR); -} +#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) +#include +#include -static ConsoleInfo consoleInfo = { - { /* pstSetup */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER }, - { /* pstDesignated[] */ PST_INITIALIZER, PST_INITIALIZER, PST_INITIALIZER }, - SAC_NoConsole /* sacSetup */ +/* VxWorks does not support getrusage() as far as we can determine */ +#if defined(_WRS_KERNEL) || defined(__RTP__) +struct rusage { + struct timeval ru_utime; /* user CPU time used */ + struct timeval ru_stime; /* system CPU time used */ }; +#define getrusage(A,B) memset(B,0,sizeof(*B)) +#endif -SQLITE_INTERNAL_LINKAGE FILE* invalidFileStream = (FILE *)~0; -# if CIO_WIN_WC_XLATE -static void maybeSetupAsConsole(PerStreamTags *ppst, short odir){ - if( pstReachesConsole(ppst) ){ - DWORD cm = odir? SHELL_CONO_MODE : SHELL_CONI_MODE; - SetConsoleMode(ppst->hx, cm); - } -} -# else -# define maybeSetupAsConsole(ppst,odir) -# endif +/* Saved resource information for the beginning of an operation */ +static struct rusage sBegin; /* CPU time at start */ +static sqlite3_int64 iBegin; /* Wall-clock time at start */ -SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void){ -# if CIO_WIN_WC_XLATE - int ix = 0; - while( ix < 6 ){ - PerStreamTags *ppst = (ix<3)? - &consoleInfo.pstSetup[ix] : &consoleInfo.pstDesignated[ix-3]; - maybeSetupAsConsole(ppst, (ix % 3)>0); - ++ix; +/* +** Begin timing an operation +*/ +static void beginTimer(void){ + if( enableTimer ){ + getrusage(RUSAGE_SELF, &sBegin); + iBegin = timeOfDay(); } -# endif } -SQLITE_INTERNAL_LINKAGE StreamsAreConsole -consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ){ - StreamsAreConsole rv = SAC_NoConsole; - FILE* apf[3] = { pfIn, pfOut, pfErr }; - int ix; - for( ix = 2; ix >= 0; --ix ){ - PerStreamTags *ppst = &consoleInfo.pstSetup[ix]; - if( streamOfConsole(apf[ix], ppst) ){ - rv |= (SAC_InConsole< 0 ) fflush(apf[ix]); - } - consoleInfo.sacSetup = rv; - consoleRenewSetup(); - return rv; +/* Return the difference of two time_structs in seconds */ +static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ + return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + + (double)(pEnd->tv_sec - pStart->tv_sec); } -SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void ){ -# if CIO_WIN_WC_XLATE - static ConsoleInfo *pci = &consoleInfo; - if( pci->sacSetup ){ - int ix; - for( ix=0; ix<3; ++ix ){ - if( pci->sacSetup & (SAC_InConsole<pstSetup[ix]; - SetConsoleMode(ppst->hx, ppst->consMode); - } - } +/* +** Print the timing results. +*/ +static void endTimer(FILE *out){ + if( enableTimer ){ + sqlite3_int64 iEnd = timeOfDay(); + struct rusage sEnd; + getrusage(RUSAGE_SELF, &sEnd); + sqlite3_fprintf(out, "Run Time: real %.3f user %f sys %f\n", + (iEnd - iBegin)*0.001, + timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); } -# endif } -#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ -#ifdef SQLITE_CIO_INPUT_REDIR -/* Say whether given FILE* is among those known, via either -** consoleClassifySetup() or set{Output,Error}Stream, as -** readable, and return an associated PerStreamTags pointer -** if so. Otherwise, return 0. -*/ -static PerStreamTags * isKnownReadable(FILE *pf){ - static PerStreamTags *apst[] = { - &consoleInfo.pstDesignated[0], &consoleInfo.pstSetup[0], 0 - }; - int ix = 0; - do { - if( apst[ix]->pf == pf ) break; - } while( apst[++ix] != 0 ); - return apst[ix]; -} -#endif +#define BEGIN_TIMER beginTimer() +#define END_TIMER(X) endTimer(X) +#define HAS_TIMER 1 -#ifndef SQLITE_CIO_NO_TRANSLATE -/* Say whether given FILE* is among those known, via either -** consoleClassifySetup() or set{Output,Error}Stream, as -** writable, and return an associated PerStreamTags pointer -** if so. Otherwise, return 0. -*/ -static PerStreamTags * isKnownWritable(FILE *pf){ - static PerStreamTags *apst[] = { - &consoleInfo.pstDesignated[1], &consoleInfo.pstDesignated[2], - &consoleInfo.pstSetup[1], &consoleInfo.pstSetup[2], 0 - }; - int ix = 0; - do { - if( apst[ix]->pf == pf ) break; - } while( apst[++ix] != 0 ); - return apst[ix]; -} - -static FILE *designateEmitStream(FILE *pf, unsigned chix){ - FILE *rv = consoleInfo.pstDesignated[chix].pf; - if( pf == invalidFileStream ) return rv; - else{ - /* Setting a possibly new output stream. */ - PerStreamTags *ppst = isKnownWritable(pf); - if( ppst != 0 ){ - PerStreamTags pst = *ppst; - consoleInfo.pstDesignated[chix] = pst; - }else streamOfConsole(pf, &consoleInfo.pstDesignated[chix]); - } - return rv; -} - -SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf){ - return designateEmitStream(pf, 1); -} -# ifdef CONSIO_SET_ERROR_STREAM -SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf){ - return designateEmitStream(pf, 2); -} -# endif -#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ - -#ifndef SQLITE_CIO_NO_SETMODE -# if CIO_WIN_WC_XLATE -static void setModeFlushQ(FILE *pf, short bFlush, int mode){ - if( bFlush ) fflush(pf); - _setmode(_fileno(pf), mode); -} -# else -# define setModeFlushQ(f, b, m) if(b) fflush(f) -# endif - -SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *pf, short bFlush){ - setModeFlushQ(pf, bFlush, _O_BINARY); -} -SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *pf, short bFlush){ - setModeFlushQ(pf, bFlush, _O_TEXT); -} -# undef setModeFlushQ - -#else /* defined(SQLITE_CIO_NO_SETMODE) */ -# define setBinaryMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0) -# define setTextMode(f, bFlush) do{ if((bFlush)) fflush(f); }while(0) -#endif /* defined(SQLITE_CIO_NO_SETMODE) */ - -#ifndef SQLITE_CIO_NO_TRANSLATE -# if CIO_WIN_WC_XLATE -/* Write buffer cBuf as output to stream known to reach console, -** limited to ncTake char's. Return ncTake on success, else 0. */ -static int conZstrEmit(PerStreamTags *ppst, const char *z, int ncTake){ - int rv = 0; - if( z!=NULL ){ - int nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, 0,0); - if( nwc > 0 ){ - WCHAR *zw = sqlite3_malloc64(nwc*sizeof(WCHAR)); - if( zw!=NULL ){ - nwc = MultiByteToWideChar(CP_UTF8,0, z,ncTake, zw,nwc); - if( nwc > 0 ){ - /* Translation from UTF-8 to UTF-16, then WCHARs out. */ - if( WriteConsoleW(ppst->hx, zw,nwc, 0, NULL) ){ - rv = ncTake; - } - } - sqlite3_free(zw); - } - } - } - return rv; -} - -/* For {f,o,e}PrintfUtf8() when stream is known to reach console. */ -static int conioVmPrintf(PerStreamTags *ppst, const char *zFormat, va_list ap){ - char *z = sqlite3_vmprintf(zFormat, ap); - if( z ){ - int rv = conZstrEmit(ppst, z, (int)strlen(z)); - sqlite3_free(z); - return rv; - }else return 0; -} -# endif /* CIO_WIN_WC_XLATE */ - -# ifdef CONSIO_GET_EMIT_STREAM -static PerStreamTags * getDesignatedEmitStream(FILE *pf, unsigned chix, - PerStreamTags *ppst){ - PerStreamTags *rv = isKnownWritable(pf); - short isValid = (rv!=0)? isValidStreamInfo(rv) : 0; - if( rv != 0 && isValid ) return rv; - streamOfConsole(pf, ppst); - return ppst; -} -# endif - -/* Get stream info, either for designated output or error stream when -** chix equals 1 or 2, or for an arbitrary stream when chix == 0. -** In either case, ppst references a caller-owned PerStreamTags -** struct which may be filled in if none of the known writable -** streams is being held by consoleInfo. The ppf parameter is a -** byref output when chix!=0 and a byref input when chix==0. - */ -static PerStreamTags * -getEmitStreamInfo(unsigned chix, PerStreamTags *ppst, - /* in/out */ FILE **ppf){ - PerStreamTags *ppstTry; - FILE *pfEmit; - if( chix > 0 ){ - ppstTry = &consoleInfo.pstDesignated[chix]; - if( !isValidStreamInfo(ppstTry) ){ - ppstTry = &consoleInfo.pstSetup[chix]; - pfEmit = ppst->pf; - }else pfEmit = ppstTry->pf; - if( !isValidStreamInfo(ppstTry) ){ - pfEmit = (chix > 1)? stderr : stdout; - ppstTry = ppst; - streamOfConsole(pfEmit, ppstTry); - } - *ppf = pfEmit; - }else{ - ppstTry = isKnownWritable(*ppf); - if( ppstTry != 0 ) return ppstTry; - streamOfConsole(*ppf, ppst); - return ppst; - } - return ppstTry; -} - -SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...){ - va_list ap; - int rv; - FILE *pfOut; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut); -# else - getEmitStreamInfo(1, &pst, &pfOut); -# endif - assert(zFormat!=0); - va_start(ap, zFormat); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - rv = conioVmPrintf(ppst, zFormat, ap); - }else{ -# endif - rv = vfprintf(pfOut, zFormat, ap); -# if CIO_WIN_WC_XLATE - } -# endif - va_end(ap); - return rv; -} - -SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...){ - va_list ap; - int rv; - FILE *pfErr; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr); -# else - getEmitStreamInfo(2, &pst, &pfErr); -# endif - assert(zFormat!=0); - va_start(ap, zFormat); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - rv = conioVmPrintf(ppst, zFormat, ap); - }else{ -# endif - rv = vfprintf(pfErr, zFormat, ap); -# if CIO_WIN_WC_XLATE - } -# endif - va_end(ap); - return rv; -} - -SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...){ - va_list ap; - int rv; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO); -# else - getEmitStreamInfo(0, &pst, &pfO); -# endif - assert(zFormat!=0); - va_start(ap, zFormat); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - maybeSetupAsConsole(ppst, 1); - rv = conioVmPrintf(ppst, zFormat, ap); - if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst); - }else{ -# endif - rv = vfprintf(pfO, zFormat, ap); -# if CIO_WIN_WC_XLATE - } -# endif - va_end(ap); - return rv; -} - -SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO){ - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO); -# else - getEmitStreamInfo(0, &pst, &pfO); -# endif - assert(z!=0); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - int rv; - maybeSetupAsConsole(ppst, 1); - rv = conZstrEmit(ppst, z, (int)strlen(z)); - if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst); - return rv; - }else { -# endif - return (fputs(z, pfO)<0)? 0 : (int)strlen(z); -# if CIO_WIN_WC_XLATE - } -# endif -} - -SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z){ - FILE *pfErr; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr); -# else - getEmitStreamInfo(2, &pst, &pfErr); -# endif - assert(z!=0); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z)); - else { -# endif - return (fputs(z, pfErr)<0)? 0 : (int)strlen(z); -# if CIO_WIN_WC_XLATE - } -# endif -} - -SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z){ - FILE *pfOut; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut); -# else - getEmitStreamInfo(1, &pst, &pfOut); -# endif - assert(z!=0); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ) return conZstrEmit(ppst, z, (int)strlen(z)); - else { -# endif - return (fputs(z, pfOut)<0)? 0 : (int)strlen(z); -# if CIO_WIN_WC_XLATE - } -# endif -} - -#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ - -#if !(defined(SQLITE_CIO_NO_UTF8SCAN) && defined(SQLITE_CIO_NO_TRANSLATE)) -/* Skip over as much z[] input char sequence as is valid UTF-8, -** limited per nAccept char's or whole characters and containing -** no char cn such that ((1<=0 => char count, nAccept<0 => character - */ -SQLITE_INTERNAL_LINKAGE const char* -zSkipValidUtf8(const char *z, int nAccept, long ccm){ - int ng = (nAccept<0)? -nAccept : 0; - const char *pcLimit = (nAccept>=0)? z+nAccept : 0; - assert(z!=0); - while( (pcLimit)? (z= pcLimit ) return z; - else{ - char ct = *zt++; - if( ct==0 || (zt-z)>4 || (ct & 0xC0)!=0x80 ){ - /* Trailing bytes are too few, too many, or invalid. */ - return z; - } - } - } while( ((c <<= 1) & 0x40) == 0x40 ); /* Eat lead byte's count. */ - z = zt; - } - } - return z; -} -#endif /*!(defined(SQLITE_CIO_NO_UTF8SCAN)&&defined(SQLITE_CIO_NO_TRANSLATE))*/ - -#ifndef SQLITE_CIO_NO_TRANSLATE - -#ifdef CONSIO_SPUTB -SQLITE_INTERNAL_LINKAGE int -fPutbUtf8(FILE *pfO, const char *cBuf, int nAccept){ - assert(pfO!=0); -# if CIO_WIN_WC_XLATE - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ - PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO); - if( pstReachesConsole(ppst) ){ - int rv; - maybeSetupAsConsole(ppst, 1); - rv = conZstrEmit(ppst, cBuf, nAccept); - if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst); - return rv; - }else { -# endif - return (int)fwrite(cBuf, 1, nAccept, pfO); -# if CIO_WIN_WC_XLATE - } -# endif -} -#endif /* defined(CONSIO_SPUTB) */ - -SQLITE_INTERNAL_LINKAGE int -oPutbUtf8(const char *cBuf, int nAccept){ - FILE *pfOut; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ -# if CIO_WIN_WC_XLATE - PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut); -# else - getEmitStreamInfo(1, &pst, &pfOut); -# endif -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - return conZstrEmit(ppst, cBuf, nAccept); - }else { -# endif - return (int)fwrite(cBuf, 1, nAccept, pfOut); -# if CIO_WIN_WC_XLATE - } -# endif -} - -# ifdef CONSIO_EPUTB -SQLITE_INTERNAL_LINKAGE int -ePutbUtf8(const char *cBuf, int nAccept){ - FILE *pfErr; - PerStreamTags pst = PST_INITIALIZER; /* for unknown streams */ - PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr); -# if CIO_WIN_WC_XLATE - if( pstReachesConsole(ppst) ){ - return conZstrEmit(ppst, cBuf, nAccept); - }else { -# endif - return (int)fwrite(cBuf, 1, nAccept, pfErr); -# if CIO_WIN_WC_XLATE - } -# endif -} -# endif /* defined(CONSIO_EPUTB) */ - -SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){ - if( pfIn==0 ) pfIn = stdin; -# if CIO_WIN_WC_XLATE - if( pfIn == consoleInfo.pstSetup[0].pf - && (consoleInfo.sacSetup & SAC_InConsole)!=0 ){ -# if CIO_WIN_WC_XLATE==1 -# define SHELL_GULP 150 /* Count of WCHARS to be gulped at a time */ - WCHAR wcBuf[SHELL_GULP+1]; - int lend = 0, noc = 0; - if( ncMax > 0 ) cBuf[0] = 0; - while( noc < ncMax-8-1 && !lend ){ - /* There is room for at least 2 more characters and a 0-terminator. */ - int na = (ncMax > SHELL_GULP*4+1 + noc)? SHELL_GULP : (ncMax-1 - noc)/4; -# undef SHELL_GULP - DWORD nbr = 0; - BOOL bRC = ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf, na, &nbr, 0); - if( bRC && nbr>0 && (wcBuf[nbr-1]&0xF800)==0xD800 ){ - /* Last WHAR read is first of a UTF-16 surrogate pair. Grab its mate. */ - DWORD nbrx; - bRC &= ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf+nbr, 1, &nbrx, 0); - if( bRC ) nbr += nbrx; - } - if( !bRC || (noc==0 && nbr==0) ) return 0; - if( nbr > 0 ){ - int nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,0,0,0,0); - if( nmb != 0 && noc+nmb <= ncMax ){ - int iseg = noc; - nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,cBuf+noc,nmb,0,0); - noc += nmb; - /* Fixup line-ends as coded by Windows for CR (or "Enter".) - ** This is done without regard for any setMode{Text,Binary}() - ** call that might have been done on the interactive input. - */ - if( noc > 0 ){ - if( cBuf[noc-1]=='\n' ){ - lend = 1; - if( noc > 1 && cBuf[noc-2]=='\r' ) cBuf[--noc-1] = '\n'; - } - } - /* Check for ^Z (anywhere in line) too, to act as EOF. */ - while( iseg < noc ){ - if( cBuf[iseg]=='\x1a' ){ - noc = iseg; /* Chop ^Z and anything following. */ - lend = 1; /* Counts as end of line too. */ - break; - } - ++iseg; - } - }else break; /* Drop apparent garbage in. (Could assert.) */ - }else break; - } - /* If got nothing, (after ^Z chop), must be at end-of-file. */ - if( noc > 0 ){ - cBuf[noc] = 0; - return cBuf; - }else return 0; -# endif - }else{ -# endif - return fgets(cBuf, ncMax, pfIn); -# if CIO_WIN_WC_XLATE - } -# endif -} -#endif /* !defined(SQLITE_CIO_NO_TRANSLATE) */ - -#undef SHELL_INVALID_FILE_PTR - -/************************* End ../ext/consio/console_io.c ********************/ - -#ifndef SQLITE_SHELL_FIDDLE -/* From here onward, fgets() is redirected to the console_io library. */ -# define fgets(b,n,f) fGetsUtf8(b,n,f) -/* - * Define macros for emitting output text in various ways: - * sputz(s, z) => emit 0-terminated string z to given stream s - * sputf(s, f, ...) => emit varargs per format f to given stream s - * oputz(z) => emit 0-terminated string z to default stream - * oputf(f, ...) => emit varargs per format f to default stream - * eputz(z) => emit 0-terminated string z to error stream - * eputf(f, ...) => emit varargs per format f to error stream - * oputb(b, n) => emit char buffer b[0..n-1] to default stream - * - * Note that the default stream is whatever has been last set via: - * setOutputStream(FILE *pf) - * This is normally the stream that CLI normal output goes to. - * For the stand-alone CLI, it is stdout with no .output redirect. - */ -# define sputz(s,z) fPutsUtf8(z,s) -# define sputf fPrintfUtf8 -# define oputz(z) oPutsUtf8(z) -# define oputf oPrintfUtf8 -# define eputz(z) ePutsUtf8(z) -# define eputf ePrintfUtf8 -# define oputb(buf,na) oPutbUtf8(buf,na) -#else -/* For Fiddle, all console handling and emit redirection is omitted. */ -# define sputz(fp,z) fputs(z,fp) -# define sputf(fp,fmt, ...) fprintf(fp,fmt,__VA_ARGS__) -# define oputz(z) fputs(z,stdout) -# define oputf(fmt, ...) printf(fmt,__VA_ARGS__) -# define eputz(z) fputs(z,stderr) -# define eputf(fmt, ...) fprintf(stderr,fmt,__VA_ARGS__) -# define oputb(buf,na) fwrite(buf,1,na,stdout) -#endif - -/* True if the timer is enabled */ -static int enableTimer = 0; - -/* A version of strcmp() that works with NULL values */ -static int cli_strcmp(const char *a, const char *b){ - if( a==0 ) a = ""; - if( b==0 ) b = ""; - return strcmp(a,b); -} -static int cli_strncmp(const char *a, const char *b, size_t n){ - if( a==0 ) a = ""; - if( b==0 ) b = ""; - return strncmp(a,b,n); -} - -/* Return the current wall-clock time */ -static sqlite3_int64 timeOfDay(void){ - static sqlite3_vfs *clockVfs = 0; - sqlite3_int64 t; - if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); - if( clockVfs==0 ) return 0; /* Never actually happens */ - if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){ - clockVfs->xCurrentTimeInt64(clockVfs, &t); - }else{ - double r; - clockVfs->xCurrentTime(clockVfs, &r); - t = (sqlite3_int64)(r*86400000.0); - } - return t; -} - -#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux) -#include -#include - -/* VxWorks does not support getrusage() as far as we can determine */ -#if defined(_WRS_KERNEL) || defined(__RTP__) -struct rusage { - struct timeval ru_utime; /* user CPU time used */ - struct timeval ru_stime; /* system CPU time used */ -}; -#define getrusage(A,B) memset(B,0,sizeof(*B)) -#endif - -/* Saved resource information for the beginning of an operation */ -static struct rusage sBegin; /* CPU time at start */ -static sqlite3_int64 iBegin; /* Wall-clock time at start */ - -/* -** Begin timing an operation -*/ -static void beginTimer(void){ - if( enableTimer ){ - getrusage(RUSAGE_SELF, &sBegin); - iBegin = timeOfDay(); - } -} - -/* Return the difference of two time_structs in seconds */ -static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ - return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + - (double)(pEnd->tv_sec - pStart->tv_sec); -} - -/* -** Print the timing results. -*/ -static void endTimer(void){ - if( enableTimer ){ - sqlite3_int64 iEnd = timeOfDay(); - struct rusage sEnd; - getrusage(RUSAGE_SELF, &sEnd); - oputf("Run Time: real %.3f user %f sys %f\n", - (iEnd - iBegin)*0.001, - timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), - timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); - } -} - -#define BEGIN_TIMER beginTimer() -#define END_TIMER endTimer() -#define HAS_TIMER 1 - -#elif (defined(_WIN32) || defined(WIN32)) +#elif (defined(_WIN32) || defined(WIN32)) /* Saved resource information for the beginning of an operation */ static HANDLE hProcess; @@ -1421,12 +760,12 @@ static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ /* ** Print the timing results. */ -static void endTimer(void){ +static void endTimer(FILE *out){ if( enableTimer && getProcessTimesAddr){ FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; sqlite3_int64 ftWallEnd = timeOfDay(); getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd); - oputf("Run Time: real %.3f user %f sys %f\n", + sqlite3_fprintf(out, "Run Time: real %.3f user %f sys %f\n", (ftWallEnd - ftWallBegin)*0.001, timeDiff(&ftUserBegin, &ftUserEnd), timeDiff(&ftKernelBegin, &ftKernelEnd)); @@ -1434,12 +773,12 @@ static void endTimer(void){ } #define BEGIN_TIMER beginTimer() -#define END_TIMER endTimer() +#define END_TIMER(X) endTimer(X) #define HAS_TIMER hasTimer() #else #define BEGIN_TIMER -#define END_TIMER +#define END_TIMER(X) /*no-op*/ #define HAS_TIMER 0 #endif @@ -1512,6 +851,14 @@ static char *shell_strncpy(char *dest, const char *src, size_t n){ return dest; } +/* +** strcpy() workalike to squelch an unwarranted link-time warning +** from OpenBSD. +*/ +static void shell_strcpy(char *dest, const char *src){ + while( (*(dest++) = *(src++))!=0 ){} +} + /* ** Optionally disable dynamic continuation prompt. ** Unless disabled, the continuation prompt shows open SQL lexemes if any, @@ -1577,7 +924,7 @@ static char *dynamicContinuePrompt(void){ size_t ncp = strlen(continuePrompt); size_t ndp = strlen(dynPrompt.zScannerAwaits); if( ndp > ncp-3 ) return continuePrompt; - strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits); + shell_strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits); while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' '; shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, PROMPT_LEN_MAX-4); @@ -1632,37 +979,212 @@ static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){ va_start(ap, zFormat); z = sqlite3_vmprintf(zFormat, ap); va_end(ap); - sputf(iotrace, "%s", z); + sqlite3_fprintf(iotrace, "%s", z); sqlite3_free(z); } #endif +/* Lookup table to estimate the number of columns consumed by a Unicode +** character. +*/ +static const struct { + unsigned char w; /* Width of the character in columns */ + int iFirst; /* First character in a span having this width */ +} aUWidth[] = { + /* {1, 0x00000}, */ + {0, 0x00300}, {1, 0x00370}, {0, 0x00483}, {1, 0x00487}, {0, 0x00488}, + {1, 0x0048a}, {0, 0x00591}, {1, 0x005be}, {0, 0x005bf}, {1, 0x005c0}, + {0, 0x005c1}, {1, 0x005c3}, {0, 0x005c4}, {1, 0x005c6}, {0, 0x005c7}, + {1, 0x005c8}, {0, 0x00600}, {1, 0x00604}, {0, 0x00610}, {1, 0x00616}, + {0, 0x0064b}, {1, 0x0065f}, {0, 0x00670}, {1, 0x00671}, {0, 0x006d6}, + {1, 0x006e5}, {0, 0x006e7}, {1, 0x006e9}, {0, 0x006ea}, {1, 0x006ee}, + {0, 0x0070f}, {1, 0x00710}, {0, 0x00711}, {1, 0x00712}, {0, 0x00730}, + {1, 0x0074b}, {0, 0x007a6}, {1, 0x007b1}, {0, 0x007eb}, {1, 0x007f4}, + {0, 0x00901}, {1, 0x00903}, {0, 0x0093c}, {1, 0x0093d}, {0, 0x00941}, + {1, 0x00949}, {0, 0x0094d}, {1, 0x0094e}, {0, 0x00951}, {1, 0x00955}, + {0, 0x00962}, {1, 0x00964}, {0, 0x00981}, {1, 0x00982}, {0, 0x009bc}, + {1, 0x009bd}, {0, 0x009c1}, {1, 0x009c5}, {0, 0x009cd}, {1, 0x009ce}, + {0, 0x009e2}, {1, 0x009e4}, {0, 0x00a01}, {1, 0x00a03}, {0, 0x00a3c}, + {1, 0x00a3d}, {0, 0x00a41}, {1, 0x00a43}, {0, 0x00a47}, {1, 0x00a49}, + {0, 0x00a4b}, {1, 0x00a4e}, {0, 0x00a70}, {1, 0x00a72}, {0, 0x00a81}, + {1, 0x00a83}, {0, 0x00abc}, {1, 0x00abd}, {0, 0x00ac1}, {1, 0x00ac6}, + {0, 0x00ac7}, {1, 0x00ac9}, {0, 0x00acd}, {1, 0x00ace}, {0, 0x00ae2}, + {1, 0x00ae4}, {0, 0x00b01}, {1, 0x00b02}, {0, 0x00b3c}, {1, 0x00b3d}, + {0, 0x00b3f}, {1, 0x00b40}, {0, 0x00b41}, {1, 0x00b44}, {0, 0x00b4d}, + {1, 0x00b4e}, {0, 0x00b56}, {1, 0x00b57}, {0, 0x00b82}, {1, 0x00b83}, + {0, 0x00bc0}, {1, 0x00bc1}, {0, 0x00bcd}, {1, 0x00bce}, {0, 0x00c3e}, + {1, 0x00c41}, {0, 0x00c46}, {1, 0x00c49}, {0, 0x00c4a}, {1, 0x00c4e}, + {0, 0x00c55}, {1, 0x00c57}, {0, 0x00cbc}, {1, 0x00cbd}, {0, 0x00cbf}, + {1, 0x00cc0}, {0, 0x00cc6}, {1, 0x00cc7}, {0, 0x00ccc}, {1, 0x00cce}, + {0, 0x00ce2}, {1, 0x00ce4}, {0, 0x00d41}, {1, 0x00d44}, {0, 0x00d4d}, + {1, 0x00d4e}, {0, 0x00dca}, {1, 0x00dcb}, {0, 0x00dd2}, {1, 0x00dd5}, + {0, 0x00dd6}, {1, 0x00dd7}, {0, 0x00e31}, {1, 0x00e32}, {0, 0x00e34}, + {1, 0x00e3b}, {0, 0x00e47}, {1, 0x00e4f}, {0, 0x00eb1}, {1, 0x00eb2}, + {0, 0x00eb4}, {1, 0x00eba}, {0, 0x00ebb}, {1, 0x00ebd}, {0, 0x00ec8}, + {1, 0x00ece}, {0, 0x00f18}, {1, 0x00f1a}, {0, 0x00f35}, {1, 0x00f36}, + {0, 0x00f37}, {1, 0x00f38}, {0, 0x00f39}, {1, 0x00f3a}, {0, 0x00f71}, + {1, 0x00f7f}, {0, 0x00f80}, {1, 0x00f85}, {0, 0x00f86}, {1, 0x00f88}, + {0, 0x00f90}, {1, 0x00f98}, {0, 0x00f99}, {1, 0x00fbd}, {0, 0x00fc6}, + {1, 0x00fc7}, {0, 0x0102d}, {1, 0x01031}, {0, 0x01032}, {1, 0x01033}, + {0, 0x01036}, {1, 0x01038}, {0, 0x01039}, {1, 0x0103a}, {0, 0x01058}, + {1, 0x0105a}, {2, 0x01100}, {0, 0x01160}, {1, 0x01200}, {0, 0x0135f}, + {1, 0x01360}, {0, 0x01712}, {1, 0x01715}, {0, 0x01732}, {1, 0x01735}, + {0, 0x01752}, {1, 0x01754}, {0, 0x01772}, {1, 0x01774}, {0, 0x017b4}, + {1, 0x017b6}, {0, 0x017b7}, {1, 0x017be}, {0, 0x017c6}, {1, 0x017c7}, + {0, 0x017c9}, {1, 0x017d4}, {0, 0x017dd}, {1, 0x017de}, {0, 0x0180b}, + {1, 0x0180e}, {0, 0x018a9}, {1, 0x018aa}, {0, 0x01920}, {1, 0x01923}, + {0, 0x01927}, {1, 0x01929}, {0, 0x01932}, {1, 0x01933}, {0, 0x01939}, + {1, 0x0193c}, {0, 0x01a17}, {1, 0x01a19}, {0, 0x01b00}, {1, 0x01b04}, + {0, 0x01b34}, {1, 0x01b35}, {0, 0x01b36}, {1, 0x01b3b}, {0, 0x01b3c}, + {1, 0x01b3d}, {0, 0x01b42}, {1, 0x01b43}, {0, 0x01b6b}, {1, 0x01b74}, + {0, 0x01dc0}, {1, 0x01dcb}, {0, 0x01dfe}, {1, 0x01e00}, {0, 0x0200b}, + {1, 0x02010}, {0, 0x0202a}, {1, 0x0202f}, {0, 0x02060}, {1, 0x02064}, + {0, 0x0206a}, {1, 0x02070}, {0, 0x020d0}, {1, 0x020f0}, {2, 0x02329}, + {1, 0x0232b}, {2, 0x02e80}, {0, 0x0302a}, {2, 0x03030}, {1, 0x0303f}, + {2, 0x03040}, {0, 0x03099}, {2, 0x0309b}, {1, 0x0a4d0}, {0, 0x0a806}, + {1, 0x0a807}, {0, 0x0a80b}, {1, 0x0a80c}, {0, 0x0a825}, {1, 0x0a827}, + {2, 0x0ac00}, {1, 0x0d7a4}, {2, 0x0f900}, {1, 0x0fb00}, {0, 0x0fb1e}, + {1, 0x0fb1f}, {0, 0x0fe00}, {2, 0x0fe10}, {1, 0x0fe1a}, {0, 0x0fe20}, + {1, 0x0fe24}, {2, 0x0fe30}, {1, 0x0fe70}, {0, 0x0feff}, {2, 0x0ff00}, + {1, 0x0ff61}, {2, 0x0ffe0}, {1, 0x0ffe7}, {0, 0x0fff9}, {1, 0x0fffc}, + {0, 0x10a01}, {1, 0x10a04}, {0, 0x10a05}, {1, 0x10a07}, {0, 0x10a0c}, + {1, 0x10a10}, {0, 0x10a38}, {1, 0x10a3b}, {0, 0x10a3f}, {1, 0x10a40}, + {0, 0x1d167}, {1, 0x1d16a}, {0, 0x1d173}, {1, 0x1d183}, {0, 0x1d185}, + {1, 0x1d18c}, {0, 0x1d1aa}, {1, 0x1d1ae}, {0, 0x1d242}, {1, 0x1d245}, + {2, 0x20000}, {1, 0x2fffe}, {2, 0x30000}, {1, 0x3fffe}, {0, 0xe0001}, + {1, 0xe0002}, {0, 0xe0020}, {1, 0xe0080}, {0, 0xe0100}, {1, 0xe01f0} +}; + /* -** Output string zUtf to Out stream as w characters. If w is negative, -** then right-justify the text. W is the width in UTF-8 characters, not -** in bytes. This is different from the %*.*s specification in printf -** since with %*.*s the width is measured in bytes, not characters. +** Return an estimate of the width, in columns, for the single Unicode +** character c. For normal characters, the answer is always 1. But the +** estimate might be 0 or 2 for zero-width and double-width characters. +** +** Different display devices display unicode using different widths. So +** it is impossible to know that true display width with 100% accuracy. +** Inaccuracies in the width estimates might cause columns to be misaligned. +** Unfortunately, there is nothing we can do about that. */ -static void utf8_width_print(int w, const char *zUtf){ - int i; - int n; - int aw = w<0 ? -w : w; - if( zUtf==0 ) zUtf = ""; - for(i=n=0; zUtf[i]; i++){ - if( (zUtf[i]&0xc0)!=0x80 ){ - n++; - if( n==aw ){ - do{ i++; }while( (zUtf[i]&0xc0)==0x80 ); +int cli_wcwidth(int c){ + int iFirst, iLast; + + /* Fast path for common characters */ + if( c<=0x300 ) return 1; + + /* The general case */ + iFirst = 0; + iLast = sizeof(aUWidth)/sizeof(aUWidth[0]) - 1; + while( iFirst c ){ + iLast = iMid - 1; + }else{ + return aUWidth[iMid].w; + } + } + if( aUWidth[iLast].iFirst > c ) return aUWidth[iFirst].w; + return aUWidth[iLast].w; +} + +/* +** Compute the value and length of a multi-byte UTF-8 character that +** begins at z[0]. Return the length. Write the Unicode value into *pU. +** +** This routine only works for *multi-byte* UTF-8 characters. +*/ +static int decodeUtf8(const unsigned char *z, int *pU){ + if( (z[0] & 0xe0)==0xc0 && (z[1] & 0xc0)==0x80 ){ + *pU = ((z[0] & 0x1f)<<6) | (z[1] & 0x3f); + return 2; + } + if( (z[0] & 0xf0)==0xe0 && (z[1] & 0xc0)==0x80 && (z[2] & 0xc0)==0x80 ){ + *pU = ((z[0] & 0x0f)<<12) | ((z[1] & 0x3f)<<6) | (z[2] & 0x3f); + return 3; + } + if( (z[0] & 0xf8)==0xf0 && (z[1] & 0xc0)==0x80 && (z[2] & 0xc0)==0x80 + && (z[3] & 0xc0)==0x80 + ){ + *pU = ((z[0] & 0x0f)<<18) | ((z[1] & 0x3f)<<12) | ((z[2] & 0x3f))<<6 + | (z[4] & 0x3f); + return 4; + } + *pU = 0; + return 1; +} + + +#if 0 /* NOT USED */ +/* +** Return the width, in display columns, of a UTF-8 string. +** +** Each normal character counts as 1. Zero-width characters count +** as zero, and double-width characters count as 2. +*/ +int cli_wcswidth(const char *z){ + const unsigned char *a = (const unsigned char*)z; + int n = 0; + int i = 0; + unsigned char c; + while( (c = a[i])!=0 ){ + if( c>=0xc0 ){ + int u; + int len = decodeUtf8(&a[i], &u); + i += len; + n += cli_wcwidth(u); + }else if( c>=' ' ){ + n++; + i++; + }else{ + i++; + } + } + return n; +} +#endif + +/* +** Output string zUtf to stdout as w characters. If w is negative, +** then right-justify the text. W is the width in UTF-8 characters, not +** in bytes. This is different from the %*.*s specification in printf +** since with %*.*s the width is measured in bytes, not characters. +** +** Take into account zero-width and double-width Unicode characters. +** In other words, a zero-width character does not count toward the +** the w limit. A double-width character counts as two. +*/ +static void utf8_width_print(FILE *out, int w, const char *zUtf){ + const unsigned char *a = (const unsigned char*)zUtf; + unsigned char c; + int i = 0; + int n = 0; + int aw = w<0 ? -w : w; + if( zUtf==0 ) zUtf = ""; + while( (c = a[i])!=0 ){ + if( (c&0xc0)==0xc0 ){ + int u; + int len = decodeUtf8(a+i, &u); + int x = cli_wcwidth(u); + if( x+n>aw ){ break; } + i += len; + n += x; + }else if( n>=aw ){ + break; + }else{ + n++; + i++; } } if( n>=aw ){ - oputf("%.*s", i, zUtf); + sqlite3_fprintf(out, "%.*s", i, zUtf); }else if( w<0 ){ - oputf("%*s%s", aw-n, "", zUtf); + sqlite3_fprintf(out, "%*s%s", aw-n, "", zUtf); }else{ - oputf("%s%*s", zUtf, aw-n, ""); + sqlite3_fprintf(out, "%s%*s", zUtf, aw-n, ""); } } @@ -1723,14 +1245,14 @@ static int strlenChar(const char *z){ */ static FILE * openChrSource(const char *zFile){ #if defined(_WIN32) || defined(WIN32) - struct _stat x = {0}; + struct __stat64 x = {0}; # define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0) /* On Windows, open first, then check the stream nature. This order ** is necessary because _stat() and sibs, when checking a named pipe, ** effectively break the pipe as its supplier sees it. */ - FILE *rv = fopen(zFile, "rb"); + FILE *rv = sqlite3_fopen(zFile, "rb"); if( rv==0 ) return 0; - if( _fstat(_fileno(rv), &x) != 0 + if( _fstat64(_fileno(rv), &x) != 0 || !STAT_CHR_SRC(x.st_mode)){ fclose(rv); rv = 0; @@ -1742,7 +1264,7 @@ static FILE * openChrSource(const char *zFile){ # define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode)) if( rc!=0 ) return 0; if( STAT_CHR_SRC(x.st_mode) ){ - return fopen(zFile, "rb"); + return sqlite3_fopen(zFile, "rb"); }else{ return 0; } @@ -1769,7 +1291,7 @@ static char *local_getline(char *zLine, FILE *in){ zLine = realloc(zLine, nLine); shell_check_oom(zLine); } - if( fgets(&zLine[n], nLine - n, in)==0 ){ + if( sqlite3_fgets(&zLine[n], nLine - n, in)==0 ){ if( n==0 ){ free(zLine); return 0; @@ -2562,7 +2084,7 @@ static FILE *memtraceOut; /* Methods that trace memory allocations */ static void *memtraceMalloc(int n){ if( memtraceOut ){ - fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", + fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", memtraceBase.xRoundup(n)); } return memtraceBase.xMalloc(n); @@ -2838,10 +2360,20 @@ int sqlite3PcacheTraceDeactivate(void){ ** Two SQL functions are implemented: ** ** sha3(X,SIZE) -** sha3_query(Y,SIZE) +** sha3_agg(Y,SIZE) +** sha3_query(Z,SIZE) ** ** The sha3(X) function computes the SHA3 hash of the input X, or NULL if -** X is NULL. +** X is NULL. If inputs X is text, the UTF-8 rendering of that text is +** used to compute the hash. If X is a BLOB, then the binary data of the +** blob is used to compute the hash. If X is an integer or real number, +** then that number if converted into UTF-8 text and the hash is computed +** over the text. +** +** The sha3_agg(Y) function computes the SHA3 hash of all Y inputs. Since +** order is important for the hash, it is recommended that the Y expression +** by followed by an ORDER BY clause to guarantee that the inputs occur +** in the desired order. ** ** The sha3_query(Y) function evaluates all queries in the SQL statements of Y ** and returns a hash of their results. @@ -2849,6 +2381,68 @@ int sqlite3PcacheTraceDeactivate(void){ ** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm ** is used. If SIZE is included it must be one of the integers 224, 256, ** 384, or 512, to determine SHA3 hash variant that is computed. +** +** Because the sha3_agg() and sha3_query() functions compute a hash over +** multiple values, the values are encode to use include type information. +** +** In sha3_agg(), the sequence of bytes that gets hashed for each input +** Y depends on the datatype of Y: +** +** typeof(Y)='null' A single "N" is hashed. (One byte) +** +** typeof(Y)='integer' The data hash is the character "I" followed +** by an 8-byte big-endian binary of the +** 64-bit signed integer. (Nine bytes total.) +** +** typeof(Y)='real' The character "F" followed by an 8-byte +** big-ending binary of the double. (Nine +** bytes total.) +** +** typeof(Y)='text' The hash is over prefix "Tnnn:" followed +** by the UTF8 encoding of the text. The "nnn" +** in the prefix is the minimum-length decimal +** representation of the octet_length of the text. +** Notice the ":" at the end of the prefix, which +** is needed to separate the prefix from the +** content in cases where the content starts +** with a digit. +** +** typeof(Y)='blob' The hash is taken over prefix "Bnnn:" followed +** by the binary content of the blob. The "nnn" +** in the prefix is the mimimum-length decimal +** representation of the byte-length of the blob. +** +** According to the rules above, all of the following SELECT statements +** should return TRUE: +** +** SELECT sha3(1) = sha3('1'); +** +** SELECT sha3('hello') = sha3(x'68656c6c6f'); +** +** WITH a(x) AS (VALUES('xyzzy')) +** SELECT sha3_agg(x) = sha3('T5:xyzzy') FROM a; +** +** WITH a(x) AS (VALUES(x'010203')) +** SELECT sha3_agg(x) = sha3(x'42333a010203') FROM a; +** +** WITH a(x) AS (VALUES(0x123456)) +** SELECT sha3_agg(x) = sha3(x'490000000000123456') FROM a; +** +** WITH a(x) AS (VALUES(100.015625)) +** SELECT sha3_agg(x) = sha3(x'464059010000000000') FROM a; +** +** WITH a(x) AS (VALUES(NULL)) +** SELECT sha3_agg(x) = sha3('N') FROM a; +** +** +** In sha3_query(), individual column values are encoded as with +** sha3_agg(), but with the addition that a single "R" character is +** inserted at the start of each row. +** +** Note that sha3_agg() hashes rows for which Y is NULL. Add a FILTER +** clause if NULL rows should be excluded: +** +** SELECT sha3_agg(x ORDER BY rowid) FILTER(WHERE x NOT NULL) FROM t1; */ /* #include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 @@ -2898,6 +2492,7 @@ struct SHA3Context { unsigned nRate; /* Bytes of input accepted per Keccak iteration */ unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */ unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */ + unsigned iSize; /* 224, 256, 358, or 512 */ }; /* @@ -3227,6 +2822,7 @@ static void KeccakF1600Step(SHA3Context *p){ */ static void SHA3Init(SHA3Context *p, int iSize){ memset(p, 0, sizeof(*p)); + p->iSize = iSize; if( iSize>=128 && iSize<=512 ){ p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; }else{ @@ -3318,7 +2914,7 @@ static unsigned char *SHA3Final(SHA3Context *p){ ** Implementation of the sha3(X,SIZE) function. ** ** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default -** size is 256. If X is a BLOB, it is hashed as is. +** size is 256. If X is a BLOB, it is hashed as is. ** For all other non-NULL types of input, X is converted into a UTF-8 string ** and the string is hashed without the trailing 0x00 terminator. The hash ** of a NULL value is NULL. @@ -3370,6 +2966,60 @@ static void sha3_step_vformat( SHA3Update(p, (unsigned char*)zBuf, n); } +/* +** Update a SHA3Context using a single sqlite3_value. +*/ +static void sha3UpdateFromValue(SHA3Context *p, sqlite3_value *pVal){ + switch( sqlite3_value_type(pVal) ){ + case SQLITE_NULL: { + SHA3Update(p, (const unsigned char*)"N",1); + break; + } + case SQLITE_INTEGER: { + sqlite3_uint64 u; + int j; + unsigned char x[9]; + sqlite3_int64 v = sqlite3_value_int64(pVal); + memcpy(&u, &v, 8); + for(j=8; j>=1; j--){ + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'I'; + SHA3Update(p, x, 9); + break; + } + case SQLITE_FLOAT: { + sqlite3_uint64 u; + int j; + unsigned char x[9]; + double r = sqlite3_value_double(pVal); + memcpy(&u, &r, 8); + for(j=8; j>=1; j--){ + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'F'; + SHA3Update(p,x,9); + break; + } + case SQLITE_TEXT: { + int n2 = sqlite3_value_bytes(pVal); + const unsigned char *z2 = sqlite3_value_text(pVal); + sha3_step_vformat(p,"T%d:",n2); + SHA3Update(p, z2, n2); + break; + } + case SQLITE_BLOB: { + int n2 = sqlite3_value_bytes(pVal); + const unsigned char *z2 = sqlite3_value_blob(pVal); + sha3_step_vformat(p,"B%d:",n2); + SHA3Update(p, z2, n2); + break; + } + } +} + /* ** Implementation of the sha3_query(SQL,SIZE) function. ** @@ -3459,54 +3109,7 @@ static void sha3QueryFunc( while( SQLITE_ROW==sqlite3_step(pStmt) ){ SHA3Update(&cx,(const unsigned char*)"R",1); for(i=0; i=1; j--){ - x[j] = u & 0xff; - u >>= 8; - } - x[0] = 'I'; - SHA3Update(&cx, x, 9); - break; - } - case SQLITE_FLOAT: { - sqlite3_uint64 u; - int j; - unsigned char x[9]; - double r = sqlite3_column_double(pStmt,i); - memcpy(&u, &r, 8); - for(j=8; j>=1; j--){ - x[j] = u & 0xff; - u >>= 8; - } - x[0] = 'F'; - SHA3Update(&cx,x,9); - break; - } - case SQLITE_TEXT: { - int n2 = sqlite3_column_bytes(pStmt, i); - const unsigned char *z2 = sqlite3_column_text(pStmt, i); - sha3_step_vformat(&cx,"T%d:",n2); - SHA3Update(&cx, z2, n2); - break; - } - case SQLITE_BLOB: { - int n2 = sqlite3_column_bytes(pStmt, i); - const unsigned char *z2 = sqlite3_column_blob(pStmt, i); - sha3_step_vformat(&cx,"B%d:",n2); - SHA3Update(&cx, z2, n2); - break; - } - } + sha3UpdateFromValue(&cx, sqlite3_column_value(pStmt,i)); } } sqlite3_finalize(pStmt); @@ -3514,6 +3117,44 @@ static void sha3QueryFunc( sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT); } +/* +** xStep function for sha3_agg(). +*/ +static void sha3AggStep( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + SHA3Context *p; + p = (SHA3Context*)sqlite3_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + if( p->nRate==0 ){ + int sz = 256; + if( argc==2 ){ + sz = sqlite3_value_int(argv[1]); + if( sz!=224 && sz!=384 && sz!=512 ){ + sz = 256; + } + } + SHA3Init(p, sz); + } + sha3UpdateFromValue(p, argv[0]); +} + + +/* +** xFinal function for sha3_agg(). +*/ +static void sha3AggFinal(sqlite3_context *context){ + SHA3Context *p; + p = (SHA3Context*)sqlite3_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + if( p->iSize ){ + sqlite3_result_blob(context, SHA3Final(p), p->iSize/8, SQLITE_TRANSIENT); + } +} + + #ifdef _WIN32 @@ -3534,6 +3175,16 @@ int sqlite3_shathree_init( SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, 0, sha3Func, 0, 0); } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha3_agg", 1, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + 0, 0, sha3AggStep, sha3AggFinal); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha3_agg", 2, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + 0, 0, sha3AggStep, sha3AggFinal); + } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8 | SQLITE_DIRECTONLY, @@ -3548,9 +3199,9 @@ int sqlite3_shathree_init( } /************************* End ../ext/misc/shathree.c ********************/ -/************************* Begin ../ext/misc/uint.c ******************/ +/************************* Begin ../ext/misc/sha1.c ******************/ /* -** 2020-04-14 +** 2017-01-27 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -3561,92 +3212,504 @@ int sqlite3_shathree_init( ** ****************************************************************************** ** -** This SQLite extension implements the UINT collating sequence. -** -** UINT works like BINARY for text, except that embedded strings -** of digits compare in numeric order. +** This SQLite extension implements functions that compute SHA1 hashes. +** Two SQL functions are implemented: ** -** * Leading zeros are handled properly, in the sense that -** they do not mess of the maginitude comparison of embedded -** strings of digits. "x00123y" is equal to "x123y". +** sha1(X) +** sha1_query(Y) ** -** * Only unsigned integers are recognized. Plus and minus -** signs are ignored. Decimal points and exponential notation -** are ignored. +** The sha1(X) function computes the SHA1 hash of the input X, or NULL if +** X is NULL. ** -** * Embedded integers can be of arbitrary length. Comparison -** is *not* limited integers that can be expressed as a -** 64-bit machine integer. +** The sha1_query(Y) function evalutes all queries in the SQL statements of Y +** and returns a hash of their results. */ /* #include "sqlite3ext.h" */ SQLITE_EXTENSION_INIT1 #include #include -#include +#include -/* -** Compare text in lexicographic order, except strings of digits -** compare in numeric order. +/****************************************************************************** +** The Hash Engine */ -static int uintCollFunc( - void *notUsed, - int nKey1, const void *pKey1, - int nKey2, const void *pKey2 +/* Context for the SHA1 hash */ +typedef struct SHA1Context SHA1Context; +struct SHA1Context { + unsigned int state[5]; + unsigned int count[2]; + unsigned char buffer[64]; +}; + +#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r)) +#define rol(x,k) SHA_ROT(x,k,32-(k)) +#define ror(x,k) SHA_ROT(x,32-(k),k) + +#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \ + |(rol(block[i],8)&0x00FF00FF)) +#define blk0be(i) block[i] +#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \ + ^block[(i+2)&15]^block[i&15],1)) + +/* + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 + * + * Rl0() for little-endian and Rb0() for big-endian. Endianness is + * determined at run-time. + */ +#define Rl0(v,w,x,y,z,i) \ + z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2); +#define Rb0(v,w,x,y,z,i) \ + z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2); +#define R1(v,w,x,y,z,i) \ + z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2); +#define R2(v,w,x,y,z,i) \ + z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2); +#define R3(v,w,x,y,z,i) \ + z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2); +#define R4(v,w,x,y,z,i) \ + z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2); + +/* + * Hash a single 512-bit block. This is the core of the algorithm. + */ +static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]){ + unsigned int qq[5]; /* a, b, c, d, e; */ + static int one = 1; + unsigned int block[16]; + memcpy(block, buffer, 64); + memcpy(qq,state,5*sizeof(unsigned int)); + +#define a qq[0] +#define b qq[1] +#define c qq[2] +#define d qq[3] +#define e qq[4] + + /* Copy p->state[] to working vars */ + /* + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + */ + + /* 4 rounds of 20 operations each. Loop unrolled. */ + if( 1 == *(unsigned char*)&one ){ + Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3); + Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7); + Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11); + Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15); + }else{ + Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3); + Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7); + Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11); + Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15); + } + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + +#undef a +#undef b +#undef c +#undef d +#undef e +} + + +/* Initialize a SHA1 context */ +static void hash_init(SHA1Context *p){ + /* SHA1 initialization constants */ + p->state[0] = 0x67452301; + p->state[1] = 0xEFCDAB89; + p->state[2] = 0x98BADCFE; + p->state[3] = 0x10325476; + p->state[4] = 0xC3D2E1F0; + p->count[0] = p->count[1] = 0; +} + +/* Add new content to the SHA1 hash */ +static void hash_step( + SHA1Context *p, /* Add content to this context */ + const unsigned char *data, /* Data to be added */ + unsigned int len /* Number of bytes in data */ ){ - const unsigned char *zA = (const unsigned char*)pKey1; - const unsigned char *zB = (const unsigned char*)pKey2; - int i=0, j=0, x; - (void)notUsed; - while( icount[0]; + if( (p->count[0] += len << 3) < j ){ + p->count[1] += (len>>29)+1; + } + j = (j >> 3) & 63; + if( (j + len) > 63 ){ + (void)memcpy(&p->buffer[j], data, (i = 64-j)); + SHA1Transform(p->state, p->buffer); + for(; i + 63 < len; i += 64){ + SHA1Transform(p->state, &data[i]); } + j = 0; + }else{ + i = 0; } - return (nKey1 - i) - (nKey2 - j); + (void)memcpy(&p->buffer[j], &data[i], len - i); } -#ifdef _WIN32 - -#endif -int sqlite3_uint_init( - sqlite3 *db, - char **pzErrMsg, - const sqlite3_api_routines *pApi +/* Compute a string using sqlite3_vsnprintf() and hash it */ +static void hash_step_vformat( + SHA1Context *p, /* Add content to this context */ + const char *zFormat, + ... ){ - SQLITE_EXTENSION_INIT2(pApi); - (void)pzErrMsg; /* Unused parameter */ - return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc); + va_list ap; + int n; + char zBuf[50]; + va_start(ap, zFormat); + sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap); + va_end(ap); + n = (int)strlen(zBuf); + hash_step(p, (unsigned char*)zBuf, n); } -/************************* End ../ext/misc/uint.c ********************/ -/************************* Begin ../ext/misc/decimal.c ******************/ -/* -** 2020-06-22 -** + +/* Add padding and compute the message digest. Render the +** message digest as lower-case hexadecimal and put it into +** zOut[]. zOut[] must be at least 41 bytes long. */ +static void hash_finish( + SHA1Context *p, /* The SHA1 context to finish and render */ + char *zOut, /* Store hex or binary hash here */ + int bAsBinary /* 1 for binary hash, 0 for hex hash */ +){ + unsigned int i; + unsigned char finalcount[8]; + unsigned char digest[20]; + static const char zEncode[] = "0123456789abcdef"; + + for (i = 0; i < 8; i++){ + finalcount[i] = (unsigned char)((p->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + hash_step(p, (const unsigned char *)"\200", 1); + while ((p->count[0] & 504) != 448){ + hash_step(p, (const unsigned char *)"\0", 1); + } + hash_step(p, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++){ + digest[i] = (unsigned char)((p->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + if( bAsBinary ){ + memcpy(zOut, digest, 20); + }else{ + for(i=0; i<20; i++){ + zOut[i*2] = zEncode[(digest[i]>>4)&0xf]; + zOut[i*2+1] = zEncode[digest[i] & 0xf]; + } + zOut[i*2]= 0; + } +} +/* End of the hashing logic +*****************************************************************************/ + +/* +** Implementation of the sha1(X) function. +** +** Return a lower-case hexadecimal rendering of the SHA1 hash of the +** argument X. If X is a BLOB, it is hashed as is. For all other +** types of input, X is converted into a UTF-8 string and the string +** is hash without the trailing 0x00 terminator. The hash of a NULL +** value is NULL. +*/ +static void sha1Func( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + SHA1Context cx; + int eType = sqlite3_value_type(argv[0]); + int nByte = sqlite3_value_bytes(argv[0]); + char zOut[44]; + + assert( argc==1 ); + if( eType==SQLITE_NULL ) return; + hash_init(&cx); + if( eType==SQLITE_BLOB ){ + hash_step(&cx, sqlite3_value_blob(argv[0]), nByte); + }else{ + hash_step(&cx, sqlite3_value_text(argv[0]), nByte); + } + if( sqlite3_user_data(context)!=0 ){ + hash_finish(&cx, zOut, 1); + sqlite3_result_blob(context, zOut, 20, SQLITE_TRANSIENT); + }else{ + hash_finish(&cx, zOut, 0); + sqlite3_result_blob(context, zOut, 40, SQLITE_TRANSIENT); + } +} + +/* +** Implementation of the sha1_query(SQL) function. +** +** This function compiles and runs the SQL statement(s) given in the +** argument. The results are hashed using SHA1 and that hash is returned. +** +** The original SQL text is included as part of the hash. +** +** The hash is not just a concatenation of the outputs. Each query +** is delimited and each row and value within the query is delimited, +** with all values being marked with their datatypes. +*/ +static void sha1QueryFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_context_db_handle(context); + const char *zSql = (const char*)sqlite3_value_text(argv[0]); + sqlite3_stmt *pStmt = 0; + int nCol; /* Number of columns in the result set */ + int i; /* Loop counter */ + int rc; + int n; + const char *z; + SHA1Context cx; + char zOut[44]; + + assert( argc==1 ); + if( zSql==0 ) return; + hash_init(&cx); + while( zSql[0] ){ + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql); + if( rc ){ + char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s", + zSql, sqlite3_errmsg(db)); + sqlite3_finalize(pStmt); + sqlite3_result_error(context, zMsg, -1); + sqlite3_free(zMsg); + return; + } + if( !sqlite3_stmt_readonly(pStmt) ){ + char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt)); + sqlite3_finalize(pStmt); + sqlite3_result_error(context, zMsg, -1); + sqlite3_free(zMsg); + return; + } + nCol = sqlite3_column_count(pStmt); + z = sqlite3_sql(pStmt); + n = (int)strlen(z); + hash_step_vformat(&cx,"S%d:",n); + hash_step(&cx,(unsigned char*)z,n); + + /* Compute a hash over the result of the query */ + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + hash_step(&cx,(const unsigned char*)"R",1); + for(i=0; i=1; j--){ + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'I'; + hash_step(&cx, x, 9); + break; + } + case SQLITE_FLOAT: { + sqlite3_uint64 u; + int j; + unsigned char x[9]; + double r = sqlite3_column_double(pStmt,i); + memcpy(&u, &r, 8); + for(j=8; j>=1; j--){ + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'F'; + hash_step(&cx,x,9); + break; + } + case SQLITE_TEXT: { + int n2 = sqlite3_column_bytes(pStmt, i); + const unsigned char *z2 = sqlite3_column_text(pStmt, i); + hash_step_vformat(&cx,"T%d:",n2); + hash_step(&cx, z2, n2); + break; + } + case SQLITE_BLOB: { + int n2 = sqlite3_column_bytes(pStmt, i); + const unsigned char *z2 = sqlite3_column_blob(pStmt, i); + hash_step_vformat(&cx,"B%d:",n2); + hash_step(&cx, z2, n2); + break; + } + } + } + } + sqlite3_finalize(pStmt); + } + hash_finish(&cx, zOut, 0); + sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT); +} + + +#ifdef _WIN32 + +#endif +int sqlite3_sha_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int rc = SQLITE_OK; + static int one = 1; + SQLITE_EXTENSION_INIT2(pApi); + (void)pzErrMsg; /* Unused parameter */ + rc = sqlite3_create_function(db, "sha1", 1, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + 0, sha1Func, 0, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha1b", 1, + SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC, + (void*)&one, sha1Func, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "sha1_query", 1, + SQLITE_UTF8|SQLITE_DIRECTONLY, 0, + sha1QueryFunc, 0, 0); + } + return rc; +} + +/************************* End ../ext/misc/sha1.c ********************/ +/************************* Begin ../ext/misc/uint.c ******************/ +/* +** 2020-04-14 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This SQLite extension implements the UINT collating sequence. +** +** UINT works like BINARY for text, except that embedded strings +** of digits compare in numeric order. +** +** * Leading zeros are handled properly, in the sense that +** they do not mess of the maginitude comparison of embedded +** strings of digits. "x00123y" is equal to "x123y". +** +** * Only unsigned integers are recognized. Plus and minus +** signs are ignored. Decimal points and exponential notation +** are ignored. +** +** * Embedded integers can be of arbitrary length. Comparison +** is *not* limited integers that can be expressed as a +** 64-bit machine integer. +*/ +/* #include "sqlite3ext.h" */ +SQLITE_EXTENSION_INIT1 +#include +#include +#include + +/* +** Compare text in lexicographic order, except strings of digits +** compare in numeric order. +*/ +static int uintCollFunc( + void *notUsed, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 +){ + const unsigned char *zA = (const unsigned char*)pKey1; + const unsigned char *zB = (const unsigned char*)pKey2; + int i=0, j=0, x; + (void)notUsed; + while( inFrac = 0; } } - if( iExp>0 ){ + if( iExp>0 ){ p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 ); if( p->a==0 ) goto new_from_text_failed; memset(p->a+p->nDigit, 0, iExp); @@ -4164,7 +4227,7 @@ static void decimalMul(Decimal *pA, Decimal *pB){ int minFrac; if( pA==0 || pA->oom || pA->isNull - || pB==0 || pB->oom || pB->isNull + || pB==0 || pB->oom || pB->isNull ){ goto mul_end; } @@ -4450,7 +4513,7 @@ static void decimalMulFunc( Decimal *pB = decimal_new(context, argv[1], 1); UNUSED_PARAMETER(argc); if( pA==0 || pA->oom || pA->isNull - || pB==0 || pB->oom || pB->isNull + || pB==0 || pB->oom || pB->isNull ){ goto mul_end; } @@ -4487,8 +4550,8 @@ static void decimalPow2Func( #endif int sqlite3_decimal_init( - sqlite3 *db, - char **pzErrMsg, + sqlite3 *db, + char **pzErrMsg, const sqlite3_api_routines *pApi ){ int rc = SQLITE_OK; @@ -4530,11 +4593,9 @@ int sqlite3_decimal_init( } /************************* End ../ext/misc/decimal.c ********************/ -#undef sqlite3_base_init -#define sqlite3_base_init sqlite3_base64_init -/************************* Begin ../ext/misc/base64.c ******************/ +/************************* Begin ../ext/misc/percentile.c ******************/ /* -** 2022-11-18 +** 2013-05-28 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: @@ -4543,13 +4604,521 @@ int sqlite3_decimal_init( ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** -************************************************************************* +****************************************************************************** ** -** This is a SQLite extension for converting in either direction -** between a (binary) blob and base64 text. Base64 can transit a -** sane USASCII channel unmolested. It also plays nicely in CSV or -** written as TCL brace-enclosed literals or SQL string literals, -** and can be used unmodified in XML-like documents. +** This file contains code to implement the percentile(Y,P) SQL function +** and similar as described below: +** +** (1) The percentile(Y,P) function is an aggregate function taking +** exactly two arguments. +** +** (2) If the P argument to percentile(Y,P) is not the same for every +** row in the aggregate then an error is thrown. The word "same" +** in the previous sentence means that the value differ by less +** than 0.001. +** +** (3) If the P argument to percentile(Y,P) evaluates to anything other +** than a number in the range of 0.0 to 100.0 inclusive then an +** error is thrown. +** +** (4) If any Y argument to percentile(Y,P) evaluates to a value that +** is not NULL and is not numeric then an error is thrown. +** +** (5) If any Y argument to percentile(Y,P) evaluates to plus or minus +** infinity then an error is thrown. (SQLite always interprets NaN +** values as NULL.) +** +** (6) Both Y and P in percentile(Y,P) can be arbitrary expressions, +** including CASE WHEN expressions. +** +** (7) The percentile(Y,P) aggregate is able to handle inputs of at least +** one million (1,000,000) rows. +** +** (8) If there are no non-NULL values for Y, then percentile(Y,P) +** returns NULL. +** +** (9) If there is exactly one non-NULL value for Y, the percentile(Y,P) +** returns the one Y value. +** +** (10) If there N non-NULL values of Y where N is two or more and +** the Y values are ordered from least to greatest and a graph is +** drawn from 0 to N-1 such that the height of the graph at J is +** the J-th Y value and such that straight lines are drawn between +** adjacent Y values, then the percentile(Y,P) function returns +** the height of the graph at P*(N-1)/100. +** +** (11) The percentile(Y,P) function always returns either a floating +** point number or NULL. +** +** (12) The percentile(Y,P) is implemented as a single C99 source-code +** file that compiles into a shared-library or DLL that can be loaded +** into SQLite using the sqlite3_load_extension() interface. +** +** (13) A separate median(Y) function is the equivalent percentile(Y,50). +** +** (14) A separate percentile_cont(Y,P) function is equivalent to +** percentile(Y,P/100.0). In other words, the fraction value in +** the second argument is in the range of 0 to 1 instead of 0 to 100. +** +** (15) A separate percentile_disc(Y,P) function is like +** percentile_cont(Y,P) except that instead of returning the weighted +** average of the nearest two input values, it returns the next lower +** value. So the percentile_disc(Y,P) will always return a value +** that was one of the inputs. +** +** (16) All of median(), percentile(Y,P), percentile_cont(Y,P) and +** percentile_disc(Y,P) can be used as window functions. +** +** Differences from standard SQL: +** +** * The percentile_cont(X,P) function is equivalent to the following in +** standard SQL: +** +** (percentile_cont(P) WITHIN GROUP (ORDER BY X)) +** +** The SQLite syntax is much more compact. The standard SQL syntax +** is also supported if SQLite is compiled with the +** -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES option. +** +** * No median(X) function exists in the SQL standard. App developers +** are expected to write "percentile_cont(0.5)WITHIN GROUP(ORDER BY X)". +** +** * No percentile(Y,P) function exists in the SQL standard. Instead of +** percential(Y,P), developers must write this: +** "percentile_cont(P/100.0) WITHIN GROUP (ORDER BY Y)". Note that +** the fraction parameter to percentile() goes from 0 to 100 whereas +** the fraction parameter in SQL standard percentile_cont() goes from +** 0 to 1. +** +** Implementation notes as of 2024-08-31: +** +** * The regular aggregate-function versions of these routines work +** by accumulating all values in an array of doubles, then sorting +** that array using quicksort before computing the answer. Thus +** the runtime is O(NlogN) where N is the number of rows of input. +** +** * For the window-function versions of these routines, the array of +** inputs is sorted as soon as the first value is computed. Thereafter, +** the array is kept in sorted order using an insert-sort. This +** results in O(N*K) performance where K is the size of the window. +** One can imagine alternative implementations that give O(N*logN*logK) +** performance, but they require more complex logic and data structures. +** The developers have elected to keep the asymptotically slower +** algorithm for now, for simplicity, under the theory that window +** functions are seldom used and when they are, the window size K is +** often small. The developers might revisit that decision later, +** should the need arise. +*/ +#if defined(SQLITE3_H) + /* no-op */ +#elif defined(SQLITE_STATIC_PERCENTILE) +/* # include "sqlite3.h" */ +#else +/* # include "sqlite3ext.h" */ + SQLITE_EXTENSION_INIT1 +#endif +#include +#include +#include + +/* The following object is the group context for a single percentile() +** aggregate. Remember all input Y values until the very end. +** Those values are accumulated in the Percentile.a[] array. +*/ +typedef struct Percentile Percentile; +struct Percentile { + unsigned nAlloc; /* Number of slots allocated for a[] */ + unsigned nUsed; /* Number of slots actually used in a[] */ + char bSorted; /* True if a[] is already in sorted order */ + char bKeepSorted; /* True if advantageous to keep a[] sorted */ + char bPctValid; /* True if rPct is valid */ + double rPct; /* Fraction. 0.0 to 1.0 */ + double *a; /* Array of Y values */ +}; + +/* Details of each function in the percentile family */ +typedef struct PercentileFunc PercentileFunc; +struct PercentileFunc { + const char *zName; /* Function name */ + char nArg; /* Number of arguments */ + char mxFrac; /* Maximum value of the "fraction" input */ + char bDiscrete; /* True for percentile_disc() */ +}; +static const PercentileFunc aPercentFunc[] = { + { "median", 1, 1, 0 }, + { "percentile", 2, 100, 0 }, + { "percentile_cont", 2, 1, 0 }, + { "percentile_disc", 2, 1, 1 }, +}; + +/* +** Return TRUE if the input floating-point number is an infinity. +*/ +static int percentIsInfinity(double r){ + sqlite3_uint64 u; + assert( sizeof(u)==sizeof(r) ); + memcpy(&u, &r, sizeof(u)); + return ((u>>52)&0x7ff)==0x7ff; +} + +/* +** Return TRUE if two doubles differ by 0.001 or less. +*/ +static int percentSameValue(double a, double b){ + a -= b; + return a>=-0.001 && a<=0.001; +} + +/* +** Search p (which must have p->bSorted) looking for an entry with +** value y. Return the index of that entry. +** +** If bExact is true, return -1 if the entry is not found. +** +** If bExact is false, return the index at which a new entry with +** value y should be insert in order to keep the values in sorted +** order. The smallest return value in this case will be 0, and +** the largest return value will be p->nUsed. +*/ +static int percentBinarySearch(Percentile *p, double y, int bExact){ + int iFirst = 0; /* First element of search range */ + int iLast = p->nUsed - 1; /* Last element of search range */ + while( iLast>=iFirst ){ + int iMid = (iFirst+iLast)/2; + double x = p->a[iMid]; + if( xy ){ + iLast = iMid - 1; + }else{ + return iMid; + } + } + if( bExact ) return -1; + return iFirst; +} + +/* +** Generate an error for a percentile function. +** +** The error format string must have exactly one occurrance of "%%s()" +** (with two '%' characters). That substring will be replaced by the name +** of the function. +*/ +static void percentError(sqlite3_context *pCtx, const char *zFormat, ...){ + PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx); + char *zMsg1; + char *zMsg2; + va_list ap; + + va_start(ap, zFormat); + zMsg1 = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + zMsg2 = zMsg1 ? sqlite3_mprintf(zMsg1, pFunc->zName) : 0; + sqlite3_result_error(pCtx, zMsg2, -1); + sqlite3_free(zMsg1); + sqlite3_free(zMsg2); +} + +/* +** The "step" function for percentile(Y,P) is called once for each +** input row. +*/ +static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){ + Percentile *p; + double rPct; + int eType; + double y; + assert( argc==2 || argc==1 ); + + if( argc==1 ){ + /* Requirement 13: median(Y) is the same as percentile(Y,50). */ + rPct = 0.5; + }else{ + /* Requirement 3: P must be a number between 0 and 100 */ + PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx); + eType = sqlite3_value_numeric_type(argv[1]); + rPct = sqlite3_value_double(argv[1])/(double)pFunc->mxFrac; + if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT) + || rPct<0.0 || rPct>1.0 + ){ + percentError(pCtx, "the fraction argument to %%s()" + " is not between 0.0 and %.1f", + (double)pFunc->mxFrac); + return; + } + } + + /* Allocate the session context. */ + p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p)); + if( p==0 ) return; + + /* Remember the P value. Throw an error if the P value is different + ** from any prior row, per Requirement (2). */ + if( !p->bPctValid ){ + p->rPct = rPct; + p->bPctValid = 1; + }else if( !percentSameValue(p->rPct,rPct) ){ + percentError(pCtx, "the fraction argument to %%s()" + " is not the same for all input rows"); + return; + } + + /* Ignore rows for which Y is NULL */ + eType = sqlite3_value_type(argv[0]); + if( eType==SQLITE_NULL ) return; + + /* If not NULL, then Y must be numeric. Otherwise throw an error. + ** Requirement 4 */ + if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){ + percentError(pCtx, "input to %%s() is not numeric"); + return; + } + + /* Throw an error if the Y value is infinity or NaN */ + y = sqlite3_value_double(argv[0]); + if( percentIsInfinity(y) ){ + percentError(pCtx, "Inf input to %%s()"); + return; + } + + /* Allocate and store the Y */ + if( p->nUsed>=p->nAlloc ){ + unsigned n = p->nAlloc*2 + 250; + double *a = sqlite3_realloc64(p->a, sizeof(double)*n); + if( a==0 ){ + sqlite3_free(p->a); + memset(p, 0, sizeof(*p)); + sqlite3_result_error_nomem(pCtx); + return; + } + p->nAlloc = n; + p->a = a; + } + if( p->nUsed==0 ){ + p->a[p->nUsed++] = y; + p->bSorted = 1; + }else if( !p->bSorted || y>=p->a[p->nUsed-1] ){ + p->a[p->nUsed++] = y; + }else if( p->bKeepSorted ){ + int i; + i = percentBinarySearch(p, y, 0); + if( i<(int)p->nUsed ){ + memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0])); + } + p->a[i] = y; + p->nUsed++; + }else{ + p->a[p->nUsed++] = y; + p->bSorted = 0; + } +} + +/* +** Interchange two doubles. +*/ +#define SWAP_DOUBLE(X,Y) {double ttt=(X);(X)=(Y);(Y)=ttt;} + +/* +** Sort an array of doubles. +** +** Algorithm: quicksort +** +** This is implemented separately rather than using the qsort() routine +** from the standard library because: +** +** (1) To avoid a dependency on qsort() +** (2) To avoid the function call to the comparison routine for each +** comparison. +*/ +static void percentSort(double *a, unsigned int n){ + int iLt; /* Entries before a[iLt] are less than rPivot */ + int iGt; /* Entries at or after a[iGt] are greater than rPivot */ + int i; /* Loop counter */ + double rPivot; /* The pivot value */ + + assert( n>=2 ); + if( a[0]>a[n-1] ){ + SWAP_DOUBLE(a[0],a[n-1]) + } + if( n==2 ) return; + iGt = n-1; + i = n/2; + if( a[0]>a[i] ){ + SWAP_DOUBLE(a[0],a[i]) + }else if( a[i]>a[iGt] ){ + SWAP_DOUBLE(a[i],a[iGt]) + } + if( n==3 ) return; + rPivot = a[i]; + iLt = i = 1; + do{ + if( a[i]iLt ) SWAP_DOUBLE(a[i],a[iLt]) + iLt++; + i++; + }else if( a[i]>rPivot ){ + do{ + iGt--; + }while( iGt>i && a[iGt]>rPivot ); + SWAP_DOUBLE(a[i],a[iGt]) + }else{ + i++; + } + }while( i=2 ) percentSort(a, iLt); + if( n-iGt>=2 ) percentSort(a+iGt, n-iGt); + +/* Uncomment for testing */ +#if 0 + for(i=0; ibSorted==0 ){ + assert( p->nUsed>1 ); + percentSort(p->a, p->nUsed); + p->bSorted = 1; + } + p->bKeepSorted = 1; + + /* Find and remove the row */ + i = percentBinarySearch(p, y, 1); + if( i>=0 ){ + p->nUsed--; + if( i<(int)p->nUsed ){ + memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0])); + } + } +} + +/* +** Compute the final output of percentile(). Clean up all allocated +** memory if and only if bIsFinal is true. +*/ +static void percentCompute(sqlite3_context *pCtx, int bIsFinal){ + Percentile *p; + PercentileFunc *pFunc = (PercentileFunc*)sqlite3_user_data(pCtx); + unsigned i1, i2; + double v1, v2; + double ix, vx; + p = (Percentile*)sqlite3_aggregate_context(pCtx, 0); + if( p==0 ) return; + if( p->a==0 ) return; + if( p->nUsed ){ + if( p->bSorted==0 ){ + assert( p->nUsed>1 ); + percentSort(p->a, p->nUsed); + p->bSorted = 1; + } + ix = p->rPct*(p->nUsed-1); + i1 = (unsigned)ix; + if( pFunc->bDiscrete ){ + vx = p->a[i1]; + }else{ + i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1; + v1 = p->a[i1]; + v2 = p->a[i2]; + vx = v1 + (v2-v1)*(ix-i1); + } + sqlite3_result_double(pCtx, vx); + } + if( bIsFinal ){ + sqlite3_free(p->a); + memset(p, 0, sizeof(*p)); + }else{ + p->bKeepSorted = 1; + } +} +static void percentFinal(sqlite3_context *pCtx){ + percentCompute(pCtx, 1); +} +static void percentValue(sqlite3_context *pCtx){ + percentCompute(pCtx, 0); +} + +#if defined(_WIN32) && !defined(SQLITE3_H) && !defined(SQLITE_STATIC_PERCENTILE) + +#endif +int sqlite3_percentile_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int rc = SQLITE_OK; + unsigned int i; +#if defined(SQLITE3_H) || defined(SQLITE_STATIC_PERCENTILE) + (void)pApi; /* Unused parameter */ +#else + SQLITE_EXTENSION_INIT2(pApi); +#endif + (void)pzErrMsg; /* Unused parameter */ + for(i=0; i