regexp: Fix issues with character ranges and escapes
diff --git a/result/regexp/issue1103 b/result/regexp/issue1103 new file mode 100644 index 0000000..13ec11b --- /dev/null +++ b/result/regexp/issue1103
@@ -0,0 +1,21 @@ +Regexp: [\--A] +-: Ok +@: Ok +A: Ok +B: Fail +Regexp: [A-\ud83d\ude0a] +@: Fail +A: Ok +B: Ok +😊: Ok +😍: Fail +Regexp: [\ud83d\ude0a-\ud83d\ude0d] +A: Fail +😊: Ok +😌: Ok +😍: Ok +Regexp: [\ud83d\ude0a\-A] +😊: Ok +A: Ok +-: Ok +😍: Fail
diff --git a/result/regexp/issue1103_err1 b/result/regexp/issue1103_err1 new file mode 100644 index 0000000..ff2b62d --- /dev/null +++ b/result/regexp/issue1103_err1
@@ -0,0 +1,2 @@ +Regexp: [--/] + failed to compile
diff --git a/result/regexp/issue1103_err1.err b/result/regexp/issue1103_err1.err new file mode 100644 index 0000000..98c3e7d --- /dev/null +++ b/result/regexp/issue1103_err1.err
@@ -0,0 +1 @@ +regexp error : failed to compile: Unescaped '-' can't be the start of a range
diff --git a/result/regexp/issue1103_err2 b/result/regexp/issue1103_err2 new file mode 100644 index 0000000..c6c511c --- /dev/null +++ b/result/regexp/issue1103_err2
@@ -0,0 +1,2 @@ +Regexp: [+--] + failed to compile
diff --git a/result/regexp/issue1103_err2.err b/result/regexp/issue1103_err2.err new file mode 100644 index 0000000..dcf8b2a --- /dev/null +++ b/result/regexp/issue1103_err2.err
@@ -0,0 +1 @@ +regexp error : failed to compile: Unescaped '-' can't be the end of a range
diff --git a/result/regexp/issue1103_err3 b/result/regexp/issue1103_err3 new file mode 100644 index 0000000..9eb5c27 --- /dev/null +++ b/result/regexp/issue1103_err3
@@ -0,0 +1,2 @@ +Regexp: [\P{L}-\D] + failed to compile
diff --git a/result/regexp/issue1103_err3.err b/result/regexp/issue1103_err3.err new file mode 100644 index 0000000..5405142 --- /dev/null +++ b/result/regexp/issue1103_err3.err
@@ -0,0 +1 @@ +regexp error : failed to compile: Multi-character escapes can't be the start of a range
diff --git a/test/regexp/issue1103 b/test/regexp/issue1103 new file mode 100644 index 0000000..7c65943 --- /dev/null +++ b/test/regexp/issue1103
@@ -0,0 +1,21 @@ +=>[\--A] +- +@ +A +B +=>[A-\ud83d\ude0a] +@ +A +B +😊 +😍 +=>[\ud83d\ude0a-\ud83d\ude0d] +A +😊 +😌 +😍 +=>[\ud83d\ude0a\-A] +😊 +A +- +😍
diff --git a/test/regexp/issue1103_err1 b/test/regexp/issue1103_err1 new file mode 100644 index 0000000..251378b --- /dev/null +++ b/test/regexp/issue1103_err1
@@ -0,0 +1 @@ +=>[--/]
diff --git a/test/regexp/issue1103_err2 b/test/regexp/issue1103_err2 new file mode 100644 index 0000000..2d63d45 --- /dev/null +++ b/test/regexp/issue1103_err2
@@ -0,0 +1 @@ +=>[+--]
diff --git a/test/regexp/issue1103_err3 b/test/regexp/issue1103_err3 new file mode 100644 index 0000000..1b36a04 --- /dev/null +++ b/test/regexp/issue1103_err3
@@ -0,0 +1 @@ +=>[\P{L}-\D]
diff --git a/xmlregexp.c b/xmlregexp.c index 0ac874f..fbc2426 100644 --- a/xmlregexp.c +++ b/xmlregexp.c
@@ -4978,6 +4978,7 @@ int cur, len; int start = -1; int end = -1; + int start_escaped = 0; if (CUR == '\0') { ERROR("Expecting ']'"); @@ -4986,6 +4987,7 @@ cur = CUR; if (cur == '\\') { + start_escaped = 1; NEXT; cur = CUR; switch (cur) { @@ -5025,7 +5027,7 @@ * Since we are "inside" a range, we can assume ctxt->cur is past * the start of ctxt->string, and PREV should be safe */ - if ((start == '-') && (NXT(1) != ']') && (PREV != '[') && (PREV != '^')) { + if ((start == '-') && (!start_escaped) && (NXT(1) != ']') && (PREV != '[') && (PREV != '^')) { NEXTL(len); return; } @@ -5036,6 +5038,10 @@ XML_REGEXP_CHARVAL, start, end, NULL); return; } + if ((start == '-') && (!start_escaped)) { + ERROR("Unescaped '-' can't be the start of a range"); + return; + } NEXT; cur = CUR; if (cur == '\\') { @@ -5065,6 +5071,10 @@ } else if ((cur != '\0') && (cur != 0x5B) && (cur != 0x5D)) { len = 4; end = xmlGetUTF8Char(ctxt->cur, &len); + if (end == '-') { + ERROR("Unescaped '-' can't be the end of a range"); + return; + } if (end < 0) { ERROR("Invalid UTF-8"); return; @@ -5094,27 +5104,19 @@ do { if (CUR == '\\') { switch (NXT(1)) { - case 'n': case 'r': case 't': + case 'n': case 'r': case 't': case 'u': 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); - } + xmlFAParseCharRange(ctxt); break; default: xmlFAParseCharClassEsc(ctxt); + if ((CUR == '-') && (NXT(1) != '[') && (NXT(1) != ']')) { + ERROR("Multi-character escapes can't be the start of a range"); + } } } else { xmlFAParseCharRange(ctxt);