| Index: third_party/sqlite/src/ext/misc/json1.c
|
| diff --git a/third_party/sqlite/src/ext/misc/json1.c b/third_party/sqlite/src/ext/misc/json1.c
|
| index 37075166607289b5b56887ab29337571d63644df..3063f9f261a8bbb365853bbf1a53dddb94662fd2 100644
|
| --- a/third_party/sqlite/src/ext/misc/json1.c
|
| +++ b/third_party/sqlite/src/ext/misc/json1.c
|
| @@ -22,7 +22,7 @@
|
| ** how JSONB might improve on that.)
|
| */
|
| #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
|
| -#if !defined(_SQLITEINT_H_)
|
| +#if !defined(SQLITEINT_H)
|
| #include "sqlite3ext.h"
|
| #endif
|
| SQLITE_EXTENSION_INIT1
|
| @@ -31,7 +31,11 @@ SQLITE_EXTENSION_INIT1
|
| #include <stdlib.h>
|
| #include <stdarg.h>
|
|
|
| -#define UNUSED_PARAM(X) (void)(X)
|
| +/* Mark a function parameter as unused, to suppress nuisance compiler
|
| +** warnings. */
|
| +#ifndef UNUSED_PARAM
|
| +# define UNUSED_PARAM(X) (void)(X)
|
| +#endif
|
|
|
| #ifndef LARGEST_INT64
|
| # define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
|
| @@ -45,13 +49,15 @@ SQLITE_EXTENSION_INIT1
|
| #ifdef sqlite3Isdigit
|
| /* Use the SQLite core versions if this routine is part of the
|
| ** SQLite amalgamation */
|
| -# define safe_isdigit(x) sqlite3Isdigit(x)
|
| -# define safe_isalnum(x) sqlite3Isalnum(x)
|
| +# define safe_isdigit(x) sqlite3Isdigit(x)
|
| +# define safe_isalnum(x) sqlite3Isalnum(x)
|
| +# define safe_isxdigit(x) sqlite3Isxdigit(x)
|
| #else
|
| /* Use the standard library for separate compilation */
|
| #include <ctype.h> /* amalgamator: keep */
|
| -# define safe_isdigit(x) isdigit((unsigned char)(x))
|
| -# define safe_isalnum(x) isalnum((unsigned char)(x))
|
| +# define safe_isdigit(x) isdigit((unsigned char)(x))
|
| +# define safe_isalnum(x) isalnum((unsigned char)(x))
|
| +# define safe_isxdigit(x) isxdigit((unsigned char)(x))
|
| #endif
|
|
|
| /*
|
| @@ -276,10 +282,33 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
|
| if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return;
|
| p->zBuf[p->nUsed++] = '"';
|
| for(i=0; i<N; i++){
|
| - char c = zIn[i];
|
| + unsigned char c = ((unsigned const char*)zIn)[i];
|
| if( c=='"' || c=='\\' ){
|
| + json_simple_escape:
|
| if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return;
|
| p->zBuf[p->nUsed++] = '\\';
|
| + }else if( c<=0x1f ){
|
| + static const char aSpecial[] = {
|
| + 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
|
| + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
| + };
|
| + assert( sizeof(aSpecial)==32 );
|
| + assert( aSpecial['\b']=='b' );
|
| + assert( aSpecial['\f']=='f' );
|
| + assert( aSpecial['\n']=='n' );
|
| + assert( aSpecial['\r']=='r' );
|
| + assert( aSpecial['\t']=='t' );
|
| + if( aSpecial[c] ){
|
| + c = aSpecial[c];
|
| + goto json_simple_escape;
|
| + }
|
| + if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return;
|
| + p->zBuf[p->nUsed++] = '\\';
|
| + p->zBuf[p->nUsed++] = 'u';
|
| + p->zBuf[p->nUsed++] = '0';
|
| + p->zBuf[p->nUsed++] = '0';
|
| + p->zBuf[p->nUsed++] = '0' + (c>>4);
|
| + c = "0123456789abcdef"[c&0xf];
|
| }
|
| p->zBuf[p->nUsed++] = c;
|
| }
|
| @@ -320,7 +349,7 @@ static void jsonAppendValue(
|
| default: {
|
| if( p->bErr==0 ){
|
| sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
|
| - p->bErr = 1;
|
| + p->bErr = 2;
|
| jsonReset(p);
|
| }
|
| break;
|
| @@ -566,12 +595,13 @@ static void jsonReturn(
|
| c = z[++i];
|
| if( c=='u' ){
|
| u32 v = 0, k;
|
| - for(k=0; k<4 && i<n-2; i++, k++){
|
| + for(k=0; k<4; i++, k++){
|
| + assert( i<n-2 );
|
| c = z[i+1];
|
| - if( c>='0' && c<='9' ) v = v*16 + c - '0';
|
| - else if( c>='A' && c<='F' ) v = v*16 + c - 'A' + 10;
|
| - else if( c>='a' && c<='f' ) v = v*16 + c - 'a' + 10;
|
| - else break;
|
| + assert( safe_isxdigit(c) );
|
| + if( c<='9' ) v = v*16 + c - '0';
|
| + else if( c<='F' ) v = v*16 + c - 'A' + 10;
|
| + else v = v*16 + c - 'a' + 10;
|
| }
|
| if( v==0 ) break;
|
| if( v<=0x7f ){
|
| @@ -676,6 +706,15 @@ static int jsonParseAddNode(
|
| }
|
|
|
| /*
|
| +** Return true if z[] begins with 4 (or more) hexadecimal digits
|
| +*/
|
| +static int jsonIs4Hex(const char *z){
|
| + int i;
|
| + for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0;
|
| + return 1;
|
| +}
|
| +
|
| +/*
|
| ** Parse a single JSON value which begins at pParse->zJson[i]. Return the
|
| ** index of the first character past the end of the value parsed.
|
| **
|
| @@ -749,8 +788,13 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
|
| if( c==0 ) return -1;
|
| if( c=='\\' ){
|
| c = pParse->zJson[++j];
|
| - if( c==0 ) return -1;
|
| - jnFlags = JNODE_ESCAPE;
|
| + if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
|
| + || c=='n' || c=='r' || c=='t'
|
| + || (c=='u' && jsonIs4Hex(pParse->zJson+j+1)) ){
|
| + jnFlags = JNODE_ESCAPE;
|
| + }else{
|
| + return -1;
|
| + }
|
| }else if( c=='"' ){
|
| break;
|
| }
|
| @@ -1185,6 +1229,26 @@ static void jsonTest1Func(
|
| ****************************************************************************/
|
|
|
| /*
|
| +** Implementation of the json_QUOTE(VALUE) function. Return a JSON value
|
| +** corresponding to the SQL value input. Mostly this means putting
|
| +** double-quotes around strings and returning the unquoted string "null"
|
| +** when given a NULL input.
|
| +*/
|
| +static void jsonQuoteFunc(
|
| + sqlite3_context *ctx,
|
| + int argc,
|
| + sqlite3_value **argv
|
| +){
|
| + JsonString jx;
|
| + UNUSED_PARAM(argc);
|
| +
|
| + jsonInit(&jx, ctx);
|
| + jsonAppendValue(&jx, argv[0]);
|
| + jsonResult(&jx);
|
| + sqlite3_result_subtype(ctx, JSON_SUBTYPE);
|
| +}
|
| +
|
| +/*
|
| ** Implementation of the json_array(VALUE,...) function. Return a JSON
|
| ** array that contains all values given in arguments. Or if any argument
|
| ** is a BLOB, throw an error.
|
| @@ -1529,6 +1593,7 @@ static void jsonArrayStep(
|
| sqlite3_value **argv
|
| ){
|
| JsonString *pStr;
|
| + UNUSED_PARAM(argc);
|
| pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
|
| if( pStr ){
|
| if( pStr->zBuf==0 ){
|
| @@ -1548,7 +1613,7 @@ static void jsonArrayFinal(sqlite3_context *ctx){
|
| pStr->pCtx = ctx;
|
| jsonAppendChar(pStr, ']');
|
| if( pStr->bErr ){
|
| - sqlite3_result_error_nomem(ctx);
|
| + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
|
| assert( pStr->bStatic );
|
| }else{
|
| sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
|
| @@ -1574,6 +1639,7 @@ static void jsonObjectStep(
|
| JsonString *pStr;
|
| const char *z;
|
| u32 n;
|
| + UNUSED_PARAM(argc);
|
| pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
|
| if( pStr ){
|
| if( pStr->zBuf==0 ){
|
| @@ -1596,7 +1662,7 @@ static void jsonObjectFinal(sqlite3_context *ctx){
|
| if( pStr ){
|
| jsonAppendChar(pStr, '}');
|
| if( pStr->bErr ){
|
| - sqlite3_result_error_nomem(ctx);
|
| + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
|
| assert( pStr->bStatic );
|
| }else{
|
| sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
|
| @@ -1874,9 +1940,9 @@ static int jsonEachColumn(
|
| /* For json_each() path and root are the same so fall through
|
| ** into the root case */
|
| }
|
| - case JEACH_ROOT: {
|
| + default: {
|
| const char *zRoot = p->zRoot;
|
| - if( zRoot==0 ) zRoot = "$";
|
| + if( zRoot==0 ) zRoot = "$";
|
| sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC);
|
| break;
|
| }
|
| @@ -2095,6 +2161,7 @@ int sqlite3Json1Init(sqlite3 *db){
|
| { "json_extract", -1, 0, jsonExtractFunc },
|
| { "json_insert", -1, 0, jsonSetFunc },
|
| { "json_object", -1, 0, jsonObjectFunc },
|
| + { "json_quote", 1, 0, jsonQuoteFunc },
|
| { "json_remove", -1, 0, jsonRemoveFunc },
|
| { "json_replace", -1, 0, jsonReplaceFunc },
|
| { "json_set", -1, 1, jsonSetFunc },
|
|
|