summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-12-02 22:00:42 -0800
committerKaz Kylheku <kaz@kylheku.com>2016-12-02 22:00:42 -0800
commitda08a3c9d4162703d1aeb3475a77777903887805 (patch)
treef6775c6882d2a71dbc2115ee6a01b71c368523c9
parenta40d3a15097f275546cb015ab9e52c0cf18d0454 (diff)
downloadtxr-da08a3c9d4162703d1aeb3475a77777903887805.tar.gz
txr-da08a3c9d4162703d1aeb3475a77777903887805.tar.bz2
txr-da08a3c9d4162703d1aeb3475a77777903887805.zip
Harden processing of character escapes.
Weakness uncovered by fuzzing with AFL (fast) 2.30b. The failing test case is regex syntax like [\1111111...111abc], where the bad character escape allows an invalid, negatively valued character object to escape out of the parser into the system leading to an an out-of-bounds array access in the char set code in the regex compiler. * parser.l (num_esc): Make sure that an out-of-range character is mapped to zero. Set up a default value of zero for the return variable. If the character token has too many digits, don't pass them through strtol at all, which will produce a garbage value. Then in the final range check, actually replace the value with zero if it is out of range: issuing a diagnostic is not enough.
-rw-r--r--parser.l12
1 files changed, 8 insertions, 4 deletions
diff --git a/parser.l b/parser.l
index cff641ae..89c89193 100644
--- a/parser.l
+++ b/parser.l
@@ -161,22 +161,26 @@ static wchar_t char_esc(int letter)
static wchar_t num_esc(scanner_t *scn, char *num)
{
- long val;
+ long val = 0;
if (num[0] == 'x') {
if (strlen(num) > 7)
yyerror(scn, yyget_extra(scn), "too many digits in hex character escape");
- val = strtol(num + 1, 0, 16);
+ else
+ val = strtol(num + 1, 0, 16);
} else {
if (num[0] == 'o')
num++;
if (strlen(num) > 8)
yyerror(scn, yyget_extra(scn), "too many digits in octal character escape");
- val = strtol(num, 0, 8);
+ else
+ val = strtol(num, 0, 8);
}
- if (val < 0 || val > 0x10FFFF || (wchar_t) val != val)
+ if (val < 0 || val > 0x10FFFF || (wchar_t) val != val) {
yyerror(scn, yyget_extra(scn), "numeric character escape out of range");
+ val = 0;
+ }
return val;
}