analyzer.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Generic options
  2. class AnalyzerOptions {
  3. constructor(heuristic_replimit) {
  4. this.heuristic_replimit = heuristic_replimit;
  5. }
  6. }
  7. class AttackString {
  8. constructor(prefixAndPumpList, suffix) {
  9. this.prefixAndPumpList = prefixAndPumpList;
  10. this.suffix = suffix;
  11. }
  12. }
  13. // Abstract class
  14. class Analyzer {
  15. constructor(analyzerOptions) {
  16. this.options = analyzerOptions;
  17. }
  18. // Subclasser must implement
  19. // Return boolean
  20. isVulnerable(regExp) {
  21. return false;
  22. }
  23. // Subclass must implement
  24. // Returns an AttackString or null
  25. genAttackString(regExp) {
  26. return null;
  27. }
  28. }
  29. module.exports = function(re, replimit) {
  30. // Build an AST
  31. let myRegExp = null;
  32. let ast = null;
  33. try {
  34. // Construct a RegExp object
  35. if (re instanceof RegExp) {
  36. myRegExp = re;
  37. } else if (typeof re === "string") {
  38. myRegExp = new RegExp(re);
  39. } else {
  40. myRegExp = new RegExp(String(re));
  41. }
  42. // Build an AST
  43. ast = regexpTree.parse(myRegExp);
  44. } catch (err) {
  45. // Invalid or unparseable input
  46. return false;
  47. }
  48. let currentStarHeight = 0;
  49. let maxObservedStarHeight = 0;
  50. let repetitionCount = 0;
  51. regexpTree.traverse(ast, {
  52. Repetition: {
  53. pre({ node }) {
  54. repetitionCount++;
  55. currentStarHeight++;
  56. if (maxObservedStarHeight < currentStarHeight) {
  57. maxObservedStarHeight = currentStarHeight;
  58. }
  59. },
  60. post({ node }) {
  61. currentStarHeight--;
  62. }
  63. }
  64. });
  65. return maxObservedStarHeight <= 1 && repetitionCount <= replimit;
  66. };
  67. module.exports = {
  68. "AnalyzerOptions": AnalyzerOptions,
  69. "Analyzer": Analyzer,
  70. };