Skip to content

Commit

Permalink
[dart/fuzzer] refactor lists into new file
Browse files Browse the repository at this point in the history
Rationale:
Refactor DartFuzz so that long lists of values appear
in separate file, making the actual fuzzing code easier
to read. Also, this prepares generating some of the
lists automaticaly (such a library methods). Note that
*no* version bump is required, since this refactoring
does not change behavior.
Change-Id: Ic58eb7bc1aa63f48ec0d37e3c2399917786086bd
Reviewed-on: https://dart-review.googlesource.com/c/87266
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Aart Bik <ajcbik@google.com>
  • Loading branch information
aartbik authored and commit-bot@chromium.org committed Dec 14, 2018
1 parent d2578de commit 80a6f4b
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 162 deletions.
176 changes: 14 additions & 162 deletions runtime/tools/dartfuzz/dartfuzz.dart
Expand Up @@ -7,6 +7,8 @@ import 'dart:math';

import 'package:args/args.dart';

import 'dartfuzz_values.dart';

// Version of DartFuzz. Increase this each time changes are made
// to preserve the property that a given version of DartFuzz yields
// the same fuzzed program for a deterministic random seed.
Expand All @@ -16,82 +18,6 @@ const String version = '1.2';
const int stmtDepth = 5;
const int exprDepth = 2;

// Interesting integer values.
const List<int> interestingIntegers = [
0x0000000000000000,
0x0000000000000001,
0x000000007fffffff,
0x0000000080000000,
0x0000000080000001,
0x00000000ffffffff,
0x0000000100000000,
0x0000000100000001,
0x000000017fffffff,
0x0000000180000000,
0x0000000180000001,
0x00000001ffffffff,
0x7fffffff00000000,
0x7fffffff00000001,
0x7fffffff7fffffff,
0x7fffffff80000000,
0x7fffffff80000001,
0x7fffffffffffffff,
0x8000000000000000,
0x8000000000000001,
0x800000007fffffff,
0x8000000080000000,
0x8000000080000001,
0x80000000ffffffff,
0x8000000100000000,
0x8000000100000001,
0x800000017fffffff,
0x8000000180000000,
0x8000000180000001,
0x80000001ffffffff,
0xffffffff00000000,
0xffffffff00000001,
0xffffffff7fffffff,
0xffffffff80000000,
0xffffffff80000001,
0xffffffffffffffff
];

// Interesting characters.
const interestingChars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#&()+- ';

// Class that represents Dart types.
class DartType {
final String name;

const DartType._withName(this.name);

static const VOID = const DartType._withName('void');
static const BOOL = const DartType._withName('bool');
static const INT = const DartType._withName('int');
static const DOUBLE = const DartType._withName('double');
static const STRING = const DartType._withName('String');
static const INT_LIST = const DartType._withName('List<int>');
static const INT_STRING_MAP = const DartType._withName('Map<int, String>');
}

// All value types.
const allTypes = [
DartType.BOOL,
DartType.INT,
DartType.DOUBLE,
DartType.STRING,
DartType.INT_LIST,
DartType.INT_STRING_MAP
];

// Class that represents Dart library methods.
class DartLib {
final String name;
final List<DartType> proto;
const DartLib(this.name, this.proto);
}

