[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#864088: marked as done (unblock (pre-approval): sqlite3/3.6.12-4)



Your message dated Mon, 05 Jun 2017 19:27:09 +0000
with message-id <E1dHxef-0008RW-Oo@respighi.debian.org>
and subject line unblock sqlite3
has caused the Debian Bug report #864088,
regarding unblock (pre-approval): sqlite3/3.6.12-4
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
864088: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=864088
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
User: release.debian.org@packages.debian.org
Usertags: unblock

Hi Release Team,

I would like to upload a security related update for sqlite3. It contains:
- Prevent a possible NULL pointer dereference in the OP_Found opcode
that can follow an OOM error. Problem found by OSS-Fuzz[1],
- Stack overflow while parsing deeply nested JSON[2],
- JSON allows unescaped control characters in strings[3],
- JSON extension accepts invalid numeric values[4].

Upstream tagged these as 'code defect' and severity 'severe'. The
changes itself are small and the 3.19.2-1 version in experimental
contains these fixes.

Debdiff is attached. Thanks for consideration.

Regards,
Laszlo/GCS
[1] http://www.sqlite.org/src/info/c2de178fe7e2e4e0
[2] https://www.sqlite.org/src/info/981329adeef51011052
[3] https://www.sqlite.org/src/info/6c9b5514077fed34551
[4] https://www.sqlite.org/src/info/b93be8729a895a528e2
diff -Nru sqlite3-3.16.2/debian/changelog sqlite3-3.16.2/debian/changelog
--- sqlite3-3.16.2/debian/changelog	2017-02-13 17:31:26.000000000 +0000
+++ sqlite3-3.16.2/debian/changelog	2017-06-04 07:58:54.000000000 +0000
@@ -1,3 +1,13 @@
+sqlite3 (3.16.2-4) unstable; urgency=high
+
+  * Backport fix for a possible NULL pointer dereference in the OP_Found
+    opcode that can follow an OOM error.
+  * Backport fix for stack overflow while parsing deeply nested JSON.
+  * Backport fix for JSON allows unescaped control characters in strings.
+  * Backport fix for JSON extension accepts invalid numeric values.
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.org>  Sun, 04 Jun 2017 07:58:54 +0000
+
 sqlite3 (3.16.2-3) unstable; urgency=medium
 
   * Backport upstream fix to ensure that sqlite3_blob_reopen() correctly
diff -Nru sqlite3-3.16.2/debian/patches/36-OSS-Fuzz.patch sqlite3-3.16.2/debian/patches/36-OSS-Fuzz.patch
--- sqlite3-3.16.2/debian/patches/36-OSS-Fuzz.patch	1970-01-01 00:00:00.000000000 +0000
+++ sqlite3-3.16.2/debian/patches/36-OSS-Fuzz.patch	2017-06-04 07:58:54.000000000 +0000
@@ -0,0 +1,24 @@
+Index: sqlite3/src/vdbe.c
+==================================================================
+--- sqlite3/src/vdbe.c
++++ sqlite3/src/vdbe.c
+@@ -4017,14 +4017,16 @@
+     }
+ #endif
+     pIdxKey = &r;
+     pFree = 0;
+   }else{
++    assert( pIn3->flags & MEM_Blob );
++    rc = ExpandBlob(pIn3);
++    assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
++    if( rc ) goto no_mem;
+     pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
+     if( pIdxKey==0 ) goto no_mem;
+-    assert( pIn3->flags & MEM_Blob );
+-    (void)ExpandBlob(pIn3);
+     sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
+   }
+   pIdxKey->default_rc = 0;
+   takeJump = 0;
+   if( pOp->opcode==OP_NoConflict ){
+
diff -Nru sqlite3-3.16.2/debian/patches/40-JSON-1.patch sqlite3-3.16.2/debian/patches/40-JSON-1.patch
--- sqlite3-3.16.2/debian/patches/40-JSON-1.patch	1970-01-01 00:00:00.000000000 +0000
+++ sqlite3-3.16.2/debian/patches/40-JSON-1.patch	2017-06-04 07:58:54.000000000 +0000
@@ -0,0 +1,205 @@
+Index: sqlite3/ext/misc/json1.c
+==================================================================
+--- sqlite3/ext/misc/json1.c
++++ sqlite3/ext/misc/json1.c
+@@ -726,17 +726,18 @@
+   char c;
+   u32 j;
+   int iThis;
+   int x;
+   JsonNode *pNode;
+-  while( safe_isspace(pParse->zJson[i]) ){ i++; }
+-  if( (c = pParse->zJson[i])=='{' ){
++  const char *z = pParse->zJson;
++  while( safe_isspace(z[i]) ){ i++; }
++  if( (c = z[i])=='{' ){
+     /* Parse object */
+     iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
+     if( iThis<0 ) return -1;
+     for(j=i+1;;j++){
+-      while( safe_isspace(pParse->zJson[j]) ){ j++; }
++      while( safe_isspace(z[j]) ){ j++; }
+       x = jsonParseValue(pParse, j);
+       if( x<0 ){
+         if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
+         return -1;
+       }
+@@ -743,18 +744,18 @@
+       if( pParse->oom ) return -1;
+       pNode = &pParse->aNode[pParse->nNode-1];
+       if( pNode->eType!=JSON_STRING ) return -1;
+       pNode->jnFlags |= JNODE_LABEL;
+       j = x;
+-      while( safe_isspace(pParse->zJson[j]) ){ j++; }
+-      if( pParse->zJson[j]!=':' ) return -1;
++      while( safe_isspace(z[j]) ){ j++; }
++      if( z[j]!=':' ) return -1;
+       j++;
+       x = jsonParseValue(pParse, j);
+       if( x<0 ) return -1;
+       j = x;
+-      while( safe_isspace(pParse->zJson[j]) ){ j++; }
+-      c = pParse->zJson[j];
++      while( safe_isspace(z[j]) ){ j++; }
++      c = z[j];
+       if( c==',' ) continue;
+       if( c!='}' ) return -1;
+       break;
+     }
+     pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
+@@ -762,19 +763,19 @@
+   }else if( c=='[' ){
+     /* Parse array */
+     iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
+     if( iThis<0 ) return -1;
+     for(j=i+1;;j++){
+-      while( safe_isspace(pParse->zJson[j]) ){ j++; }
++      while( safe_isspace(z[j]) ){ j++; }
+       x = jsonParseValue(pParse, j);
+       if( x<0 ){
+         if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
+         return -1;
+       }
+       j = x;
+-      while( safe_isspace(pParse->zJson[j]) ){ j++; }
+-      c = pParse->zJson[j];
++      while( safe_isspace(z[j]) ){ j++; }
++      c = z[j];
+       if( c==',' ) continue;
+       if( c!=']' ) return -1;
+       break;
+     }
+     pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
+@@ -782,75 +783,80 @@
+   }else if( c=='"' ){
+     /* Parse string */
+     u8 jnFlags = 0;
+     j = i+1;
+     for(;;){
+-      c = pParse->zJson[j];
++      c = z[j];
+       if( c==0 ) return -1;
+       if( c=='\\' ){
+-        c = pParse->zJson[++j];
++        c = z[++j];
+         if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
+            || c=='n' || c=='r' || c=='t'
+-           || (c=='u' && jsonIs4Hex(pParse->zJson+j+1)) ){
++           || (c=='u' && jsonIs4Hex(z+j+1)) ){
+           jnFlags = JNODE_ESCAPE;
+         }else{
+           return -1;
+         }
+       }else if( c=='"' ){
+         break;
+       }
+       j++;
+     }
+-    jsonParseAddNode(pParse, JSON_STRING, j+1-i, &pParse->zJson[i]);
++    jsonParseAddNode(pParse, JSON_STRING, j+1-i, &z[i]);
+     if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags;
+     return j+1;
+   }else if( c=='n'
+-         && strncmp(pParse->zJson+i,"null",4)==0
+-         && !safe_isalnum(pParse->zJson[i+4]) ){
++         && strncmp(z+i,"null",4)==0
++         && !safe_isalnum(z[i+4]) ){
+     jsonParseAddNode(pParse, JSON_NULL, 0, 0);
+     return i+4;
+   }else if( c=='t'
+-         && strncmp(pParse->zJson+i,"true",4)==0
+-         && !safe_isalnum(pParse->zJson[i+4]) ){
++         && strncmp(z+i,"true",4)==0
++         && !safe_isalnum(z[i+4]) ){
+     jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
+     return i+4;
+   }else if( c=='f'
+-         && strncmp(pParse->zJson+i,"false",5)==0
+-         && !safe_isalnum(pParse->zJson[i+5]) ){
++         && strncmp(z+i,"false",5)==0
++         && !safe_isalnum(z[i+5]) ){
+     jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
+     return i+5;
+   }else if( c=='-' || (c>='0' && c<='9') ){
+     /* Parse number */
+     u8 seenDP = 0;
+     u8 seenE = 0;
++    assert( '-' < '0' );
++    if( c<='0' ){
++      j = c=='-' ? i+1 : i;
++      if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return -1;
++    }
+     j = i+1;
+     for(;; j++){
+-      c = pParse->zJson[j];
++      c = z[j];
+       if( c>='0' && c<='9' ) continue;
+       if( c=='.' ){
+-        if( pParse->zJson[j-1]=='-' ) return -1;
++        if( z[j-1]=='-' ) return -1;
+         if( seenDP ) return -1;
+         seenDP = 1;
+         continue;
+       }
+       if( c=='e' || c=='E' ){
+-        if( pParse->zJson[j-1]<'0' ) return -1;
++        if( z[j-1]<'0' ) return -1;
+         if( seenE ) return -1;
+         seenDP = seenE = 1;
+-        c = pParse->zJson[j+1];
++        c = z[j+1];
+         if( c=='+' || c=='-' ){
+           j++;
+-          c = pParse->zJson[j+1];
++          c = z[j+1];
+         }
+         if( c<'0' || c>'9' ) return -1;
+         continue;
+       }
+       break;
+     }
+-    if( pParse->zJson[j-1]<'0' ) return -1;
++    if( z[j-1]<'0' ) return -1;
+     jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT,
+-                        j - i, &pParse->zJson[i]);
++                        j - i, &z[i]);
+     return j;
+   }else if( c=='}' ){
+     return -2;  /* End of {...} */
+   }else if( c==']' ){
+     return -3;  /* End of [...] */
+
+Index: sqlite3/test/json102.test
+==================================================================
+--- sqlite3/test/json102.test
++++ sqlite3/test/json102.test
+@@ -295,7 +295,28 @@
+   set str abcdef[string repeat \" [expr {$i+50}]]uvwxyz
+   do_test json102-[format %d [expr {$i+1300}]] {
+     db eval {SELECT json_extract(json_array($::str),'$[0]')==$::str}
+   } {1}
+ }
++
++#-------------------------------------------------------------------------
++# 2017-04-08 ticket b93be8729a895a528e2849fca99f7
++# JSON extension accepts invalid numeric values
++#
++# JSON does not allow leading zeros.  But the JSON extension was
++# allowing them.  The following tests verify that the problem is now
++# fixed.
++#
++do_execsql_test json102-1401 { SELECT json_valid('{"x":01}') } 0
++do_execsql_test json102-1402 { SELECT json_valid('{"x":-01}') } 0
++do_execsql_test json102-1403 { SELECT json_valid('{"x":0}') } 1
++do_execsql_test json102-1404 { SELECT json_valid('{"x":-0}') } 1
++do_execsql_test json102-1405 { SELECT json_valid('{"x":0.1}') } 1
++do_execsql_test json102-1406 { SELECT json_valid('{"x":-0.1}') } 1
++do_execsql_test json102-1407 { SELECT json_valid('{"x":0.0000}') } 1
++do_execsql_test json102-1408 { SELECT json_valid('{"x":-0.0000}') } 1
++do_execsql_test json102-1409 { SELECT json_valid('{"x":01.5}') } 0
++do_execsql_test json102-1410 { SELECT json_valid('{"x":-01.5}') } 0
++do_execsql_test json102-1411 { SELECT json_valid('{"x":00}') } 0
++do_execsql_test json102-1412 { SELECT json_valid('{"x":-00}') } 0
+ 
+ finish_test
+
diff -Nru sqlite3-3.16.2/debian/patches/41-JSON-2_1.patch sqlite3-3.16.2/debian/patches/41-JSON-2_1.patch
--- sqlite3-3.16.2/debian/patches/41-JSON-2_1.patch	1970-01-01 00:00:00.000000000 +0000
+++ sqlite3-3.16.2/debian/patches/41-JSON-2_1.patch	2017-06-04 07:58:54.000000000 +0000
@@ -0,0 +1,42 @@
+Index: sqlite3/ext/misc/json1.c
+==================================================================
+--- sqlite3/ext/misc/json1.c
++++ sqlite3/ext/misc/json1.c
+@@ -784,11 +784,11 @@
+     /* Parse string */
+     u8 jnFlags = 0;
+     j = i+1;
+     for(;;){
+       c = z[j];
+-      if( c==0 ) return -1;
++      if( c<=0x1f ) return -1;  /* Control characters not allowed in strings */
+       if( c=='\\' ){
+         c = z[++j];
+         if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
+            || c=='n' || c=='r' || c=='t'
+            || (c=='u' && jsonIs4Hex(z+j+1)) ){
+
+Index: sqlite3/test/json102.test
+==================================================================
+--- sqlite3/test/json102.test
++++ sqlite3/test/json102.test
+@@ -316,7 +316,18 @@
+ do_execsql_test json102-1408 { SELECT json_valid('{"x":-0.0000}') } 1
+ do_execsql_test json102-1409 { SELECT json_valid('{"x":01.5}') } 0
+ do_execsql_test json102-1410 { SELECT json_valid('{"x":-01.5}') } 0
+ do_execsql_test json102-1411 { SELECT json_valid('{"x":00}') } 0
+ do_execsql_test json102-1412 { SELECT json_valid('{"x":-00}') } 0
++
++#------------------------------------------------------------------------
++# 2017-04-10 ticket 6c9b5514077fed34551f98e64c09a10dc2fc8e16
++# JSON extension accepts strings containing control characters.
++#
++# The JSON spec requires that all control characters be escaped.
++#
++do_execsql_test json102-1500 {
++  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<0x20)
++  SELECT x FROM c WHERE json_valid(printf('{"a":"x%sz"}', char(x))) ORDER BY x;
++} {32}
+ 
+ finish_test
+
diff -Nru sqlite3-3.16.2/debian/patches/42-JSON-2_2.patch sqlite3-3.16.2/debian/patches/42-JSON-2_2.patch
--- sqlite3-3.16.2/debian/patches/42-JSON-2_2.patch	1970-01-01 00:00:00.000000000 +0000
+++ sqlite3-3.16.2/debian/patches/42-JSON-2_2.patch	2017-06-04 07:58:54.000000000 +0000
@@ -0,0 +1,46 @@
+Index: sqlite3/ext/misc/json1.c
+==================================================================
+--- sqlite3/ext/misc/json1.c
++++ sqlite3/ext/misc/json1.c
+@@ -784,11 +784,14 @@
+     /* Parse string */
+     u8 jnFlags = 0;
+     j = i+1;
+     for(;;){
+       c = z[j];
+-      if( c<=0x1f ) return -1;  /* Control characters not allowed in strings */
++      if( (c & ~0x1f)==0 ){
++        /* Control characters are not allowed in strings */
++        return -1;
++      }
+       if( c=='\\' ){
+         c = z[++j];
+         if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
+            || c=='n' || c=='r' || c=='t'
+            || (c=='u' && jsonIs4Hex(z+j+1)) ){
+
+Index: sqlite3/test/json101.test
+==================================================================
+--- sqlite3/test/json101.test
++++ sqlite3/test/json101.test
+@@ -353,10 +353,19 @@
+   SELECT b FROM t8;
+ } {{["abc\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#xyz"]}}
+ do_execsql_test json-8.2 {
+   SELECT a=json_extract(b,'$[0]') FROM t8;
+ } {1}
++
++# 2017-04-12.  Regression reported on the mailing list by Rolf Ade
++#
++do_execsql_test json-8.3 {
++  SELECT json_valid(char(0x22,0xe4,0x22));
++} {1}
++do_execsql_test json-8.4 {
++  SELECT unicode(json_extract(char(0x22,228,0x22),'$'));
++} {228}
+ 
+ # The json_quote() function transforms an SQL value into a JSON value.
+ # String values are quoted and interior quotes are escaped.  NULL values
+ # are rendered as the unquoted string "null".
+ #
+
diff -Nru sqlite3-3.16.2/debian/patches/43-JSON-3.patch sqlite3-3.16.2/debian/patches/43-JSON-3.patch
--- sqlite3-3.16.2/debian/patches/43-JSON-3.patch	1970-01-01 00:00:00.000000000 +0000
+++ sqlite3-3.16.2/debian/patches/43-JSON-3.patch	2017-06-04 07:58:54.000000000 +0000
@@ -0,0 +1,130 @@
+Index: sqlite3/ext/misc/json1.c
+==================================================================
+--- sqlite3/ext/misc/json1.c
++++ sqlite3/ext/misc/json1.c
+@@ -88,10 +88,11 @@
+ #ifndef SQLITE_AMALGAMATION
+   /* Unsigned integer types.  These are already defined in the sqliteInt.h,
+   ** but the definitions need to be repeated for separate compilation. */
+   typedef sqlite3_uint64 u64;
+   typedef unsigned int u32;
++  typedef unsigned short int u16;
+   typedef unsigned char u8;
+ #endif
+ 
+ /* Objects */
+ typedef struct JsonString JsonString;
+@@ -165,12 +166,22 @@
+   JsonNode *aNode;   /* Array of nodes containing the parse */
+   const char *zJson; /* Original JSON string */
+   u32 *aUp;          /* Index of parent of each node */
+   u8 oom;            /* Set to true if out of memory */
+   u8 nErr;           /* Number of errors seen */
++  u16 iDepth;        /* Nesting depth */
+ };
+ 
++/*
++** Maximum nesting depth of JSON for this implementation.
++**
++** This limit is needed to avoid a stack overflow in the recursive
++** descent parser.  A depth of 2000 is far deeper than any sane JSON
++** should go.
++*/
++#define JSON_MAX_DEPTH  2000
++
+ /**************************************************************************
+ ** Utility routines for dealing with JsonString objects
+ **************************************************************************/
+ 
+ /* Set the JsonString object to an empty string
+@@ -734,12 +745,14 @@
+     /* Parse object */
+     iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
+     if( iThis<0 ) return -1;
+     for(j=i+1;;j++){
+       while( safe_isspace(z[j]) ){ j++; }
++      if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
+       x = jsonParseValue(pParse, j);
+       if( x<0 ){
++        pParse->iDepth--;
+         if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
+         return -1;
+       }
+       if( pParse->oom ) return -1;
+       pNode = &pParse->aNode[pParse->nNode-1];
+@@ -748,10 +761,11 @@
+       j = x;
+       while( safe_isspace(z[j]) ){ j++; }
+       if( z[j]!=':' ) return -1;
+       j++;
+       x = jsonParseValue(pParse, j);
++      pParse->iDepth--;
+       if( x<0 ) return -1;
+       j = x;
+       while( safe_isspace(z[j]) ){ j++; }
+       c = z[j];
+       if( c==',' ) continue;
+@@ -764,11 +778,13 @@
+     /* Parse array */
+     iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
+     if( iThis<0 ) return -1;
+     for(j=i+1;;j++){
+       while( safe_isspace(z[j]) ){ j++; }
++      if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
+       x = jsonParseValue(pParse, j);
++      pParse->iDepth--;
+       if( x<0 ){
+         if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
+         return -1;
+       }
+       j = x;
+@@ -887,10 +903,11 @@
+   if( zJson==0 ) return 1;
+   pParse->zJson = zJson;
+   i = jsonParseValue(pParse, 0);
+   if( pParse->oom ) i = -1;
+   if( i>0 ){
++    assert( pParse->iDepth==0 );
+     while( safe_isspace(zJson[i]) ) i++;
+     if( zJson[i] ) i = -1;
+   }
+   if( i<=0 ){
+     if( pCtx!=0 ){
+
+Index: sqlite3/test/json101.test
+==================================================================
+--- sqlite3/test/json101.test
++++ sqlite3/test/json101.test
+@@ -695,7 +695,31 @@
+ } {0}
+ do_execsql_test json-10.95 {
+   SELECT json_valid('" \~ "');
+ } {0}
+ 
++#--------------------------------------------------------------------------
++# 2017-04-11.  https://www.sqlite.org/src/info/981329adeef51011
++# Stack overflow on deeply nested JSON.
++#
++# The following tests confirm that deeply nested JSON is considered invalid.
++#
++do_execsql_test json-11.0 {
++  /* Shallow enough to be parsed */
++  SELECT json_valid(printf('%.2000c0%.2000c','[',']'));
++} {1}
++do_execsql_test json-11.1 {
++  /* Too deep by one */
++  SELECT json_valid(printf('%.2001c0%.2001c','[',']'));
++} {0}
++do_execsql_test json-11.2 {
++  /* Shallow enough to be parsed { */
++  SELECT json_valid(replace(printf('%.2000c0%.2000c','[','}'),'[','{"a":'));
++  /* } */
++} {1}
++do_execsql_test json-11.3 {
++  /* Too deep by one { */
++  SELECT json_valid(replace(printf('%.2001c0%.2001c','[','}'),'[','{"a":'));
++  /* } */
++} {0}
+ 
+ finish_test
+
diff -Nru sqlite3-3.16.2/debian/patches/series sqlite3-3.16.2/debian/patches/series
--- sqlite3-3.16.2/debian/patches/series	2017-02-13 17:31:26.000000000 +0000
+++ sqlite3-3.16.2/debian/patches/series	2017-06-04 07:58:54.000000000 +0000
@@ -7,3 +7,8 @@
 02-use-packaged-lempar.c.patch
 32-fix_an_uninitialized_variable_in_the_command-line_shell.patch
 35-fix-sqlite3_blob_reopen.patch
+36-OSS-Fuzz.patch
+40-JSON-1.patch
+41-JSON-2_1.patch
+42-JSON-2_2.patch
+43-JSON-3.patch

--- End Message ---
--- Begin Message ---
Unblocked sqlite3.

--- End Message ---

Reply to: