heuristic-analyzer.js 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. // Exports an Analyzer subclass
  2. const regexpTree = require("regexp-tree");
  3. const analyzer = require("./analyzer");
  4. class HeuristicAnalyzer extends analyzer.Analyzer {
  5. constructor(analyzerOptions) {
  6. super(analyzerOptions);
  7. }
  8. isVulnerable(regExp) {
  9. // Heuristic #1: Star height > 1
  10. const starHeight = this._measureStarHeight(regExp);
  11. if (starHeight > 1) {
  12. return true;
  13. }
  14. // Heuristic #2: # repetitions > limit
  15. // TODO This is a poor heuristic
  16. const nRepetitions = this._measureRepetitions(regExp);
  17. if (nRepetitions > this.options.heuristic_replimit) {
  18. return true;
  19. }
  20. return false;
  21. }
  22. genAttackString(regExp) {
  23. return null;
  24. }
  25. _measureStarHeight(regExp) {
  26. let currentStarHeight = 0;
  27. let maxObservedStarHeight = 0;
  28. const ast = regexpTree.parse(regExp);
  29. regexpTree.traverse(ast, {
  30. Repetition: {
  31. pre({ node }) {
  32. currentStarHeight++;
  33. if (maxObservedStarHeight < currentStarHeight) {
  34. maxObservedStarHeight = currentStarHeight;
  35. }
  36. },
  37. post({ node }) {
  38. currentStarHeight--;
  39. }
  40. }
  41. });
  42. return maxObservedStarHeight;
  43. }
  44. _measureRepetitions(regExp) {
  45. let nRepetitions = 0;
  46. const ast = regexpTree.parse(regExp);
  47. regexpTree.traverse(ast, {
  48. Repetition: {
  49. pre({ node }) {
  50. nRepetitions++;
  51. }
  52. }
  53. });
  54. return nRepetitions;
  55. }
  56. }
  57. module.exports = HeuristicAnalyzer;