- commit
- 395d1260d86312f594ee3d956f33ca5df33be9ed
- parent
- f4e658e9449491b09285b881a84c43aabd057af5
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2019-03-25 19:40
generic fuzzer
Diffstat
| A | fuzz/fuzzer.js | 48 | ++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | fuzz/html.js | 147 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 195 insertions, 0 deletions
diff --git a/fuzz/fuzzer.js b/fuzz/fuzzer.js
@@ -0,0 +1,48 @@
-1 1 var getFingerprint = function(covPath) {
-1 2 var coverage = window.__coverage__[covPath].b;
-1 3 var fingerprint = Object.values(coverage).map(x => x.join(':')).join('-');
-1 4 for (var key in coverage) {
-1 5 for (var i = 0; i < coverage[key].length; i++) {
-1 6 coverage[key][i] = 0;
-1 7 }
-1 8 }
-1 9 return fingerprint;
-1 10 };
-1 11
-1 12 var run = function(corpus, oracle, covPath, onFingerprint, onReport, done) {
-1 13 var fingerprints = [];
-1 14 var queue = [];
-1 15 var count = 0;
-1 16
-1 17 corpus.forEach(function(item) {
-1 18 queue.push(item);
-1 19 });
-1 20
-1 21 var step = function() {
-1 22 if (queue.length) {
-1 23 var item = queue.shift();
-1 24 var report = oracle(item);
-1 25 var fingerprint = getFingerprint(covPath);
-1 26
-1 27 if (!fingerprints.includes(fingerprint)) {
-1 28 fingerprints.push(fingerprint);
-1 29 item.mutate().forEach(mutation => queue.push(mutation));
-1 30 onFingerprint(fingerprint, fingerprints.length);
-1 31
-1 32 if (report) {
-1 33 onReport(report);
-1 34 }
-1 35 }
-1 36
-1 37 setTimeout(step);
-1 38 } else {
-1 39 done();
-1 40 }
-1 41 };
-1 42
-1 43 step();
-1 44 };
-1 45
-1 46 module.exports = {
-1 47 'run': run,
-1 48 };
diff --git a/fuzz/html.js b/fuzz/html.js
@@ -0,0 +1,147 @@
-1 1 var constants = require('aria-api/lib/constants');
-1 2
-1 3 var attributes = [
-1 4 ['role', Array.prototype.concat.apply([], Object.values(constants.subRoles)).filter((v, i, a) => a.indexOf(v) === i)],
-1 5 ['hidden', ['']],
-1 6 ['aria-hidden', ['', 'true', 'false']],
-1 7 ['aria-label', ['', '__random__']],
-1 8 ['title', ['', '__random__']],
-1 9 ['value', ['', '__random__']],
-1 10 ['placeholder', ['', '__random__']],
-1 11 ['alt', ['', '__random__']],
-1 12 ['aria-valuenow', ['', '__random__']],
-1 13 ['aria-valuetext', ['', '__random__']],
-1 14 ['aria-labelledby', ['__randint__']],
-1 15 ['aria-owns', ['__randint__']],
-1 16 ['list', ['__randint__']],
-1 17 ['for', ['__randint__']],
-1 18 ['type', ['', '__random__', 'hidden', 'checkbox', 'text', 'password', 'color', 'reset']],
-1 19 ['style', ['', '__random__', 'display: none', 'display: block', 'display: inline-block', 'display: inline', 'visibility: hidden']],
-1 20 ];
-1 21
-1 22 var tags = ['a', 'button', 'form', 'label', 'input', 'article', 'table', 'td', 'tr', 'th', 'pre', 'legend', 'h1', 'div', 'span', 'fieldset', 'img', 'abbr', 'strong', 'br', 'hr', 'select', 'option', 'datalist'];
-1 23
-1 24 var randomInt = function(n) {
-1 25 return Math.floor(Math.random() * n);
-1 26 };
-1 27
-1 28 var randomChoice = function(list) {
-1 29 return list[randomInt(list.length)];
-1 30 };
-1 31
-1 32 var randomString = function(len) {
-1 33 var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 -_.,#';
-1 34 var result = '';
-1 35 for (var i = 0; i < len; i++) {
-1 36 result += randomChoice(chars);
-1 37 }
-1 38 return result;
-1 39 };
-1 40
-1 41 function AttributeList(len) {
-1 42 this.value = [];
-1 43 for (var i = 0; i < len; i++) {
-1 44 var attr = randomChoice(attributes);
-1 45 var value = randomChoice(attr[1]);
-1 46 if (value === '__random__') {
-1 47 // shortcut: always use fixed string length
-1 48 value = randomString(10);
-1 49 } else if (value === '__randint__') {
-1 50 value = randomInt(len);
-1 51 }
-1 52 this.value.push(attr[0] + '="' + value + '"');
-1 53 }
-1 54 }
-1 55
-1 56 AttributeList.prototype.shrink = function() {
-1 57 var result = [];
-1 58 for (var i = 0; i < this.value.length; i++) {
-1 59 var item = new AttributeList(0);
-1 60 for (var j = 0; j < this.value.length; j++) {
-1 61 if (j !== i) {
-1 62 item.value.push(this.value[j]);
-1 63 }
-1 64 }
-1 65 result.push(item);
-1 66 }
-1 67 return result;
-1 68 };
-1 69
-1 70 function Element(len, ctx) {
-1 71 ctx = ctx || {k: 0};
-1 72 this.tag = randomChoice(tags);
-1 73 this.id = ctx.k;
-1 74 this.content = ctx.k;
-1 75 ctx.k += 1;
-1 76 this.attrs = new AttributeList(randomInt(len));
-1 77 this.children = new Children(randomInt(len), ctx);
-1 78 }
-1 79
-1 80 Element.prototype.shrink = function() {
-1 81 var result = [];
-1 82 var tag = this.tag;
-1 83 var id = this.id;
-1 84 var content = this.content;
-1 85 var attrsList = [this.attrs].concat(this.attrs.shrink());
-1 86 var childrenList = [this.children].concat(this.children.shrink());
-1 87 attrsList.forEach(function(attrs) {
-1 88 childrenList.forEach(function(children) {
-1 89 if (attrs !== this.attrs || children !== this.children) {
-1 90 var item = new Element(0, {});
-1 91 item.tag = tag;
-1 92 item.id = id;
-1 93 item.content = content;
-1 94 item.attrs = attrs;
-1 95 item.children = children;
-1 96 result.push(item);
-1 97 }
-1 98 });
-1 99 });
-1 100 return result;
-1 101 };
-1 102
-1 103 Element.prototype.mutate = function() {
-1 104 return this.shrink();
-1 105 };
-1 106
-1 107 Element.prototype.toString = function() {
-1 108 var s = '<' + this.tag + ' id="' + this.id + '"';
-1 109 this.attrs.value.forEach(function(attr) {
-1 110 s += ' ' + attr;
-1 111 });
-1 112 s += '>' + this.content;
-1 113 this.children.value.forEach(function(child) {
-1 114 s += child.toString();
-1 115 });
-1 116 s += '</' + this.tag + '>';
-1 117 return s;
-1 118 };
-1 119
-1 120 function Children(len, ctx) {
-1 121 this.value = [];
-1 122 for (var i = 0; i < len; i++) {
-1 123 this.value.push(new Element(randomInt(len), ctx));
-1 124 }
-1 125 }
-1 126
-1 127 Children.prototype.shrink = function() {
-1 128 var result = [];
-1 129 for (var i = 0; i < this.value.length; i++) {
-1 130 var item = new Children(0, {});
-1 131 for (var j = 0; j < this.value.length; j++) {
-1 132 if (j !== i) {
-1 133 // shortcut: pick random shrink result
-1 134 var shrunken = this.value[j].shrink();
-1 135 if (shrunken.length) {
-1 136 item.value.push(randomChoice(shrunken));
-1 137 }
-1 138 }
-1 139 }
-1 140 result.push(item);
-1 141 }
-1 142 return result;
-1 143 };
-1 144
-1 145 module.exports = {
-1 146 'Element': Element,
-1 147 };