diff options
author | Darwin Huang <huangdarwin@chromium.org> | 2020-01-13 02:11:53 +0000 |
---|---|---|
committer | Michal Klocek <michal.klocek@qt.io> | 2020-01-24 17:54:43 +0000 |
commit | 5ca6ac0f951adec1f816b42f1c862d699e56a645 (patch) | |
tree | d4697af855db45cd377616daffdfb7a140563d78 | |
parent | f91f6b419073f2f2d1b8b53d5d5b5cbf0247eefe (diff) |
[Backport] Security bugs 1029506, 1029210, 1029027, 1029002, 1028722v5.12.7
sqlite: Backport bugfixes (M79).
Backport onto M79.
(cherry picked from commit b87a7be55a14220b4ce69ab178d7ba6238664c85)
Bug: 1028722, 1029027, 1029210, 1029506, 1032390, 1028402, 1029002, 1030709
Change-Id: I0a51eceb98bd6724ed279386b0fb5dc85ee177db
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
6 files changed, 103 insertions, 87 deletions
diff --git a/chromium/third_party/sqlite/amalgamation/sqlite3.c b/chromium/third_party/sqlite/amalgamation/sqlite3.c index 4e0fcf4c9e1..f19e34be58a 100644 --- a/chromium/third_party/sqlite/amalgamation/sqlite3.c +++ b/chromium/third_party/sqlite/amalgamation/sqlite3.c @@ -30774,7 +30774,7 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ #ifndef SQLITE_OMIT_FLOATING_POINT int incr; - const char *zEnd = z + length; + const char *zEnd; /* sign * significand * (10 ^ (esign * exponent)) */ int sign = 1; /* sign of significand */ i64 s = 0; /* significand */ @@ -30788,9 +30788,11 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); *pResult = 0.0; /* Default return value, in case of an error */ + if( length==0 ) return 0; if( enc==SQLITE_UTF8 ){ incr = 1; + zEnd = z + length; }else{ int i; incr = 2; @@ -133227,8 +133229,12 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const ch Table *pTab = tableOfTrigger(pTrigger); if( pTab ){ Trigger **pp; - for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext)); - *pp = (*pp)->pNext; + for(pp=&pTab->pTrigger; *pp; pp=&((*pp)->pNext)){ + if( *pp==pTrigger ){ + *pp = (*pp)->pNext; + break; + } + } } } sqlite3DeleteTrigger(db, pTrigger); @@ -161343,6 +161349,9 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */ # define TESTONLY(X) #endif +#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) +#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) + #endif /* SQLITE_AMALGAMATION */ #ifdef SQLITE_DEBUG @@ -161724,6 +161733,7 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int); SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...); SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); +SQLITE_PRIVATE int sqlite3Fts3GetVarintU(const char *, sqlite_uint64 *); SQLITE_PRIVATE int sqlite3Fts3GetVarintBounded(const char*,const char*,sqlite3_int64*); SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *); SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64); @@ -161811,18 +161821,6 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); SQLITE_EXTENSION_INIT1 #endif -/* -** The following are copied from sqliteInt.h. -** -** Constants for the largest and smallest possible 64-bit signed integers. -** These macros are designed to work correctly on both 32-bit and 64-bit -** compilers. -*/ -#ifndef SQLITE_AMALGAMATION -# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) -# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) -#endif - static int fts3EvalNext(Fts3Cursor *pCsr); static int fts3EvalStart(Fts3Cursor *pCsr); static int fts3TermSegReaderCursor( @@ -161867,12 +161865,7 @@ SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){ v = (*ptr++); \ if( (v & mask2)==0 ){ var = v; return ret; } -/* -** Read a 64-bit variable-length integer from memory starting at p[0]. -** Return the number of bytes read, or 0 on error. -** The value is stored in *v. -*/ -SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ +SQLITE_PRIVATE int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){ const unsigned char *p = (const unsigned char*)pBuf; const unsigned char *pStart = p; u32 a; @@ -161895,6 +161888,15 @@ SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ } /* +** Read a 64-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read, or 0 on error. +** The value is stored in *v. +*/ +SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ + return sqlite3Fts3GetVarintU(pBuf, (sqlite3_uint64*)v); +} + +/* ** Read a 64-bit variable-length integer from memory starting at p[0] and ** not extending past pEnd[-1]. ** Return the number of bytes read, or 0 on error. @@ -163987,12 +163989,12 @@ static void fts3GetDeltaVarint3( if( *pp>=pEnd ){ *pp = 0; }else{ - sqlite3_int64 iVal; - *pp += sqlite3Fts3GetVarint(*pp, &iVal); + u64 iVal; + *pp += sqlite3Fts3GetVarintU(*pp, &iVal); if( bDescIdx ){ - *pVal -= iVal; + *pVal = (i64)((u64)*pVal - iVal); }else{ - *pVal += iVal; + *pVal = (i64)((u64)*pVal + iVal); } } } @@ -164021,9 +164023,9 @@ static void fts3PutDeltaVarint3( ){ sqlite3_int64 iWrite; if( bDescIdx==0 || *pbFirst==0 ){ - iWrite = iVal - *piPrev; + iWrite = (u64)iVal - (u64)*piPrev; }else{ - iWrite = *piPrev - iVal; + iWrite = (u64)*piPrev - (u64)iVal; } assert( *pbFirst || *piPrev==0 ); assert_fts3_nc( *pbFirst==0 || iWrite>0 ); @@ -164043,7 +164045,8 @@ static void fts3PutDeltaVarint3( ** Using this makes it easier to write code that can merge doclists that are ** sorted in either ascending or descending order. */ -#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2)) +// #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i64)((u64)i1-i2)) +#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1>i2?1:((i1==i2)?0:-1))) /* ** This function does an "OR" merge of two doclists (output contains all @@ -172362,7 +172365,7 @@ static int fts3PendingListAppend( assert( !p || p->iLastDocid<=iDocid ); if( !p || p->iLastDocid!=iDocid ){ - sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0); + u64 iDelta = (u64)iDocid - (u64)(p ? p->iLastDocid : 0); if( p ){ assert( p->nData<p->nSpace ); assert( p->aData[p->nData]==0 ); @@ -173195,18 +173198,18 @@ static int fts3SegReaderNextDocid( }else{ rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX); if( rc==SQLITE_OK ){ - sqlite3_int64 iDelta; - pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta); + u64 iDelta; + pReader->pOffsetList = p + sqlite3Fts3GetVarintU(p, &iDelta); if( pTab->bDescIdx ){ - pReader->iDocid -= iDelta; + pReader->iDocid = (i64)((u64)pReader->iDocid - iDelta); }else{ - pReader->iDocid += iDelta; + pReader->iDocid = (i64)((u64)pReader->iDocid + iDelta); } } } } - return SQLITE_OK; + return rc; } @@ -173945,6 +173948,7 @@ static int fts3SegWriterAdd( int rc; /* The current leaf node is full. Write it out to the database. */ + if( pWriter->iFree==LARGEST_INT64 ) return FTS_CORRUPT_VTAB; rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData); if( rc!=SQLITE_OK ) return rc; p->nLeafAdd++; @@ -174641,9 +174645,9 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep( ** doclist. */ sqlite3_int64 iDelta; if( p->bDescIdx && nDoclist>0 ){ - iDelta = iPrev - iDocid; + iDelta = (i64)((u64)iPrev - (u64)iDocid); }else{ - iDelta = iDocid - iPrev; + iDelta = (i64)((u64)iDocid - (u64)iPrev); } if( iDelta<=0 && (nDoclist>0 || iDelta!=iDocid) ){ return FTS_CORRUPT_VTAB; @@ -174930,7 +174934,7 @@ static int fts3SegmentMerge( csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist); } if( rc!=SQLITE_OK ) goto finished; - assert( pWriter || bIgnoreEmpty ); + assert_fts3_nc( pWriter || bIgnoreEmpty ); if( iLevel!=FTS3_SEGCURSOR_PENDING ){ rc = fts3DeleteSegdir( @@ -176510,13 +176514,17 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){ const int nHint = pHint->n; int i; - i = pHint->n-2; + i = pHint->n-1; + if( (pHint->a[i] & 0x80) ) return FTS_CORRUPT_VTAB; while( i>0 && (pHint->a[i-1] & 0x80) ) i--; + if( i==0 ) return FTS_CORRUPT_VTAB; + i--; while( i>0 && (pHint->a[i-1] & 0x80) ) i--; pHint->n = i; i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); i += fts3GetVarint32(&pHint->a[i], pnInput); + assert( i<=nHint ); if( i!=nHint ) return FTS_CORRUPT_VTAB; return SQLITE_OK; @@ -176837,12 +176845,12 @@ static u64 fts3ChecksumIndex( i64 iDocid = 0; i64 iCol = 0; - i64 iPos = 0; + u64 iPos = 0; pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid); while( pCsr<pEnd ){ - i64 iVal = 0; - pCsr += sqlite3Fts3GetVarint(pCsr, &iVal); + u64 iVal = 0; + pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal); if( pCsr<pEnd ){ if( iVal==0 || iVal==1 ){ iCol = 0; @@ -176850,8 +176858,8 @@ static u64 fts3ChecksumIndex( if( iVal ){ pCsr += sqlite3Fts3GetVarint(pCsr, &iCol); }else{ - pCsr += sqlite3Fts3GetVarint(pCsr, &iVal); - iDocid += iVal; + pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal); + iDocid = (i64)((u64)iDocid + iVal); } }else{ iPos += (iVal - 2); @@ -224684,7 +224692,7 @@ SQLITE_API int sqlite3_stmt_init( #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ -#if __LINE__!=224663 +#if __LINE__!=224671 #undef SQLITE_SOURCE_ID #define SQLITE_SOURCE_ID "2019-10-10 20:19:45 18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3dfalt2" #endif diff --git a/chromium/third_party/sqlite/patched/ext/fts3/fts3.c b/chromium/third_party/sqlite/patched/ext/fts3/fts3.c index 8d48f22fec2..a198a0f09f1 100644 --- a/chromium/third_party/sqlite/patched/ext/fts3/fts3.c +++ b/chromium/third_party/sqlite/patched/ext/fts3/fts3.c @@ -308,18 +308,6 @@ SQLITE_EXTENSION_INIT1 #endif -/* -** The following are copied from sqliteInt.h. -** -** Constants for the largest and smallest possible 64-bit signed integers. -** These macros are designed to work correctly on both 32-bit and 64-bit -** compilers. -*/ -#ifndef SQLITE_AMALGAMATION -# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) -# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) -#endif - static int fts3EvalNext(Fts3Cursor *pCsr); static int fts3EvalStart(Fts3Cursor *pCsr); static int fts3TermSegReaderCursor( @@ -364,12 +352,7 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){ v = (*ptr++); \ if( (v & mask2)==0 ){ var = v; return ret; } -/* -** Read a 64-bit variable-length integer from memory starting at p[0]. -** Return the number of bytes read, or 0 on error. -** The value is stored in *v. -*/ -int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ +int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){ const unsigned char *p = (const unsigned char*)pBuf; const unsigned char *pStart = p; u32 a; @@ -392,6 +375,15 @@ int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ } /* +** Read a 64-bit variable-length integer from memory starting at p[0]. +** Return the number of bytes read, or 0 on error. +** The value is stored in *v. +*/ +int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){ + return sqlite3Fts3GetVarintU(pBuf, (sqlite3_uint64*)v); +} + +/* ** Read a 64-bit variable-length integer from memory starting at p[0] and ** not extending past pEnd[-1]. ** Return the number of bytes read, or 0 on error. @@ -2484,12 +2476,12 @@ static void fts3GetDeltaVarint3( if( *pp>=pEnd ){ *pp = 0; }else{ - sqlite3_int64 iVal; - *pp += sqlite3Fts3GetVarint(*pp, &iVal); + u64 iVal; + *pp += sqlite3Fts3GetVarintU(*pp, &iVal); if( bDescIdx ){ - *pVal -= iVal; + *pVal = (i64)((u64)*pVal - iVal); }else{ - *pVal += iVal; + *pVal = (i64)((u64)*pVal + iVal); } } } @@ -2518,9 +2510,9 @@ static void fts3PutDeltaVarint3( ){ sqlite3_int64 iWrite; if( bDescIdx==0 || *pbFirst==0 ){ - iWrite = iVal - *piPrev; + iWrite = (u64)iVal - (u64)*piPrev; }else{ - iWrite = *piPrev - iVal; + iWrite = (u64)*piPrev - (u64)iVal; } assert( *pbFirst || *piPrev==0 ); assert_fts3_nc( *pbFirst==0 || iWrite>0 ); @@ -2540,7 +2532,8 @@ static void fts3PutDeltaVarint3( ** Using this makes it easier to write code that can merge doclists that are ** sorted in either ascending or descending order. */ -#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2)) +// #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i64)((u64)i1-i2)) +#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1>i2?1:((i1==i2)?0:-1))) /* ** This function does an "OR" merge of two doclists (output contains all diff --git a/chromium/third_party/sqlite/patched/ext/fts3/fts3Int.h b/chromium/third_party/sqlite/patched/ext/fts3/fts3Int.h index 5cafa1fe9b9..44bf78ef8f1 100644 --- a/chromium/third_party/sqlite/patched/ext/fts3/fts3Int.h +++ b/chromium/third_party/sqlite/patched/ext/fts3/fts3Int.h @@ -196,6 +196,9 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */ # define TESTONLY(X) #endif +#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) +#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) + #endif /* SQLITE_AMALGAMATION */ #ifdef SQLITE_DEBUG @@ -577,6 +580,7 @@ int sqlite3Fts3Incrmerge(Fts3Table*,int,int); void sqlite3Fts3ErrMsg(char**,const char*,...); int sqlite3Fts3PutVarint(char *, sqlite3_int64); int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); +int sqlite3Fts3GetVarintU(const char *, sqlite_uint64 *); int sqlite3Fts3GetVarintBounded(const char*,const char*,sqlite3_int64*); int sqlite3Fts3GetVarint32(const char *, int *); int sqlite3Fts3VarintLen(sqlite3_uint64); diff --git a/chromium/third_party/sqlite/patched/ext/fts3/fts3_write.c b/chromium/third_party/sqlite/patched/ext/fts3/fts3_write.c index 953b9d86959..8b6b729987c 100644 --- a/chromium/third_party/sqlite/patched/ext/fts3/fts3_write.c +++ b/chromium/third_party/sqlite/patched/ext/fts3/fts3_write.c @@ -696,7 +696,7 @@ static int fts3PendingListAppend( assert( !p || p->iLastDocid<=iDocid ); if( !p || p->iLastDocid!=iDocid ){ - sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0); + u64 iDelta = (u64)iDocid - (u64)(p ? p->iLastDocid : 0); if( p ){ assert( p->nData<p->nSpace ); assert( p->aData[p->nData]==0 ); @@ -1529,18 +1529,18 @@ static int fts3SegReaderNextDocid( }else{ rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX); if( rc==SQLITE_OK ){ - sqlite3_int64 iDelta; - pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta); + u64 iDelta; + pReader->pOffsetList = p + sqlite3Fts3GetVarintU(p, &iDelta); if( pTab->bDescIdx ){ - pReader->iDocid -= iDelta; + pReader->iDocid = (i64)((u64)pReader->iDocid - iDelta); }else{ - pReader->iDocid += iDelta; + pReader->iDocid = (i64)((u64)pReader->iDocid + iDelta); } } } } - return SQLITE_OK; + return rc; } @@ -2279,6 +2279,7 @@ static int fts3SegWriterAdd( int rc; /* The current leaf node is full. Write it out to the database. */ + if( pWriter->iFree==LARGEST_INT64 ) return FTS_CORRUPT_VTAB; rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData); if( rc!=SQLITE_OK ) return rc; p->nLeafAdd++; @@ -2975,9 +2976,9 @@ int sqlite3Fts3SegReaderStep( ** doclist. */ sqlite3_int64 iDelta; if( p->bDescIdx && nDoclist>0 ){ - iDelta = iPrev - iDocid; + iDelta = (i64)((u64)iPrev - (u64)iDocid); }else{ - iDelta = iDocid - iPrev; + iDelta = (i64)((u64)iDocid - (u64)iPrev); } if( iDelta<=0 && (nDoclist>0 || iDelta!=iDocid) ){ return FTS_CORRUPT_VTAB; @@ -3264,7 +3265,7 @@ static int fts3SegmentMerge( csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist); } if( rc!=SQLITE_OK ) goto finished; - assert( pWriter || bIgnoreEmpty ); + assert_fts3_nc( pWriter || bIgnoreEmpty ); if( iLevel!=FTS3_SEGCURSOR_PENDING ){ rc = fts3DeleteSegdir( @@ -4844,13 +4845,17 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){ const int nHint = pHint->n; int i; - i = pHint->n-2; + i = pHint->n-1; + if( (pHint->a[i] & 0x80) ) return FTS_CORRUPT_VTAB; while( i>0 && (pHint->a[i-1] & 0x80) ) i--; + if( i==0 ) return FTS_CORRUPT_VTAB; + i--; while( i>0 && (pHint->a[i-1] & 0x80) ) i--; pHint->n = i; i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); i += fts3GetVarint32(&pHint->a[i], pnInput); + assert( i<=nHint ); if( i!=nHint ) return FTS_CORRUPT_VTAB; return SQLITE_OK; @@ -5171,12 +5176,12 @@ static u64 fts3ChecksumIndex( i64 iDocid = 0; i64 iCol = 0; - i64 iPos = 0; + u64 iPos = 0; pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid); while( pCsr<pEnd ){ - i64 iVal = 0; - pCsr += sqlite3Fts3GetVarint(pCsr, &iVal); + u64 iVal = 0; + pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal); if( pCsr<pEnd ){ if( iVal==0 || iVal==1 ){ iCol = 0; @@ -5184,8 +5189,8 @@ static u64 fts3ChecksumIndex( if( iVal ){ pCsr += sqlite3Fts3GetVarint(pCsr, &iCol); }else{ - pCsr += sqlite3Fts3GetVarint(pCsr, &iVal); - iDocid += iVal; + pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal); + iDocid = (i64)((u64)iDocid + iVal); } }else{ iPos += (iVal - 2); diff --git a/chromium/third_party/sqlite/patched/src/trigger.c b/chromium/third_party/sqlite/patched/src/trigger.c index 64ccfdeb081..8a756ca47d8 100644 --- a/chromium/third_party/sqlite/patched/src/trigger.c +++ b/chromium/third_party/sqlite/patched/src/trigger.c @@ -662,8 +662,12 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ Table *pTab = tableOfTrigger(pTrigger); if( pTab ){ Trigger **pp; - for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext)); - *pp = (*pp)->pNext; + for(pp=&pTab->pTrigger; *pp; pp=&((*pp)->pNext)){ + if( *pp==pTrigger ){ + *pp = (*pp)->pNext; + break; + } + } } } sqlite3DeleteTrigger(db, pTrigger); diff --git a/chromium/third_party/sqlite/patched/src/util.c b/chromium/third_party/sqlite/patched/src/util.c index d70b93bb79b..d86fc04e02b 100644 --- a/chromium/third_party/sqlite/patched/src/util.c +++ b/chromium/third_party/sqlite/patched/src/util.c @@ -385,7 +385,7 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ #ifndef SQLITE_OMIT_FLOATING_POINT int incr; - const char *zEnd = z + length; + const char *zEnd; /* sign * significand * (10 ^ (esign * exponent)) */ int sign = 1; /* sign of significand */ i64 s = 0; /* significand */ @@ -399,9 +399,11 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); *pResult = 0.0; /* Default return value, in case of an error */ + if( length==0 ) return 0; if( enc==SQLITE_UTF8 ){ incr = 1; + zEnd = z + length; }else{ int i; incr = 2; |