aboutsummaryrefslogtreecommitdiff
path: root/ext/misc/json1.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2016-02-04 10:28:57 +0000
committerdrh <drh@noemail.net>2016-02-04 10:28:57 +0000
commit3b7f9a68d5172c215fe56dc5dc60378aec268820 (patch)
treed3d2a4483c1fbe5398194c44a4f32a60bef8579e /ext/misc/json1.c
parent6d258995e65e606f65b9189c409801c3da01f4ef (diff)
downloadsqlite-3b7f9a68d5172c215fe56dc5dc60378aec268820.tar.gz
sqlite-3b7f9a68d5172c215fe56dc5dc60378aec268820.zip
Escape control characters in JSON.
Fix for ticket [ad2559db380abf8]. FossilOrigin-Name: 4f1b5229a3bbc9d40b7433a5eb3139d59d31dcb1
Diffstat (limited to 'ext/misc/json1.c')
-rw-r--r--ext/misc/json1.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/ext/misc/json1.c b/ext/misc/json1.c
index 370751666..e4ea4fb9f 100644
--- a/ext/misc/json1.c
+++ b/ext/misc/json1.c
@@ -276,10 +276,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;
}