1
1
'use strict'
2
2
3
3
const test = require ( 'tape' ) . test
4
- const j = require ( './index ' )
4
+ const j = require ( '.. ' )
5
5
6
6
test ( 'parse' , t => {
7
7
t . test ( 'parses object string' , t => {
@@ -324,40 +324,82 @@ test('parse', t => {
324
324
t . end ( )
325
325
} )
326
326
327
- t . end ( )
328
- } )
329
-
330
- test ( 'scan' , t => {
331
327
t . test ( 'sanitizes nested object string' , t => {
332
328
const text = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
333
- const obj = JSON . parse ( text )
334
329
335
- j . scan ( obj , { protoAction : 'remove' } )
330
+ const obj = j . parse ( text , { protoAction : 'remove' } )
336
331
t . deepEqual ( obj , { a : 5 , b : 6 , c : { d : 0 , e : 'text' , f : { g : 2 } } } )
337
332
t . end ( )
338
333
} )
339
334
335
+ t . test ( 'errors on constructor property' , t => {
336
+ const text = '{ "a": 5, "b": 6, "constructor": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
337
+
338
+ t . throws ( ( ) => j . parse ( text ) , SyntaxError )
339
+ t . end ( )
340
+ } )
341
+
340
342
t . test ( 'errors on proto property' , t => {
341
343
const text = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
342
- const obj = JSON . parse ( text )
343
344
344
- t . throws ( ( ) => j . scan ( obj ) , SyntaxError )
345
+ t . throws ( ( ) => j . parse ( text ) , SyntaxError )
346
+ t . end ( )
347
+ } )
348
+
349
+ t . test ( 'errors on constructor property' , t => {
350
+ const text = '{ "a": 5, "b": 6, "constructor": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
351
+
352
+ t . throws ( ( ) => j . parse ( text ) , SyntaxError )
345
353
t . end ( )
346
354
} )
347
355
348
356
t . test ( 'does not break when hasOwnProperty is overwritten' , t => {
349
357
const text = '{ "a": 5, "b": 6, "hasOwnProperty": "text", "__proto__": { "x": 7 } }'
350
- const obj = JSON . parse ( text )
351
358
352
- j . scan ( obj , { protoAction : 'remove' } )
359
+ const obj = j . parse ( text , { protoAction : 'remove' } )
353
360
t . deepEqual ( obj , { a : 5 , b : 6 , hasOwnProperty : 'text' } )
354
361
t . end ( )
355
362
} )
356
-
357
363
t . end ( )
358
364
} )
359
365
360
366
test ( 'safeParse' , t => {
367
+ t . test ( 'parses buffer' , t => {
368
+ t . strictEqual (
369
+ j . safeParse ( Buffer . from ( '"X"' ) ) ,
370
+ JSON . parse ( Buffer . from ( '"X"' ) )
371
+ )
372
+ t . end ( )
373
+ } )
374
+
375
+ t . test ( 'sanitizes nested object string' , t => {
376
+ const text = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
377
+
378
+ t . same ( j . safeParse ( text ) , null )
379
+ t . end ( )
380
+ } )
381
+
382
+ t . test ( 'returns null on constructor property' , t => {
383
+ const text = '{ "a": 5, "b": 6, "constructor": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
384
+
385
+ t . same ( j . safeParse ( text ) , null )
386
+ t . end ( )
387
+ } )
388
+
389
+ t . test ( 'returns null on proto property' , t => {
390
+ const text = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
391
+
392
+ t . same ( j . safeParse ( text ) , null )
393
+ t . end ( )
394
+ } )
395
+
396
+ t . test ( 'returns null on constructor property' , t => {
397
+ const text = '{ "a": 5, "b": 6, "constructor": { "x": 7 }, "c": { "d": 0, "e": "text", "__proto__": { "y": 8 }, "f": { "g": 2 } } }'
398
+
399
+ t . same ( j . safeParse ( text ) , null )
400
+ t . end ( )
401
+ } )
402
+
361
403
t . test ( 'parses object string' , t => {
362
404
t . deepEqual (
363
405
j . safeParse ( '{"a": 5, "b": 6}' ) ,
@@ -382,6 +424,22 @@ test('safeParse', t => {
382
424
t . end ( )
383
425
} )
384
426
427
+ t . test ( 'sanitizes object string (options)' , t => {
428
+ t . deepEqual (
429
+ j . safeParse ( '{"a": 5, "b": 6, "constructor":{"prototype":{"bar":"baz"}} }' ) ,
430
+ null
431
+ )
432
+ t . end ( )
433
+ } )
434
+
435
+ t . test ( 'sanitizes object string (no prototype key)' , t => {
436
+ t . deepEqual (
437
+ j . safeParse ( '{"a": 5, "b": 6,"constructor":{"bar":"baz"} }' ) ,
438
+ { a : 5 , b : 6 , constructor : { bar : 'baz' } }
439
+ )
440
+ t . end ( )
441
+ } )
442
+
385
443
t . end ( )
386
444
} )
387
445
@@ -404,3 +462,28 @@ test('parse buffer with BOM', t => {
404
462
t . deepEqual ( j . parse ( buffer ) , theJson )
405
463
t . end ( )
406
464
} )
465
+
466
+ test ( 'safeParse string with BOM' , t => {
467
+ const theJson = { hello : 'world' }
468
+ const buffer = Buffer . concat ( [
469
+ Buffer . from ( [ 239 , 187 , 191 ] ) , // the utf8 BOM
470
+ Buffer . from ( JSON . stringify ( theJson ) )
471
+ ] )
472
+ t . deepEqual ( j . safeParse ( buffer . toString ( ) ) , theJson )
473
+ t . end ( )
474
+ } )
475
+
476
+ test ( 'safeParse buffer with BOM' , t => {
477
+ const theJson = { hello : 'world' }
478
+ const buffer = Buffer . concat ( [
479
+ Buffer . from ( [ 239 , 187 , 191 ] ) , // the utf8 BOM
480
+ Buffer . from ( JSON . stringify ( theJson ) )
481
+ ] )
482
+ t . deepEqual ( j . safeParse ( buffer ) , theJson )
483
+ t . end ( )
484
+ } )
485
+
486
+ test ( 'scan handles optional options' , t => {
487
+ t . doesNotThrow ( ( ) => j . scan ( { a : 'b' } ) )
488
+ t . end ( )
489
+ } )
0 commit comments