From e7b3470705f87b30813d8412bd2765a7e7fed7eb Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 1 Jun 2009 18:18:20 +0000 Subject: [PATCH] Malloc for space to hold the Parse object in sqlite3_prepare() and friends. Or, if compiled with SQLITE_USE_ALLOCA, obtain space for the object from alloca(). (CVS 6702) FossilOrigin-Name: c7c0c58e472cd8277b2ad58bb60834190bace4fa --- manifest | 16 ++++---- manifest.uuid | 2 +- src/prepare.c | 102 ++++++++++++++++++++++++++++-------------------- src/sqliteInt.h | 21 +++++++++- 4 files changed, 88 insertions(+), 53 deletions(-) diff --git a/manifest b/manifest index 4896ad9cd9..6e99447d88 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Added\sassert\sto\sverify\swinMutex\ssystem\sis\sinited\sbefore\s"static"\smutexes\sare\sused.\s(CVS\s6701) -D 2009-06-01T17:10:22 +C Malloc\sfor\sspace\sto\shold\sthe\sParse\sobject\sin\ssqlite3_prepare()\sand\sfriends.\nOr,\sif\scompiled\swith\sSQLITE_USE_ALLOCA,\sobtain\sspace\sfor\sthe\sobject\sfrom\nalloca().\s(CVS\s6702) +D 2009-06-01T18:18:21 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -153,7 +153,7 @@ F src/pcache.c 395f752a13574120bd7513a400ba02a265aaa76d F src/pcache.h 9b927ccc5a538e31b4c3bc7eec4f976db42a1324 F src/pcache1.c bed75f157283e7c666f323df0c874c6a2515f76e F src/pragma.c d4a6fd74fd1dba0f22c8930791f7fbbe80d2ef26 -F src/prepare.c f46d1a029760edee5447e27164fb3ae10e2a6839 +F src/prepare.c 706efe9fb08b2f01c14c8077dce8ab8450c47cfb F src/printf.c 3f4dca207a88258d37af5a7a03e800a825fe6456 F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628 F src/resolve.c f86d3490cf93a12f8a451720defc622cbc79873a @@ -162,7 +162,7 @@ F src/select.c 2d97084a176a63eabce2d043eb4fbb13c46d6e9f F src/shell.c db2643650b9268df89a4bedca3f1c6d9e786f1bb F src/sqlite.h.in 79210c4d8905cfb4b038486dde5f36fabb796a86 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 -F src/sqliteInt.h 9d9e15a343bc56e8fc11217d5095f3c9f0508bed +F src/sqliteInt.h 210280ec1b4ecc2627b37a6555943e253e615d65 F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76 F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d @@ -731,7 +731,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 4e75897ee177bd24145f9dbfccd41a03c108440f -R c9b75933dd204df4863fe45c2a3da85c -U shane -Z 73868adefad3a7d624bd940507eb93ad +P b126013b5a1d6526810139d19acbec7fd0ab8168 +R 5749ee12901dac70e7e5afa66675a445 +U drh +Z d18ab08e2623638148c802e092f00e62 diff --git a/manifest.uuid b/manifest.uuid index 7007bfd72d..595fbe7504 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b126013b5a1d6526810139d19acbec7fd0ab8168 \ No newline at end of file +c7c0c58e472cd8277b2ad58bb60834190bace4fa \ No newline at end of file diff --git a/src/prepare.c b/src/prepare.c index 909a74acef..bfab9d4ade 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.118 2009/05/11 20:53:29 drh Exp $ +** $Id: prepare.c,v 1.119 2009/06/01 18:18:21 drh Exp $ */ #include "sqliteInt.h" @@ -520,12 +520,22 @@ static int sqlite3Prepare( sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ - Parse sParse; - char *zErrMsg = 0; - int rc = SQLITE_OK; - int i; + Parse *pParse; /* Parsing context */ + char *zErrMsg = 0; /* Error message */ + int rc = SQLITE_OK; /* Result code */ + int i; /* Loop counter */ - if( sqlite3SafetyOn(db) ) return SQLITE_MISUSE; + /* Allocate the parsing context */ + pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); + if( pParse==0 ){ + rc = SQLITE_NOMEM; + goto end_prepare; + } + + if( sqlite3SafetyOn(db) ){ + rc = SQLITE_MISUSE; + goto end_prepare; + } assert( ppStmt && *ppStmt==0 ); assert( !db->mallocFailed ); assert( sqlite3_mutex_held(db->mutex) ); @@ -563,68 +573,71 @@ static int sqlite3Prepare( sqlite3Error(db, rc, "database schema is locked: %s", zDb); (void)sqlite3SafetyOff(db); testcase( db->flags & SQLITE_ReadUncommitted ); - return sqlite3ApiExit(db, rc); + goto end_prepare; } } } - - memset(&sParse, 0, sizeof(sParse)); - sParse.db = db; + + + pParse->db = db; if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ char *zSqlCopy; int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; if( nBytes>mxLen ){ sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); (void)sqlite3SafetyOff(db); - return sqlite3ApiExit(db, SQLITE_TOOBIG); + rc = sqlite3ApiExit(db, SQLITE_TOOBIG); + goto end_prepare; } zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); if( zSqlCopy ){ - sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); + sqlite3RunParser(pParse, zSqlCopy, &zErrMsg); sqlite3DbFree(db, zSqlCopy); - sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; + pParse->zTail = &zSql[pParse->zTail-zSqlCopy]; }else{ - sParse.zTail = &zSql[nBytes]; + pParse->zTail = &zSql[nBytes]; } }else{ - sqlite3RunParser(&sParse, zSql, &zErrMsg); + sqlite3RunParser(pParse, zSql, &zErrMsg); } if( db->mallocFailed ){ - sParse.rc = SQLITE_NOMEM; + pParse->rc = SQLITE_NOMEM; } - if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; - if( sParse.checkSchema && !schemaIsValid(db) ){ - sParse.rc = SQLITE_SCHEMA; + if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK; + if( pParse->checkSchema && !schemaIsValid(db) ){ + pParse->rc = SQLITE_SCHEMA; } - if( sParse.rc==SQLITE_SCHEMA ){ + if( pParse->rc==SQLITE_SCHEMA ){ sqlite3ResetInternalSchema(db, 0); } if( db->mallocFailed ){ - sParse.rc = SQLITE_NOMEM; + pParse->rc = SQLITE_NOMEM; } if( pzTail ){ - *pzTail = sParse.zTail; + *pzTail = pParse->zTail; } - rc = sParse.rc; + rc = pParse->rc; #ifndef SQLITE_OMIT_EXPLAIN - if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ - if( sParse.explain==2 ){ - sqlite3VdbeSetNumCols(sParse.pVdbe, 3); - sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", SQLITE_STATIC); + if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){ + static const char * const azColName[] = { + "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment", + "order", "from", "detail" + }; + int iFirst, mx; + if( pParse->explain==2 ){ + sqlite3VdbeSetNumCols(pParse->pVdbe, 3); + iFirst = 8; + mx = 11; }else{ - sqlite3VdbeSetNumCols(sParse.pVdbe, 8); - sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 5, COLNAME_NAME, "p4", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 6, COLNAME_NAME, "p5", SQLITE_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 7, COLNAME_NAME, "comment", SQLITE_STATIC); + sqlite3VdbeSetNumCols(pParse->pVdbe, 8); + iFirst = 0; + mx = 8; + } + for(i=iFirst; ipVdbe, i-iFirst, COLNAME_NAME, + azColName[i], SQLITE_STATIC); } } #endif @@ -635,14 +648,14 @@ static int sqlite3Prepare( assert( db->init.busy==0 || saveSqlFlag==0 ); if( db->init.busy==0 ){ - Vdbe *pVdbe = sParse.pVdbe; - sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag); + Vdbe *pVdbe = pParse->pVdbe; + sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag); } - if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ - sqlite3VdbeFinalize(sParse.pVdbe); + if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ + sqlite3VdbeFinalize(pParse->pVdbe); assert(!(*ppStmt)); }else{ - *ppStmt = (sqlite3_stmt*)sParse.pVdbe; + *ppStmt = (sqlite3_stmt*)pParse->pVdbe; } if( zErrMsg ){ @@ -652,6 +665,9 @@ static int sqlite3Prepare( sqlite3Error(db, rc, 0); } +end_prepare: + + sqlite3StackFree(db, pParse); rc = sqlite3ApiExit(db, rc); assert( (rc&db->errMask)==rc ); return rc; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b370fe071e..d6b150630c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.879 2009/05/30 14:16:32 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.880 2009/06/01 18:18:21 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -475,6 +475,7 @@ extern const int sqlite3one; */ #define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) + /* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. @@ -2360,6 +2361,24 @@ void sqlite3MemSetDefault(void); void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); int sqlite3MemoryAlarm(void (*)(void*, sqlite3_int64, int), void*, sqlite3_int64); +/* +** On systems with ample stack space and that support alloca(), make +** use of alloca() to obtain space for large automatic objects. By default, +** obtain space from malloc(). +** +** The alloca() routine never returns NULL. This will cause code paths +** that deal with sqlite3StackAlloc() failures to be unreachable. +*/ +#ifdef SQLITE_USE_ALLOCA +# define sqlite3StackAllocRaw(D,N) alloca(N) +# define sqlite3StackAllocZero(D,N) memset(alloca(N), 0, N) +# define sqlite3StackFree(D,P) +#else +# define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N) +# define sqlite3StackAllocZero(D,N) sqlite3DbMallocZero(D,N) +# define sqlite3StackFree(D,P) sqlite3DbFree(D,P) +#endif + #ifdef SQLITE_ENABLE_MEMSYS3 const sqlite3_mem_methods *sqlite3MemGetMemsys3(void); #endif