{
  "version": 3,
  "sources": ["../../../src/optimizer/transforms/prevent-redos.ts"],
  "sourcesContent": ["import type {QuantifierNode} from '../../parser/parse.js';\nimport type {Visitor} from '../../traverser/traverse.js';\nimport {hasOnlyChild} from '../../parser/node-utils.js';\n\n/**\nRemove identified ReDoS vulnerabilities without changing matches.\n*/\nconst preventReDoS: Visitor = {\n  Quantifier({node}) {\n    // Prevent a common cause of catastrophic backtracking by removing an unneeded nested\n    // quantifier from the first alternative of infinitely-quantified groups. Can't remove nested\n    // quantifiers from other alternatives or when the first alternative contains more than one\n    // node, because that might change the match\n    // TODO: It's safe to skip this transform if the quantified group is the last node in the\n    // pattern, since there's no backtracking trigger if there's no following node\n    const {body, max} = node;\n    if (\n      max !== Infinity ||\n      // Can't operate on capturing groups because that could change the captured value\n      body.type !== 'Group' ||\n      // No benefit with atomic groups\n      body.atomic\n    ) {\n      return;\n    }\n    const firstAlt = body.body[0];\n    if (!hasOnlyChild(firstAlt, {type: 'Quantifier'})) {\n      return;\n    }\n    const nestedQuantifier = firstAlt.body[0] as QuantifierNode;\n    if (\n      // No benefit with possessive quantifiers\n      nestedQuantifier.kind === 'possessive' ||\n      nestedQuantifier.min > 1 ||\n      nestedQuantifier.max < 2\n    ) {\n      return;\n    }\n    if (!nestedQuantifier.min) {\n      // Ex: Change `*` or `{0,2}` to `?`; preserve laziness\n      nestedQuantifier.max = 1;\n    } else if (nestedQuantifier.min === 1) {\n      // Ex: Remove `+` or `{1,2}`\n      firstAlt.body[0] = nestedQuantifier.body;\n    }\n  },\n};\n\nexport {\n  preventReDoS,\n};\n"],
  "mappings": "aAEA,OAAQ,gBAAAA,MAAmB,6BAK3B,MAAMC,EAAwB,CAC5B,WAAW,CAAC,KAAAC,CAAI,EAAG,CAOjB,KAAM,CAAC,KAAAC,EAAM,IAAAC,CAAG,EAAIF,EACpB,GACEE,IAAQ,KAERD,EAAK,OAAS,SAEdA,EAAK,OAEL,OAEF,MAAME,EAAWF,EAAK,KAAK,CAAC,EAC5B,GAAI,CAACH,EAAaK,EAAU,CAAC,KAAM,YAAY,CAAC,EAC9C,OAEF,MAAMC,EAAmBD,EAAS,KAAK,CAAC,EAGtCC,EAAiB,OAAS,cAC1BA,EAAiB,IAAM,GACvBA,EAAiB,IAAM,IAIpBA,EAAiB,IAGXA,EAAiB,MAAQ,IAElCD,EAAS,KAAK,CAAC,EAAIC,EAAiB,MAHpCA,EAAiB,IAAM,EAK3B,CACF,EAEA,OACEL,KAAA",
  "names": ["hasOnlyChild", "preventReDoS", "node", "body", "max", "firstAlt", "nestedQuantifier"]
}
