/ Check-in [6713e35b]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Avoid passing (signed char) values directly to isspace(), isalnum() or isdigit() in json1.c. Cast the value to (unsigned char) first.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6713e35b8a8c997aa2717e86ce6dcd63bb993477
User & Date: dan 2015-09-17 17:21:09
Context
2015-09-18
14:22
Remove a test made obsolete by the ONEPASS DELETE optimization. check-in: c88b62c2 user: drh tags: trunk
2015-09-17
17:21
Avoid passing (signed char) values directly to isspace(), isalnum() or isdigit() in json1.c. Cast the value to (unsigned char) first. check-in: 6713e35b user: dan tags: trunk
09:48
Fix a crash in FTS5 caused by specifying NULL as the rhs of a MATCH operator. check-in: e8ed62f8 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/json1.c.

    29     29   #include <string.h>
    30     30   #include <ctype.h>
    31     31   #include <stdlib.h>
    32     32   #include <stdarg.h>
    33     33   
    34     34   #define UNUSED_PARAM(X)  (void)(X)
    35     35   
           36  +/*
           37  +** Versions of isspace(), isalnum() and isdigit() to which it is safe
           38  +** to pass signed char values.
           39  +*/
           40  +#define safe_isspace(x) isspace((unsigned char)(x))
           41  +#define safe_isdigit(x) isdigit((unsigned char)(x))
           42  +#define safe_isalnum(x) isalnum((unsigned char)(x))
           43  +
    36     44   /* Unsigned integer types */
    37     45   typedef sqlite3_uint64 u64;
    38     46   typedef unsigned int u32;
    39     47   typedef unsigned char u8;
    40     48   
    41     49   /* Objects */
    42     50   typedef struct JsonString JsonString;
