1 /*
2 ** 2016-09-07
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 ******************************************************************************
12 **
13 ** This file implements an in-memory VFS. A database is held as a contiguous
14 ** block of memory.
15 **
16 ** This file also implements interface sqlite3_serialize() and
17 ** sqlite3_deserialize().
18 */
19 #include "sqliteInt.h"
20 #ifdef SQLITE_ENABLE_DESERIALIZE
21 
22 /*
23 ** Forward declaration of objects used by this utility
24 */
25 typedef struct sqlite3_vfs MemVfs;
26 typedef struct MemFile MemFile;
27 
28 /* Access to a lower-level VFS that (might) implement dynamic loading,
29 ** access to randomness, etc.
30 */
31 #define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
32 
33 /* An open file */
34 struct MemFile {
35   sqlite3_file base;              /* IO methods */
36   sqlite3_int64 sz;               /* Size of the file */
37   sqlite3_int64 szAlloc;          /* Space allocated to aData */
38   sqlite3_int64 szMax;            /* Maximum allowed size of the file */
39   unsigned char *aData;           /* content of the file */
40   int nMmap;                      /* Number of memory mapped pages */
41   unsigned mFlags;                /* Flags */
42   int eLock;                      /* Most recent lock against this file */
43 };
44 
45 /*
46 ** Methods for MemFile
47 */
48 static int memdbClose(sqlite3_file*);
49 static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
50 static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
51 static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
52 static int memdbSync(sqlite3_file*, int flags);
53 static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
54 static int memdbLock(sqlite3_file*, int);
55 /* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
56 static int memdbFileControl(sqlite3_file*, int op, void *pArg);
57 /* static int memdbSectorSize(sqlite3_file*); // not used */
58 static int memdbDeviceCharacteristics(sqlite3_file*);
59 static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
60 static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
61 
62 /*
63 ** Methods for MemVfs
64 */
65 static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
66 /* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */
67 static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *);
68 static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
69 static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename);
70 static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
71 static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
72 static void memdbDlClose(sqlite3_vfs*, void*);
73 static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut);
74 static int memdbSleep(sqlite3_vfs*, int microseconds);
75 /* static int memdbCurrentTime(sqlite3_vfs*, double*); */
76 static int memdbGetLastError(sqlite3_vfs*, int, char *);
77 static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
78 
79 static sqlite3_vfs memdb_vfs = {
80   2,                           /* iVersion */
81   0,                           /* szOsFile (set when registered) */
82   1024,                        /* mxPathname */
83   0,                           /* pNext */
84   "memdb",                     /* zName */
85   0,                           /* pAppData (set when registered) */
86   memdbOpen,                   /* xOpen */
87   0, /* memdbDelete, */        /* xDelete */
88   memdbAccess,                 /* xAccess */
89   memdbFullPathname,           /* xFullPathname */
90   memdbDlOpen,                 /* xDlOpen */
91   memdbDlError,                /* xDlError */
92   memdbDlSym,                  /* xDlSym */
93   memdbDlClose,                /* xDlClose */
94   memdbRandomness,             /* xRandomness */
95   memdbSleep,                  /* xSleep */
96   0, /* memdbCurrentTime, */   /* xCurrentTime */
97   memdbGetLastError,           /* xGetLastError */
98   memdbCurrentTimeInt64        /* xCurrentTimeInt64 */
99 };
100 
101 static const sqlite3_io_methods memdb_io_methods = {
102   3,                              /* iVersion */
103   memdbClose,                      /* xClose */
104   memdbRead,                       /* xRead */
105   memdbWrite,                      /* xWrite */
106   memdbTruncate,                   /* xTruncate */
107   memdbSync,                       /* xSync */
108   memdbFileSize,                   /* xFileSize */
109   memdbLock,                       /* xLock */
110   memdbLock,                       /* xUnlock - same as xLock in this case */
111   0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
112   memdbFileControl,                /* xFileControl */
113   0, /* memdbSectorSize,*/         /* xSectorSize */
114   memdbDeviceCharacteristics,      /* xDeviceCharacteristics */
115   0,                               /* xShmMap */
116   0,                               /* xShmLock */
117   0,                               /* xShmBarrier */
118   0,                               /* xShmUnmap */
119   memdbFetch,                      /* xFetch */
120   memdbUnfetch                     /* xUnfetch */
121 };
122 
123 
124 
125 /*
126 ** Close an memdb-file.
127 **
128 ** The pData pointer is owned by the application, so there is nothing
129 ** to free.
130 */
memdbClose(sqlite3_file * pFile)131 static int memdbClose(sqlite3_file *pFile){
132   MemFile *p = (MemFile *)pFile;
133   if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData);
134   return SQLITE_OK;
135 }
136 
137 /*
138 ** Read data from an memdb-file.
139 */
memdbRead(sqlite3_file * pFile,void * zBuf,int iAmt,sqlite_int64 iOfst)140 static int memdbRead(
141   sqlite3_file *pFile,
142   void *zBuf,
143   int iAmt,
144   sqlite_int64 iOfst
145 ){
146   MemFile *p = (MemFile *)pFile;
147   if( iOfst+iAmt>p->sz ){
148     memset(zBuf, 0, iAmt);
149     if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
150     return SQLITE_IOERR_SHORT_READ;
151   }
152   memcpy(zBuf, p->aData+iOfst, iAmt);
153   return SQLITE_OK;
154 }
155 
156 /*
157 ** Try to enlarge the memory allocation to hold at least sz bytes
158 */
memdbEnlarge(MemFile * p,sqlite3_int64 newSz)159 static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
160   unsigned char *pNew;
161   if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
162     return SQLITE_FULL;
163   }
164   if( newSz>p->szMax ){
165     return SQLITE_FULL;
166   }
167   newSz *= 2;
168   if( newSz>p->szMax ) newSz = p->szMax;
169   pNew = sqlite3_realloc64(p->aData, newSz);
170   if( pNew==0 ) return SQLITE_NOMEM;
171   p->aData = pNew;
172   p->szAlloc = newSz;
173   return SQLITE_OK;
174 }
175 
176 /*
177 ** Write data to an memdb-file.
178 */
memdbWrite(sqlite3_file * pFile,const void * z,int iAmt,sqlite_int64 iOfst)179 static int memdbWrite(
180   sqlite3_file *pFile,
181   const void *z,
182   int iAmt,
183   sqlite_int64 iOfst
184 ){
185   MemFile *p = (MemFile *)pFile;
186   if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ) return SQLITE_READONLY;
187   if( iOfst+iAmt>p->sz ){
188     int rc;
189     if( iOfst+iAmt>p->szAlloc
190      && (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
191     ){
192       return rc;
193     }
194     if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
195     p->sz = iOfst+iAmt;
196   }
197   memcpy(p->aData+iOfst, z, iAmt);
198   return SQLITE_OK;
199 }
200 
201 /*
202 ** Truncate an memdb-file.
203 **
204 ** In rollback mode (which is always the case for memdb, as it does not
205 ** support WAL mode) the truncate() method is only used to reduce
206 ** the size of a file, never to increase the size.
207 */
memdbTruncate(sqlite3_file * pFile,sqlite_int64 size)208 static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
209   MemFile *p = (MemFile *)pFile;
210   if( NEVER(size>p->sz) ) return SQLITE_FULL;
211   p->sz = size;
212   return SQLITE_OK;
213 }
214 
215 /*
216 ** Sync an memdb-file.
217 */
memdbSync(sqlite3_file * pFile,int flags)218 static int memdbSync(sqlite3_file *pFile, int flags){
219   return SQLITE_OK;
220 }
221 
222 /*
223 ** Return the current file-size of an memdb-file.
224 */
memdbFileSize(sqlite3_file * pFile,sqlite_int64 * pSize)225 static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
226   MemFile *p = (MemFile *)pFile;
227   *pSize = p->sz;
228   return SQLITE_OK;
229 }
230 
231 /*
232 ** Lock an memdb-file.
233 */
memdbLock(sqlite3_file * pFile,int eLock)234 static int memdbLock(sqlite3_file *pFile, int eLock){
235   MemFile *p = (MemFile *)pFile;
236   if( eLock>SQLITE_LOCK_SHARED
237    && (p->mFlags & SQLITE_DESERIALIZE_READONLY)!=0
238   ){
239     return SQLITE_READONLY;
240   }
241   p->eLock = eLock;
242   return SQLITE_OK;
243 }
244 
245 #if 0 /* Never used because memdbAccess() always returns false */
246 /*
247 ** Check if another file-handle holds a RESERVED lock on an memdb-file.
248 */
249 static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
250   *pResOut = 0;
251   return SQLITE_OK;
252 }
253 #endif
254 
255 /*
256 ** File control method. For custom operations on an memdb-file.
257 */
memdbFileControl(sqlite3_file * pFile,int op,void * pArg)258 static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
259   MemFile *p = (MemFile *)pFile;
260   int rc = SQLITE_NOTFOUND;
261   if( op==SQLITE_FCNTL_VFSNAME ){
262     *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
263     rc = SQLITE_OK;
264   }
265   if( op==SQLITE_FCNTL_SIZE_LIMIT ){
266     sqlite3_int64 iLimit = *(sqlite3_int64*)pArg;
267     if( iLimit<p->sz ){
268       if( iLimit<0 ){
269         iLimit = p->szMax;
270       }else{
271         iLimit = p->sz;
272       }
273     }
274     p->szMax = iLimit;
275     *(sqlite3_int64*)pArg = iLimit;
276     rc = SQLITE_OK;
277   }
278   return rc;
279 }
280 
281 #if 0  /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
282 /*
283 ** Return the sector-size in bytes for an memdb-file.
284 */
285 static int memdbSectorSize(sqlite3_file *pFile){
286   return 1024;
287 }
288 #endif
289 
290 /*
291 ** Return the device characteristic flags supported by an memdb-file.
292 */
memdbDeviceCharacteristics(sqlite3_file * pFile)293 static int memdbDeviceCharacteristics(sqlite3_file *pFile){
294   return SQLITE_IOCAP_ATOMIC |
295          SQLITE_IOCAP_POWERSAFE_OVERWRITE |
296          SQLITE_IOCAP_SAFE_APPEND |
297          SQLITE_IOCAP_SEQUENTIAL;
298 }
299 
300 /* Fetch a page of a memory-mapped file */
memdbFetch(sqlite3_file * pFile,sqlite3_int64 iOfst,int iAmt,void ** pp)301 static int memdbFetch(
302   sqlite3_file *pFile,
303   sqlite3_int64 iOfst,
304   int iAmt,
305   void **pp
306 ){
307   MemFile *p = (MemFile *)pFile;
308   if( iOfst+iAmt>p->sz ){
309     *pp = 0;
310   }else{
311     p->nMmap++;
312     *pp = (void*)(p->aData + iOfst);
313   }
314   return SQLITE_OK;
315 }
316 
317 /* Release a memory-mapped page */
memdbUnfetch(sqlite3_file * pFile,sqlite3_int64 iOfst,void * pPage)318 static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
319   MemFile *p = (MemFile *)pFile;
320   p->nMmap--;
321   return SQLITE_OK;
322 }
323 
324 /*
325 ** Open an mem file handle.
326 */
memdbOpen(sqlite3_vfs * pVfs,const char * zName,sqlite3_file * pFile,int flags,int * pOutFlags)327 static int memdbOpen(
328   sqlite3_vfs *pVfs,
329   const char *zName,
330   sqlite3_file *pFile,
331   int flags,
332   int *pOutFlags
333 ){
334   MemFile *p = (MemFile*)pFile;
335   if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
336     return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
337   }
338   memset(p, 0, sizeof(*p));
339   p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
340   assert( pOutFlags!=0 );  /* True because flags==SQLITE_OPEN_MAIN_DB */
341   *pOutFlags = flags | SQLITE_OPEN_MEMORY;
342   p->base.pMethods = &memdb_io_methods;
343   p->szMax = sqlite3GlobalConfig.mxMemdbSize;
344   return SQLITE_OK;
345 }
346 
347 #if 0 /* Only used to delete rollback journals, master journals, and WAL
348       ** files, none of which exist in memdb.  So this routine is never used */
349 /*
350 ** Delete the file located at zPath. If the dirSync argument is true,
351 ** ensure the file-system modifications are synced to disk before
352 ** returning.
353 */
354 static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
355   return SQLITE_IOERR_DELETE;
356 }
357 #endif
358 
359 /*
360 ** Test for access permissions. Return true if the requested permission
361 ** is available, or false otherwise.
362 **
363 ** With memdb, no files ever exist on disk.  So always return false.
364 */
memdbAccess(sqlite3_vfs * pVfs,const char * zPath,int flags,int * pResOut)365 static int memdbAccess(
366   sqlite3_vfs *pVfs,
367   const char *zPath,
368   int flags,
369   int *pResOut
370 ){
371   *pResOut = 0;
372   return SQLITE_OK;
373 }
374 
375 /*
376 ** Populate buffer zOut with the full canonical pathname corresponding
377 ** to the pathname in zPath. zOut is guaranteed to point to a buffer
378 ** of at least (INST_MAX_PATHNAME+1) bytes.
379 */
memdbFullPathname(sqlite3_vfs * pVfs,const char * zPath,int nOut,char * zOut)380 static int memdbFullPathname(
381   sqlite3_vfs *pVfs,
382   const char *zPath,
383   int nOut,
384   char *zOut
385 ){
386   sqlite3_snprintf(nOut, zOut, "%s", zPath);
387   return SQLITE_OK;
388 }
389 
390 /*
391 ** Open the dynamic library located at zPath and return a handle.
392 */
memdbDlOpen(sqlite3_vfs * pVfs,const char * zPath)393 static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){
394   return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
395 }
396 
397 /*
398 ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
399 ** utf-8 string describing the most recent error encountered associated
400 ** with dynamic libraries.
401 */
memdbDlError(sqlite3_vfs * pVfs,int nByte,char * zErrMsg)402 static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
403   ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
404 }
405 
406 /*
407 ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
408 */
memdbDlSym(sqlite3_vfs * pVfs,void * p,const char * zSym)409 static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
410   return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
411 }
412 
413 /*
414 ** Close the dynamic library handle pHandle.
415 */
memdbDlClose(sqlite3_vfs * pVfs,void * pHandle)416 static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){
417   ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
418 }
419 
420 /*
421 ** Populate the buffer pointed to by zBufOut with nByte bytes of
422 ** random data.
423 */
memdbRandomness(sqlite3_vfs * pVfs,int nByte,char * zBufOut)424 static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
425   return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
426 }
427 
428 /*
429 ** Sleep for nMicro microseconds. Return the number of microseconds
430 ** actually slept.
431 */
memdbSleep(sqlite3_vfs * pVfs,int nMicro)432 static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){
433   return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
434 }
435 
436 #if 0  /* Never used.  Modern cores only call xCurrentTimeInt64() */
437 /*
438 ** Return the current time as a Julian Day number in *pTimeOut.
439 */
440 static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
441   return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
442 }
443 #endif
444 
memdbGetLastError(sqlite3_vfs * pVfs,int a,char * b)445 static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){
446   return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
447 }
memdbCurrentTimeInt64(sqlite3_vfs * pVfs,sqlite3_int64 * p)448 static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
449   return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
450 }
451 
452 /*
453 ** Translate a database connection pointer and schema name into a
454 ** MemFile pointer.
455 */
memdbFromDbSchema(sqlite3 * db,const char * zSchema)456 static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
457   MemFile *p = 0;
458   int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
459   if( rc ) return 0;
460   if( p->base.pMethods!=&memdb_io_methods ) return 0;
461   return p;
462 }
463 
464 /*
465 ** Return the serialization of a database
466 */
sqlite3_serialize(sqlite3 * db,const char * zSchema,sqlite3_int64 * piSize,unsigned int mFlags)467 unsigned char *sqlite3_serialize(
468   sqlite3 *db,              /* The database connection */
469   const char *zSchema,      /* Which database within the connection */
470   sqlite3_int64 *piSize,    /* Write size here, if not NULL */
471   unsigned int mFlags       /* Maybe SQLITE_SERIALIZE_NOCOPY */
472 ){
473   MemFile *p;
474   int iDb;
475   Btree *pBt;
476   sqlite3_int64 sz;
477   int szPage = 0;
478   sqlite3_stmt *pStmt = 0;
479   unsigned char *pOut;
480   char *zSql;
481   int rc;
482 
483 #ifdef SQLITE_ENABLE_API_ARMOR
484   if( !sqlite3SafetyCheckOk(db) ){
485     (void)SQLITE_MISUSE_BKPT;
486     return 0;
487   }
488 #endif
489 
490   if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
491   p = memdbFromDbSchema(db, zSchema);
492   iDb = sqlite3FindDbName(db, zSchema);
493   if( piSize ) *piSize = -1;
494   if( iDb<0 ) return 0;
495   if( p ){
496     if( piSize ) *piSize = p->sz;
497     if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
498       pOut = p->aData;
499     }else{
500       pOut = sqlite3_malloc64( p->sz );
501       if( pOut ) memcpy(pOut, p->aData, p->sz);
502     }
503     return pOut;
504   }
505   pBt = db->aDb[iDb].pBt;
506   if( pBt==0 ) return 0;
507   szPage = sqlite3BtreeGetPageSize(pBt);
508   zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
509   rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
510   sqlite3_free(zSql);
511   if( rc ) return 0;
512   rc = sqlite3_step(pStmt);
513   if( rc!=SQLITE_ROW ){
514     pOut = 0;
515   }else{
516     sz = sqlite3_column_int64(pStmt, 0)*szPage;
517     if( piSize ) *piSize = sz;
518     if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
519       pOut = 0;
520     }else{
521       pOut = sqlite3_malloc64( sz );
522       if( pOut ){
523         int nPage = sqlite3_column_int(pStmt, 0);
524         Pager *pPager = sqlite3BtreePager(pBt);
525         int pgno;
526         for(pgno=1; pgno<=nPage; pgno++){
527           DbPage *pPage = 0;
528           unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1);
529           rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0);
530           if( rc==SQLITE_OK ){
531             memcpy(pTo, sqlite3PagerGetData(pPage), szPage);
532           }else{
533             memset(pTo, 0, szPage);
534           }
535           sqlite3PagerUnref(pPage);
536         }
537       }
538     }
539   }
540   sqlite3_finalize(pStmt);
541   return pOut;
542 }
543 
544 /* Convert zSchema to a MemDB and initialize its content.
545 */
sqlite3_deserialize(sqlite3 * db,const char * zSchema,unsigned char * pData,sqlite3_int64 szDb,sqlite3_int64 szBuf,unsigned mFlags)546 int sqlite3_deserialize(
547   sqlite3 *db,            /* The database connection */
548   const char *zSchema,    /* Which DB to reopen with the deserialization */
549   unsigned char *pData,   /* The serialized database content */
550   sqlite3_int64 szDb,     /* Number bytes in the deserialization */
551   sqlite3_int64 szBuf,    /* Total size of buffer pData[] */
552   unsigned mFlags         /* Zero or more SQLITE_DESERIALIZE_* flags */
553 ){
554   MemFile *p;
555   char *zSql;
556   sqlite3_stmt *pStmt = 0;
557   int rc;
558   int iDb;
559 
560 #ifdef SQLITE_ENABLE_API_ARMOR
561   if( !sqlite3SafetyCheckOk(db) ){
562     return SQLITE_MISUSE_BKPT;
563   }
564   if( szDb<0 ) return SQLITE_MISUSE_BKPT;
565   if( szBuf<0 ) return SQLITE_MISUSE_BKPT;
566 #endif
567 
568   sqlite3_mutex_enter(db->mutex);
569   if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
570   iDb = sqlite3FindDbName(db, zSchema);
571   if( iDb<0 ){
572     rc = SQLITE_ERROR;
573     goto end_deserialize;
574   }
575   zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
576   rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
577   sqlite3_free(zSql);
578   if( rc ) goto end_deserialize;
579   db->init.iDb = (u8)iDb;
580   db->init.reopenMemdb = 1;
581   rc = sqlite3_step(pStmt);
582   db->init.reopenMemdb = 0;
583   if( rc!=SQLITE_DONE ){
584     rc = SQLITE_ERROR;
585     goto end_deserialize;
586   }
587   p = memdbFromDbSchema(db, zSchema);
588   if( p==0 ){
589     rc = SQLITE_ERROR;
590   }else{
591     p->aData = pData;
592     p->sz = szDb;
593     p->szAlloc = szBuf;
594     p->szMax = szBuf;
595     if( p->szMax<sqlite3GlobalConfig.mxMemdbSize ){
596       p->szMax = sqlite3GlobalConfig.mxMemdbSize;
597     }
598     p->mFlags = mFlags;
599     rc = SQLITE_OK;
600   }
601 
602 end_deserialize:
603   sqlite3_finalize(pStmt);
604   sqlite3_mutex_leave(db->mutex);
605   return rc;
606 }
607 
608 /*
609 ** This routine is called when the extension is loaded.
610 ** Register the new VFS.
611 */
sqlite3MemdbInit(void)612 int sqlite3MemdbInit(void){
613   sqlite3_vfs *pLower = sqlite3_vfs_find(0);
614   int sz = pLower->szOsFile;
615   memdb_vfs.pAppData = pLower;
616   /* In all known configurations of SQLite, the size of a default
617   ** sqlite3_file is greater than the size of a memdb sqlite3_file.
618   ** Should that ever change, remove the following NEVER() */
619   if( NEVER(sz<sizeof(MemFile)) ) sz = sizeof(MemFile);
620   memdb_vfs.szOsFile = sz;
621   return sqlite3_vfs_register(&memdb_vfs, 0);
622 }
623 #endif /* SQLITE_ENABLE_DESERIALIZE */
624