84 lines
1.6 KiB
JavaScript
84 lines
1.6 KiB
JavaScript
// Generic options
|
|
class AnalyzerOptions {
|
|
constructor(heuristic_replimit) {
|
|
this.heuristic_replimit = heuristic_replimit;
|
|
}
|
|
}
|
|
|
|
class AttackString {
|
|
constructor(prefixAndPumpList, suffix) {
|
|
this.prefixAndPumpList = prefixAndPumpList;
|
|
this.suffix = suffix;
|
|
}
|
|
}
|
|
|
|
// Abstract class
|
|
class Analyzer {
|
|
constructor(analyzerOptions) {
|
|
this.options = analyzerOptions;
|
|
}
|
|
|
|
// Subclasser must implement
|
|
// Return boolean
|
|
isVulnerable(regExp) {
|
|
return false;
|
|
}
|
|
|
|
// Subclass must implement
|
|
// Returns an AttackString or null
|
|
genAttackString(regExp) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
module.exports = function(re, replimit) {
|
|
// Build an AST
|
|
let myRegExp = null;
|
|
let ast = null;
|
|
try {
|
|
// Construct a RegExp object
|
|
if (re instanceof RegExp) {
|
|
myRegExp = re;
|
|
} else if (typeof re === "string") {
|
|
myRegExp = new RegExp(re);
|
|
} else {
|
|
myRegExp = new RegExp(String(re));
|
|
}
|
|
|
|
// Build an AST
|
|
ast = regexpTree.parse(myRegExp);
|
|
} catch (err) {
|
|
// Invalid or unparseable input
|
|
return false;
|
|
}
|
|
|
|
let currentStarHeight = 0;
|
|
let maxObservedStarHeight = 0;
|
|
|
|
let repetitionCount = 0;
|
|
|
|
regexpTree.traverse(ast, {
|
|
Repetition: {
|
|
pre({ node }) {
|
|
repetitionCount++;
|
|
|
|
currentStarHeight++;
|
|
if (maxObservedStarHeight < currentStarHeight) {
|
|
maxObservedStarHeight = currentStarHeight;
|
|
}
|
|
},
|
|
|
|
post({ node }) {
|
|
currentStarHeight--;
|
|
}
|
|
}
|
|
});
|
|
|
|
return maxObservedStarHeight <= 1 && repetitionCount <= replimit;
|
|
};
|
|
|
|
module.exports = {
|
|
"AnalyzerOptions": AnalyzerOptions,
|
|
"Analyzer": Analyzer,
|
|
};
|