................................................................................
   581    589   */
   582    590   static int jsonParseValue(JsonParse *pParse, u32 i){
   583    591     char c;
   584    592     u32 j;
   585    593     int iThis;
   586    594     int x;
   587    595     JsonNode *pNode;
   588         -  while( isspace(pParse->zJson[i]) ){ i++; }
          596  +  while( safe_isspace(pParse->zJson[i]) ){ i++; }
   589    597     if( (c = pParse->zJson[i])==0 ) return 0;
   590    598     if( c=='{' ){
   591    599       /* Parse object */
   592    600       iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
   593    601       if( iThis<0 ) return -1;
   594    602       for(j=i+1;;j++){
   595         -      while( isspace(pParse->zJson[j]) ){ j++; }
          603  +      while( safe_isspace(pParse->zJson[j]) ){ j++; }
   596    604         x = jsonParseValue(pParse, j);
   597    605         if( x<0 ){
   598    606           if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
   599    607           return -1;
   600    608         }
   601    609         if( pParse->oom ) return -1;
   602    610         pNode = &pParse->aNode[pParse->nNode-1];
   603    611         if( pNode->eType!=JSON_STRING ) return -1;
   604    612         pNode->jnFlags |= JNODE_LABEL;
   605    613         j = x;
   606         -      while( isspace(pParse->zJson[j]) ){ j++; }
          614  +      while( safe_isspace(pParse->zJson[j]) ){ j++; }
   607    615         if( pParse->zJson[j]!=':' ) return -1;
   608    616         j++;
   609    617         x = jsonParseValue(pParse, j);
   610    618         if( x<0 ) return -1;
   611    619         j = x;
   612         -      while( isspace(pParse->zJson[j]) ){ j++; }
          620  +      while( safe_isspace(pParse->zJson[j]) ){ j++; }
   613    621         c = pParse->zJson[j];
   614    622         if( c==',' ) continue;
   615    623         if( c!='}' ) return -1;
   616    624         break;
   617    625       }
   618    626       pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
   619    627       return j+1;
   620    628     }else if( c=='[' ){
   621    629       /* Parse array */
   622    630       iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
   623    631       if( iThis<0 ) return -1;
   624    632       for(j=i+1;;j++){
   625         -      while( isspace(pParse->zJson[j]) ){ j++; }
          633  +      while( safe_isspace(pParse->zJson[j]) ){ j++; }
   626    634         x = jsonParseValue(pParse, j);
   627    635         if( x<0 ){
   628    636           if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
   629    637           return -1;
   630    638         }
   631    639         j = x;
   632         -      while( isspace(pParse->zJson[j]) ){ j++; }
          640  +      while( safe_isspace(pParse->zJson[j]) ){ j++; }
   633    641         c = pParse->zJson[j];
   634    642         if( c==',' ) continue;
   635    643         if( c!=']' ) return -1;
   636    644         break;
   637    645       }
   638    646       pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
   639    647       return j+1;
................................................................................
   654    662         j++;
   655    663       }
   656    664       jsonParseAddNode(pParse, JSON_STRING, j+1-i, &pParse->zJson[i]);
   657    665       if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags;
   658    666       return j+1;
   659    667     }else if( c=='n'
   660    668            && strncmp(pParse->zJson+i,"null",4)==0
   661         -         && !isalnum(pParse->zJson[i+4]) ){
          669  +         && !safe_isalnum(pParse->zJson[i+4]) ){
   662    670       jsonParseAddNode(pParse, JSON_NULL, 0, 0);
   663    671       return i+4;
   664    672     }else if( c=='t'
   665    673            && strncmp(pParse->zJson+i,"true",4)==0
   666         -         && !isalnum(pParse->zJson[i+4]) ){
          674  +         && !safe_isalnum(pParse->zJson[i+4]) ){
   667    675       jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
   668    676       return i+4;
   669    677     }else if( c=='f'
   670    678            && strncmp(pParse->zJson+i,"false",5)==0
   671         -         && !isalnum(pParse->zJson[i+5]) ){
          679  +         && !safe_isalnum(pParse->zJson[i+5]) ){
   672    680       jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
   673    681       return i+5;
   674    682     }else if( c=='-' || (c>='0' && c<='9') ){
   675    683       /* Parse number */
   676    684       u8 seenDP = 0;
   677    685       u8 seenE = 0;
   678    686       j = i+1;
................................................................................
   727    735     int i;
   728    736     memset(pParse, 0, sizeof(*pParse));
   729    737     if( zJson==0 ) return 1;
   730    738     pParse->zJson = zJson;
   731    739     i = jsonParseValue(pParse, 0);
   732    740     if( pParse->oom ) i = -1;
   733    741     if( i>0 ){
   734         -    while( isspace(zJson[i]) ) i++;
          742  +    while( safe_isspace(zJson[i]) ) i++;
   735    743       if( zJson[i] ) i = -1;
   736    744     }
   737    745     if( i<=0 ){
   738    746       if( pCtx!=0 ){
   739    747         if( pParse->oom ){
   740    748           sqlite3_result_error_nomem(pCtx);
   741    749         }else{
................................................................................
   858    866           pRoot = &pParse->aNode[iRoot];
   859    867           pRoot->u.iAppend = iStart - iRoot;
   860    868           pRoot->jnFlags |= JNODE_APPEND;
   861    869           pParse->aNode[iLabel].jnFlags |= JNODE_RAW;
   862    870         }
   863    871         return pNode;
   864    872       }
   865         -  }else if( zPath[0]=='[' && isdigit(zPath[1]) ){
          873  +  }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){
   866    874       if( pRoot->eType!=JSON_ARRAY ) return 0;
   867    875       i = 0;
   868    876       zPath++;
   869         -    while( isdigit(zPath[0]) ){
          877  +    while( safe_isdigit(zPath[0]) ){
   870    878         i = i*10 + zPath[0] - '0';
   871    879         zPath++;
   872    880       }
   873    881       if( zPath[0]!=']' ){
   874    882         *pzErr = zPath;
   875    883         return 0;
   876    884       }

Changes to test/json102.test.

   273    273   do_execsql_test json102-1132 {
   274    274     SELECT DISTINCT json_extract(big.json,'$.id')
   275    275       FROM big, json_tree(big.json)
   276    276      WHERE json_tree.key='uuid'
   277    277        AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';
   278    278   } {123}
   279    279   } ;# end ifcapable vtab
          280  +
          281  +#-------------------------------------------------------------------------
          282  +# Test that json_valid() correctly identifies non-ascii range 
          283  +# characters as non-whitespace.
          284  +#
          285  +do_execsql_test json102-1201 { SELECT json_valid(char(32)  || '"xyz"') } 1
          286  +do_execsql_test json102-1202 { SELECT json_valid(char(200) || '"xyz"') } 0
   280    287   
   281    288   finish_test