// Naming conventions.
const varName = 'var';
const paramName = 'par';
Expand All @@ -112,7 +38,7 @@ class DartFuzz {
// Setup the types.
localVars = new List<DartType>();
globalVars = fillTypes1();
globalVars.addAll(allTypes); // always one each
globalVars.addAll(DartType.allTypes); // always one each
globalMethods = fillTypes2();
classFields = fillTypes2();
classMethods = fillTypes3(classFields.length);
Expand Down Expand Up @@ -387,7 +313,7 @@ class DartFuzz {
// favors small positive int
case 0:
emit(
'${interestingIntegers[rand.nextInt(interestingIntegers.length)]}');
'${DartFuzzValues.interestingIntegers[rand.nextInt(DartFuzzValues.interestingIntegers.length)]}');
break;
case 1:
emitSmallNegativeInt();
Expand Down Expand Up @@ -432,7 +358,8 @@ class DartFuzz {
emit('\\u{1f600}'); // rune
break;
default:
emit(interestingChars[rand.nextInt(interestingChars.length)]);
emit(DartFuzzValues.interestingChars[
rand.nextInt(DartFuzzValues.interestingChars.length)]);
break;
}
}
Expand Down Expand Up @@ -607,7 +534,7 @@ class DartFuzz {
emitTerminal(tp); // resort to terminal
return;
}
DartLib lib = oneOf(getLibrary(tp));
DartLib lib = getLibraryMethod(tp);
List<DartType> proto = lib.proto;
// Receiver.
if (proto[0] != null) {
Expand Down Expand Up @@ -786,93 +713,18 @@ class DartFuzz {
// Library methods.
//

// Get list of library methods, organized by return type.
// Proto list:
// [ receiver-type (null denotes none),
// param1 type (null denotes getter),
// param2 type,
// ...
// ]
List<DartLib> getLibrary(DartType tp) {
// Get a library method that returns given type.
DartLib getLibraryMethod(DartType tp) {
if (tp == DartType.BOOL) {
return const [
DartLib('isEven', [DartType.INT, null]),
DartLib('isOdd', [DartType.INT, null]),
DartLib('isEmpty', [DartType.STRING, null]),
DartLib('isEmpty', [DartType.INT_STRING_MAP, null]),
DartLib('isNotEmpty', [DartType.STRING, null]),
DartLib('isNotEmpty', [DartType.INT_STRING_MAP, null]),
DartLib('endsWith', [DartType.STRING, DartType.STRING]),
DartLib('remove', [DartType.INT_LIST, DartType.INT]),
DartLib('containsValue', [DartType.INT_STRING_MAP, DartType.STRING]),
DartLib('containsKey', [DartType.INT_STRING_MAP, DartType.INT]),
];
return oneOf(DartLib.boolLibs);
} else if (tp == DartType.INT) {
return const [
DartLib('bitLength', [DartType.INT, null]),
DartLib('sign', [DartType.INT, null]),
DartLib('abs', [DartType.INT]),
DartLib('round', [DartType.INT]),
DartLib('round', [DartType.DOUBLE]),
DartLib('floor', [DartType.INT]),
DartLib('floor', [DartType.DOUBLE]),
DartLib('ceil', [DartType.INT]),
DartLib('ceil', [DartType.DOUBLE]),
DartLib('truncate', [DartType.INT]),
DartLib('truncate', [DartType.DOUBLE]),
DartLib('toInt', [DartType.DOUBLE]),
DartLib('toUnsigned', [DartType.INT, DartType.INT]),
DartLib('toSigned', [DartType.INT, DartType.INT]),
DartLib('modInverse', [DartType.INT, DartType.INT]),
DartLib('modPow', [DartType.INT, DartType.INT, DartType.INT]),
DartLib('length', [DartType.STRING, null]),
DartLib('length', [DartType.INT_LIST, null]),
DartLib('length', [DartType.INT_STRING_MAP, null]),
DartLib('codeUnitAt', [DartType.STRING, DartType.INT]),
DartLib('compareTo', [DartType.STRING, DartType.STRING]),
DartLib('removeLast', [DartType.INT_LIST]),
DartLib('removeAt', [DartType.INT_LIST, DartType.INT]),
DartLib('indexOf', [DartType.INT_LIST, DartType.INT]),
DartLib('lastIndexOf', [DartType.INT_LIST, DartType.INT]),
];
return oneOf(DartLib.intLibs);
} else if (tp == DartType.DOUBLE) {
return const [
DartLib('sign', [DartType.DOUBLE, null]),
DartLib('abs', [DartType.DOUBLE]),
DartLib('toDouble', [DartType.INT]),
DartLib('roundToDouble', [DartType.INT]),
DartLib('roundToDouble', [DartType.DOUBLE]),
DartLib('floorToDouble', [DartType.INT]),
DartLib('floorToDouble', [DartType.DOUBLE]),
DartLib('ceilToDouble', [DartType.INT]),
DartLib('ceilToDouble', [DartType.DOUBLE]),
DartLib('truncateToDouble', [DartType.INT]),
DartLib('truncateToDouble', [DartType.DOUBLE]),
DartLib('remainder', [DartType.DOUBLE, DartType.DOUBLE]),
];
return oneOf(DartLib.doubleLibs);
} else if (tp == DartType.STRING) {
return const [
DartLib('toString', [DartType.BOOL]),
DartLib('toString', [DartType.INT]),
DartLib('toString', [DartType.DOUBLE]),
DartLib('toRadixString', [DartType.INT, DartType.INT]),
DartLib('trim', [DartType.STRING]),
DartLib('trimLeft', [DartType.STRING]),
DartLib('trimRight', [DartType.STRING]),
DartLib('toLowerCase', [DartType.STRING]),
DartLib('toUpperCase', [DartType.STRING]),
DartLib('substring', [DartType.STRING, DartType.INT]),
DartLib('replaceRange',
[DartType.STRING, DartType.INT, DartType.INT, DartType.STRING]),
DartLib('remove', [DartType.INT_STRING_MAP, DartType.INT]),
// Avoid (OOM divergences, unless we restrict parameters):
// DartLib('padLeft', [DartType.STRING, DartType.INT]),
// DartLib('padRight', [DartType.STRING, DartType.INT]),
];
return oneOf(DartLib.stringLibs);
} else if (tp == DartType.INT_LIST) {
return const [
DartLib('sublist', [DartType.INT_LIST, DartType.INT])
];
return oneOf(DartLib.intListLibs);
} else {
assert(false);
}
Expand Down
167 changes: 167 additions & 0 deletions runtime/tools/dartfuzz/dartfuzz_values.dart
@@ -0,0 +1,167 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// Class that represents some common Dart types.
///
/// TODO(ajcbik): generalize
///
class DartType {
final String name;

const DartType._withName(this.name);

static const VOID = const DartType._withName('void');
static const BOOL = const DartType._withName('bool');
static const INT = const DartType._withName('int');
static const DOUBLE = const DartType._withName('double');
static const STRING = const DartType._withName('String');
static const INT_LIST = const DartType._withName('List<int>');
static const INT_STRING_MAP = const DartType._withName('Map<int, String>');

// All value types.
static const allTypes = [BOOL, INT, DOUBLE, STRING, INT_LIST, INT_STRING_MAP];
}

/// Class with interesting values for fuzzing.
class DartFuzzValues {
// Interesting characters.
static const interestingChars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#&()+- ';

// Interesting integer values.
static const List<int> interestingIntegers = [
0x0000000000000000,
0x0000000000000001,
0x000000007fffffff,
0x0000000080000000,
0x0000000080000001,
0x00000000ffffffff,
0x0000000100000000,
0x0000000100000001,
0x000000017fffffff,
0x0000000180000000,
0x0000000180000001,
0x00000001ffffffff,
0x7fffffff00000000,
0x7fffffff00000001,
0x7fffffff7fffffff,
0x7fffffff80000000,
0x7fffffff80000001,
0x7fffffffffffffff,
0x8000000000000000,
0x8000000000000001,
0x800000007fffffff,
0x8000000080000000,
0x8000000080000001,
0x80000000ffffffff,
0x8000000100000000,
0x8000000100000001,
0x800000017fffffff,
0x8000000180000000,
0x8000000180000001,
0x80000001ffffffff,
0xffffffff00000000,
0xffffffff00000001,
0xffffffff7fffffff,
0xffffffff80000000,
0xffffffff80000001,
0xffffffffffffffff
];
}

/// Class that represents Dart library methods.
/// The invididual lists are organized by return type.
/// Proto list:
/// [ receiver-type (null denotes none),
/// param1 type (null denotes getter),
/// param2 type,
/// ...
/// ]
///
/// TODO(ajcbik): generate these lists automatically
///
class DartLib {
final String name;
final List<DartType> proto;
const DartLib(this.name, this.proto);

static const boolLibs = [
DartLib('isEven', [DartType.INT, null]),
DartLib('isOdd', [DartType.INT, null]),
DartLib('isEmpty', [DartType.STRING, null]),
DartLib('isEmpty', [DartType.INT_STRING_MAP, null]),
DartLib('isNotEmpty', [DartType.STRING, null]),
DartLib('isNotEmpty', [DartType.INT_STRING_MAP, null]),
DartLib('endsWith', [DartType.STRING, DartType.STRING]),
DartLib('remove', [DartType.INT_LIST, DartType.INT]),
DartLib('containsValue', [DartType.INT_STRING_MAP, DartType.STRING]),
DartLib('containsKey', [DartType.INT_STRING_MAP, DartType.INT]),
];

static const intLibs = [
DartLib('bitLength', [DartType.INT, null]),
DartLib('sign', [DartType.INT, null]),
DartLib('abs', [DartType.INT]),
DartLib('round', [DartType.INT]),
DartLib('round', [DartType.DOUBLE]),
DartLib('floor', [DartType.INT]),
DartLib('floor', [DartType.DOUBLE]),
DartLib('ceil', [DartType.INT]),
DartLib('ceil', [DartType.DOUBLE]),
DartLib('truncate', [DartType.INT]),
DartLib('truncate', [DartType.DOUBLE]),
DartLib('toInt', [DartType.DOUBLE]),
DartLib('toUnsigned', [DartType.INT, DartType.INT]),
DartLib('toSigned', [DartType.INT, DartType.INT]),
DartLib('modInverse', [DartType.INT, DartType.INT]),
DartLib('modPow', [DartType.INT, DartType.INT, DartType.INT]),
DartLib('length', [DartType.STRING, null]),
DartLib('length', [DartType.INT_LIST, null]),
DartLib('length', [DartType.INT_STRING_MAP, null]),
DartLib('codeUnitAt', [DartType.STRING, DartType.INT]),
DartLib('compareTo', [DartType.STRING, DartType.STRING]),
DartLib('removeLast', [DartType.INT_LIST]),
DartLib('removeAt', [DartType.INT_LIST, DartType.INT]),
DartLib('indexOf', [DartType.INT_LIST, DartType.INT]),
DartLib('lastIndexOf', [DartType.INT_LIST, DartType.INT]),
];

static const doubleLibs = [
DartLib('sign', [DartType.DOUBLE, null]),
DartLib('abs', [DartType.DOUBLE]),
DartLib('toDouble', [DartType.INT]),
DartLib('roundToDouble', [DartType.INT]),
DartLib('roundToDouble', [DartType.DOUBLE]),
DartLib('floorToDouble', [DartType.INT]),
DartLib('floorToDouble', [DartType.DOUBLE]),
DartLib('ceilToDouble', [DartType.INT]),
DartLib('ceilToDouble', [DartType.DOUBLE]),
DartLib('truncateToDouble', [DartType.INT]),
DartLib('truncateToDouble', [DartType.DOUBLE]),
DartLib('remainder', [DartType.DOUBLE, DartType.DOUBLE]),
];

static const stringLibs = [
DartLib('toString', [DartType.BOOL]),
DartLib('toString', [DartType.INT]),
DartLib('toString', [DartType.DOUBLE]),
DartLib('toRadixString', [DartType.INT, DartType.INT]),
DartLib('trim', [DartType.STRING]),
DartLib('trimLeft', [DartType.STRING]),
DartLib('trimRight', [DartType.STRING]),
DartLib('toLowerCase', [DartType.STRING]),
DartLib('toUpperCase', [DartType.STRING]),
DartLib('substring', [DartType.STRING, DartType.INT]),
DartLib('replaceRange',
[DartType.STRING, DartType.INT, DartType.INT, DartType.STRING]),
DartLib('remove', [DartType.INT_STRING_MAP, DartType.INT]),
// Avoid (OOM divergences, TODO(ajcbik): restrict parameters)
// DartLib('padLeft', [DartType.STRING, DartType.INT]),
// DartLib('padRight', [DartType.STRING, DartType.INT]),
];

static const intListLibs = [
DartLib('sublist', [DartType.INT_LIST, DartType.INT])
];
}

0 comments on commit 80a6f4b

Please sign in to comment.