summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibRegex
AgeCommit message (Collapse)Author
2021-09-07LibRegex: Use the correct capture group index in ERE bytecode generationAli Mohammad Pur
Otherwise the left and right capture instructions wouldn't point to the same capture group if there was another nested group there.
2021-09-07Everywhere: Behaviour => BehaviorAndreas Kling
2021-09-06LibRegex: Avoid keeping track of checkpoints across forksAli Mohammad Pur
Doing so would increase memory consumption by quite a bit, since many useless copies of the checkpoints hashmap would be created and later thrown away.
2021-09-06LibRegex: Make infinite repetitions short-circuit on empty matchesAli Mohammad Pur
This makes (addmittedly weird) patterns like `(a*)*` work correctly without going into an infinite fork loop.
2021-09-04AK+LibRegex: Disable construction of views from temporary StringsIdan Horowitz
2021-09-01LibRegex: Correctly advance string positions in Compare::compare_stringAli Mohammad Pur
Fixes a bug where backreferences could cause desync between the code point index and regular index, making comparison off-by-N.
2021-09-01LibRegex: Correctly handle failing in the middle of explicit repeatsAli Mohammad Pur
- Make sure that all the Repeat ops are reset (otherwise the operation would not be correct when going over the Repeat op a second time) - Make sure that all matches that are allowed to fail are backed by a fork, otherwise the last failing fork would not have anywhere to return to. Fixes #9707.
2021-08-31LibRegex: Implement min/max repetition using the Repeat bytecodeAli Mohammad Pur
This makes repetitions with large max bounds work correctly. Also fixes an OOM issue found by OSS-Fuzz: https://oss-fuzz.com/testcase?key=4725721980338176
2021-08-31LibRegex: Limit the number of nested capture groups allowed in BREAli Mohammad Pur
Found by OSS-Fuzz: https://oss-fuzz.com/testcase?key=4869334212673536
2021-08-30LibRegex: Allow null bytes in patternAli Mohammad Pur
That check was rather pointless as the input is a StringView which knows its own bounds. Fixes #9686.
2021-08-20LibRegex: Treat pattern string characters as unsignedTimothy Flynn
For example, consider the following pattern: new RegExp('\ud834\udf06', 'u') With this pattern, the regex parser should insert the UTF-8 encoded bytes 0xf0, 0x9d, 0x8c, and 0x86. However, because these characters are currently treated as normal char types, they have a negative value since they are all > 0x7f. Then, due to sign extension, when these characters are cast to u64, the sign bit is preserved. The result is that these bytes are inserted as 0xfffffffffffffff0, 0xffffffffffffff9d, etc. Fortunately, there are only a few places where we insert bytecode with the raw characters. In these places, be sure to treat the bytes as u8 before they are cast to u64.
2021-08-19LibRegex+LibJS: Change capture group names from a String to a FlyStringTimothy Flynn
The parser now stores this as a FlyString everywhere, so consumers can also use it as a FlyString.
2021-08-19LibRegex: Allow Unicode escape sequences in capture group namesTimothy Flynn
Unfortunately, this requires a slight divergence in the way the capture group names are stored. Previously, the generated byte code would simply store a view into the regex pattern string, so no string copying was required. Now, the escape sequences are decoded into a new string, and a vector of all parsed capture group names are stored in a vector in the parser result structure. The byte code then stores a view into the corresponding string in that vector.
2021-08-19LibRegex: Use GenericLexer to consume escaped code pointsTimothy Flynn
2021-08-19LibRegex: Convert regex::Lexer to inherit from GenericLexerTimothy Flynn
This will allow regex::Lexer users to invoke GenericLexer consumption methods, such as GenericLexer::consume_escaped_codepoint(). This also allows for de-duplicating common methods between the lexers.
2021-08-19AK: Move FormatParser definition from header to implementation fileTimothy Flynn
This is primarily to be able to remove the GenericLexer include out of Format.h as well. A subsequent commit will add AK::Result to GenericLexer, which will cause naming conflicts with other structures named Result. This can be avoided (for now) by preventing nearly every file in the system from implicitly including GenericLexer. Other changes in this commit are to add the GenericLexer include to files where it is missing.
2021-08-18LibRegex: Ensure the GoBack operation decrements the code unit indexTimothy Flynn
This was missed in commit 27d555bab0d84913599cea3c4a6b0a0ed2a15b66.
2021-08-18LibRegex: In non-Unicode mode, parse \u{4} as a repetition patternTimothy Flynn
2021-08-15LibRegex: Implement and use a REPEAT operation for bytecode repetitionTimothy Flynn
Currently, when we need to repeat an instruction N times, we simply add that instruction N times in a for-loop. This doesn't scale well with extremely large values of N, and ECMA-262 allows up to N = 2^53 - 1. Instead, add a new REPEAT bytecode operation to defer this loop from the parser to the runtime executor. This allows the parser to complete sans any loops (for this instruction), and allows the executor to bail early if the repeated bytecode fails. Note: The templated ByteCode methods are to allow the Posix parsers to continue using u32 because they are limited to N = 2^20.
2021-08-15LibRegex: Remove (mostly) unused regex::MatchOutputTimothy Flynn
This struct holds a counter for the number of executed operations, and vectors for matches, captures groups, and named capture groups. Each of the vectors is unused. Remove the struct and just keep a separate counter for the executed operations.
2021-08-15LibRegex+LibJS: Combine named and unnamed capture groups in MatchStateTimothy Flynn
Combining these into one list helps reduce the size of MatchState, and as a result, reduces the amount of memory consumed during execution of very large regex matches. Doing this also allows us to remove a few regex byte code instructions: ClearNamedCaptureGroup, SaveLeftNamedCaptureGroup, and NamedReference. Named groups now behave the same as unnamed groups for these operations. Note that SaveRightNamedCaptureGroup still exists to cache the matched group name. This also removes the recursion level from the MatchState, as it can exist as a local variable in Matcher::execute instead.
2021-08-15LibRegex: Reduce RegexMatcher's BumpAllocator chunk sizeTimothy Flynn
Before the BumpAllocator OOB access issue was understood and fixed, the chunk size was increased to 8MiB as a workaround in commit: 27d555bab0d84913599cea3c4a6b0a0ed2a15b66. The issue is now resolved by: 0f1425c895ace40fbb10d68a55eeb3a6354479d3. We can reduce the chunk size to 2MiB, which has the added benefit of reducing runtime of the RegExp.prototype.exec test.
2021-08-15LibRegex: Disallow unescaped quantifiers in Unicode modeTimothy Flynn
2021-08-15LibRegex: Use correct source characters for Unicode identity escapesTimothy Flynn
2021-08-15LibRegex: Implement legacy octal escape parsing closer to the specTimothy Flynn
The grammar for the ECMA-262 CharacterEscape is: CharacterEscape[U, N] :: ControlEscape c ControlLetter 0 [lookahead ∉ DecimalDigit] HexEscapeSequence RegExpUnicodeEscapeSequence[?U] [~U]LegacyOctalEscapeSequence IdentityEscape[?U, ?N] It's important to parse the standalone "\0 [lookahead ∉ DecimalDigit]" before parsing LegacyOctalEscapeSequence. Otherwise, all standalone "\0" patterns are parsed as octal, which are disallowed in Unicode mode. Further, LegacyOctalEscapeSequence should also be parsed while parsing character classes.
2021-08-15LibRegex: Ensure escaped hexadecimals are exactly 2 digits in lengthTimothy Flynn
2021-08-15LibRegex: Ensure escaped code points are exactly 4 digits in lengthTimothy Flynn
2021-08-15LibRegex: Fix ECMA-262 parsing of invalid identity escapesTimothy Flynn
* Only alphabetic (A-Z, a-z) characters may be escaped with \c. The loop currently parsing \c includes code points between the upper/lower case groups. * In Unicode mode, all invalid identity escapes should cause a parser error, even in browser-extended mode. * Avoid an infinite loop when parsing the pattern "\c" on its own.
2021-08-13AK+Everywhere: Delete Variant's default constructorAli Mohammad Pur
This was exposed to the user by mistake, and even accumulated a bunch of users that didn't blow up out of sheer luck.
2021-08-11LibRegex: Disallow invalid interval qualifiers in Unicode modeTimothy Flynn
Fixes all remaining 'built-ins/RegExp/property-escapes' test262 tests.
2021-08-04LibRegex: Support property escapes of Unicode script extensionsTimothy Flynn
2021-08-04LibRegex: Support property escapes of the Unicode script propertyTimothy Flynn
Note that unlike binary properties and general categories, scripts must be specified in the non-binary (Script=Value) form.
2021-08-04LibRegex: Track string position in both code units and code pointsTimothy Flynn
In non-Unicode mode, the existing MatchState::string_position is tracked in code units; in Unicode mode, it is tracked in code points. In order for some RegexStringView operations to be performant, it is useful for the MatchState to have a field to always track the position in code units. This will allow RegexStringView methods (e.g. operator[]) to perform lookups based on code unit offsets, rather than needing to iterate over the entire string to find a code point offset.
2021-08-04AK+LibRegex: Add Utf16View::code_point_at and use it in RegexStringViewTimothy Flynn
The current method of iterating through the string to access a code point hurts performance quite badly for very large strings. The test262 test "RegExp/property-escapes/generated/Any.js" previously took 3 hours to complete; this one change brings it down to under 10 seconds.
2021-08-02LibRegex: Generate negated property escapes as a single instructionTimothy Flynn
These were previously generated as two instructions, Compare [Inverse] and Compare [Property].
2021-08-02LibRegex: Support property escapes of the form \p{Type=Value}Timothy Flynn
Before now, only binary properties could be parsed. Non-binary props are of the form "Type=Value", where "Type" may be General_Category, Script, or Script_Extension (or their aliases). Of these, LibUnicode currently supports General_Category, so LibRegex can parse only that type.
2021-08-02LibRegex: Support property escapes of Unicode General CategoriesTimothy Flynn
This changes LibRegex to parse the property escape as a Variant of Unicode Property & General Category values. A byte code instruction is added to perform matching based on General Category values.
2021-08-02LibRegex: Make Matcher<>::match(Vector<>) take a reference to the vectorAli Mohammad Pur
It was previously copying the entire vector every time, which is not a nice thing to do. :^)
2021-08-02LibRegex: Use a bump-allocated linked list for fork save statesAli Mohammad Pur
This makes it avoid the excessively high malloc() traffic.
2021-08-02LibRegex: Make Fork{Jump,Stay} non-recursiveAli Mohammad Pur
This makes very fork-heavy expressions (like `(aa)*`) not run out of stack space when matching very long strings.
2021-08-01Libraries: Remove unused header includesBrian Gianforcaro
2021-07-30LibRegex+LibUnicode: Begin implementing Unicode property escapesTimothy Flynn
This supports some binary property matching. It does not support any properties not yet parsed by LibUnicode, nor does it support value matching (such as Script_Extensions=Latin).
2021-07-30LibRegex: Allow separately parsing patterns and creating Regex objectsTimothy Flynn
Adds a static method to parse a regex pattern and return the result, and a constructor to accept a parse result. This is to allow LibJS to parse the pattern string of a RegExpLiteral once and hand off regex objects any number of times thereafter.
2021-07-30LibRegex: Take ownership of pattern string and fix move operationsTimothy Flynn
The Regex object created a copy of the pattern string anyways, so tweak the constructor to allow callers to move() pattern strings into the regex. The Regex move constructor and assignment operator currently result in memory corruption. The Regex object stores a Matcher object, which holds a reference to the Regex object. So when the Regex object is moved, that reference is no longer valid. To fix this, the reference stored in the Matcher must be updated when the Regex is moved.
2021-07-30LibRegex: Allow RegexOptions to be declared at compile timeTimothy Flynn
2021-07-24LibRegex: Make unclosed-at-eof brace quantifiers an errorAli Mohammad Pur
Otherwise we'd just loop trying to parse it over and over again, for instance in `/a{/` or `/a{1,/`. Unless we're parsing in Annex B mode, which allows `{` as a normal ExtendedSourceCharacter.
2021-07-24LibRegex: Preserve the type of the match when clearing capture groupsAli Mohammad Pur
Even though the contents are supposed to be reset, the type should stay unchanged, as that's an assumption the engine is making.
2021-07-23LibRegex: Support ECMA-262 Unicode escapes of the form "\u{code_point}"Timothy Flynn
When the Unicode flag is set, regular expressions may escape code points by surrounding the hexadecimal code point with curly braces, e.g. \u{41} is the character "A". When the Unicode flag is not set, this should be considered a repetition symbol - \u{41} is the character "u" repeated 41 times. This is left as a TODO for now.
2021-07-23AK+LibRegex: Partially implement case insensitive UTF-16 comparisonTimothy Flynn
This will work for ASCII code points. Unicode case folding will be needed for non-ASCII.
2021-07-23LibRegex: Support UTF-16 RegexStringView and improve Unicode matchingTimothy Flynn
When the Unicode option is not set, regular expressions should match based on code units; when it is set, they should match based on code points. To do so, the regex parser must combine surrogate pairs when the Unicode option is set. Further, RegexStringView needs to know if the flag is set in order to return code point vs. code unit based string lengths and substrings.