Skip to content

Commit 07a1a60

Browse files
committed
Fix issue #228
Function sqlite3mc_cipher_name is not thread-safe. This could cause runtime errors, if several threads try to open a database connection at the same time. - The internal implementation has been changed to avoid calling sqlite3mc_cipher_name - API function sqlite3mc_cipher_name_copy has been added, which is thread-safe
1 parent 158d582 commit 07a1a60

File tree

2 files changed

+56
-12
lines changed

2 files changed

+56
-12
lines changed

src/cipher_config.c

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
** Purpose: Configuration of SQLite codecs
44
** Author: Ulrich Telle
55
** Created: 2020-03-02
6-
** Copyright: (c) 2006-2024 Ulrich Telle
6+
** Copyright: (c) 2006-2026 Ulrich Telle
77
** License: MIT
88
*/
99

@@ -150,18 +150,17 @@ sqlite3mc_cipher_index(const char* cipherName)
150150
return (j < count && globalCodecDescriptorTable[j].m_name[0] != 0) ? j + 1 : -1;
151151
}
152152

153-
SQLITE_API const char*
154-
sqlite3mc_cipher_name(int cipherIndex)
153+
static const char*
154+
sqlite3mcFindCipherName(int cipherIndex)
155155
{
156-
static char cipherName[CIPHER_NAME_MAXLEN] = "";
156+
const char* cipherName = NULL;
157157
int count;
158158
int j;
159159
#ifndef SQLITE_OMIT_AUTOINIT
160-
if( sqlite3_initialize() ) return cipherName;
160+
if (sqlite3_initialize()) return NULL;
161161
#endif
162162
count = sqlite3mcGetGlobalCipherCount();
163163
j = 0;
164-
cipherName[0] = '\0';
165164
if (cipherIndex > 0 && cipherIndex <= count)
166165
{
167166
for (j = 0; j < count && globalCodecDescriptorTable[j].m_name[0] != 0; ++j)
@@ -170,13 +169,57 @@ sqlite3mc_cipher_name(int cipherIndex)
170169
}
171170
if (j < count && globalCodecDescriptorTable[j].m_name[0] != 0)
172171
{
173-
strncpy(cipherName, globalCodecDescriptorTable[j].m_name, CIPHER_NAME_MAXLEN - 1);
174-
cipherName[CIPHER_NAME_MAXLEN - 1] = '\0';
172+
cipherName = globalCodecDescriptorTable[j].m_name;
175173
}
176174
}
177175
return cipherName;
178176
}
179177

178+
SQLITE_API const char*
179+
sqlite3mc_cipher_name(int cipherIndex)
180+
{
181+
static char cipherName[CIPHER_NAME_MAXLEN] = "";
182+
const char* globalCipherName = sqlite3mcFindCipherName(cipherIndex);
183+
if (globalCipherName)
184+
{
185+
strncpy(cipherName, globalCipherName, CIPHER_NAME_MAXLEN - 1);
186+
cipherName[CIPHER_NAME_MAXLEN - 1] = '\0';
187+
}
188+
else
189+
{
190+
cipherName[0] = '\0';
191+
}
192+
return cipherName;
193+
}
194+
195+
SQLITE_API int
196+
sqlite3mc_cipher_name_copy(int cipherIndex, char* cipherName, int maxCipherNameSize)
197+
{
198+
int ok = 1;
199+
const char* globalCipherName = sqlite3mcFindCipherName(cipherIndex);
200+
if (globalCipherName)
201+
{
202+
int cipherNameLen = (int)strlen(globalCipherName) + 1;
203+
if (maxCipherNameSize >= cipherNameLen)
204+
{
205+
strncpy(cipherName, globalCipherName, maxCipherNameSize - 1);
206+
cipherName[maxCipherNameSize - 1] = '\0';
207+
}
208+
else
209+
{
210+
/* Buffer too small, return negative value of minimum required buffer length */
211+
ok = -cipherNameLen;
212+
}
213+
}
214+
else
215+
{
216+
/* Invalid index */
217+
cipherName[0] = '\0';
218+
ok = 0;
219+
}
220+
return ok;
221+
}
222+
180223
static
181224
int checkParameterValue(const char* paramName, int value, const char* cipherName)
182225
{
@@ -720,16 +763,16 @@ sqlite3mcConfigureFromUri(sqlite3* db, const char* zDbName, int configDefault)
720763
{
721764
/* Check whether cipher is specified */
722765
const char* cipherName = sqlite3_uri_parameter(dbFileName, "cipher");
723-
if (cipherName == NULL)
766+
if (cipherName == NULL || cipherName[0] == 0)
724767
{
725768
int defaultCipherIndex = sqlite3mc_config(db, "cipher", -1);
726769
if (defaultCipherIndex > 0)
727770
{
728-
cipherName = sqlite3mc_cipher_name(defaultCipherIndex);
771+
cipherName = sqlite3mcFindCipherName(defaultCipherIndex);
729772
sqlite3mc_config(db, "cipher", defaultCipherIndex);
730773
}
731774
}
732-
if (cipherName != NULL)
775+
if (cipherName != NULL && cipherName[0] != 0)
733776
{
734777
int j = 0;
735778
CipherParams* cipherParams = NULL;

src/sqlite3mc.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
** Purpose: Header file for SQLite3 Multiple Ciphers support
44
** Author: Ulrich Telle
55
** Created: 2020-03-01
6-
** Copyright: (c) 2019-2024 Ulrich Telle
6+
** Copyright: (c) 2019-2026 Ulrich Telle
77
** License: MIT
88
*/
99

@@ -107,6 +107,7 @@ SQLITE_API void sqlite3_activate_see(const char* zPassPhrase);
107107
SQLITE_API int sqlite3mc_cipher_count();
108108
SQLITE_API int sqlite3mc_cipher_index(const char* cipherName);
109109
SQLITE_API const char* sqlite3mc_cipher_name(int cipherIndex);
110+
SQLITE_API int sqlite3mc_cipher_name_copy(int cipherIndex, char* cipherName, int maxCipherNameSize);
110111
SQLITE_API int sqlite3mc_config(sqlite3* db, const char* paramName, int newValue);
111112
SQLITE_API int sqlite3mc_config_cipher(sqlite3* db, const char* cipherName, const char* paramName, int newValue);
112113
SQLITE_API unsigned char* sqlite3mc_codec_data(sqlite3* db, const char* zDbName, const char* paramName);

0 commit comments

Comments
 (0)