#include <string.h>
#ifdef _WIN32
#include <windows.h>
#include <winbase.h>
#endif
SQLITE_PRIVATE void sqlite3mcSecureZeroMemory(void* v, size_t n)
{
#ifdef _WIN32
SecureZeroMemory(v, n);
#elif defined(__DARWIN__) || defined(__STDC_LIB_EXT1__)
memset_s(v, n, 0, n);
#elif defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 11)
explicit_bzero(v, n);
#else
static void* (* const volatile memset_sec)(void*, int, size_t) = &memset;
memset_sec(v, 0, n);
#endif
}
#if SQLITE3MC_SECURE_MEMORY
static volatile int mcSecureMemoryInitialized = 0;
static volatile int mcSecureMemoryFlag = 0;
static volatile sqlite3_mem_methods mcDefaultMemoryMethods;
static int mcMemorySize(void* pBuf)
{
return mcDefaultMemoryMethods.xSize(pBuf);
}
static void* mcMemoryAlloc(int nByte)
{
return mcDefaultMemoryMethods.xMalloc(nByte);
}
static void mcMemoryFree(void* pPrior)
{
if (mcSecureMemoryFlag)
{
int nSize = mcMemorySize(pPrior);
sqlite3mcSecureZeroMemory(pPrior, 0, nSize);
}
mcDefaultMemoryMethods.xFree(pPrior);
}
static void* mcMemoryRealloc(void* pPrior, int nByte)
{
void* pNew = NULL;
if (mcSecureMemoryFlag)
{
int nPriorSize = mcMemorySize(pPrior);
if (nByte == 0)
{
mcMemoryFree(pPrior);
return NULL;
}
else if (!pPrior)
{
return mcMemoryAlloc(nByte);
}
else if(nByte <= nPriorSize)
{
return pPrior;
}
else
{
pNew = mcMemoryAlloc(nByte);
if (pNew)
{
memcpy(pNew, pPrior, nPriorSize);
mcMemoryFree(pPrior);
}
return pNew;
}
}
else
{
return mcDefaultMemoryMethods.xRealloc(pPrior, nByte);
}
}
static int mcMemoryRoundup(int nByte)
{
return mcDefaultMemoryMethods.xRoundup(nByte);
}
static int mcMemoryInit(void* pAppData)
{
return mcDefaultMemoryMethods.xInit(pAppData);
}
static void mcMemoryShutdown(void* pAppData)
{
mcDefaultMemoryMethods.xShutdown(pAppData);
}
static sqlite3_mem_methods mcSecureMemoryMethods =
{
mcMemoryAlloc,
mcMemoryFree,
mcMemoryRealloc,
mcMemorySize,
mcMemoryRoundup,
mcMemoryInit,
mcMemoryShutdown,
0
};
SQLITE_PRIVATE void sqlite3mcSetMemorySecurity(int value)
{
if (mcSecureMemoryFlag < 2)
{
mcSecureMemoryFlag = (value >= 0 && value <= 2) ? value : 0;
}
}
SQLITE_PRIVATE int sqlite3mcGetMemorySecurity()
{
return mcSecureMemoryFlag;
}
#endif
SQLITE_PRIVATE void sqlite3mcInitMemoryMethods()
{
#if SQLITE3MC_SECURE_MEMORY
if (!mcSecureMemoryInitialized)
{
if (sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mcDefaultMemoryMethods) != SQLITE_OK ||
sqlite3_config(SQLITE_CONFIG_MALLOC, &mcSecureMemoryMethods) != SQLITE_OK)
{
mcSecureMemoryFlag = mcSecureMemoryInitialized = 0;
}
else
{
mcSecureMemoryInitialized = 1;
}
}
#endif
}