diff --git a/configure.ac b/configure.ac index 613f747..5030b9b 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl Copyright (C) 2019-2022 Ulrich Telle dnl dnl This file is covered by the same licence as the entire SQLite3 Multiple Ciphers package. -AC_INIT([sqlite3mc], [1.4.8], [ulrich@telle-online.de]) +AC_INIT([sqlite3mc], [1.5.0], [ulrich@telle-online.de]) dnl This is the version tested with, might work with earlier ones. AC_PREREQ([2.69]) diff --git a/readme.md b/readme.md index 9d1d88c..3c0f9ff 100644 --- a/readme.md +++ b/readme.md @@ -10,6 +10,10 @@ The code was mainly developed under Windows, but was tested under Linux as well. ## Version history +* 1.5.0 - *September 2022* + - Based on SQLite version 3.39.3 + - Added option to register cipher schemes dynamically + - Eliminated a few compile time warnings * 1.4.8 - *July 2022* - Based on SQLite version 3.39.2 - Fix issue in `PRAGMA rekey` that could lead to a crash diff --git a/src/cipher_common.c b/src/cipher_common.c index c175303..1f7330d 100644 --- a/src/cipher_common.c +++ b/src/cipher_common.c @@ -3,7 +3,7 @@ ** Purpose: Implementation of SQLite codecs ** Author: Ulrich Telle ** Created: 2020-02-02 -** Copyright: (c) 2006-2021 Ulrich Telle +** Copyright: (c) 2006-2022 Ulrich Telle ** License: MIT */ @@ -23,21 +23,24 @@ static unsigned char padding[] = static CipherParams commonParams[] = { - { "cipher", CODEC_TYPE, CODEC_TYPE, 1, CODEC_TYPE_MAX }, - { "hmac_check", 1, 1, 0, 1 }, - { "mc_legacy_wal", SQLITE3MC_LEGACY_WAL, SQLITE3MC_LEGACY_WAL, 0, 1 }, + { "cipher", CODEC_TYPE_UNKNOWN, CODEC_TYPE_UNKNOWN, 1, CODEC_COUNT_MAX }, + { "hmac_check", 1, 1, 0, 1 }, + { "mc_legacy_wal", SQLITE3MC_LEGACY_WAL, SQLITE3MC_LEGACY_WAL, 0, 1 }, CIPHER_PARAMS_SENTINEL }; +static CodecParameter globalCommonParams = { "global", CODEC_TYPE_UNKNOWN, commonParams }; +static CodecParameter globalSentinelParams = { "", CODEC_TYPE_UNKNOWN, NULL }; + SQLITE_PRIVATE int sqlite3mcGetCipherParameter(CipherParams* cipherParams, const char* paramName) { int value = -1; - for (; strlen(cipherParams->m_name) > 0; ++cipherParams) + for (; cipherParams->m_name[0] != 0; ++cipherParams) { if (sqlite3_stricmp(paramName, cipherParams->m_name) == 0) break; } - if (strlen(cipherParams->m_name) > 0) + if (cipherParams->m_name[0] != 0) { value = cipherParams->m_value; cipherParams->m_value = cipherParams->m_default; @@ -45,26 +48,15 @@ sqlite3mcGetCipherParameter(CipherParams* cipherParams, const char* paramName) return value; } -static CodecParameter globalCodecParameterTable[] = +typedef struct _CipherName { - { "global", CODEC_TYPE_UNKNOWN, commonParams }, -#if HAVE_CIPHER_AES_128_CBC - { "aes128cbc", CODEC_TYPE_AES128, mcAES128Params }, -#endif -#if HAVE_CIPHER_AES_256_CBC - { "aes256cbc", CODEC_TYPE_AES256, mcAES256Params }, -#endif -#if HAVE_CIPHER_CHACHA20 - { "chacha20", CODEC_TYPE_CHACHA20, mcChaCha20Params }, -#endif -#if HAVE_CIPHER_SQLCIPHER - { "sqlcipher", CODEC_TYPE_SQLCIPHER, mcSQLCipherParams }, -#endif -#if HAVE_CIPHER_RC4 - { "rc4", CODEC_TYPE_RC4, mcRC4Params }, -#endif - { "", CODEC_TYPE_UNKNOWN, NULL } -}; + char m_name[CIPHER_NAME_MAXLEN]; +} CipherName; + +static int globalCipherCount = 0; +static char* globalSentinelName = ""; +static CipherName globalCipherNameTable[CODEC_COUNT_LIMIT + 2] = { 0 }; +static CodecParameter globalCodecParameterTable[CODEC_COUNT_LIMIT + 2]; SQLITE_PRIVATE CodecParameter* sqlite3mcCloneCodecParameterTable() @@ -76,10 +68,10 @@ sqlite3mcCloneCodecParameterTable() CipherParams* cloneCipherParams; CodecParameter* cloneCodecParams; - for (j = 0; strlen(globalCodecParameterTable[j].m_name) > 0; ++j) + for (j = 0; globalCodecParameterTable[j].m_name[0] != 0; ++j) { CipherParams* params = globalCodecParameterTable[j].m_params; - for (k = 0; strlen(params[k].m_name) > 0; ++k); + for (k = 0; params[k].m_name[0] != 0; ++k); nParams += k; } nTables = j; @@ -98,7 +90,7 @@ sqlite3mcCloneCodecParameterTable() cloneCodecParams[j].m_name = globalCodecParameterTable[j].m_name; cloneCodecParams[j].m_id = globalCodecParameterTable[j].m_id; cloneCodecParams[j].m_params = &cloneCipherParams[offset]; - for (n = 0; strlen(params[n].m_name) > 0; ++n); + for (n = 0; params[n].m_name[0] != 0; ++n); /* Copy all parameters of the current table (including sentinel) */ for (k = 0; k <= n; ++k) { @@ -138,35 +130,7 @@ static const CipherDescriptor mcDummyDescriptor = "@dummy@", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static const CipherDescriptor* codecDescriptorTable[] = -{ -#if HAVE_CIPHER_AES_128_CBC - &mcAES128Descriptor, -#else - &mcDummyDescriptor, -#endif -#if HAVE_CIPHER_AES_256_CBC - &mcAES256Descriptor, -#else - &mcDummyDescriptor, -#endif -#if HAVE_CIPHER_CHACHA20 - &mcChaCha20Descriptor, -#else - &mcDummyDescriptor, -#endif -#if HAVE_CIPHER_SQLCIPHER - &mcSQLCipherDescriptor, -#else - &mcDummyDescriptor, -#endif -#if HAVE_CIPHER_RC4 - &mcRC4Descriptor, -#else - &mcDummyDescriptor, -#endif - &mcSentinelDescriptor -}; +static CipherDescriptor globalCodecDescriptorTable[CODEC_COUNT_MAX + 1]; /* --- Codec --- */ @@ -180,11 +144,11 @@ sqlite3mcGetCipherType(sqlite3* db) CipherParams* cipherParamTable = (codecParams != NULL) ? codecParams[0].m_params : commonParams; int cipherType = CODEC_TYPE; CipherParams* cipher = cipherParamTable; - for (; strlen(cipher->m_name) > 0; ++cipher) + for (; cipher->m_name[0] != 0; ++cipher) { if (sqlite3_stricmp("cipher", cipher->m_name) == 0) break; } - if (strlen(cipher->m_name) > 0) + if (cipher->m_name[0] != 0) { cipherType = cipher->m_value; cipher->m_value = cipher->m_default; @@ -255,12 +219,12 @@ sqlite3mcCodecTerm(Codec* codec) { if (codec->m_readCipher != NULL) { - codecDescriptorTable[codec->m_readCipherType - 1]->m_freeCipher(codec->m_readCipher); + globalCodecDescriptorTable[codec->m_readCipherType - 1].m_freeCipher(codec->m_readCipher); codec->m_readCipher = NULL; } if (codec->m_writeCipher != NULL) { - codecDescriptorTable[codec->m_writeCipherType - 1]->m_freeCipher(codec->m_writeCipher); + globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_freeCipher(codec->m_writeCipher); codec->m_writeCipher = NULL; } memset(codec, 0, sizeof(Codec)); @@ -284,7 +248,7 @@ sqlite3mcCodecSetup(Codec* codec, int cipherType, char* userPassword, int passwo codec->m_hasReadCipher = 1; codec->m_hasWriteCipher = 1; codec->m_readCipherType = cipherType; - codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType-1]->m_allocateCipher(codec->m_db); + codec->m_readCipher = globalCodecDescriptorTable[codec->m_readCipherType-1].m_allocateCipher(codec->m_db); if (codec->m_readCipher != NULL) { unsigned char* keySalt = (codec->m_hasKeySalt != 0) ? codec->m_keySalt : NULL; @@ -305,14 +269,14 @@ sqlite3mcSetupWriteCipher(Codec* codec, int cipherType, char* userPassword, int CipherParams* globalParams = sqlite3mcGetCipherParams(codec->m_db, 0); if (codec->m_writeCipher != NULL) { - codecDescriptorTable[codec->m_writeCipherType-1]->m_freeCipher(codec->m_writeCipher); + globalCodecDescriptorTable[codec->m_writeCipherType-1].m_freeCipher(codec->m_writeCipher); } codec->m_isEncrypted = 1; codec->m_hmacCheck = sqlite3mcGetCipherParameter(globalParams, "hmac_check"); codec->m_walLegacy = sqlite3mcGetCipherParameter(globalParams, "mc_legacy_wal"); codec->m_hasWriteCipher = 1; codec->m_writeCipherType = cipherType; - codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType-1]->m_allocateCipher(codec->m_db); + codec->m_writeCipher = globalCodecDescriptorTable[codec->m_writeCipherType-1].m_allocateCipher(codec->m_db); if (codec->m_writeCipher != NULL) { unsigned char* keySalt = (codec->m_hasKeySalt != 0) ? codec->m_keySalt : NULL; @@ -433,57 +397,57 @@ sqlite3mcGetPageBuffer(Codec* codec) SQLITE_PRIVATE int sqlite3mcGetLegacyReadCipher(Codec* codec) { - int legacy = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType - 1]->m_getLegacy(codec->m_readCipher) : 0; + int legacy = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType - 1].m_getLegacy(codec->m_readCipher) : 0; return legacy; } SQLITE_PRIVATE int sqlite3mcGetLegacyWriteCipher(Codec* codec) { - int legacy = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getLegacy(codec->m_writeCipher) : -1; + int legacy = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_getLegacy(codec->m_writeCipher) : -1; return legacy; } SQLITE_PRIVATE int sqlite3mcGetPageSizeReadCipher(Codec* codec) { - int pageSize = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[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) : 0; return pageSize; } SQLITE_PRIVATE int sqlite3mcGetPageSizeWriteCipher(Codec* codec) { - int pageSize = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getPageSize(codec->m_writeCipher) : -1; + int pageSize = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_getPageSize(codec->m_writeCipher) : -1; return pageSize; } SQLITE_PRIVATE int sqlite3mcGetReservedReadCipher(Codec* codec) { - int reserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType-1]->m_getReserved(codec->m_readCipher) : -1; + int reserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType-1].m_getReserved(codec->m_readCipher) : -1; return reserved; } SQLITE_PRIVATE int sqlite3mcGetReservedWriteCipher(Codec* codec) { - int reserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType-1]->m_getReserved(codec->m_writeCipher) : -1; + int reserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType-1].m_getReserved(codec->m_writeCipher) : -1; return reserved; } SQLITE_PRIVATE int sqlite3mcReservedEqual(Codec* codec) { - int readReserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType-1]->m_getReserved(codec->m_readCipher) : -1; - int writeReserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType-1]->m_getReserved(codec->m_writeCipher) : -1; + int readReserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType-1].m_getReserved(codec->m_readCipher) : -1; + int writeReserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType-1].m_getReserved(codec->m_writeCipher) : -1; return (readReserved == writeReserved); } SQLITE_PRIVATE unsigned char* sqlite3mcGetSaltWriteCipher(Codec* codec) { - unsigned char* salt = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getSalt(codec->m_writeCipher) : NULL; + unsigned char* salt = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_getSalt(codec->m_writeCipher) : NULL; return salt; } @@ -505,10 +469,10 @@ sqlite3mcCodecCopy(Codec* codec, Codec* other) if (codec->m_hasReadCipher) { - codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType - 1]->m_allocateCipher(codec->m_db); + codec->m_readCipher = globalCodecDescriptorTable[codec->m_readCipherType - 1].m_allocateCipher(codec->m_db); if (codec->m_readCipher != NULL) { - codecDescriptorTable[codec->m_readCipherType - 1]->m_cloneCipher(codec->m_readCipher, other->m_readCipher); + globalCodecDescriptorTable[codec->m_readCipherType - 1].m_cloneCipher(codec->m_readCipher, other->m_readCipher); } else { @@ -518,10 +482,10 @@ sqlite3mcCodecCopy(Codec* codec, Codec* other) if (codec->m_hasWriteCipher) { - codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType - 1]->m_allocateCipher(codec->m_db); + codec->m_writeCipher = globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_allocateCipher(codec->m_db); if (codec->m_writeCipher != NULL) { - codecDescriptorTable[codec->m_writeCipherType - 1]->m_cloneCipher(codec->m_writeCipher, other->m_writeCipher); + globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_cloneCipher(codec->m_writeCipher, other->m_writeCipher); } else { @@ -544,17 +508,17 @@ sqlite3mcCopyCipher(Codec* codec, int read2write) { if (codec->m_writeCipher != NULL && codec->m_writeCipherType != codec->m_readCipherType) { - codecDescriptorTable[codec->m_writeCipherType-1]->m_freeCipher(codec->m_writeCipher); + globalCodecDescriptorTable[codec->m_writeCipherType-1].m_freeCipher(codec->m_writeCipher); codec->m_writeCipher = NULL; } if (codec->m_writeCipher == NULL) { codec->m_writeCipherType = codec->m_readCipherType; - codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType-1]->m_allocateCipher(codec->m_db); + codec->m_writeCipher = globalCodecDescriptorTable[codec->m_writeCipherType-1].m_allocateCipher(codec->m_db); } if (codec->m_writeCipher != NULL) { - codecDescriptorTable[codec->m_writeCipherType-1]->m_cloneCipher(codec->m_writeCipher, codec->m_readCipher); + globalCodecDescriptorTable[codec->m_writeCipherType-1].m_cloneCipher(codec->m_writeCipher, codec->m_readCipher); } else { @@ -565,17 +529,17 @@ sqlite3mcCopyCipher(Codec* codec, int read2write) { if (codec->m_readCipher != NULL && codec->m_readCipherType != codec->m_writeCipherType) { - codecDescriptorTable[codec->m_readCipherType-1]->m_freeCipher(codec->m_readCipher); + globalCodecDescriptorTable[codec->m_readCipherType-1].m_freeCipher(codec->m_readCipher); codec->m_readCipher = NULL; } if (codec->m_readCipher == NULL) { codec->m_readCipherType = codec->m_writeCipherType; - codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType-1]->m_allocateCipher(codec->m_db); + codec->m_readCipher = globalCodecDescriptorTable[codec->m_readCipherType-1].m_allocateCipher(codec->m_db); } if (codec->m_readCipher != NULL) { - codecDescriptorTable[codec->m_readCipherType-1]->m_cloneCipher(codec->m_readCipher, codec->m_writeCipher); + globalCodecDescriptorTable[codec->m_readCipherType-1].m_cloneCipher(codec->m_readCipher, codec->m_writeCipher); } else { @@ -606,13 +570,13 @@ sqlite3mcPadPassword(char* password, int pswdlen, unsigned char pswd[32]) SQLITE_PRIVATE void sqlite3mcGenerateReadKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt) { - codecDescriptorTable[codec->m_readCipherType-1]->m_generateKey(codec->m_readCipher, codec->m_btShared, userPassword, passwordLength, 0, cipherSalt); + globalCodecDescriptorTable[codec->m_readCipherType-1].m_generateKey(codec->m_readCipher, codec->m_btShared, userPassword, passwordLength, 0, cipherSalt); } SQLITE_PRIVATE void sqlite3mcGenerateWriteKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt) { - codecDescriptorTable[codec->m_writeCipherType-1]->m_generateKey(codec->m_writeCipher, codec->m_btShared, userPassword, passwordLength, 1, cipherSalt); + globalCodecDescriptorTable[codec->m_writeCipherType-1].m_generateKey(codec->m_writeCipher, codec->m_btShared, userPassword, passwordLength, 1, cipherSalt); } SQLITE_PRIVATE int @@ -622,7 +586,7 @@ sqlite3mcEncrypt(Codec* codec, int page, unsigned char* data, int len, int useWr void* cipher = (useWriteKey) ? codec->m_writeCipher : codec->m_readCipher; int reserved = (useWriteKey) ? (codec->m_writeReserved >= 0) ? codec->m_writeReserved : codec->m_reserved : (codec->m_readReserved >= 0) ? codec->m_readReserved : codec->m_reserved; - return codecDescriptorTable[cipherType-1]->m_encryptPage(cipher, page, data, len, reserved); + return globalCodecDescriptorTable[cipherType-1].m_encryptPage(cipher, page, data, len, reserved); } SQLITE_PRIVATE int @@ -631,7 +595,7 @@ sqlite3mcDecrypt(Codec* codec, int page, unsigned char* data, int len) int cipherType = codec->m_readCipherType; void* cipher = codec->m_readCipher; int reserved = (codec->m_readReserved >= 0) ? codec->m_readReserved : codec->m_reserved; - return codecDescriptorTable[cipherType-1]->m_decryptPage(cipher, page, data, len, reserved, codec->m_hmacCheck); + return globalCodecDescriptorTable[cipherType-1].m_decryptPage(cipher, page, data, len, reserved, codec->m_hmacCheck); } #if HAVE_CIPHER_SQLCIPHER diff --git a/src/cipher_common.h b/src/cipher_common.h index 292a3d7..8c7df40 100644 --- a/src/cipher_common.h +++ b/src/cipher_common.h @@ -3,7 +3,7 @@ ** Purpose: Header for the ciphers of SQLite3 Multiple Ciphers ** Author: Ulrich Telle ** Created: 2020-02-02 -** Copyright: (c) 2006-2021 Ulrich Telle +** Copyright: (c) 2006-2022 Ulrich Telle ** License: MIT */ @@ -24,10 +24,31 @@ #define CODEC_TYPE CODEC_TYPE_DEFAULT #endif -#if CODEC_TYPE < 1 || CODEC_TYPE > CODEC_TYPE_MAX +#if CODEC_TYPE < 1 || CODEC_TYPE > CODEC_TYPE_MAX_BUILTIN #error "Invalid codec type selected" #endif +/* +** Define the maximum number of ciphers that can be registered +*/ + +/* Use a reasonable upper limit for the maximum number of ciphers */ +#define CODEC_COUNT_LIMIT 16 + +#ifdef SQLITE3MC_MAX_CODEC_COUNT +/* Allow at least to register all built-in ciphers, but use a reasonable upper limit */ +#if SQLITE3MC_MAX_CODEC_COUNT >= CODEC_TYPE_MAX_BUILTIN && SQLITE3MC_MAX_CODEC_COUNT <= CODEC_COUNT_LIMIT +#define CODEC_COUNT_MAX SQLITE3MC_MAX_CODEC_COUNT +#else +#error "Maximum cipher count not in range [CODEC_TYPE_MAX_BUILTIN .. CODEC_COUNT_LIMIT]" +#endif +#else +#define CODEC_COUNT_MAX CODEC_COUNT_LIMIT +#endif + +#define CIPHER_NAME_MAXLEN 32 +#define CIPHER_PARAMS_COUNT_MAX 64 + #define MAXKEYLENGTH 32 #define KEYLENGTH_AES128 16 #define KEYLENGTH_AES256 32 @@ -35,6 +56,13 @@ #define CODEC_SHA_ITER 4001 +typedef struct _CodecParameter +{ + char* m_name; + int m_id; + CipherParams* m_params; +} CodecParameter; + typedef struct _Codec { int m_isEncrypted; @@ -66,48 +94,6 @@ typedef struct _Codec #define CIPHER_PARAMS_SENTINEL { "", 0, 0, 0, 0 } #define CIPHER_PAGE1_OFFSET 24 -typedef struct _CipherParams -{ - char* m_name; - int m_value; - int m_default; - int m_minValue; - int m_maxValue; -} CipherParams; - -typedef struct _CodecParameter -{ - char* m_name; - int m_id; - CipherParams* m_params; -} CodecParameter; - -typedef void* (*AllocateCipher_t)(sqlite3* db); -typedef void (*FreeCipher_t)(void* cipher); -typedef void (*CloneCipher_t)(void* cipherTo, void* cipherFrom); -typedef int (*GetLegacy_t)(void* cipher); -typedef int (*GetPageSize_t)(void* cipher); -typedef int (*GetReserved_t)(void* cipher); -typedef unsigned char* (*GetSalt_t)(void* cipher); -typedef void (*GenerateKey_t)(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt); -typedef int (*EncryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved); -typedef int (*DecryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved, int hmacCheck); - -typedef struct _CodecDescriptor -{ - char m_name[32]; - AllocateCipher_t m_allocateCipher; - FreeCipher_t m_freeCipher; - CloneCipher_t m_cloneCipher; - GetLegacy_t m_getLegacy; - GetPageSize_t m_getPageSize; - GetReserved_t m_getReserved; - GetSalt_t m_getSalt; - GenerateKey_t m_generateKey; - EncryptPage_t m_encryptPage; - DecryptPage_t m_decryptPage; -} CipherDescriptor; - SQLITE_PRIVATE int sqlite3mcGetCipherParameter(CipherParams* cipherParams, const char* paramName); SQLITE_PRIVATE int sqlite3mcGetCipherType(sqlite3* db); diff --git a/src/cipher_config.c b/src/cipher_config.c index d43caac..201bd09 100644 --- a/src/cipher_config.c +++ b/src/cipher_config.c @@ -12,6 +12,8 @@ /* --- Codec --- */ +SQLITE_PRIVATE int +sqlite3mcGetGlobalCipherCount(); SQLITE_PRIVATE Codec* sqlite3mcGetCodec(sqlite3* db, const char* zDbName); @@ -80,28 +82,30 @@ sqlite3mc_config(sqlite3* db, const char* paramName, int newValue) } param = codecParams[0].m_params; - for (; strlen(param->m_name) > 0; ++param) + for (; param->m_name[0] != 0; ++param) { if (sqlite3_stricmp(paramName, param->m_name) == 0) break; } - if (strlen(param->m_name) > 0) + if (param->m_name[0] != 0) { + int cipherCount = sqlite3mcGetGlobalCipherCount(); if (db != NULL) { sqlite3_mutex_enter(db->mutex); } else { - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); } value = (hasDefaultPrefix) ? param->m_default : (hasMinPrefix) ? param->m_minValue : (hasMaxPrefix) ? param->m_maxValue : param->m_value; if (!hasMinPrefix && !hasMaxPrefix && newValue >= 0 && newValue >= param->m_minValue && newValue <= param->m_maxValue) { int allowChange = 1; + /* Allow cipher change only if new cipher is actually available */ if (sqlite3_stricmp(paramName, "cipher") == 0) { - allowChange = (codecDescriptorTable[newValue - 1] != &mcDummyDescriptor); + allowChange = newValue > 0 && newValue <= cipherCount; } if (allowChange) @@ -121,12 +125,52 @@ sqlite3mc_config(sqlite3* db, const char* paramName, int newValue) } else { - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); } } return value; } +SQLITE_API int +sqlite3mc_cipher_count() +{ + return sqlite3mcGetGlobalCipherCount(); +} + +SQLITE_API int +sqlite3mc_cipher_index(const char* cipherName) +{ + int count = sqlite3mcGetGlobalCipherCount(); + int j = 0; + for (j = 0; j < count && globalCodecDescriptorTable[j].m_name[0] != 0; ++j) + { + if (sqlite3_stricmp(cipherName, globalCodecDescriptorTable[j].m_name) == 0) break; + } + return (j < count && globalCodecDescriptorTable[j].m_name[0] != 0) ? j + 1 : -1; +} + +SQLITE_API const char* +sqlite3mc_cipher_name(int cipherIndex) +{ + static char cipherName[CIPHER_NAME_MAXLEN] = ""; + int count = sqlite3mcGetGlobalCipherCount(); + int j = 0; + cipherName[0] = '\0'; + if (cipherIndex > 0 && cipherIndex <= count) + { + for (j = 0; j < count && globalCodecDescriptorTable[j].m_name[0] != 0; ++j) + { + if (cipherIndex == j + 1) break; + } + if (j < count && globalCodecDescriptorTable[j].m_name[0] != 0) + { + strncpy(cipherName, globalCodecDescriptorTable[j].m_name, CIPHER_NAME_MAXLEN - 1); + cipherName[CIPHER_NAME_MAXLEN - 1] = '\0'; + } + } + return cipherName; +} + SQLITE_API int sqlite3mc_config_cipher(sqlite3* db, const char* cipherName, const char* paramName, int newValue) { @@ -158,11 +202,11 @@ sqlite3mc_config_cipher(sqlite3* db, const char* cipherName, const char* paramNa return value; } - for (j = 0; strlen(codecParams[j].m_name) > 0; ++j) + for (j = 0; codecParams[j].m_name[0] != 0; ++j) { if (sqlite3_stricmp(cipherName, codecParams[j].m_name) == 0) break; } - if (strlen(codecParams[j].m_name) > 0) + if (codecParams[j].m_name[0] != 0) { cipherParamTable = codecParams[j].m_params; } @@ -212,11 +256,11 @@ sqlite3mc_config_cipher(sqlite3* db, const char* cipherName, const char* paramNa } #endif - for (; strlen(param->m_name) > 0; ++param) + for (; param->m_name[0] != 0; ++param) { if (sqlite3_stricmp(paramName, param->m_name) == 0) break; } - if (strlen(param->m_name) > 0) + if (param->m_name[0] != 0) { if (db != NULL) { @@ -392,11 +436,11 @@ sqlite3mcConfigParams(sqlite3_context* context, int argc, sqlite3_value** argv) param1 = codecParams[0].m_params; cipherParamTable = NULL; - for (; strlen(param1->m_name) > 0; ++param1) + for (; param1->m_name[0] != 0; ++param1) { if (sqlite3_stricmp(nameParam1, param1->m_name) == 0) break; } - isCommonParam1 = strlen(param1->m_name) > 0; + isCommonParam1 = param1->m_name[0] != 0; /* Check first argument whether it is a cipher name, if it wasn't a common parameter */ /* If the first argument is a cipher name, cipherParamTable will point to the corresponding cipher parameter table */ @@ -405,11 +449,11 @@ sqlite3mcConfigParams(sqlite3_context* context, int argc, sqlite3_value** argv) if (!hasDefaultPrefix && !hasMinPrefix && !hasMaxPrefix) { int j = 0; - for (j = 0; strlen(codecParams[j].m_name) > 0; ++j) + for (j = 0; codecParams[j].m_name[0] != 0; ++j) { if (sqlite3_stricmp(nameParam1, codecParams[j].m_name) == 0) break; } - isCipherParam1 = strlen(codecParams[j].m_name) > 0; + isCipherParam1 = codecParams[j].m_name[0] != 0; if (isCipherParam1) { cipherParamTable = codecParams[j].m_params; @@ -431,7 +475,7 @@ sqlite3mcConfigParams(sqlite3_context* context, int argc, sqlite3_value** argv) int value = (hasDefaultPrefix) ? param1->m_default : (hasMinPrefix) ? param1->m_minValue : (hasMaxPrefix) ? param1->m_maxValue : param1->m_value; if (sqlite3_stricmp(nameParam1, "cipher") == 0) { - sqlite3_result_text(context, codecDescriptorTable[value - 1]->m_name, -1, SQLITE_STATIC); + sqlite3_result_text(context, globalCodecDescriptorTable[value - 1].m_name, -1, SQLITE_STATIC); } else { @@ -444,7 +488,7 @@ sqlite3mcConfigParams(sqlite3_context* context, int argc, sqlite3_value** argv) int nParams = 0; int lenTotal = 0; int j; - for (j = 0; strlen(cipherParamTable[j].m_name) > 0; ++j) + for (j = 0; cipherParamTable[j].m_name[0] != 0; ++j) { ++nParams; lenTotal += (int) strlen(cipherParamTable[j].m_name); @@ -490,18 +534,18 @@ sqlite3mcConfigParams(sqlite3_context* context, int argc, sqlite3_value** argv) { const char* nameCipher = (const char*)sqlite3_value_text(argv[1]); int j = 0; - for (j = 0; strlen(codecDescriptorTable[j]->m_name) > 0; ++j) + for (j = 0; globalCodecDescriptorTable[j].m_name[0] != 0; ++j) { - if (sqlite3_stricmp(nameCipher, codecDescriptorTable[j]->m_name) == 0) break; + if (sqlite3_stricmp(nameCipher, globalCodecDescriptorTable[j].m_name) == 0) break; } - if (strlen(codecDescriptorTable[j]->m_name) > 0) + if (globalCodecDescriptorTable[j].m_name[0] != 0) { if (hasDefaultPrefix) { param1->m_default = j + 1; } param1->m_value = j + 1; - sqlite3_result_text(context, codecDescriptorTable[j]->m_name, -1, SQLITE_STATIC); + sqlite3_result_text(context, globalCodecDescriptorTable[j].m_name, -1, SQLITE_STATIC); } else { @@ -563,7 +607,7 @@ sqlite3mcConfigParams(sqlite3_context* context, int argc, sqlite3_value** argv) hasMaxPrefix = 1; nameParam2 += 4; } - for (; strlen(param2->m_name) > 0; ++param2) + for (; param2->m_name[0] != 0; ++param2) { if (sqlite3_stricmp(nameParam2, param2->m_name) == 0) break; } @@ -586,7 +630,7 @@ sqlite3mcConfigParams(sqlite3_context* context, int argc, sqlite3_value** argv) } #endif - if (strlen(param2->m_name) > 0) + if (param2->m_name[0] != 0) { if (argc == 2) { @@ -650,13 +694,13 @@ sqlite3mcConfigureFromUri(sqlite3* db, const char *zDbName, int configDefault) CipherParams* cipherParams = NULL; /* Try to locate the cipher name */ - for (j = 1; strlen(globalCodecParameterTable[j].m_name) > 0; ++j) + for (j = 1; globalCodecParameterTable[j].m_name[0] != 0; ++j) { if (sqlite3_stricmp(cipherName, globalCodecParameterTable[j].m_name) == 0) break; } /* j is the index of the cipher name, if found */ - cipherParams = (strlen(globalCodecParameterTable[j].m_name) > 0) ? globalCodecParameterTable[j].m_params : NULL; + cipherParams = (globalCodecParameterTable[j].m_name[0] != 0) ? globalCodecParameterTable[j].m_params : NULL; if (cipherParams != NULL) { /* @@ -696,7 +740,7 @@ sqlite3mcConfigureFromUri(sqlite3* db, const char *zDbName, int configDefault) #endif /* Check all cipher specific parameters */ - for (j = 0; strlen(cipherParams[j].m_name) > 0; ++j) + for (j = 0; cipherParams[j].m_name[0] != 0; ++j) { if (skipLegacy && sqlite3_stricmp(cipherParams[j].m_name, "legacy") == 0) continue; @@ -773,15 +817,15 @@ sqlite3mcFileControlPragma(sqlite3* db, const char* zDbName, int op, void* pArg) { int j = 1; /* Try to locate the cipher name */ - for (j = 1; strlen(globalCodecParameterTable[j].m_name) > 0; ++j) + for (j = 1; globalCodecParameterTable[j].m_name[0] != 0; ++j) { if (sqlite3_stricmp(pragmaValue, globalCodecParameterTable[j].m_name) == 0) break; } - cipherId = (strlen(globalCodecParameterTable[j].m_name) > 0) ? globalCodecParameterTable[j].m_id : CODEC_TYPE_UNKNOWN; + cipherId = (globalCodecParameterTable[j].m_name[0] != 0) ? globalCodecParameterTable[j].m_id : CODEC_TYPE_UNKNOWN; } /* cipherId is the numeric id of the cipher name, if found */ - if ((cipherId == -1) || (cipherId > 0 && cipherId <= CODEC_TYPE_MAX)) + if ((cipherId == -1) || (cipherId > 0 && cipherId <= CODEC_COUNT_MAX)) { int value; if (configDefault) @@ -793,7 +837,7 @@ sqlite3mcFileControlPragma(sqlite3* db, const char* zDbName, int op, void* pArg) value = sqlite3mc_config(db, "cipher", cipherId); } rc = SQLITE_OK; - ((char**)pArg)[0] = sqlite3_mprintf("%s", codecDescriptorTable[value - 1]->m_name); + ((char**)pArg)[0] = sqlite3_mprintf("%s", globalCodecDescriptorTable[value - 1].m_name); } else { @@ -837,10 +881,10 @@ sqlite3mcFileControlPragma(sqlite3* db, const char* zDbName, int op, void* pArg) else if (sqlite3StrICmp(pragmaName, "hexkey") == 0) { int nValue = sqlite3Strlen30(pragmaValue); - if (((nValue & 1) == 0) && (sqlite3mcIsHexKey(pragmaValue, nValue) != 0)) + if (((nValue & 1) == 0) && (sqlite3mcIsHexKey((const unsigned char*) pragmaValue, nValue) != 0)) { - char* zHexKey = sqlite3_malloc(nValue/2); - sqlite3mcConvertHex2Bin(pragmaValue, nValue, zHexKey); + unsigned char* zHexKey = sqlite3_malloc(nValue/2); + sqlite3mcConvertHex2Bin((const unsigned char*) pragmaValue, nValue, zHexKey); rc = sqlite3_key_v2(db, zDbName, zHexKey, nValue/2); sqlite3_free(zHexKey); if (rc == SQLITE_OK) @@ -887,10 +931,10 @@ sqlite3mcFileControlPragma(sqlite3* db, const char* zDbName, int op, void* pArg) else if (sqlite3StrICmp(pragmaName, "hexrekey") == 0) { int nValue = sqlite3Strlen30(pragmaValue); - if (((nValue & 1) == 0) && (sqlite3mcIsHexKey(pragmaValue, nValue) != 0)) + if (((nValue & 1) == 0) && (sqlite3mcIsHexKey((const unsigned char*) pragmaValue, nValue) != 0)) { - char* zHexKey = sqlite3_malloc(nValue/2); - sqlite3mcConvertHex2Bin(pragmaValue, nValue, zHexKey); + unsigned char* zHexKey = sqlite3_malloc(nValue/2); + sqlite3mcConvertHex2Bin((const unsigned char*) pragmaValue, nValue, zHexKey); rc = sqlite3_rekey_v2(db, zDbName, zHexKey, nValue/2); sqlite3_free(zHexKey); if (rc == SQLITE_OK) @@ -926,21 +970,21 @@ sqlite3mcFileControlPragma(sqlite3* db, const char* zDbName, int op, void* pArg) CipherParams* cipherParams = NULL; /* Try to locate the cipher name */ - for (j = 1; strlen(globalCodecParameterTable[j].m_name) > 0; ++j) + for (j = 1; globalCodecParameterTable[j].m_name[0] != 0; ++j) { if (cipher == globalCodecParameterTable[j].m_id) break; } /* j is the index of the cipher name, if found */ - cipherParams = (strlen(globalCodecParameterTable[j].m_name) > 0) ? globalCodecParameterTable[j].m_params : NULL; + cipherParams = (globalCodecParameterTable[j].m_name[0] != 0) ? globalCodecParameterTable[j].m_params : NULL; if (cipherParams != NULL) { const char* cipherName = globalCodecParameterTable[j].m_name; - for (j = 0; strlen(cipherParams[j].m_name) > 0; ++j) + for (j = 0; cipherParams[j].m_name[0] != 0; ++j) { if (sqlite3_stricmp(pragmaName, cipherParams[j].m_name) == 0) break; } - if (strlen(cipherParams[j].m_name) > 0) + if (cipherParams[j].m_name[0] != 0) { char* param = (configDefault) ? sqlite3_mprintf("default:%s", pragmaName) : pragmaName; if (isIntValue) diff --git a/src/codecext.c b/src/codecext.c index dc43f0a..ddc8450 100644 --- a/src/codecext.c +++ b/src/codecext.c @@ -452,6 +452,10 @@ 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; } } @@ -480,6 +484,10 @@ 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; } } @@ -501,6 +509,10 @@ 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; } } diff --git a/src/rekeyvacuum.c b/src/rekeyvacuum.c index 4a3f581..b564146 100644 --- a/src/rekeyvacuum.c +++ b/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.39.2 amalgamation. +** This code is generated by the script rekeyvacuum.sh from SQLite version 3.39.3 amalgamation. */ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3mcRunVacuumForRekey( char **pzErrMsg, /* Write error message here */ diff --git a/src/sqlite3.c b/src/sqlite3.c index b8f98c7..451ca8e 100644 --- a/src/sqlite3.c +++ b/src/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.39.2. By combining all the individual C code files into this +** version 3.39.3. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -452,9 +452,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.39.2" -#define SQLITE_VERSION_NUMBER 3039002 -#define SQLITE_SOURCE_ID "2022-07-21 15:24:47 698edb77537b67c41adc68f9b892db56bcf9a55e00371a61420f3ddd668e6603" +#define SQLITE_VERSION "3.39.3" +#define SQLITE_VERSION_NUMBER 3039003 +#define SQLITE_SOURCE_ID "2022-09-05 11:02:23 4635f4a69c8c2a8df242b384a992aea71224e39a2ccab42d8c0b0602f1e826e8" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -13144,6 +13144,11 @@ struct fts5_api { /************** End of sqlite3.h *********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ +/* +** Reuse the STATIC_LRU for mutex access to sqlite3_temp_directory. +*/ +#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1 + /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build @@ -29563,8 +29568,13 @@ SQLITE_PRIVATE void *sqlite3OomFault(sqlite3 *db){ } DisableLookaside; if( db->pParse ){ + Parse *pParse; sqlite3ErrorMsg(db->pParse, "out of memory"); db->pParse->rc = SQLITE_NOMEM_BKPT; + for(pParse=db->pParse->pOuterParse; pParse; pParse = pParse->pOuterParse){ + pParse->nErr++; + pParse->rc = SQLITE_NOMEM; + } } } return 0; @@ -33459,7 +33469,7 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ va_list ap; sqlite3 *db = pParse->db; assert( db!=0 ); - assert( db->pParse==pParse ); + assert( db->pParse==pParse || db->pParse->pToplevel==pParse ); db->errByteOffset = -2; va_start(ap, zFormat); zMsg = sqlite3VMPrintf(db, zFormat, ap); @@ -41320,6 +41330,7 @@ static const char *unixTempFileDir(void){ static int unixGetTempname(int nBuf, char *zBuf){ const char *zDir; int iLimit = 0; + int rc = SQLITE_OK; /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this @@ -41328,18 +41339,26 @@ static int unixGetTempname(int nBuf, char *zBuf){ zBuf[0] = 0; SimulateIOError( return SQLITE_IOERR ); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); zDir = unixTempFileDir(); - if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH; - do{ - u64 r; - sqlite3_randomness(sizeof(r), &r); - assert( nBuf>2 ); - zBuf[nBuf-2] = 0; - sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c", - zDir, r, 0); - if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR; - }while( osAccess(zBuf,0)==0 ); - return SQLITE_OK; + if( zDir==0 ){ + rc = SQLITE_IOERR_GETTEMPPATH; + }else{ + do{ + u64 r; + sqlite3_randomness(sizeof(r), &r); + assert( nBuf>2 ); + zBuf[nBuf-2] = 0; + sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c", + zDir, r, 0); + if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ){ + rc = SQLITE_ERROR; + break; + } + }while( osAccess(zBuf,0)==0 ); + } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return rc; } #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) @@ -45482,6 +45501,7 @@ SQLITE_API int sqlite3_win32_set_directory8( int rc = sqlite3_initialize(); if( rc ) return rc; #endif + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){ ppDirectory = &sqlite3_data_directory; }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){ @@ -45496,14 +45516,19 @@ SQLITE_API int sqlite3_win32_set_directory8( if( zValue && zValue[0] ){ zCopy = sqlite3_mprintf("%s", zValue); if ( zCopy==0 ){ - return SQLITE_NOMEM_BKPT; + rc = SQLITE_NOMEM_BKPT; + goto set_directory8_done; } } sqlite3_free(*ppDirectory); *ppDirectory = zCopy; - return SQLITE_OK; + rc = SQLITE_OK; + }else{ + rc = SQLITE_ERROR; } - return SQLITE_ERROR; +set_directory8_done: + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return rc; } /* @@ -48277,6 +48302,18 @@ static int winMakeEndInDirSep(int nBuf, char *zBuf){ return 0; } +/* +** If sqlite3_temp_directory is not, take the mutex and return true. +** +** If sqlite3_temp_directory is NULL, omit the mutex and return false. +*/ +static int winTempDirDefined(void){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + if( sqlite3_temp_directory!=0 ) return 1; + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return 0; +} + /* ** Create a temporary file name and store the resulting pointer into pzBuf. ** The pointer returned in pzBuf must be freed via sqlite3_free(). @@ -48313,20 +48350,23 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ */ nDir = nMax - (nPre + 15); assert( nDir>0 ); - if( sqlite3_temp_directory ){ + if( winTempDirDefined() ){ int nDirLen = sqlite3Strlen30(sqlite3_temp_directory); if( nDirLen>0 ){ if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){ nDirLen++; } if( nDirLen>nDir ){ + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0); } sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory); } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); } + #if defined(__CYGWIN__) else{ static const char *azDirs[] = { @@ -49115,7 +49155,7 @@ static BOOL winIsVerbatimPathname( ** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname ** bytes in size. */ -static int winFullPathname( +static int winFullPathnameNoMutex( sqlite3_vfs *pVfs, /* Pointer to vfs object */ const char *zRelative, /* Possibly relative input path */ int nFull, /* Size of output buffer in bytes */ @@ -49294,6 +49334,19 @@ static int winFullPathname( } #endif } +static int winFullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zRelative, /* Possibly relative input path */ + int nFull, /* Size of output buffer in bytes */ + char *zFull /* Output buffer */ +){ + int rc; + sqlite3_mutex *pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); + sqlite3_mutex_enter(pMutex); + rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull); + sqlite3_mutex_leave(pMutex); + return rc; +} #ifndef SQLITE_OMIT_LOAD_EXTENSION /* @@ -59676,6 +59729,7 @@ static int pager_open_journal(Pager *pPager){ if( rc!=SQLITE_OK ){ sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; + pPager->journalOff = 0; }else{ assert( pPager->eState==PAGER_WRITER_LOCKED ); pPager->eState = PAGER_WRITER_CACHEMOD; @@ -61231,7 +61285,7 @@ SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){ SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){ assert( assert_pager_state(pPager) ); if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0; - if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0; + if( isOpen(pPager->jfd) && pPager->journalOff>0 ) return 0; return 1; } @@ -81035,6 +81089,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall( addr = sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function, p1, p2, p3, (char*)pCtx, P4_FUNCCTX); sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef); + sqlite3MayAbort(pParse); return addr; } @@ -81370,6 +81425,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ || opcode==OP_VDestroy || opcode==OP_VCreate || opcode==OP_ParseSchema + || opcode==OP_Function || opcode==OP_PureFunc || ((opcode==OP_Halt || opcode==OP_HaltIfNull) && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort)) ){ @@ -132704,6 +132760,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** */ case PragTyp_TEMP_STORE_DIRECTORY: { + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( !zRight ){ returnSingleText(v, sqlite3_temp_directory); }else{ @@ -132713,6 +132770,7 @@ SQLITE_PRIVATE void sqlite3Pragma( rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); if( rc!=SQLITE_OK || res==0 ){ sqlite3ErrorMsg(pParse, "not a writable directory"); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); goto pragma_out; } } @@ -132730,6 +132788,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } #endif /* SQLITE_OMIT_WSD */ } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); break; } @@ -132748,6 +132807,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** */ case PragTyp_DATA_STORE_DIRECTORY: { + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( !zRight ){ returnSingleText(v, sqlite3_data_directory); }else{ @@ -132757,6 +132817,7 @@ SQLITE_PRIVATE void sqlite3Pragma( rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); if( rc!=SQLITE_OK || res==0 ){ sqlite3ErrorMsg(pParse, "not a writable directory"); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); goto pragma_out; } } @@ -132768,6 +132829,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } #endif /* SQLITE_OMIT_WSD */ } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); break; } #endif @@ -137213,7 +137275,7 @@ static void generateSortTail( if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); VdbeCoverage(v); - codeOffset(v, p->iOffset, addrContinue); + assert( p->iLimit==0 && p->iOffset==0 ); sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab); bSeq = 0; }else{ @@ -137221,6 +137283,9 @@ static void generateSortTail( codeOffset(v, p->iOffset, addrContinue); iSortTab = iTab; bSeq = 1; + if( p->iOffset>0 ){ + sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); + } } for(i=0, iCol=nKey+bSeq-1; ipPrior ){ - sqlite3SelectDelete(db, pSplit->pPrior); + sqlite3ParserAddCleanup(pParse, + (void(*)(sqlite3*,void*))sqlite3SelectDelete, pSplit->pPrior); } pSplit->pPrior = pPrior; pPrior->pNext = pSplit; @@ -140735,6 +140801,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect || pAggInfo->nFunc!=1 + || p->pHaving ){ return 0; } @@ -149783,7 +149850,8 @@ static int codeEqualityTerm( } sqlite3ExprDelete(db, pX); }else{ - aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq); + int n = sqlite3ExprVectorSize(pX->pLeft); + aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n)); eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab); } pX = pExpr; @@ -181120,7 +181188,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ nDistance = iPrev - nMaxUndeferred; } - aOut = (char *)sqlite3_malloc(nPoslist+8); + aOut = (char *)sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING); if( !aOut ){ sqlite3_free(aPoslist); return SQLITE_NOMEM; @@ -204146,7 +204214,7 @@ static int geopolyUpdate( sqlite3_free(p); nChange = 1; } - for(jj=1; jjnAux; jj++){ + for(jj=1; jj= CIPHER_NAME_MAXLEN) + return SQLITE_ERROR; + + /* Check for already registered names */ + CipherName* cipherNameTable = &globalCipherNameTable[0]; + for (; cipherNameTable->m_name[0] != 0; ++cipherNameTable) + { + if (sqlite3_stricmp(name, cipherNameTable->m_name) == 0) break; + } + if (cipherNameTable->m_name[0] != 0) + return SQLITE_ERROR; + + /* Check for valid character set (1st char = alpha, rest = alpha-numeric or underscore) */ + if (sqlite3Isalpha(name[0])) + { + size_t j; + for (j = 1; j < nl && (name[j] == '_' || sqlite3Isalnum(name[j])); ++j) {} + if (j == nl) + return SQLITE_OK; + } + return SQLITE_ERROR; +} + +SQLITE_PRIVATE int +sqlite3mcGetGlobalCipherCount() +{ + int cipherCount = 0; + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); + cipherCount = globalCipherCount; + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); + return cipherCount; +} + +static int +sqlite3mcRegisterCipher(const CipherDescriptor* desc, const CipherParams* params, int makeDefault) +{ + int rc; + int np; + CipherParams* cipherParams; + + /* Sanity checks */ + + /* Cipher description AND parameter are required */ + if (!desc || !params) + return SQLITE_ERROR; + + /* ALL methods of the cipher descriptor need to be defined */ + if (!desc->m_name || + !desc->m_allocateCipher || + !desc->m_freeCipher || + !desc->m_cloneCipher || + !desc->m_getLegacy || + !desc->m_getPageSize || + !desc->m_getReserved || + !desc->m_getSalt || + !desc->m_generateKey || + !desc->m_encryptPage || + !desc->m_decryptPage) + return SQLITE_ERROR; + + /* Check for valid cipher name */ + if (mcCheckValidName(desc->m_name) != SQLITE_OK) + return SQLITE_ERROR; + + /* Check cipher parameters */ + for (np = 0; np < CIPHER_PARAMS_COUNT_MAX; ++np) + { + CipherParams entry = params[np]; + /* Check for sentinel parameter */ + if (entry.m_name == 0 || entry.m_name[0] == 0) + break; + /* Check for valid parameter name */ + if (mcCheckValidName(entry.m_name) != SQLITE_OK) + return SQLITE_ERROR; + /* Check for valid parameter specification */ + if (!(entry.m_minValue >= 0 && entry.m_maxValue >= 0 && entry.m_minValue <= entry.m_maxValue && + entry.m_value >= entry.m_minValue && entry.m_value <= entry.m_maxValue && + entry.m_default >= entry.m_minValue && entry.m_default <= entry.m_maxValue)) + return SQLITE_ERROR; + } + + /* Check for parameter count in valid range and valid sentinel parameter */ + if (np >= CIPHER_PARAMS_COUNT_MAX || params[np].m_name == 0) + return SQLITE_ERROR; + + /* Sanity checks were successful, now register cipher */ + + cipherParams = (CipherParams*) sqlite3_malloc((np+1) * sizeof(CipherParams)); + if (!cipherParams) + return SQLITE_NOMEM; + + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); + + /* Check for */ + if (globalCipherCount < CODEC_COUNT_MAX) + { + int n; + char* cipherName; + ++globalCipherCount; + cipherName = globalCipherNameTable[globalCipherCount].m_name; + strcpy(cipherName, desc->m_name); + + globalCodecDescriptorTable[globalCipherCount - 1] = *desc; + globalCodecDescriptorTable[globalCipherCount - 1].m_name = cipherName; + + globalCodecParameterTable[globalCipherCount].m_name = cipherName; + globalCodecParameterTable[globalCipherCount].m_id = globalCipherCount; + globalCodecParameterTable[globalCipherCount].m_params = cipherParams; + + /* Copy parameters */ + for (n = 0; n < np; ++n) + { + cipherParams[n] = params[n]; + cipherParams[n].m_name = (char*) sqlite3_malloc(strlen(params[n].m_name) + 1); + strcpy(cipherParams[n].m_name, params[n].m_name); + } + /* Add sentinel */ + cipherParams[n] = params[n]; + cipherParams[n].m_name = globalSentinelName; + + /* Make cipher default, if requested */ + if (makeDefault) + { + CipherParams* param = globalCodecParameterTable[0].m_params; + for (; param->m_name[0] != 0; ++param) + { + if (sqlite3_stricmp("cipher", param->m_name) == 0) break; + } + if (param->m_name[0] != 0) + { + param->m_value = param->m_default = globalCipherCount; + } + } + + rc = SQLITE_OK; + } + else + { + rc = SQLITE_NOMEM; + } + + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); + + return rc; +} + +SQLITE_API int +sqlite3mc_register_cipher(const CipherDescriptor* desc, const CipherParams* params, int makeDefault) +{ + int rc; +#ifndef SQLITE_OMIT_AUTOINIT + rc = sqlite3_initialize(); + if (rc) return rc; +#endif + return sqlite3mcRegisterCipher(desc, params, makeDefault); +} + +SQLITE_PRIVATE int +sqlite3mcInitCipherTables() +{ + size_t n; + + /* Initialize cipher name table */ + strcpy(globalCipherNameTable[0].m_name, "global"); + for (n = 1; n < CODEC_COUNT_MAX + 2; ++n) + { + strcpy(globalCipherNameTable[n].m_name, ""); + } + + /* Initialize cipher descriptor table */ + for (n = 0; n < CODEC_COUNT_MAX + 1; ++n) + { + globalCodecDescriptorTable[n] = mcSentinelDescriptor; + } + + /* Initialize cipher parameter table */ + globalCodecParameterTable[0] = globalCommonParams; + for (n = 1; n < CODEC_COUNT_MAX + 2; ++n) + { + globalCodecParameterTable[n] = globalSentinelParams; + } + + return SQLITE_OK; +} + +SQLITE_PRIVATE void +sqlite3mcTermCipherTables() +{ + size_t n; + for (n = CODEC_COUNT_MAX+1; n > 0; --n) + { + if (globalCodecParameterTable[n].m_name[0] != 0) + { + int k; + CipherParams* params = globalCodecParameterTable[n].m_params; + for (k = 0; params->m_name[0] != 0; ++k) + { + sqlite3_free(params->m_name); + } + sqlite3_free(globalCodecParameterTable[n].m_params); + } + } +} + int sqlite3mc_initialize(const char* arg) { - int rc = SQLITE_OK; + int rc = sqlite3mcInitCipherTables(); +#if HAVE_CIPHER_AES_128_CBC + if (rc == SQLITE_OK) + { + rc = sqlite3mcRegisterCipher(&mcAES128Descriptor, mcAES128Params, (CODEC_TYPE_AES128 == CODEC_TYPE)); + } +#endif +#if HAVE_CIPHER_AES_256_CBC + if (rc == SQLITE_OK) + { + rc = sqlite3mcRegisterCipher(&mcAES256Descriptor, mcAES256Params, (CODEC_TYPE_AES256 == CODEC_TYPE)); + } +#endif +#if HAVE_CIPHER_CHACHA20 + if (rc == SQLITE_OK) + { + rc = sqlite3mcRegisterCipher(&mcChaCha20Descriptor, mcChaCha20Params, (CODEC_TYPE_CHACHA20 == CODEC_TYPE)); + } +#endif +#if HAVE_CIPHER_SQLCIPHER + if (rc == SQLITE_OK) + { + rc = sqlite3mcRegisterCipher(&mcSQLCipherDescriptor, mcSQLCipherParams, (CODEC_TYPE_SQLCIPHER == CODEC_TYPE)); + } +#endif +#if HAVE_CIPHER_RC4 + if (rc == SQLITE_OK) + { + rc = sqlite3mcRegisterCipher(&mcRC4Descriptor, mcRC4Params, (CODEC_TYPE_RC4 == CODEC_TYPE)); + } +#endif /* ** Initialize and register MultiCipher VFS as default VFS ** if it isn't already registered */ - rc = sqlite3mc_vfs_create(NULL, 1); + if (rc == SQLITE_OK) + { + rc = sqlite3mc_vfs_create(NULL, 1); + } /* ** Register Multi Cipher extension @@ -480,6 +726,7 @@ void sqlite3mc_shutdown(void) { sqlite3mc_vfs_shutdown(); + sqlite3mcTermCipherTables(); } /* diff --git a/src/sqlite3mc.def b/src/sqlite3mc.def index ef9a8b2..8ef14b0 100644 --- a/src/sqlite3mc.def +++ b/src/sqlite3mc.def @@ -298,9 +298,13 @@ sqlite3_win32_utf8_to_mbcs sqlite3_win32_utf8_to_mbcs_v2 sqlite3_win32_utf8_to_unicode sqlite3_win32_write_debug +sqlite3mc_cipher_count +sqlite3mc_cipher_index +sqlite3mc_cipher_name sqlite3mc_codec_data sqlite3mc_config sqlite3mc_config_cipher +sqlite3mc_register_cipher sqlite3mc_version sqlite3mc_vfs_create sqlite3mc_vfs_destroy diff --git a/src/sqlite3mc.h b/src/sqlite3mc.h index b7a52ed..0b2f695 100644 --- a/src/sqlite3mc.h +++ b/src/sqlite3mc.h @@ -3,7 +3,7 @@ ** Purpose: Header file for SQLite3 Multiple Ciphers support ** Author: Ulrich Telle ** Created: 2020-03-01 -** Copyright: (c) 2019-2021 Ulrich Telle +** Copyright: (c) 2019-2022 Ulrich Telle ** License: MIT */ @@ -27,13 +27,13 @@ /* ** Symbols for ciphers */ -#define CODEC_TYPE_UNKNOWN 0 -#define CODEC_TYPE_AES128 1 -#define CODEC_TYPE_AES256 2 -#define CODEC_TYPE_CHACHA20 3 -#define CODEC_TYPE_SQLCIPHER 4 -#define CODEC_TYPE_RC4 5 -#define CODEC_TYPE_MAX 5 +#define CODEC_TYPE_UNKNOWN 0 +#define CODEC_TYPE_AES128 1 +#define CODEC_TYPE_AES256 2 +#define CODEC_TYPE_CHACHA20 3 +#define CODEC_TYPE_SQLCIPHER 4 +#define CODEC_TYPE_RC4 5 +#define CODEC_TYPE_MAX_BUILTIN 5 /* ** Definition of API functions @@ -102,6 +102,9 @@ SQLITE_API void sqlite3_activate_see(const char* zPassPhrase); /* ** Define functions for the configuration of the wxSQLite3 encryption extension */ +SQLITE_API int sqlite3mc_cipher_count(); +SQLITE_API int sqlite3mc_cipher_index(const char* cipherName); +SQLITE_API const char* sqlite3mc_cipher_name(int cipherIndex); SQLITE_API int sqlite3mc_config(sqlite3* db, const char* paramName, int newValue); SQLITE_API int sqlite3mc_config_cipher(sqlite3* db, const char* cipherName, const char* paramName, int newValue); SQLITE_API unsigned char* sqlite3mc_codec_data(sqlite3* db, const char* zDbName, const char* paramName); @@ -113,6 +116,88 @@ SQLITE_API int wxsqlite3_config_cipher(sqlite3* db, const char* cipherName, cons SQLITE_API unsigned char* wxsqlite3_codec_data(sqlite3* db, const char* zDbName, const char* paramName); #endif +/* +** Structures and functions to dynamically register a cipher +*/ + +/* +** Structure for a single cipher configuration parameter +** +** Components: +** m_name - name of parameter (1st char = alpha, rest = alphanumeric or underscore, max 63 characters) +** m_value - current/transient parameter value +** m_default - default parameter value +** m_minValue - minimum valid parameter value +** m_maxValue - maximum valid parameter value +*/ +typedef struct _CipherParams +{ + char* m_name; + int m_value; + int m_default; + int m_minValue; + int m_maxValue; +} CipherParams; + +/* +** Structure for a cipher API +** +** Components: +** m_name - name of cipher (1st char = alpha, rest = alphanumeric or underscore, max 63 characters) +** m_allocateCipher - Function pointer for function AllocateCipher +** m_freeCipher - Function pointer for function FreeCipher +** m_cloneCipher - Function pointer for function CloneCipher +** m_getLegacy - Function pointer for function GetLegacy +** m_getPageSize - Function pointer for function GetPageSize +** m_getReserved - Function pointer for function GetReserved +** m_getSalt - Function pointer for function GetSalt +** m_generateKey - Function pointer for function GenerateKey +** m_encryptPage - Function pointer for function EncryptPage +** m_decryptPage - Function pointer for function DecryptPage +*/ + +typedef struct BtShared BtSharedMC; + +typedef void* (*AllocateCipher_t)(sqlite3* db); +typedef void (*FreeCipher_t)(void* cipher); +typedef void (*CloneCipher_t)(void* cipherTo, void* cipherFrom); +typedef int (*GetLegacy_t)(void* cipher); +typedef int (*GetPageSize_t)(void* cipher); +typedef int (*GetReserved_t)(void* cipher); +typedef unsigned char* (*GetSalt_t)(void* cipher); +typedef void (*GenerateKey_t)(void* cipher, BtSharedMC* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt); +typedef int (*EncryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved); +typedef int (*DecryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved, int hmacCheck); + +typedef struct _CipherDescriptor +{ + char* m_name; + AllocateCipher_t m_allocateCipher; + FreeCipher_t m_freeCipher; + CloneCipher_t m_cloneCipher; + GetLegacy_t m_getLegacy; + GetPageSize_t m_getPageSize; + GetReserved_t m_getReserved; + GetSalt_t m_getSalt; + GenerateKey_t m_generateKey; + EncryptPage_t m_encryptPage; + DecryptPage_t m_decryptPage; +} CipherDescriptor; + +/* +** Register a cipher +** +** Arguments: +** desc - Cipher descriptor structure +** params - Cipher configuration parameter table +** makeDefault - flag whether to make the cipher the default cipher +** +** Returns: +** SQLITE_OK - the cipher could be registered successfully +** SQLITE_ERROR - the cipher could not be registered +*/ +SQLITE_API int sqlite3mc_register_cipher(const CipherDescriptor* desc, const CipherParams* params, int makeDefault); + #ifdef __cplusplus } #endif diff --git a/src/sqlite3mc_config.h b/src/sqlite3mc_config.h index 45ef162..4a1aa79 100644 --- a/src/sqlite3mc_config.h +++ b/src/sqlite3mc_config.h @@ -3,7 +3,7 @@ ** Purpose: Header file for SQLite3 Multiple Ciphers compile-time configuration ** Author: Ulrich Telle ** Created: 2021-09-27 -** Copyright: (c) 2019-2021 Ulrich Telle +** Copyright: (c) 2019-2022 Ulrich Telle ** License: MIT */ @@ -60,6 +60,27 @@ #define HAVE_CIPHER_RC4 1 #endif +/* +** Disable all built-in ciphers on request +*/ + +#if 0 +#define SQLITE3MC_OMIT_BUILTIN_CIPHERS +#endif + +#ifdef SQLITE3MC_OMIT_BUILTIN_CIPHERS +#undef HAVE_CIPHER_AES_128_CBC +#undef HAVE_CIPHER_AES_256_CBC +#undef HAVE_CIPHER_CHACHA20 +#undef HAVE_CIPHER_SQLCIPHER +#undef HAVE_CIPHER_RC4 +#define HAVE_CIPHER_AES_128_CBC 0 +#define HAVE_CIPHER_AES_256_CBC 0 +#define HAVE_CIPHER_CHACHA20 0 +#define HAVE_CIPHER_SQLCIPHER 0 +#define HAVE_CIPHER_RC4 0 +#endif + /* ** Check that at least one cipher is be supported */ @@ -68,7 +89,7 @@ HAVE_CIPHER_CHACHA20 == 0 && \ HAVE_CIPHER_SQLCIPHER == 0 && \ HAVE_CIPHER_RC4 == 0 -#error Enable at least one cipher scheme! +#pragma message ("sqlite3mc_config.h: WARNING - No built-in cipher scheme enabled!") #endif /* diff --git a/src/sqlite3mc_version.h b/src/sqlite3mc_version.h index 17ae6b7..021eff7 100644 --- a/src/sqlite3mc_version.h +++ b/src/sqlite3mc_version.h @@ -13,9 +13,9 @@ #define SQLITE3MC_VERSION_H_ #define SQLITE3MC_VERSION_MAJOR 1 -#define SQLITE3MC_VERSION_MINOR 4 -#define SQLITE3MC_VERSION_RELEASE 8 +#define SQLITE3MC_VERSION_MINOR 5 +#define SQLITE3MC_VERSION_RELEASE 0 #define SQLITE3MC_VERSION_SUBRELEASE 0 -#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 1.4.8" +#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 1.5.0" #endif /* SQLITE3MC_VERSION_H_ */ diff --git a/src/sqlite3patched.c b/src/sqlite3patched.c index 16d45d6..e5c03d8 100644 --- a/src/sqlite3patched.c +++ b/src/sqlite3patched.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.39.2. By combining all the individual C code files into this +** version 3.39.3. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -452,9 +452,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.39.2" -#define SQLITE_VERSION_NUMBER 3039002 -#define SQLITE_SOURCE_ID "2022-07-21 15:24:47 698edb77537b67c41adc68f9b892db56bcf9a55e00371a61420f3ddd668e6603" +#define SQLITE_VERSION "3.39.3" +#define SQLITE_VERSION_NUMBER 3039003 +#define SQLITE_SOURCE_ID "2022-09-05 11:02:23 4635f4a69c8c2a8df242b384a992aea71224e39a2ccab42d8c0b0602f1e826e8" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -13151,6 +13151,11 @@ struct fts5_api { /************** End of sqlite3.h *********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ +/* +** Reuse the STATIC_LRU for mutex access to sqlite3_temp_directory. +*/ +#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1 + /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build @@ -29570,8 +29575,13 @@ SQLITE_PRIVATE void *sqlite3OomFault(sqlite3 *db){ } DisableLookaside; if( db->pParse ){ + Parse *pParse; sqlite3ErrorMsg(db->pParse, "out of memory"); db->pParse->rc = SQLITE_NOMEM_BKPT; + for(pParse=db->pParse->pOuterParse; pParse; pParse = pParse->pOuterParse){ + pParse->nErr++; + pParse->rc = SQLITE_NOMEM; + } } } return 0; @@ -33466,7 +33476,7 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ va_list ap; sqlite3 *db = pParse->db; assert( db!=0 ); - assert( db->pParse==pParse ); + assert( db->pParse==pParse || db->pParse->pToplevel==pParse ); db->errByteOffset = -2; va_start(ap, zFormat); zMsg = sqlite3VMPrintf(db, zFormat, ap); @@ -41327,6 +41337,7 @@ static const char *unixTempFileDir(void){ static int unixGetTempname(int nBuf, char *zBuf){ const char *zDir; int iLimit = 0; + int rc = SQLITE_OK; /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this @@ -41335,18 +41346,26 @@ static int unixGetTempname(int nBuf, char *zBuf){ zBuf[0] = 0; SimulateIOError( return SQLITE_IOERR ); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); zDir = unixTempFileDir(); - if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH; - do{ - u64 r; - sqlite3_randomness(sizeof(r), &r); - assert( nBuf>2 ); - zBuf[nBuf-2] = 0; - sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c", - zDir, r, 0); - if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR; - }while( osAccess(zBuf,0)==0 ); - return SQLITE_OK; + if( zDir==0 ){ + rc = SQLITE_IOERR_GETTEMPPATH; + }else{ + do{ + u64 r; + sqlite3_randomness(sizeof(r), &r); + assert( nBuf>2 ); + zBuf[nBuf-2] = 0; + sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c", + zDir, r, 0); + if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ){ + rc = SQLITE_ERROR; + break; + } + }while( osAccess(zBuf,0)==0 ); + } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return rc; } #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) @@ -45489,6 +45508,7 @@ SQLITE_API int sqlite3_win32_set_directory8( int rc = sqlite3_initialize(); if( rc ) return rc; #endif + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){ ppDirectory = &sqlite3_data_directory; }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){ @@ -45503,14 +45523,19 @@ SQLITE_API int sqlite3_win32_set_directory8( if( zValue && zValue[0] ){ zCopy = sqlite3_mprintf("%s", zValue); if ( zCopy==0 ){ - return SQLITE_NOMEM_BKPT; + rc = SQLITE_NOMEM_BKPT; + goto set_directory8_done; } } sqlite3_free(*ppDirectory); *ppDirectory = zCopy; - return SQLITE_OK; + rc = SQLITE_OK; + }else{ + rc = SQLITE_ERROR; } - return SQLITE_ERROR; +set_directory8_done: + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return rc; } /* @@ -48284,6 +48309,18 @@ static int winMakeEndInDirSep(int nBuf, char *zBuf){ return 0; } +/* +** If sqlite3_temp_directory is not, take the mutex and return true. +** +** If sqlite3_temp_directory is NULL, omit the mutex and return false. +*/ +static int winTempDirDefined(void){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + if( sqlite3_temp_directory!=0 ) return 1; + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return 0; +} + /* ** Create a temporary file name and store the resulting pointer into pzBuf. ** The pointer returned in pzBuf must be freed via sqlite3_free(). @@ -48320,20 +48357,23 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ */ nDir = nMax - (nPre + 15); assert( nDir>0 ); - if( sqlite3_temp_directory ){ + if( winTempDirDefined() ){ int nDirLen = sqlite3Strlen30(sqlite3_temp_directory); if( nDirLen>0 ){ if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){ nDirLen++; } if( nDirLen>nDir ){ + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0); } sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory); } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); } + #if defined(__CYGWIN__) else{ static const char *azDirs[] = { @@ -49122,7 +49162,7 @@ static BOOL winIsVerbatimPathname( ** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname ** bytes in size. */ -static int winFullPathname( +static int winFullPathnameNoMutex( sqlite3_vfs *pVfs, /* Pointer to vfs object */ const char *zRelative, /* Possibly relative input path */ int nFull, /* Size of output buffer in bytes */ @@ -49301,6 +49341,19 @@ static int winFullPathname( } #endif } +static int winFullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zRelative, /* Possibly relative input path */ + int nFull, /* Size of output buffer in bytes */ + char *zFull /* Output buffer */ +){ + int rc; + sqlite3_mutex *pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); + sqlite3_mutex_enter(pMutex); + rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull); + sqlite3_mutex_leave(pMutex); + return rc; +} #ifndef SQLITE_OMIT_LOAD_EXTENSION /* @@ -59683,6 +59736,7 @@ static int pager_open_journal(Pager *pPager){ if( rc!=SQLITE_OK ){ sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; + pPager->journalOff = 0; }else{ assert( pPager->eState==PAGER_WRITER_LOCKED ); pPager->eState = PAGER_WRITER_CACHEMOD; @@ -61238,7 +61292,7 @@ SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){ SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){ assert( assert_pager_state(pPager) ); if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0; - if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0; + if( isOpen(pPager->jfd) && pPager->journalOff>0 ) return 0; return 1; } @@ -81042,6 +81096,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall( addr = sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function, p1, p2, p3, (char*)pCtx, P4_FUNCCTX); sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef); + sqlite3MayAbort(pParse); return addr; } @@ -81377,6 +81432,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ || opcode==OP_VDestroy || opcode==OP_VCreate || opcode==OP_ParseSchema + || opcode==OP_Function || opcode==OP_PureFunc || ((opcode==OP_Halt || opcode==OP_HaltIfNull) && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort)) ){ @@ -132716,6 +132772,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** */ case PragTyp_TEMP_STORE_DIRECTORY: { + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( !zRight ){ returnSingleText(v, sqlite3_temp_directory); }else{ @@ -132725,6 +132782,7 @@ SQLITE_PRIVATE void sqlite3Pragma( rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); if( rc!=SQLITE_OK || res==0 ){ sqlite3ErrorMsg(pParse, "not a writable directory"); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); goto pragma_out; } } @@ -132742,6 +132800,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } #endif /* SQLITE_OMIT_WSD */ } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); break; } @@ -132760,6 +132819,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** */ case PragTyp_DATA_STORE_DIRECTORY: { + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( !zRight ){ returnSingleText(v, sqlite3_data_directory); }else{ @@ -132769,6 +132829,7 @@ SQLITE_PRIVATE void sqlite3Pragma( rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); if( rc!=SQLITE_OK || res==0 ){ sqlite3ErrorMsg(pParse, "not a writable directory"); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); goto pragma_out; } } @@ -132780,6 +132841,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } #endif /* SQLITE_OMIT_WSD */ } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); break; } #endif @@ -137225,7 +137287,7 @@ static void generateSortTail( if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); VdbeCoverage(v); - codeOffset(v, p->iOffset, addrContinue); + assert( p->iLimit==0 && p->iOffset==0 ); sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab); bSeq = 0; }else{ @@ -137233,6 +137295,9 @@ static void generateSortTail( codeOffset(v, p->iOffset, addrContinue); iSortTab = iTab; bSeq = 1; + if( p->iOffset>0 ){ + sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); + } } for(i=0, iCol=nKey+bSeq-1; ipPrior ){ - sqlite3SelectDelete(db, pSplit->pPrior); + sqlite3ParserAddCleanup(pParse, + (void(*)(sqlite3*,void*))sqlite3SelectDelete, pSplit->pPrior); } pSplit->pPrior = pPrior; pPrior->pNext = pSplit; @@ -140747,6 +140813,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect || pAggInfo->nFunc!=1 + || p->pHaving ){ return 0; } @@ -149795,7 +149862,8 @@ static int codeEqualityTerm( } sqlite3ExprDelete(db, pX); }else{ - aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq); + int n = sqlite3ExprVectorSize(pX->pLeft); + aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n)); eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab); } pX = pExpr; @@ -181137,7 +181205,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ nDistance = iPrev - nMaxUndeferred; } - aOut = (char *)sqlite3_malloc(nPoslist+8); + aOut = (char *)sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING); if( !aOut ){ sqlite3_free(aPoslist); return SQLITE_NOMEM; @@ -204163,7 +204231,7 @@ static int geopolyUpdate( sqlite3_free(p); nChange = 1; } - for(jj=1; jjnAux; jj++){ + for(jj=1; jj