diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/func.c | 92 | ||||
-rw-r--r-- | src/os_unix.c | 2 | ||||
-rw-r--r-- | src/pager.c | 2 | ||||
-rw-r--r-- | src/shell.c.in | 1 | ||||
-rw-r--r-- | src/sqlite.h.in | 5 | ||||
-rw-r--r-- | src/vdbe.c | 2 | ||||
-rw-r--r-- | src/vdbeInt.h | 2 | ||||
-rw-r--r-- | src/vdbeapi.c | 22 | ||||
-rw-r--r-- | src/vtab.c | 2 | ||||
-rw-r--r-- | src/where.c | 4 |
10 files changed, 123 insertions, 11 deletions
diff --git a/src/func.c b/src/func.c index 9a62470a0..6a279a9d7 100644 --- a/src/func.c +++ b/src/func.c @@ -1224,6 +1224,96 @@ static void hexFunc( } /* +** Buffer zStr contains nStr bytes of utf-8 encoded text. Return 1 if zStr +** contains character ch, or 0 if it does not. +*/ +static int strContainsChar(const u8 *zStr, int nStr, u32 ch){ + const u8 *zEnd = &zStr[nStr]; + const u8 *z = zStr; + while( z<zEnd ){ + u32 tst = Utf8Read(z); + if( tst==ch ) return 1; + } + return 0; +} + +/* +** The unhex() function. This function may be invoked with either one or +** two arguments. In both cases the first argument is interpreted as text +** a text value containing a set of pairs of hexadecimal digits which are +** decoded and returned as a blob. +** +** If there is only a single argument, then it must consist only of an +** even number of hexadeximal digits. Otherwise, return NULL. +** +** Or, if there is a second argument, then any character that appears in +** the second argument is also allowed to appear between pairs of hexadecimal +** digits in the first argument. If any other character appears in the +** first argument, or if one of the allowed characters appears between +** two hexadecimal digits that make up a single byte, NULL is returned. +** +** The following expressions are all true: +** +** unhex('ABCD') IS x'ABCD' +** unhex('AB CD') IS NULL +** unhex('AB CD', ' ') IS x'ABCD' +** unhex('A BCD', ' ') IS NULL +*/ +static void unhexFunc( + sqlite3_context *pCtx, + int argc, + sqlite3_value **argv +){ + const u8 *zPass = (const u8*)""; + int nPass = 0; + const u8 *zHex = sqlite3_value_text(argv[0]); + int nHex = sqlite3_value_bytes(argv[0]); +#ifdef SQLITE_DEBUG + const u8 *zEnd = &zHex[nHex]; +#endif + u8 *pBlob = 0; + u8 *p = 0; + + assert( argc==1 || argc==2 ); + if( argc==2 ){ + zPass = sqlite3_value_text(argv[1]); + nPass = sqlite3_value_bytes(argv[1]); + } + if( !zHex || !zPass ) return; + + p = pBlob = contextMalloc(pCtx, (nHex/2)+1); + if( pBlob ){ + u8 c; /* Most significant digit of next byte */ + u8 d; /* Least significant digit of next byte */ + + while( (c = *zHex)!=0x00 ){ + while( !sqlite3Isxdigit(c) ){ + u32 ch = Utf8Read(zHex); + assert( zHex<=zEnd ); + if( !strContainsChar(zPass, nPass, ch) ) goto unhex_null; + c = *zHex; + if( c==0x00 ) goto unhex_done; + } + zHex++; + assert( *zEnd==0x00 ); + assert( zHex<=zEnd ); + d = *(zHex++); + if( !sqlite3Isxdigit(d) ) goto unhex_null; + *(p++) = (sqlite3HexToInt(c)<<4) | sqlite3HexToInt(d); + } + } + + unhex_done: + sqlite3_result_blob(pCtx, pBlob, (p - pBlob), sqlite3_free); + return; + + unhex_null: + sqlite3_free(pBlob); + return; +} + + +/* ** The zeroblob(N) function returns a zero-filled blob of size N bytes. */ static void zeroblobFunc( @@ -2287,6 +2377,8 @@ void sqlite3RegisterBuiltinFunctions(void){ FUNCTION(upper, 1, 0, 0, upperFunc ), FUNCTION(lower, 1, 0, 0, lowerFunc ), FUNCTION(hex, 1, 0, 0, hexFunc ), + FUNCTION(unhex, 1, 0, 0, unhexFunc ), + FUNCTION(unhex, 2, 0, 0, unhexFunc ), INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ), VFUNCTION(random, 0, 0, 0, randomFunc ), VFUNCTION(randomblob, 1, 0, 0, randomBlob ), diff --git a/src/os_unix.c b/src/os_unix.c index 78ce223d9..e430e5df3 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -218,7 +218,7 @@ #endif /* SQLITE_WASI */ #ifdef SQLITE_WASI -# define osGetpid(X) 1 +# define osGetpid(X) (pid_t)1 #else /* Always cast the getpid() return type for compatibility with ** kernel modules in VxWorks. */ diff --git a/src/pager.c b/src/pager.c index c859f5028..6e6527e15 100644 --- a/src/pager.c +++ b/src/pager.c @@ -2935,7 +2935,7 @@ end_playback: ** see if it is possible to delete the super-journal. */ assert( zSuper==&pPager->pTmpSpace[4] ); - memset(&zSuper[-4], 0, 4); + memset(pPager->pTmpSpace, 0, 4); rc = pager_delsuper(pPager, zSuper); testcase( rc!=SQLITE_OK ); } diff --git a/src/shell.c.in b/src/shell.c.in index 70774938a..3da0bf3b9 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -4789,6 +4789,7 @@ static const char *(azHelp[]) = { ".unmodule NAME ... Unregister virtual table modules", " --allexcept Unregister everything except those named", #endif + ".version Show source, library and compiler versions", ".vfsinfo ?AUX? Information about the top-level VFS", ".vfslist List all available VFSes", ".vfsname ?AUX? Print the name of the VFS stack", diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 2ee27898d..ba8306ce1 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -9806,14 +9806,13 @@ int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle); ** is undefined and probably harmful. ** ** The X parameter in a call to sqlite3_vtab_in_first(X,P) or -** sqlite3_vtab_in_next(X,P) must be one of the parameters to the +** sqlite3_vtab_in_next(X,P) should be one of the parameters to the ** xFilter method which invokes these routines, and specifically ** a parameter that was previously selected for all-at-once IN constraint ** processing use the [sqlite3_vtab_in()] interface in the ** [xBestIndex|xBestIndex method]. ^(If the X parameter is not ** an xFilter argument that was selected for all-at-once IN constraint -** processing, then these routines return [SQLITE_MISUSE])^ or perhaps -** exhibit some other undefined or harmful behavior. +** processing, then these routines return [SQLITE_ERROR].)^ ** ** ^(Use these routines to access all values on the right-hand side ** of the IN constraint using code like the following: diff --git a/src/vdbe.c b/src/vdbe.c index db6086233..fb5e04a81 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -8031,7 +8031,7 @@ case OP_VInitIn: { /* out2, ncycle */ pRhs->pOut = &aMem[pOp->p3]; pOut = out2Prerelease(p, pOp); pOut->flags = MEM_Null; - sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3_free); + sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3VdbeValueListFree); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 03f4ec542..b901a0180 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -657,6 +657,8 @@ int sqlite3VdbeSorterRewind(const VdbeCursor *, int *); int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *); int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *); +void sqlite3VdbeValueListFree(void*); + #ifdef SQLITE_DEBUG void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*); void sqlite3VdbeAssertAbortable(Vdbe*); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index e080449c5..476b6a2ad 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -883,6 +883,17 @@ int sqlite3_vtab_nochange(sqlite3_context *p){ } /* +** The destructor function for a ValueList object. This needs to be +** a separate function, unknowable to the application, to ensure that +** calls to sqlite3_vtab_in_first()/sqlite3_vtab_in_next() that are not +** preceeded by activation of IN processing via sqlite3_vtab_int() do not +** try to access a fake ValueList object inserted by a hostile extension. +*/ +void sqlite3VdbeValueListFree(void *pToDelete){ + sqlite3_free(pToDelete); +} + +/* ** Implementation of sqlite3_vtab_in_first() (if bNext==0) and ** sqlite3_vtab_in_next() (if bNext!=0). */ @@ -896,8 +907,15 @@ static int valueFromValueList( *ppOut = 0; if( pVal==0 ) return SQLITE_MISUSE; - pRhs = (ValueList*)sqlite3_value_pointer(pVal, "ValueList"); - if( pRhs==0 ) return SQLITE_MISUSE; + if( (pVal->flags & MEM_Dyn)==0 || pVal->xDel!=sqlite3VdbeValueListFree ){ + return SQLITE_ERROR; + }else{ + assert( (pVal->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) == + (MEM_Null|MEM_Term|MEM_Subtype) ); + assert( pVal->eSubtype=='p' ); + assert( pVal->u.zPType!=0 && strcmp(pVal->u.zPType,"ValueList")==0 ); + pRhs = (ValueList*)pVal->z; + } if( bNext ){ rc = sqlite3BtreeNext(pRhs->pCsr, 0); }else{ diff --git a/src/vtab.c b/src/vtab.c index 3814b0355..2dd92762b 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -211,10 +211,10 @@ void sqlite3VtabUnlock(VTable *pVTab){ pVTab->nRef--; if( pVTab->nRef==0 ){ sqlite3_vtab *p = pVTab->pVtab; - sqlite3VtabModuleUnref(pVTab->db, pVTab->pMod); if( p ){ p->pModule->xDisconnect(p); } + sqlite3VtabModuleUnref(pVTab->db, pVTab->pMod); sqlite3DbFree(db, pVTab); } } diff --git a/src/where.c b/src/where.c index 205f24762..6a9edd028 100644 --- a/src/where.c +++ b/src/where.c @@ -4095,7 +4095,7 @@ int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){ && !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** Cause the prepared statement that is associated with a call to -** xBestIndex to potentiall use all schemas. If the statement being +** xBestIndex to potentially use all schemas. If the statement being ** prepared is read-only, then just start read transactions on all ** schemas. But if this is a write operation, start writes on all ** schemas. @@ -4110,7 +4110,7 @@ void sqlite3VtabUsesAllSchemas(sqlite3_index_info *pIdxInfo){ for(i=0; i<nDb; i++){ sqlite3CodeVerifySchema(pParse, i); } - if( pParse->writeMask ){ + if( DbMaskNonZero(pParse->writeMask) ){ for(i=0; i<nDb; i++){ sqlite3BeginWriteOperation(pParse, 0, i); } |