// Generated by dts-bundle v0.7.3 // Dependencies for this module: // ../refa // ../@eslint-community/regexpp declare module "scslre" { import { CharSet } from "refa"; import { AST } from "@eslint-community/regexpp"; export interface AnalysisResult { /** * The parse AST of the analysed literal. */ parsed: ParsedLiteral; /** * The analysed literal. */ literal: Literal; /** * A list of all reports found under the constraints of the given analysis options. */ reports: Report[]; } export interface ReportBase { type: Report["type"]; /** * The character to be repeated in order to create an input for which the analysed literal will have super-linear * runtime behavior. */ character: { /** * A non-empty set of characters that can be repeated to cause super-linear runtime. * * CharSet is a class from the [refa](https://github.com/RunDevelopment/refa) library. */ set: CharSet; /** * A single character that can be repeated to cause super-linear runtime. * * The implementation is allowed to pick any character in `set` but makes a best effort to pick a * "humanly readable" character. */ pick: string; /** * A literal that represents `set`. * * E.g. if `set` only contained the character "a" (lower case A), then the literal may be `/a/`. */ literal: Literal; }; /** * Returns a new literal with this cause of super-linear runtime being fixed. If the cause of this report could not * be automatically fixed, `undefined` will be returned. * * A fixed literal is guaranteed to behave exactly the same as the analysed literal. */ fix(): Literal | undefined; /** * Whether the polynomial backtracking of this report causes exponential backtracking. */ exponential: boolean; } /** * This report indicates super-linear runtime caused by polynomial backtracking between two distinct quantifiers. * * ### Examples * * `/a+a+/`, `/\d*\w+/`, `/a*(?:a{2}d?|cd?)b?a+/`, `/(?:a+ba+){2}/`, `(?:a|ba+)+` * * ### Description * * This type of super-linear runtime is caused by the polynomial backtracking between two unbounded quantifiers. * * #### Start and end quantifiers * * While the start and end quantifiers are guaranteed to be distinct unbounded quantifiers, one may be parent * (or ancestor) of the other (e.g. `/(?:a|ba+)+/`). The matching direction of the quantifiers may also be different * (e.g. `/a+(? `/(?:a)+/`), using assertions (e.g. `/(a+|b){0,3}/` => `/(a+(?!a)|b){0,3}/`), or * rewriting the affected parts of the pattern. Reports of simple cases usually have a fix for you. */ export interface SelfReport extends ReportBase { type: "Self"; /** * An unbounded quantifier that can reach itself. */ quant: AST.Quantifier; /** * A parent quantifier of [[`quant`]]. * * The maximum of this quantifier is at least 2. * * This is guaranteed to be not the same quantifier as [[`quant`]]. */ parentQuant: AST.Quantifier; } /** * This report indicates super-linear runtime cause by the matching algorithm moving the regexes across the input * string. * * ### Examples * * `/a+b/` * * ### Description * * This type of super-linear runtime is not caused by backtracking but by the matching algorithm itself. While the * regex engine will try to optimize as much as possible, in some cases, it will be forced to match a pattern against * every suffix of the given input string according the * [ECMAScript specification](https://tc39.es/ecma262/#sec-regexpbuiltinexec). Because there are _n_ many suffixes for * a rejecting input string with length _n_, the total runtime will be the time it takes to reject every suffix times * _n_. For non-finite languages, even a DFA (that guarantees _O(n)_ __for every suffix__) might have a total worst-case * time complexity of _O(n^2)_. * * ### Fixing * * This type of super-linear runtime is the hardest to fix (if at all possible) because the fixed regex has to reject * all suffixes with an average worst-case time complexity of _O(1)_. * * ### Notes * * Literals with the * [sticky flag](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/sticky) * (e.g. `/a+b/y`) and anchored literals (e.g. `/^a+b/` and `/\ba+b/` but not `/^\s+b/m` and `/\Ba+b/`) are immune to * this type of super-linear runtime. * * This type can never cause exponential backtracking. */ export interface MoveReport extends ReportBase { type: "Move"; /** * The unbounded quantifier that caused this report. */ quant: AST.Quantifier; /** * This type can never cause exponential backtracking. */ exponential: false; } export type Report = TradeReport | MoveReport | SelfReport; /** * A light-weight representation of JS RegExp literal. * * Only the `source` and `flags` properties have to be given. `source` and `flags` are required to be syntactically * valid. * * Literals are only guaranteed to be compatible with the `RegExp` constructor. The `source` may contain line breaks or * unescaped `/` characters. To convert a literal to a valid RegExp literal, use: * * ```js * RegExp(literal.source, literal.flags).toString() * ``` * * _Note:_ A [bug](https://bugs.chromium.org/p/v8/issues/detail?id=9618) in v8's `RegExp.properties.toString` * implementation caused some line breaks to not be escaped in older versions of NodeJS. You can use * [this workaround](https://github.com/terser/terser/pull/425/files#diff-9aa82f0ed674e050695a7422b1cd56d43ce47e6953688a16a003bf49c3481622R216) * to correct invalid RegExp literals. */ export interface Literal { source: string; flags: string; } /** * A representation of a parsed `RegExp` instance. * * This library uses [regexpp](https://github.com/mysticatea/regexpp) to parse JS RegExps. For more information on the * regexpp AST format, see [the definition](https://github.com/mysticatea/regexpp/blob/master/src/ast.ts) or see it live * in action on [astexplorer.net](https://astexplorer.net/#/gist/3b0c6dc514ab66df13b87c441a653a1a/latest). */ export interface ParsedLiteral { pattern: AST.Pattern; flags: AST.Flags; } export interface AnalysisOptions { /** * The maximum number of reports to be returned. * * @default Infinity */ maxReports?: number; /** * A record of allowed report types. All reports of a type that is mapped to `false` will be omitted. * * By default, all report types are allowed. */ reportTypes?: Partial>; /** * Whether the analyser is allowed to assume that a rejecting suffix can always be found. * * To exploit ambiguity in quantifiers, it is necessary to force the regex engine to go through all possible paths. * This can only be done by finding a suffix that causes the exploitable part of analysed regex to reject the input * string. If such a suffix cannot be found, the regex is not exploitable. * * If this option is set to `false`, a heuristic will be used to determine whether a rejecting suffix can be found. * This will prevent reporting false positives - non-exploitable quantifiers. * * The heuristic makes the assumption that the regex is used as is - that the regex is not modified or used to * construct other regexes. If this assumption is not met, the heuristic will prevent the reporting of potential * true positives. * * By setting this option to `true`, the heuristic will not be used and all reports are assumed to be true * positives. * * @default false */ assumeRejectingSuffix?: boolean; } /** * Analyses the given (parsed or unparsed) RegExp literal for causes of super-linear runtime complexity. * * If the given (unparsed) literal is not a syntactically valid JS RegExp, a `SyntaxError` will be thrown. * * @param input A literal or parsed literal. * @param options An optional record of options. */ export function analyse( input: Readonly | Readonly, options?: Readonly ): AnalysisResult; }