/ Check-in [204e72f0]
Login

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

Overview
Comment:Disallow leading zeros on numeric constants in JSON. Fix for ticket [b93be8729a895a528e2]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 204e72f0080e8f08f99978870bd3cb9d59b068ecffee82192d707c650548b43b
User & Date: drh 2017-04-08 18:18:22
Context
2017-04-09
19:23
Do not expose the name of the internal Mem object in the public interface defined by sqlite3.h. check-in: 19dd753f user: drh tags: trunk
2017-04-08
19:00
Merge latest trunk with this branch. check-in: e051e8f2 user: dan tags: schemalint
18:24
Merge all recent changes from trunk. check-in: c23ef5e2 user: drh tags: apple-osx
18:18
Disallow leading zeros on numeric constants in JSON. Fix for ticket [b93be8729a895a528e2] check-in: 204e72f0 user: drh tags: trunk
14:11
Expand on the comment above OP_Destroy to explain why it throws an error if there are any active reader VMs. check-in: b9a8c2b9 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/json1.c.

   723    723   */
   724    724   static int jsonParseValue(JsonParse *pParse, u32 i){
   725    725     char c;
   726    726     u32 j;
   727    727     int iThis;
   728    728     int x;
   729    729     JsonNode *pNode;
   730         -  while( safe_isspace(pParse->zJson[i]) ){ i++; }
   731         -  if( (c = pParse->zJson[i])=='{' ){
          730  +  const char *z = pParse->zJson;
          731  +  while( safe_isspace(z[i]) ){ i++; }
          732  +  if( (c = z[i])=='{' ){
   732    733       /* Parse object */
   733    734       iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
   734    735       if( iThis<0 ) return -1;
   735    736       for(j=i+1;;j++){
   736         -      while( safe_isspace(pParse->zJson[j]) ){ j++; }
          737  +      while( safe_isspace(z[j]) ){ j++; }
   737    738         x = jsonParseValue(pParse, j);
   738    739         if( x<0 ){
   739    740           if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
   740    741           return -1;
   741    742         }
   742    743         if( pParse->oom ) return -1;
   743    744         pNode = &pParse->aNode[pParse->nNode-1];
   744    745         if( pNode->eType!=JSON_STRING ) return -1;
   745    746         pNode->jnFlags |= JNODE_LABEL;
   746    747         j = x;
   747         -      while( safe_isspace(pParse->zJson[j]) ){ j++; }
   748         -      if( pParse->zJson[j]!=':' ) return -1;
          748  +      while( safe_isspace(z[j]) ){ j++; }
          749  +      if( z[j]!=':' ) return -1;
   749    750         j++;
   750    751         x = jsonParseValue(pParse, j);
   751    752         if( x<0 ) return -1;
   752    753         j = x;
   753         -      while( safe_isspace(pParse->zJson[j]) ){ j++; }
   754         -      c = pParse->zJson[j];
          754  +      while( safe_isspace(z[j]) ){ j++; }
          755  +      c = z[j];
   755    756         if( c==',' ) continue;
   756    757         if( c!='}' ) return -1;
   757    758         break;
   758    759       }
   759    760       pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
   760    761       return j+1;
   761    762     }else if( c=='[' ){
   762    763       /* Parse array */
   763    764       iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
   764    765       if( iThis<0 ) return -1;
   765    766       for(j=i+1;;j++){
   766         -      while( safe_isspace(pParse->zJson[j]) ){ j++; }
          767  +      while( safe_isspace(z[j]) ){ j++; }
   767    768         x = jsonParseValue(pParse, j);
   768    769         if( x<0 ){
   769    770           if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
   770    771           return -1;
   771    772         }
   772    773         j = x;
   773         -      while( safe_isspace(pParse->zJson[j]) ){ j++; }
   774         -      c = pParse->zJson[j];
          774  +      while( safe_isspace(z[j]) ){ j++; }
          775  +      c = z[j];
   775    776         if( c==',' ) continue;
   776    777         if( c!=']' ) return -1;
   777    778         break;
   778    779       }
   779    780       pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
   780    781       return j+1;
   781    782     }else if( c=='"' ){
   782    783       /* Parse string */
   783    784       u8 jnFlags = 0;
   784    785       j = i+1;
   785    786       for(;;){
   786         -      c = pParse->zJson[j];
          787  +      c = z[j];
   787    788         if( c==0 ) return -1;
   788    789         if( c=='\\' ){
   789         -        c = pParse->zJson[++j];
          790  +        c = z[++j];
   790    791           if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
   791    792              || c=='n' || c=='r' || c=='t'
   792         -           || (c=='u' && jsonIs4Hex(pParse->zJson+j+1)) ){
          793  +           || (c=='u' && jsonIs4Hex(z+j+1)) ){
   793    794             jnFlags = JNODE_ESCAPE;
   794    795           }else{
   795    796             return -1;
   796    797           }
   797    798         }else if( c=='"' ){
   798    799           break;
   799    800         }
   800    801         j++;
   801    802       }
   802         -    jsonParseAddNode(pParse, JSON_STRING, j+1-i, &pParse->zJson[i]);
          803  +    jsonParseAddNode(pParse, JSON_STRING, j+1-i, &z[i]);
   803    804       if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags;
   804    805       return j+1;
   805    806     }else if( c=='n'
   806         -         && strncmp(pParse->zJson+i,"null",4)==0
   807         -         && !safe_isalnum(pParse->zJson[i+4]) ){
          807  +         && strncmp(z+i,"null",4)==0
          808  +         && !safe_isalnum(z[i+4]) ){
   808    809       jsonParseAddNode(pParse, JSON_NULL, 0, 0);
   809    810       return i+4;
   810    811     }else if( c=='t'
   811         -         && strncmp(pParse->zJson+i,"true",4)==0
   812         -         && !safe_isalnum(pParse->zJson[i+4]) ){
          812  +         && strncmp(z+i,"true",4)==0
          813  +         && !safe_isalnum(z[i+4]) ){
   813    814       jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
   814    815       return i+4;
   815    816     }else if( c=='f'
   816         -         && strncmp(pParse->zJson+i,"false",5)==0
   817         -         && !safe_isalnum(pParse->zJson[i+5]) ){
          817  +         && strncmp(z+i,"false",5)==0
          818  +         && !safe_isalnum(z[i+5]) ){
   818    819       jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
   819    820       return i+5;
   820    821     }else if( c=='-' || (c>='0' && c<='9') ){
   821    822       /* Parse number */
   822    823       u8 seenDP = 0;
   823    824       u8 seenE = 0;
          825  +    assert( '-' < '0' );
          826  +    if( c<='0' ){
          827  +      j = c=='-' ? i+1 : i;
          828  +      if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return -1;
          829  +    }
   824    830       j = i+1;
   825    831       for(;; j++){
   826         -      c = pParse->zJson[j];
          832  +      c = z[j];
   827    833         if( c>='0' && c<='9' ) continue;
   828    834         if( c=='.' ){
   829         -        if( pParse->zJson[j-1]=='-' ) return -1;
          835  +        if( z[j-1]=='-' ) return -1;
   830    836           if( seenDP ) return -1;
   831    837           seenDP = 1;
   832    838           continue;
   833    839         }
   834    840         if( c=='e' || c=='E' ){
   835         -        if( pParse->zJson[j-1]<'0' ) return -1;
          841  +        if( z[j-1]<'0' ) return -1;
   836    842           if( seenE ) return -1;
   837    843           seenDP = seenE = 1;
   838         -        c = pParse->zJson[j+1];
          844  +        c = z[j+1];
   839    845           if( c=='+' || c=='-' ){
   840    846             j++;
   841         -          c = pParse->zJson[j+1];
          847  +          c = z[j+1];
   842    848           }
   843    849           if( c<'0' || c>'9' ) return -1;
   844    850           continue;
   845    851         }
   846    852         break;
   847    853       }
   848         -    if( pParse->zJson[j-1]<'0' ) return -1;
          854  +    if( z[j-1]<'0' ) return -1;
   849    855       jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT,
   850         -                        j - i, &pParse->zJson[i]);
          856  +                        j - i, &z[i]);
   851    857       return j;
   852    858     }else if( c=='}' ){
   853    859       return -2;  /* End of {...} */
   854    860     }else if( c==']' ){
   855    861       return -3;  /* End of [...] */
   856    862     }else if( c==0 ){
   857    863       return 0;   /* End of file */

Changes to test/json102.test.

   293    293   #
   294    294   for {set i 0} {$i<100} {incr i} {
   295    295     set str abcdef[string repeat \" [expr {$i+50}]]uvwxyz
   296    296     do_test json102-[format %d [expr {$i+1300}]] {
   297    297       db eval {SELECT json_extract(json_array($::str),'$[0]')==$::str}
   298    298     } {1}
   299    299   }
          300  +
          301  +#-------------------------------------------------------------------------
          302  +# 2017-04-08 ticket b93be8729a895a528e2849fca99f7
          303  +# JSON extension accepts invalid numeric values
          304  +#
          305  +# JSON does not allow leading zeros.  But the JSON extension was
          306  +# allowing them.  The following tests verify that the problem is now
          307  +# fixed.
          308  +#
          309  +do_execsql_test json102-1401 { SELECT json_valid('{"x":01}') } 0
          310  +do_execsql_test json102-1402 { SELECT json_valid('{"x":-01}') } 0
          311  +do_execsql_test json102-1403 { SELECT json_valid('{"x":0}') } 1
          312  +do_execsql_test json102-1404 { SELECT json_valid('{"x":-0}') } 1
          313  +do_execsql_test json102-1405 { SELECT json_valid('{"x":0.1}') } 1
          314  +do_execsql_test json102-1406 { SELECT json_valid('{"x":-0.1}') } 1
          315  +do_execsql_test json102-1407 { SELECT json_valid('{"x":0.0000}') } 1
          316  +do_execsql_test json102-1408 { SELECT json_valid('{"x":-0.0000}') } 1
          317  +do_execsql_test json102-1409 { SELECT json_valid('{"x":01.5}') } 0
          318  +do_execsql_test json102-1410 { SELECT json_valid('{"x":-01.5}') } 0
          319  +do_execsql_test json102-1411 { SELECT json_valid('{"x":00}') } 0
          320  +do_execsql_test json102-1412 { SELECT json_valid('{"x":-00}') } 0
   300    321   
   301    322   finish_test