Merge branch 'additional-validations-regex' into auditfix
This commit is contained in:
@@ -106,4 +106,132 @@ describe('parseRegexRule', () => {
|
||||
expect(() => parseRegexRule('/a++b/')).toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
// HARDREGEX/SOFTREGEX RULE_VALUEs collected from an existing
|
||||
// MPE_VALIDATIONS table. None of these use PRX-only syntax (no inline
|
||||
// (?i), \Q...\E, \A/\z, atomic groups, or possessive quantifiers), so
|
||||
// they pass through parseRegexRule with only the /pattern/flags
|
||||
// delimiter stripped - the same PCRE-compatible escape rules apply on
|
||||
// both the SAS PRX side and the JS side, so behavior here is verified
|
||||
// to match, not just "doesn't throw".
|
||||
describe('RULE_VALUE corpus collected from an existing MPE_VALIDATIONS table', () => {
|
||||
const collectedRuleValues = [
|
||||
'/^-?[0-9]{1,13}([.]{0,1}[0-9]{0,3})$/',
|
||||
'/^-?[0-9]{1,3}$/',
|
||||
'/^(?:(?!31\\\\.12).)*$/',
|
||||
'/^([0-9]{1,3}([.][0-9]{1,7})?)%$/',
|
||||
'/^(100|[0-9]{1,2})%$/',
|
||||
'/^[-,0-9]{1,13}([.]{0,1}[0-9]{0,3})$/',
|
||||
'/^[-0-9]{1,19}([.]{0,1}[0-9]{0,3})$/',
|
||||
'/^[-0-9]*([.]{0,1}[0-9]{0,2})$/',
|
||||
'/^[-0-9]*([.]{0,1}[0-9]{0,3})$/',
|
||||
'/^[-0-9]*([.]{0,1}[0-9]*)$/',
|
||||
'/^[-0-9]*$/',
|
||||
'/^[0-2]$/',
|
||||
'/^[0-3]$/',
|
||||
'/^[0-9]{1,19}([.]{0,1}[0-9]{0,3})$/',
|
||||
'/^[0-9]{1,36}$/',
|
||||
'/^[0-9]{1,72}$/',
|
||||
'/^[0-9]{4}$/',
|
||||
'/^[0-9]{5}$/',
|
||||
'/^[0-9]*([.]{0,1}[0-9]{0,4})$/',
|
||||
'/^[0,1]{1}([.]{0,1}[0-9]{0,4})$/',
|
||||
'/^[1]{1,1}$/',
|
||||
'/^[A-Z0-1]{5,5}$/',
|
||||
'/^[a-zA-Z]{1,1}$/',
|
||||
'/^[a-zA-Z]{1,3}$/',
|
||||
'/^[a-zA-Z0-9_]{0,36}$/',
|
||||
'/^[a-zA-Z0-9_=@\\/.:;,= -]{1,8}$/',
|
||||
'/^[a-zA-Z0-9@_-]{1,100}$/',
|
||||
'/^[a-zA-Z0-9@_-]{1,50}$/',
|
||||
'/^[a-zA-Z0-9=@.:;,= -_]{1,50}$/',
|
||||
'/^[a-zA-Z0-9=@.:;,= -_]{1,80}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,10}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,100}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,12}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,14}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,15}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,20}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,3}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,300}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,32}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,4}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,40}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,400}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,50}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= \\-_]{1,500}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,510}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,6}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,72}$/',
|
||||
'/^[a-zA-Z0-9=@\\/.:;,= -_]{1,8}$/',
|
||||
"/^[a-zA-Z0-9=@\\/.:;,= -_`']{1,100}$/",
|
||||
"/^[a-zA-Z0-9=@\\/.:;,= -_`']{1,20}$/",
|
||||
"/^[a-zA-Z0-9=@\\/.:;,= \\-_`']{1,500}$/",
|
||||
"/^[a-zA-Z0-9=@\\/.:;,= -_`']*$/"
|
||||
]
|
||||
|
||||
collectedRuleValues.forEach((ruleValue) => {
|
||||
it(`compiles without throwing: ${ruleValue}`, () => {
|
||||
expect(() => parseRegexRule(ruleValue)).not.toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
it('preserves the exact pattern body and applies no flags for a plain numeric-range rule', () => {
|
||||
const regex = parseRegexRule('/^[0-9]{1,13}([.]{0,1}[0-9]{0,3})$/')
|
||||
|
||||
expect(regex.source).toEqual('^[0-9]{1,13}([.]{0,1}[0-9]{0,3})$')
|
||||
expect(regex.flags).toEqual('')
|
||||
expect(regex.test('1234.56')).toBeTrue()
|
||||
expect(regex.test('abc')).toBeFalse()
|
||||
})
|
||||
|
||||
it('handles the percentage-with-alternation rule (100 or 0-99, optionally with a decimal)', () => {
|
||||
const regex = parseRegexRule('/^(100|[0-9]{1,2})%$/')
|
||||
|
||||
expect(regex.test('100%')).toBeTrue()
|
||||
expect(regex.test('42%')).toBeTrue()
|
||||
expect(regex.test('101%')).toBeFalse()
|
||||
})
|
||||
|
||||
it('handles a character class with an escaped delimiter slash and a non-edge escaped hyphen', () => {
|
||||
const regex = parseRegexRule('/^[a-zA-Z0-9=@\\/.:;,= \\-_]{1,500}$/')
|
||||
|
||||
expect(regex.test('a/b-c d.e:f;g,h=i')).toBeTrue()
|
||||
expect(regex.test('has a # in it')).toBeFalse()
|
||||
})
|
||||
|
||||
it('handles a character class with literal backtick/single-quote characters', () => {
|
||||
const regex = parseRegexRule("/^[a-zA-Z0-9=@\\/.:;,= -_`']*$/")
|
||||
|
||||
expect(regex.test("O'Brien`s value")).toBeTrue()
|
||||
// The unescaped space-to-underscore run (` -_`) in this class is a
|
||||
// range (space is code point 32, underscore 95), not three literal
|
||||
// characters - so it also matches '#' (35), which falls inside that
|
||||
// range. Same behavior in SAS PRX (identical character-class rules),
|
||||
// so this is a faithful translation, not a parseRegexRule bug.
|
||||
expect(regex.test('has a # in it')).toBeTrue()
|
||||
expect(regex.test('has a ~ in it')).toBeFalse()
|
||||
})
|
||||
|
||||
// This is the one inconsistency in the whole corpus: every other escaped
|
||||
// '/' in this file uses a single backslash, but this rule has \\. (two
|
||||
// backslashes) where every other sign points to a single \. having been
|
||||
// intended (a literal dot, inside a negative lookahead meant to exclude
|
||||
// "31.12" - e.g. a 31-December date - from matching). SAS PRX and JS
|
||||
// regex use identical backslash-escape semantics for this (no PRX-only
|
||||
// construct is involved), so parseRegexRule's output is a faithful,
|
||||
// parity-preserving translation of whatever was actually authored -
|
||||
// this test pins down what the corpus *actually* does today, verbatim,
|
||||
// not what was likely intended. \\ (escaped backslash) followed by an
|
||||
// unescaped . (any character) means the lookahead is functionally a
|
||||
// no-op: it only fails to match text containing a literal backslash,
|
||||
// which excludes nothing in practice, so every value - including dates
|
||||
// that literally contain "31.12" - passes.
|
||||
it('as authored (double backslash): the 31.12-exclusion lookahead is a no-op and matches everything', () => {
|
||||
const regex = parseRegexRule('/^(?:(?!31\\\\.12).)*$/')
|
||||
|
||||
expect(regex.test('31.12.2024')).toBeTrue()
|
||||
expect(regex.test('01.01.2024')).toBeTrue()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user