| | @@ -1,8 +1,8 @@ |
| 1 | 1 | /****************************************************************************** |
| 2 | 2 | ** This file is an amalgamation of many separate C source files from SQLite |
| 3 | | -** version 3.45.0. By combining all the individual C code files into this |
| 3 | +** version 3.45.1. By combining all the individual C code files into this |
| 4 | 4 | ** single large file, the entire code can be compiled as a single translation |
| 5 | 5 | ** unit. This allows many compilers to do optimizations that would not be |
| 6 | 6 | ** possible if the files were compiled separately. Performance improvements |
| 7 | 7 | ** of 5% or more are commonly seen when SQLite is compiled as a single |
| 8 | 8 | ** translation unit. |
| | @@ -16,11 +16,11 @@ |
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | 19 | ** |
| 20 | 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | | -** 97709ce2a1f5ae05495e412ca27108048e5b. |
| 21 | +** e876e51a0ed5c5b3126f52e532044363a014. |
| 22 | 22 | */ |
| 23 | 23 | #define SQLITE_CORE 1 |
| 24 | 24 | #define SQLITE_AMALGAMATION 1 |
| 25 | 25 | #ifndef SQLITE_PRIVATE |
| 26 | 26 | # define SQLITE_PRIVATE static |
| | @@ -457,13 +457,13 @@ |
| 457 | 457 | ** |
| 458 | 458 | ** See also: [sqlite3_libversion()], |
| 459 | 459 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 460 | 460 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 461 | 461 | */ |
| 462 | | -#define SQLITE_VERSION "3.45.0" |
| 463 | | -#define SQLITE_VERSION_NUMBER 3045000 |
| 464 | | -#define SQLITE_SOURCE_ID "2024-01-09 12:28:51 97709ce2a1f5ae05495e412ca27108048e5b8a63a1e3bca4be13933f7527da7b" |
| 462 | +#define SQLITE_VERSION "3.45.1" |
| 463 | +#define SQLITE_VERSION_NUMBER 3045001 |
| 464 | +#define SQLITE_SOURCE_ID "2024-01-30 16:01:20 e876e51a0ed5c5b3126f52e532044363a014bc594cfefa87ffb5b82257cc467a" |
| 465 | 465 | |
| 466 | 466 | /* |
| 467 | 467 | ** CAPI3REF: Run-Time Library Version Numbers |
| 468 | 468 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 469 | 469 | ** |
| | @@ -43406,15 +43406,20 @@ |
| 43406 | 43406 | #endif |
| 43407 | 43407 | *pp = 0; |
| 43408 | 43408 | |
| 43409 | 43409 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 43410 | 43410 | if( pFd->mmapSizeMax>0 ){ |
| 43411 | + /* Ensure that there is always at least a 256 byte buffer of addressable |
| 43412 | + ** memory following the returned page. If the database is corrupt, |
| 43413 | + ** SQLite may overread the page slightly (in practice only a few bytes, |
| 43414 | + ** but 256 is safe, round, number). */ |
| 43415 | + const int nEofBuffer = 256; |
| 43411 | 43416 | if( pFd->pMapRegion==0 ){ |
| 43412 | 43417 | int rc = unixMapfile(pFd, -1); |
| 43413 | 43418 | if( rc!=SQLITE_OK ) return rc; |
| 43414 | 43419 | } |
| 43415 | | - if( pFd->mmapSize >= iOff+nAmt ){ |
| 43420 | + if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ |
| 43416 | 43421 | *pp = &((u8 *)pFd->pMapRegion)[iOff]; |
| 43417 | 43422 | pFd->nFetchOut++; |
| 43418 | 43423 | } |
| 43419 | 43424 | } |
| 43420 | 43425 | #endif |
| | @@ -50763,19 +50768,24 @@ |
| 50763 | 50768 | OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n", |
| 50764 | 50769 | osGetCurrentProcessId(), fd, iOff, nAmt, pp)); |
| 50765 | 50770 | |
| 50766 | 50771 | #if SQLITE_MAX_MMAP_SIZE>0 |
| 50767 | 50772 | if( pFd->mmapSizeMax>0 ){ |
| 50773 | + /* Ensure that there is always at least a 256 byte buffer of addressable |
| 50774 | + ** memory following the returned page. If the database is corrupt, |
| 50775 | + ** SQLite may overread the page slightly (in practice only a few bytes, |
| 50776 | + ** but 256 is safe, round, number). */ |
| 50777 | + const int nEofBuffer = 256; |
| 50768 | 50778 | if( pFd->pMapRegion==0 ){ |
| 50769 | 50779 | int rc = winMapfile(pFd, -1); |
| 50770 | 50780 | if( rc!=SQLITE_OK ){ |
| 50771 | 50781 | OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n", |
| 50772 | 50782 | osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); |
| 50773 | 50783 | return rc; |
| 50774 | 50784 | } |
| 50775 | 50785 | } |
| 50776 | | - if( pFd->mmapSize >= iOff+nAmt ){ |
| 50786 | + if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){ |
| 50777 | 50787 | assert( pFd->pMapRegion!=0 ); |
| 50778 | 50788 | *pp = &((u8 *)pFd->pMapRegion)[iOff]; |
| 50779 | 50789 | pFd->nFetchOut++; |
| 50780 | 50790 | } |
| 50781 | 50791 | } |
| | @@ -67665,13 +67675,17 @@ |
| 67665 | 67675 | |
| 67666 | 67676 | (void)walEnableBlockingMs(pWal, nBlockTmout); |
| 67667 | 67677 | rc = walLockShared(pWal, WAL_READ_LOCK(mxI)); |
| 67668 | 67678 | walDisableBlocking(pWal); |
| 67669 | 67679 | if( rc ){ |
| 67680 | +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT |
| 67670 | 67681 | if( rc==SQLITE_BUSY_TIMEOUT ){ |
| 67671 | 67682 | *pCnt |= WAL_RETRY_BLOCKED_MASK; |
| 67672 | 67683 | } |
| 67684 | +#else |
| 67685 | + assert( rc!=SQLITE_BUSY_TIMEOUT ); |
| 67686 | +#endif |
| 67673 | 67687 | assert( (rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT ); |
| 67674 | 67688 | return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc; |
| 67675 | 67689 | } |
| 67676 | 67690 | /* Now that the read-lock has been obtained, check that neither the |
| 67677 | 67691 | ** value in the aReadMark[] array or the contents of the wal-index |
| | @@ -76396,11 +76410,14 @@ |
| 76396 | 76410 | if( pCur->skipNext<0 ) return SQLITE_OK; |
| 76397 | 76411 | } |
| 76398 | 76412 | } |
| 76399 | 76413 | |
| 76400 | 76414 | pPage = pCur->pPage; |
| 76401 | | - assert( pPage->isInit ); |
| 76415 | + if( sqlite3FaultSim(412) ) pPage->isInit = 0; |
| 76416 | + if( !pPage->isInit ){ |
| 76417 | + return SQLITE_CORRUPT_BKPT; |
| 76418 | + } |
| 76402 | 76419 | if( !pPage->leaf ){ |
| 76403 | 76420 | int idx = pCur->ix; |
| 76404 | 76421 | rc = moveToChild(pCur, get4byte(findCell(pPage, idx))); |
| 76405 | 76422 | if( rc ) return rc; |
| 76406 | 76423 | rc = moveToRightmost(pCur); |
| | @@ -166806,11 +166823,14 @@ |
| 166806 | 166823 | db = pParse->db; |
| 166807 | 166824 | memset(&sWLB, 0, sizeof(sWLB)); |
| 166808 | 166825 | |
| 166809 | 166826 | /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ |
| 166810 | 166827 | testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); |
| 166811 | | - if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0; |
| 166828 | + if( pOrderBy && pOrderBy->nExpr>=BMS ){ |
| 166829 | + pOrderBy = 0; |
| 166830 | + wctrlFlags &= ~WHERE_WANT_DISTINCT; |
| 166831 | + } |
| 166812 | 166832 | |
| 166813 | 166833 | /* The number of tables in the FROM clause is limited by the number of |
| 166814 | 166834 | ** bits in a Bitmask |
| 166815 | 166835 | */ |
| 166816 | 166836 | testcase( pTabList->nSrc==BMS ); |
| | @@ -184743,10 +184763,12 @@ |
| 184743 | 184763 | SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); |
| 184744 | 184764 | #endif |
| 184745 | 184765 | |
| 184746 | 184766 | SQLITE_PRIVATE int sqlite3Fts3ExprIterate(Fts3Expr*, int (*x)(Fts3Expr*,int,void*), void*); |
| 184747 | 184767 | |
| 184768 | +SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk); |
| 184769 | + |
| 184748 | 184770 | #endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */ |
| 184749 | 184771 | #endif /* _FTSINT_H */ |
| 184750 | 184772 | |
| 184751 | 184773 | /************** End of fts3Int.h *********************************************/ |
| 184752 | 184774 | /************** Continuing where we left off in fts3.c ***********************/ |
| | @@ -188465,42 +188487,33 @@ |
| 188465 | 188487 | |
| 188466 | 188488 | /* |
| 188467 | 188489 | ** Implementation of the xIntegrity() method on the FTS3/FTS4 virtual |
| 188468 | 188490 | ** table. |
| 188469 | 188491 | */ |
| 188470 | | -static int fts3Integrity( |
| 188492 | +static int fts3IntegrityMethod( |
| 188471 | 188493 | sqlite3_vtab *pVtab, /* The virtual table to be checked */ |
| 188472 | 188494 | const char *zSchema, /* Name of schema in which pVtab lives */ |
| 188473 | 188495 | const char *zTabname, /* Name of the pVTab table */ |
| 188474 | 188496 | int isQuick, /* True if this is a quick_check */ |
| 188475 | 188497 | char **pzErr /* Write error message here */ |
| 188476 | 188498 | ){ |
| 188477 | 188499 | Fts3Table *p = (Fts3Table*)pVtab; |
| 188478 | | - char *zSql; |
| 188479 | 188500 | int rc; |
| 188480 | | - char *zErr = 0; |
| 188501 | + int bOk = 0; |
| 188481 | 188502 | |
| 188482 | | - assert( pzErr!=0 ); |
| 188483 | | - assert( *pzErr==0 ); |
| 188484 | 188503 | UNUSED_PARAMETER(isQuick); |
| 188485 | | - zSql = sqlite3_mprintf( |
| 188486 | | - "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');", |
| 188487 | | - zSchema, zTabname, zTabname); |
| 188488 | | - if( zSql==0 ){ |
| 188489 | | - return SQLITE_NOMEM; |
| 188490 | | - } |
| 188491 | | - rc = sqlite3_exec(p->db, zSql, 0, 0, &zErr); |
| 188492 | | - sqlite3_free(zSql); |
| 188493 | | - if( (rc&0xff)==SQLITE_CORRUPT ){ |
| 188504 | + rc = sqlite3Fts3IntegrityCheck(p, &bOk); |
| 188505 | + assert( rc!=SQLITE_CORRUPT_VTAB || bOk==0 ); |
| 188506 | + if( rc!=SQLITE_OK && rc!=SQLITE_CORRUPT_VTAB ){ |
| 188507 | + *pzErr = sqlite3_mprintf("unable to validate the inverted index for" |
| 188508 | + " FTS%d table %s.%s: %s", |
| 188509 | + p->bFts4 ? 4 : 3, zSchema, zTabname, sqlite3_errstr(rc)); |
| 188510 | + }else if( bOk==0 ){ |
| 188494 | 188511 | *pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s", |
| 188495 | 188512 | p->bFts4 ? 4 : 3, zSchema, zTabname); |
| 188496 | | - }else if( rc!=SQLITE_OK ){ |
| 188497 | | - *pzErr = sqlite3_mprintf("unable to validate the inverted index for" |
| 188498 | | - " FTS%d table %s.%s: %s", |
| 188499 | | - p->bFts4 ? 4 : 3, zSchema, zTabname, zErr); |
| 188500 | 188513 | } |
| 188501 | | - sqlite3_free(zErr); |
| 188514 | + sqlite3Fts3SegmentsClose(p); |
| 188502 | 188515 | return SQLITE_OK; |
| 188503 | 188516 | } |
| 188504 | 188517 | |
| 188505 | 188518 | |
| 188506 | 188519 | |
| | @@ -188527,11 +188540,11 @@ |
| 188527 | 188540 | /* xRename */ fts3RenameMethod, |
| 188528 | 188541 | /* xSavepoint */ fts3SavepointMethod, |
| 188529 | 188542 | /* xRelease */ fts3ReleaseMethod, |
| 188530 | 188543 | /* xRollbackTo */ fts3RollbackToMethod, |
| 188531 | 188544 | /* xShadowName */ fts3ShadowName, |
| 188532 | | - /* xIntegrity */ fts3Integrity, |
| 188545 | + /* xIntegrity */ fts3IntegrityMethod, |
| 188533 | 188546 | }; |
| 188534 | 188547 | |
| 188535 | 188548 | /* |
| 188536 | 188549 | ** This function is registered as the module destructor (called when an |
| 188537 | 188550 | ** FTS3 enabled database connection is closed). It frees the memory |
| | @@ -200081,11 +200094,11 @@ |
| 200081 | 200094 | ** to false before returning. |
| 200082 | 200095 | ** |
| 200083 | 200096 | ** If an error occurs (e.g. an OOM or IO error), return an SQLite error |
| 200084 | 200097 | ** code. The final value of *pbOk is undefined in this case. |
| 200085 | 200098 | */ |
| 200086 | | -static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){ |
| 200099 | +SQLITE_PRIVATE int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){ |
| 200087 | 200100 | int rc = SQLITE_OK; /* Return code */ |
| 200088 | 200101 | u64 cksum1 = 0; /* Checksum based on FTS index contents */ |
| 200089 | 200102 | u64 cksum2 = 0; /* Checksum based on %_content contents */ |
| 200090 | 200103 | sqlite3_stmt *pAllLangid = 0; /* Statement to return all language-ids */ |
| 200091 | 200104 | |
| | @@ -200159,11 +200172,11 @@ |
| 200159 | 200172 | } |
| 200160 | 200173 | |
| 200161 | 200174 | sqlite3_finalize(pStmt); |
| 200162 | 200175 | } |
| 200163 | 200176 | |
| 200164 | | - *pbOk = (cksum1==cksum2); |
| 200177 | + *pbOk = (rc==SQLITE_OK && cksum1==cksum2); |
| 200165 | 200178 | return rc; |
| 200166 | 200179 | } |
| 200167 | 200180 | |
| 200168 | 200181 | /* |
| 200169 | 200182 | ** Run the integrity-check. If no error occurs and the current contents of |
| | @@ -200199,11 +200212,11 @@ |
| 200199 | 200212 | static int fts3DoIntegrityCheck( |
| 200200 | 200213 | Fts3Table *p /* FTS3 table handle */ |
| 200201 | 200214 | ){ |
| 200202 | 200215 | int rc; |
| 200203 | 200216 | int bOk = 0; |
| 200204 | | - rc = fts3IntegrityCheck(p, &bOk); |
| 200217 | + rc = sqlite3Fts3IntegrityCheck(p, &bOk); |
| 200205 | 200218 | if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB; |
| 200206 | 200219 | return rc; |
| 200207 | 200220 | } |
| 200208 | 200221 | |
| 200209 | 200222 | /* |
| | @@ -203751,19 +203764,29 @@ |
| 203751 | 203764 | jsonAppendCharExpand(p,c); |
| 203752 | 203765 | }else{ |
| 203753 | 203766 | p->zBuf[p->nUsed++] = c; |
| 203754 | 203767 | } |
| 203755 | 203768 | } |
| 203769 | + |
| 203770 | +/* Remove a single character from the end of the string |
| 203771 | +*/ |
| 203772 | +static void jsonStringTrimOneChar(JsonString *p){ |
| 203773 | + if( p->eErr==0 ){ |
| 203774 | + assert( p->nUsed>0 ); |
| 203775 | + p->nUsed--; |
| 203776 | + } |
| 203777 | +} |
| 203778 | + |
| 203756 | 203779 | |
| 203757 | 203780 | /* Make sure there is a zero terminator on p->zBuf[] |
| 203758 | 203781 | ** |
| 203759 | 203782 | ** Return true on success. Return false if an OOM prevents this |
| 203760 | 203783 | ** from happening. |
| 203761 | 203784 | */ |
| 203762 | 203785 | static int jsonStringTerminate(JsonString *p){ |
| 203763 | 203786 | jsonAppendChar(p, 0); |
| 203764 | | - p->nUsed--; |
| 203787 | + jsonStringTrimOneChar(p); |
| 203765 | 203788 | return p->eErr==0; |
| 203766 | 203789 | } |
| 203767 | 203790 | |
| 203768 | 203791 | /* Append a comma separator to the output buffer, if the previous |
| 203769 | 203792 | ** character is not '[' or '{'. |
| | @@ -205225,12 +205248,12 @@ |
| 205225 | 205248 | } |
| 205226 | 205249 | sz = (pParse->aBlob[i+5]<<24) + (pParse->aBlob[i+6]<<16) + |
| 205227 | 205250 | (pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8]; |
| 205228 | 205251 | n = 9; |
| 205229 | 205252 | } |
| 205230 | | - if( i+sz+n > pParse->nBlob |
| 205231 | | - && i+sz+n > pParse->nBlob-pParse->delta |
| 205253 | + if( (i64)i+sz+n > pParse->nBlob |
| 205254 | + && (i64)i+sz+n > pParse->nBlob-pParse->delta |
| 205232 | 205255 | ){ |
| 205233 | 205256 | sz = 0; |
| 205234 | 205257 | n = 0; |
| 205235 | 205258 | } |
| 205236 | 205259 | *pSz = sz; |
| | @@ -205276,18 +205299,20 @@ |
| 205276 | 205299 | jsonAppendRawNZ(pOut, "false", 5); |
| 205277 | 205300 | return i+1; |
| 205278 | 205301 | } |
| 205279 | 205302 | case JSONB_INT: |
| 205280 | 205303 | case JSONB_FLOAT: { |
| 205304 | + if( sz==0 ) goto malformed_jsonb; |
| 205281 | 205305 | jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz); |
| 205282 | 205306 | break; |
| 205283 | 205307 | } |
| 205284 | 205308 | case JSONB_INT5: { /* Integer literal in hexadecimal notation */ |
| 205285 | 205309 | u32 k = 2; |
| 205286 | 205310 | sqlite3_uint64 u = 0; |
| 205287 | 205311 | const char *zIn = (const char*)&pParse->aBlob[i+n]; |
| 205288 | 205312 | int bOverflow = 0; |
| 205313 | + if( sz==0 ) goto malformed_jsonb; |
| 205289 | 205314 | if( zIn[0]=='-' ){ |
| 205290 | 205315 | jsonAppendChar(pOut, '-'); |
| 205291 | 205316 | k++; |
| 205292 | 205317 | }else if( zIn[0]=='+' ){ |
| 205293 | 205318 | k++; |
| | @@ -205306,10 +205331,11 @@ |
| 205306 | 205331 | break; |
| 205307 | 205332 | } |
| 205308 | 205333 | case JSONB_FLOAT5: { /* Float literal missing digits beside "." */ |
| 205309 | 205334 | u32 k = 0; |
| 205310 | 205335 | const char *zIn = (const char*)&pParse->aBlob[i+n]; |
| 205336 | + if( sz==0 ) goto malformed_jsonb; |
| 205311 | 205337 | if( zIn[0]=='-' ){ |
| 205312 | 205338 | jsonAppendChar(pOut, '-'); |
| 205313 | 205339 | k++; |
| 205314 | 205340 | } |
| 205315 | 205341 | if( zIn[k]=='.' ){ |
| | @@ -205419,34 +205445,36 @@ |
| 205419 | 205445 | } |
| 205420 | 205446 | case JSONB_ARRAY: { |
| 205421 | 205447 | jsonAppendChar(pOut, '['); |
| 205422 | 205448 | j = i+n; |
| 205423 | 205449 | iEnd = j+sz; |
| 205424 | | - while( j<iEnd ){ |
| 205450 | + while( j<iEnd && pOut->eErr==0 ){ |
| 205425 | 205451 | j = jsonTranslateBlobToText(pParse, j, pOut); |
| 205426 | 205452 | jsonAppendChar(pOut, ','); |
| 205427 | 205453 | } |
| 205428 | | - if( sz>0 ) pOut->nUsed--; |
| 205454 | + if( j>iEnd ) pOut->eErr |= JSTRING_MALFORMED; |
| 205455 | + if( sz>0 ) jsonStringTrimOneChar(pOut); |
| 205429 | 205456 | jsonAppendChar(pOut, ']'); |
| 205430 | 205457 | break; |
| 205431 | 205458 | } |
| 205432 | 205459 | case JSONB_OBJECT: { |
| 205433 | 205460 | int x = 0; |
| 205434 | 205461 | jsonAppendChar(pOut, '{'); |
| 205435 | 205462 | j = i+n; |
| 205436 | 205463 | iEnd = j+sz; |
| 205437 | | - while( j<iEnd ){ |
| 205464 | + while( j<iEnd && pOut->eErr==0 ){ |
| 205438 | 205465 | j = jsonTranslateBlobToText(pParse, j, pOut); |
| 205439 | 205466 | jsonAppendChar(pOut, (x++ & 1) ? ',' : ':'); |
| 205440 | 205467 | } |
| 205441 | | - if( x & 1 ) pOut->eErr |= JSTRING_MALFORMED; |
| 205442 | | - if( sz>0 ) pOut->nUsed--; |
| 205468 | + if( (x & 1)!=0 || j>iEnd ) pOut->eErr |= JSTRING_MALFORMED; |
| 205469 | + if( sz>0 ) jsonStringTrimOneChar(pOut); |
| 205443 | 205470 | jsonAppendChar(pOut, '}'); |
| 205444 | 205471 | break; |
| 205445 | 205472 | } |
| 205446 | 205473 | |
| 205447 | 205474 | default: { |
| 205475 | + malformed_jsonb: |
| 205448 | 205476 | pOut->eErr |= JSTRING_MALFORMED; |
| 205449 | 205477 | break; |
| 205450 | 205478 | } |
| 205451 | 205479 | } |
| 205452 | 205480 | return i+n+sz; |
| | @@ -206368,10 +206396,42 @@ |
| 206368 | 206396 | }else{ |
| 206369 | 206397 | jsonBadPathError(ctx, zPath); |
| 206370 | 206398 | } |
| 206371 | 206399 | return; |
| 206372 | 206400 | } |
| 206401 | + |
| 206402 | +/* |
| 206403 | +** If pArg is a blob that seems like a JSONB blob, then initialize |
| 206404 | +** p to point to that JSONB and return TRUE. If pArg does not seem like |
| 206405 | +** a JSONB blob, then return FALSE; |
| 206406 | +** |
| 206407 | +** This routine is only called if it is already known that pArg is a |
| 206408 | +** blob. The only open question is whether or not the blob appears |
| 206409 | +** to be a JSONB blob. |
| 206410 | +*/ |
| 206411 | +static int jsonArgIsJsonb(sqlite3_value *pArg, JsonParse *p){ |
| 206412 | + u32 n, sz = 0; |
| 206413 | + p->aBlob = (u8*)sqlite3_value_blob(pArg); |
| 206414 | + p->nBlob = (u32)sqlite3_value_bytes(pArg); |
| 206415 | + if( p->nBlob==0 ){ |
| 206416 | + p->aBlob = 0; |
| 206417 | + return 0; |
| 206418 | + } |
| 206419 | + if( NEVER(p->aBlob==0) ){ |
| 206420 | + return 0; |
| 206421 | + } |
| 206422 | + if( (p->aBlob[0] & 0x0f)<=JSONB_OBJECT |
| 206423 | + && (n = jsonbPayloadSize(p, 0, &sz))>0 |
| 206424 | + && sz+n==p->nBlob |
| 206425 | + && ((p->aBlob[0] & 0x0f)>JSONB_FALSE || sz==0) |
| 206426 | + ){ |
| 206427 | + return 1; |
| 206428 | + } |
| 206429 | + p->aBlob = 0; |
| 206430 | + p->nBlob = 0; |
| 206431 | + return 0; |
| 206432 | +} |
| 206373 | 206433 | |
| 206374 | 206434 | /* |
| 206375 | 206435 | ** Generate a JsonParse object, containing valid JSONB in aBlob and nBlob, |
| 206376 | 206436 | ** from the SQL function argument pArg. Return a pointer to the new |
| 206377 | 206437 | ** JsonParse object. |
| | @@ -206425,33 +206485,28 @@ |
| 206425 | 206485 | p->hasNonstd = pFromCache->hasNonstd; |
| 206426 | 206486 | jsonParseFree(pFromCache); |
| 206427 | 206487 | return p; |
| 206428 | 206488 | } |
| 206429 | 206489 | if( eType==SQLITE_BLOB ){ |
| 206430 | | - u32 n, sz = 0; |
| 206431 | | - p->aBlob = (u8*)sqlite3_value_blob(pArg); |
| 206432 | | - p->nBlob = (u32)sqlite3_value_bytes(pArg); |
| 206433 | | - if( p->nBlob==0 ){ |
| 206434 | | - goto json_pfa_malformed; |
| 206435 | | - } |
| 206436 | | - if( NEVER(p->aBlob==0) ){ |
| 206437 | | - goto json_pfa_oom; |
| 206438 | | - } |
| 206439 | | - if( (p->aBlob[0] & 0x0f)>JSONB_OBJECT ){ |
| 206440 | | - goto json_pfa_malformed; |
| 206441 | | - } |
| 206442 | | - n = jsonbPayloadSize(p, 0, &sz); |
| 206443 | | - if( n==0 |
| 206444 | | - || sz+n!=p->nBlob |
| 206445 | | - || ((p->aBlob[0] & 0x0f)<=JSONB_FALSE && sz>0) |
| 206446 | | - ){ |
| 206447 | | - goto json_pfa_malformed; |
| 206448 | | - } |
| 206449 | | - if( (flgs & JSON_EDITABLE)!=0 && jsonBlobMakeEditable(p, 0)==0 ){ |
| 206450 | | - goto json_pfa_oom; |
| 206451 | | - } |
| 206452 | | - return p; |
| 206490 | + if( jsonArgIsJsonb(pArg,p) ){ |
| 206491 | + if( (flgs & JSON_EDITABLE)!=0 && jsonBlobMakeEditable(p, 0)==0 ){ |
| 206492 | + goto json_pfa_oom; |
| 206493 | + } |
| 206494 | + return p; |
| 206495 | + } |
| 206496 | + /* If the blob is not valid JSONB, fall through into trying to cast |
| 206497 | + ** the blob into text which is then interpreted as JSON. (tag-20240123-a) |
| 206498 | + ** |
| 206499 | + ** This goes against all historical documentation about how the SQLite |
| 206500 | + ** JSON functions were suppose to work. From the beginning, blob was |
| 206501 | + ** reserved for expansion and a blob value should have raised an error. |
| 206502 | + ** But it did not, due to a bug. And many applications came to depend |
| 206503 | + ** upon this buggy behavior, espeically when using the CLI and reading |
| 206504 | + ** JSON text using readfile(), which returns a blob. For this reason |
| 206505 | + ** we will continue to support the bug moving forward. |
| 206506 | + ** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d |
| 206507 | + */ |
| 206453 | 206508 | } |
| 206454 | 206509 | p->zJson = (char*)sqlite3_value_text(pArg); |
| 206455 | 206510 | p->nJson = sqlite3_value_bytes(pArg); |
| 206456 | 206511 | if( p->nJson==0 ) goto json_pfa_malformed; |
| 206457 | 206512 | if( NEVER(p->zJson==0) ) goto json_pfa_oom; |
| | @@ -207423,16 +207478,16 @@ |
| 207423 | 207478 | sqlite3_result_int(ctx, 0); |
| 207424 | 207479 | #endif |
| 207425 | 207480 | return; |
| 207426 | 207481 | } |
| 207427 | 207482 | case SQLITE_BLOB: { |
| 207428 | | - if( (flags & 0x0c)!=0 && jsonFuncArgMightBeBinary(argv[0]) ){ |
| 207483 | + if( jsonFuncArgMightBeBinary(argv[0]) ){ |
| 207429 | 207484 | if( flags & 0x04 ){ |
| 207430 | 207485 | /* Superficial checking only - accomplished by the |
| 207431 | 207486 | ** jsonFuncArgMightBeBinary() call above. */ |
| 207432 | 207487 | res = 1; |
| 207433 | | - }else{ |
| 207488 | + }else if( flags & 0x08 ){ |
| 207434 | 207489 | /* Strict checking. Check by translating BLOB->TEXT->BLOB. If |
| 207435 | 207490 | ** no errors occur, call that a "strict check". */ |
| 207436 | 207491 | JsonParse px; |
| 207437 | 207492 | u32 iErr; |
| 207438 | 207493 | memset(&px, 0, sizeof(px)); |
| | @@ -207439,12 +207494,15 @@ |
| 207439 | 207494 | px.aBlob = (u8*)sqlite3_value_blob(argv[0]); |
| 207440 | 207495 | px.nBlob = sqlite3_value_bytes(argv[0]); |
| 207441 | 207496 | iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1); |
| 207442 | 207497 | res = iErr==0; |
| 207443 | 207498 | } |
| 207499 | + break; |
| 207444 | 207500 | } |
| 207445 | | - break; |
| 207501 | + /* Fall through into interpreting the input as text. See note |
| 207502 | + ** above at tag-20240123-a. */ |
| 207503 | + /* no break */ deliberate_fall_through |
| 207446 | 207504 | } |
| 207447 | 207505 | default: { |
| 207448 | 207506 | JsonParse px; |
| 207449 | 207507 | if( (flags & 0x3)==0 ) break; |
| 207450 | 207508 | memset(&px, 0, sizeof(px)); |
| | @@ -207565,21 +207623,21 @@ |
| 207565 | 207623 | }else if( flags & JSON_BLOB ){ |
| 207566 | 207624 | jsonReturnStringAsBlob(pStr); |
| 207567 | 207625 | if( isFinal ){ |
| 207568 | 207626 | if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf); |
| 207569 | 207627 | }else{ |
| 207570 | | - pStr->nUsed--; |
| 207628 | + jsonStringTrimOneChar(pStr); |
| 207571 | 207629 | } |
| 207572 | 207630 | return; |
| 207573 | 207631 | }else if( isFinal ){ |
| 207574 | 207632 | sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, |
| 207575 | 207633 | pStr->bStatic ? SQLITE_TRANSIENT : |
| 207576 | 207634 | sqlite3RCStrUnref); |
| 207577 | 207635 | pStr->bStatic = 1; |
| 207578 | 207636 | }else{ |
| 207579 | 207637 | sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); |
| 207580 | | - pStr->nUsed--; |
| 207638 | + jsonStringTrimOneChar(pStr); |
| 207581 | 207639 | } |
| 207582 | 207640 | }else{ |
| 207583 | 207641 | sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); |
| 207584 | 207642 | } |
| 207585 | 207643 | sqlite3_result_subtype(ctx, JSON_SUBTYPE); |
| | @@ -207685,21 +207743,21 @@ |
| 207685 | 207743 | }else if( flags & JSON_BLOB ){ |
| 207686 | 207744 | jsonReturnStringAsBlob(pStr); |
| 207687 | 207745 | if( isFinal ){ |
| 207688 | 207746 | if( !pStr->bStatic ) sqlite3RCStrUnref(pStr->zBuf); |
| 207689 | 207747 | }else{ |
| 207690 | | - pStr->nUsed--; |
| 207748 | + jsonStringTrimOneChar(pStr); |
| 207691 | 207749 | } |
| 207692 | 207750 | return; |
| 207693 | 207751 | }else if( isFinal ){ |
| 207694 | 207752 | sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, |
| 207695 | 207753 | pStr->bStatic ? SQLITE_TRANSIENT : |
| 207696 | 207754 | sqlite3RCStrUnref); |
| 207697 | 207755 | pStr->bStatic = 1; |
| 207698 | 207756 | }else{ |
| 207699 | 207757 | sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); |
| 207700 | | - pStr->nUsed--; |
| 207758 | + jsonStringTrimOneChar(pStr); |
| 207701 | 207759 | } |
| 207702 | 207760 | }else{ |
| 207703 | 207761 | sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); |
| 207704 | 207762 | } |
| 207705 | 207763 | sqlite3_result_subtype(ctx, JSON_SUBTYPE); |
| | @@ -208176,17 +208234,13 @@ |
| 208176 | 208234 | jsonEachCursorReset(p); |
| 208177 | 208235 | if( idxNum==0 ) return SQLITE_OK; |
| 208178 | 208236 | memset(&p->sParse, 0, sizeof(p->sParse)); |
| 208179 | 208237 | p->sParse.nJPRef = 1; |
| 208180 | 208238 | p->sParse.db = p->db; |
| 208181 | | - if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ |
| 208182 | | - if( jsonFuncArgMightBeBinary(argv[0]) ){ |
| 208183 | | - p->sParse.nBlob = sqlite3_value_bytes(argv[0]); |
| 208184 | | - p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]); |
| 208185 | | - }else{ |
| 208186 | | - goto json_each_malformed_input; |
| 208187 | | - } |
| 208239 | + if( jsonFuncArgMightBeBinary(argv[0]) ){ |
| 208240 | + p->sParse.nBlob = sqlite3_value_bytes(argv[0]); |
| 208241 | + p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]); |
| 208188 | 208242 | }else{ |
| 208189 | 208243 | p->sParse.zJson = (char*)sqlite3_value_text(argv[0]); |
| 208190 | 208244 | p->sParse.nJson = sqlite3_value_bytes(argv[0]); |
| 208191 | 208245 | if( p->sParse.zJson==0 ){ |
| 208192 | 208246 | p->i = p->iEnd = 0; |
| | @@ -225283,13 +225337,11 @@ |
| 225283 | 225337 | |
| 225284 | 225338 | /* Delete all attached table objects. And the contents of their |
| 225285 | 225339 | ** associated hash-tables. */ |
| 225286 | 225340 | sessionDeleteTable(pSession, pSession->pTable); |
| 225287 | 225341 | |
| 225288 | | - /* Assert that all allocations have been freed and then free the |
| 225289 | | - ** session object itself. */ |
| 225290 | | - // assert( pSession->nMalloc==0 ); |
| 225342 | + /* Free the session object. */ |
| 225291 | 225343 | sqlite3_free(pSession); |
| 225292 | 225344 | } |
| 225293 | 225345 | |
| 225294 | 225346 | /* |
| 225295 | 225347 | ** Set a table filter on a Session Object. |
| | @@ -249139,11 +249191,14 @@ |
| 249139 | 249191 | pConfig->bPrefixIndex = sqlite3_value_int(pVal); |
| 249140 | 249192 | #endif |
| 249141 | 249193 | }else if( 0==sqlite3_stricmp("flush", zCmd) ){ |
| 249142 | 249194 | rc = sqlite3Fts5FlushToDisk(&pTab->p); |
| 249143 | 249195 | }else{ |
| 249144 | | - rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); |
| 249196 | + rc = sqlite3Fts5FlushToDisk(&pTab->p); |
| 249197 | + if( rc==SQLITE_OK ){ |
| 249198 | + rc = sqlite3Fts5IndexLoadConfig(pTab->p.pIndex); |
| 249199 | + } |
| 249145 | 249200 | if( rc==SQLITE_OK ){ |
| 249146 | 249201 | rc = sqlite3Fts5ConfigSetValue(pTab->p.pConfig, zCmd, pVal, &bError); |
| 249147 | 249202 | } |
| 249148 | 249203 | if( rc==SQLITE_OK ){ |
| 249149 | 249204 | if( bError ){ |
| | @@ -250490,11 +250545,11 @@ |
| 250490 | 250545 | int nArg, /* Number of args */ |
| 250491 | 250546 | sqlite3_value **apUnused /* Function arguments */ |
| 250492 | 250547 | ){ |
| 250493 | 250548 | assert( nArg==0 ); |
| 250494 | 250549 | UNUSED_PARAM2(nArg, apUnused); |
| 250495 | | - sqlite3_result_text(pCtx, "fts5: 2024-01-08 19:55:40 cd016f26bb61549a304f2148035e050f76a8f4a35cdb7131bba2f5fc5d09f49e", -1, SQLITE_TRANSIENT); |
| 250550 | + sqlite3_result_text(pCtx, "fts5: 2024-01-30 16:01:20 e876e51a0ed5c5b3126f52e532044363a014bc594cfefa87ffb5b82257cc467a", -1, SQLITE_TRANSIENT); |
| 250496 | 250551 | } |
| 250497 | 250552 | |
| 250498 | 250553 | /* |
| 250499 | 250554 | ** Return true if zName is the extension on one of the shadow tables used |
| 250500 | 250555 | ** by this module. |
| | @@ -250521,31 +250576,25 @@ |
| 250521 | 250576 | const char *zTabname, /* Name of the table itself */ |
| 250522 | 250577 | int isQuick, /* True if this is a quick-check */ |
| 250523 | 250578 | char **pzErr /* Write error message here */ |
| 250524 | 250579 | ){ |
| 250525 | 250580 | Fts5FullTable *pTab = (Fts5FullTable*)pVtab; |
| 250526 | | - Fts5Config *pConfig = pTab->p.pConfig; |
| 250527 | | - char *zSql; |
| 250528 | | - char *zErr = 0; |
| 250529 | 250581 | int rc; |
| 250582 | + |
| 250530 | 250583 | assert( pzErr!=0 && *pzErr==0 ); |
| 250531 | 250584 | UNUSED_PARAM(isQuick); |
| 250532 | | - zSql = sqlite3_mprintf( |
| 250533 | | - "INSERT INTO \"%w\".\"%w\"(\"%w\") VALUES('integrity-check');", |
| 250534 | | - zSchema, zTabname, pConfig->zName); |
| 250535 | | - if( zSql==0 ) return SQLITE_NOMEM; |
| 250536 | | - rc = sqlite3_exec(pConfig->db, zSql, 0, 0, &zErr); |
| 250537 | | - sqlite3_free(zSql); |
| 250585 | + rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0); |
| 250538 | 250586 | if( (rc&0xff)==SQLITE_CORRUPT ){ |
| 250539 | 250587 | *pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s", |
| 250540 | 250588 | zSchema, zTabname); |
| 250541 | 250589 | }else if( rc!=SQLITE_OK ){ |
| 250542 | 250590 | *pzErr = sqlite3_mprintf("unable to validate the inverted index for" |
| 250543 | 250591 | " FTS5 table %s.%s: %s", |
| 250544 | | - zSchema, zTabname, zErr); |
| 250592 | + zSchema, zTabname, sqlite3_errstr(rc)); |
| 250545 | 250593 | } |
| 250546 | | - sqlite3_free(zErr); |
| 250594 | + sqlite3Fts5IndexCloseReader(pTab->p.pIndex); |
| 250595 | + |
| 250547 | 250596 | return SQLITE_OK; |
| 250548 | 250597 | } |
| 250549 | 250598 | |
| 250550 | 250599 | static int fts5Init(sqlite3 *db){ |
| 250551 | 250600 | static const sqlite3_module fts5Mod = { |
| 250552 | 250601 | |