unescape: add boundaries check on utf-8 (oss-fuzz 22180)
@@ -67,7 +67,7 @@ static int u8_wc_toutf8(char *dest, uint32_t ch)
/* assumes that src points to the character after a backslash
returns number of input characters processed */
-static int u8_read_escape_sequence(const char *str, uint32_t *dest)
+static int u8_read_escape_sequence(const char *str, int size, uint32_t *dest)
{
uint32_t ch;
char digs[9]="\0\0\0\0\0\0\0\0";
@@ -93,30 +93,33 @@ static int u8_read_escape_sequence(const char *str, uint32_t *dest)
i = 0;
do {
digs[dno++] = str[i++];
- } while (octal_digit(str[i]) && dno < 3);
+ } while (i < size && octal_digit(str[i]) && dno < 3);
ch = strtol(digs, NULL, 8);
}
else if (str[0] == 'x') {
- while (hex_digit(str[i]) && dno < 2) {
+ while (i < size && hex_digit(str[i]) && dno < 2) {
digs[dno++] = str[i++];
}
- if (dno > 0)
+ if (dno > 0) {
ch = strtol(digs, NULL, 16);
}
+ }
else if (str[0] == 'u') {
- while (hex_digit(str[i]) && dno < 4) {
+ while (i < size && hex_digit(str[i]) && dno < 4) {
digs[dno++] = str[i++];
}
- if (dno > 0)
+ if (dno > 0) {
ch = strtol(digs, NULL, 16);
}
+ }
else if (str[0] == 'U') {
- while (hex_digit(str[i]) && dno < 8) {
+ while (i < size && hex_digit(str[i]) && dno < 8) {
digs[dno++] = str[i++];
}
- if (dno > 0)
+ if (dno > 0) {
ch = strtol(digs, NULL, 16);
}
+ }
*dest = ch;
return i;
@@ -128,6 +131,8 @@ int flb_unescape_string_utf8(const char *in_buf, int sz, char *out_buf)
char temp[4];
const char *end;
const char *next;
+ int size;
+
int count_out = 0;
int count_in = 0;
@@ -168,7 +173,14 @@ int flb_unescape_string_utf8(const char *in_buf, int sz, char *out_buf)
ch = '\r';
break;
default:
- esc_in = u8_read_escape_sequence((in_buf + 1), &ch) + 1;
+ size = end - next;
+ if (size > 0) {
+ esc_in = u8_read_escape_sequence(next, size, &ch) + 1;
+ }
+ else {
+ ch = (uint32_t) *in_buf;
+ esc_in = 1;
+ }
}
}
else {
