@@ -372,33 +372,89 @@ export class FuzzedDataProvider {
372
372
* is not sufficiently long.
373
373
* @param maxLength the maximum length of the string
374
374
* @param encoding the encoding of the string
375
+ * @param printable - a boolean, which defaults to false that indicates whether consumed strings
376
+ * should be forced to contain only valid printable characters
375
377
* @returns a `string` of length between 0 and `maxLength` (inclusive)
376
378
*/
377
379
consumeString (
378
380
maxLength : number ,
379
- encoding : BufferEncoding | undefined = "ascii"
381
+ encoding : BufferEncoding | undefined = "ascii" ,
382
+ printable : boolean | undefined = false
380
383
) : string {
381
384
if ( maxLength < 0 ) throw new Error ( "maxLength must be non-negative" ) ;
385
+ let result ;
382
386
const arrayLength = Math . min ( maxLength , this . _remainingBytes ) ;
383
- const result = this . data . toString (
384
- encoding ,
385
- this . dataPtr ,
386
- this . dataPtr + arrayLength
387
- ) ;
387
+
388
+ if ( printable ) {
389
+ result = this . bufToPrintableString (
390
+ this . data ,
391
+ this . dataPtr ,
392
+ this . dataPtr + arrayLength ,
393
+ encoding
394
+ ) ;
395
+ } else {
396
+ result = this . data . toString (
397
+ encoding ,
398
+ this . dataPtr ,
399
+ this . dataPtr + arrayLength
400
+ ) ;
401
+ }
388
402
this . dataPtr += arrayLength ;
389
403
this . _remainingBytes -= arrayLength ;
390
404
return result ;
391
405
}
392
406
407
+ /**
408
+ * A simple conversion helper that yields the ASCII representaion of a character.
409
+ * @param char is a single character from a string represented as a number
410
+ * @returns a 'string' from a single character that was represented by a number
411
+ */
412
+ toAscii ( char : number ) : number {
413
+ if ( char < 32 || char > 126 ) {
414
+ const moduloInRange = ( char - 32 + 256 ) % 256 ;
415
+ return ( moduloInRange % 95 ) + 32 ;
416
+ }
417
+ return char ;
418
+ }
419
+
420
+ /**
421
+ * Helper function that converts the given string type into one that only
422
+ * contains printable characters. This conversion produces seemingly arbitrary
423
+ * (non-smart) but printable strings, IFF the entropy of the input buffer is
424
+ * high enough. Limitations are that there are collisions such that, e.g.:
425
+ * the conversion of values: `0x1`, `0x42`, and `0xa2` all yield the character `B`.
426
+ * Elements in `buf` that are already in ASCII printable range are not undergoing
427
+ * any conversion.
428
+ * @param buf - Buffer that contains arbitrary values
429
+ * @param min - lower bound at which processing of the provided `Buffer` shall begin
430
+ * @param max - upper bound, analogous to the lower bound
431
+ * @param encoding - a valid `BufferEncoding`.
432
+ * @returns a string that was sanitized and only contains printable characters
433
+ */
434
+ bufToPrintableString (
435
+ buf : Buffer ,
436
+ min : number ,
437
+ max : number ,
438
+ encoding : BufferEncoding
439
+ ) : string {
440
+ for ( let i = min ; i < max ; i ++ ) {
441
+ buf [ i ] = this . toAscii ( buf [ i ] ) ;
442
+ }
443
+ return buf . subarray ( min , max ) . toString ( encoding ) ;
444
+ }
445
+
393
446
/**
394
447
* Consumes the remaining bytes of the fuzzer input as a string.
395
448
* @param encoding - the encoding of the string
449
+ * @param printable - a boolean, which defaults to false that indicates whether consumed strings
450
+ * should be forced to contain only valid printable characters
396
451
* @returns a string constructed from the remaining bytes of the fuzzer input using the given encoding
397
452
*/
398
453
consumeRemainingAsString (
399
- encoding : BufferEncoding | undefined = "ascii"
454
+ encoding : BufferEncoding | undefined = "ascii" ,
455
+ printable : boolean | undefined = false
400
456
) : string {
401
- return this . consumeString ( this . _remainingBytes , encoding ) ;
457
+ return this . consumeString ( this . _remainingBytes , encoding , printable ) ;
402
458
}
403
459
404
460
/**
@@ -408,16 +464,19 @@ export class FuzzedDataProvider {
408
464
* @param maxArrayLength the maximum length of the array
409
465
* @param maxStringLength the maximum length of the strings
410
466
* @param encoding the encoding of the strings
467
+ * @param printable - a boolean, which defaults to false that indicates whether consumed strings
468
+ * should be forced to contain only valid printable characters
411
469
* @returns an array containing strings constructed from the remaining bytes of the fuzzer input using the given encoding
412
470
*/
413
471
consumeStringArray (
414
472
maxArrayLength : number ,
415
473
maxStringLength : number ,
416
- encoding : BufferEncoding | undefined = "ascii"
474
+ encoding : BufferEncoding | undefined = "ascii" ,
475
+ printable : boolean | undefined = false
417
476
) {
418
477
const strs = [ ] ;
419
478
while ( strs . length < maxArrayLength && this . remainingBytes > 0 ) {
420
- const str = this . consumeString ( maxStringLength , encoding ) ;
479
+ const str = this . consumeString ( maxStringLength , encoding , printable ) ;
421
480
if ( str ) {
422
481
strs . push ( str ) ;
423
482
}
0 commit comments