diff --git a/python/tests/regexp.py b/python/tests/regexp.py index 682194b7d..866b36b84 100755 --- a/python/tests/regexp.py +++ b/python/tests/regexp.py @@ -29,7 +29,11 @@ check_regex(r"[\t-\r]", "\t\n\r", ["a", "(", ""]) check_regex("[\\t-\\r]", "\t\n\r", ["a", "(", ""]) check_regex(r"[\[-\]]", "[]\\", "Z^") check_regex(r"[\*-/]", "*+,-./", "()0") - +# Non-standard escape sequences +check_regex(r"[\u0041-\u005A]", "ABCMYZ", ["a", "0", "[", ""]) +check_regex(r"[\u0009\u0061-\u007A]", "\tabcmyz", ["A", "0", "{", "", "\n"]) +check_regex(r"[\!-\%]", '!"#$%', ["&", " ", "a", ""]) +check_regex(r"[\:-\>]", ':;<=>', ["?", "9", "@", ""]) # Memory debug specific libxml2.cleanupParser() diff --git a/xmlregexp.c b/xmlregexp.c index f12620cd5..3fe20ac0d 100644 --- a/xmlregexp.c +++ b/xmlregexp.c @@ -4896,6 +4896,12 @@ xmlFAParseCharClassEsc(xmlRegParserCtxtPtr ctxt) { case 't': cur = '\t'; break; + case 'u': + cur = parse_escaped_codepoint(ctxt); + if (cur < 0) { + return; + } + break; } xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, XML_REGEXP_CHARVAL, cur, cur, NULL); @@ -4980,9 +4986,17 @@ xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) { case 'n': start = 0xA; break; case 'r': start = 0xD; break; case 't': start = 0x9; break; + case 'u': + start = parse_escaped_codepoint(ctxt); + if (start < 0) { + return; + } + break; case '\\': case '|': case '.': case '-': case '^': case '?': case '*': case '+': case '{': case '}': case '(': case ')': - case '[': case ']': + case '[': case ']': case '!': case '"': case '#': case '$': + case '%': case ',': case '/': case ':': case ';': case '=': + case '>': case '@': case '`': case '~': start = cur; break; default: ERROR("Invalid escape value"); @@ -5025,9 +5039,17 @@ xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) { case 'n': end = 0xA; break; case 'r': end = 0xD; break; case 't': end = 0x9; break; + case 'u': + end = parse_escaped_codepoint(ctxt); + if (end < 0) { + return; + } + break; case '\\': case '|': case '.': case '-': case '^': case '?': case '*': case '+': case '{': case '}': case '(': case ')': - case '[': case ']': + case '[': case ']': case '!': case '"': case '#': case '$': + case '%': case ',': case '/': case ':': case ';': case '=': + case '>': case '@': case '`': case '~': end = cur; break; default: ERROR("Invalid escape value"); @@ -5069,13 +5091,22 @@ xmlFAParsePosCharGroup(xmlRegParserCtxtPtr ctxt) { case 'n': case 'r': case 't': case '\\': case '|': case '.': case '-': case '^': case '?': case '*': case '+': case '{': case '}': case '(': case ')': - case '[': case ']': + case '[': case ']': case '!': case '"': case '#': case '$': + case '%': case ',': case '/': case ':': case ';': case '=': + case '>': case '@': case '`': case '~': if (NXT(2) == '-') { xmlFAParseCharRange(ctxt); } else { xmlFAParseCharClassEsc(ctxt); } break; + case 'u': + if (NXT(6) == '-') { + xmlFAParseCharRange(ctxt); + } else { + xmlFAParseCharClassEsc(ctxt); + } + break; default: xmlFAParseCharClassEsc(ctxt); }