basic/utf8: do not read past end of string when looking for a multi-byte character
Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9341.
This commit is contained in:
@@ -28,7 +28,7 @@ int encode_devnode_name(const char *str, char *str_enc, size_t len) {
|
||||
for (i = 0, j = 0; str[i] != '\0'; i++) {
|
||||
int seqlen;
|
||||
|
||||
seqlen = utf8_encoded_valid_unichar(&str[i]);
|
||||
seqlen = utf8_encoded_valid_unichar(str + i, (size_t) -1);
|
||||
if (seqlen > 1) {
|
||||
|
||||
if (len-j < (size_t)seqlen)
|
||||
|
||||
+16
-9
@@ -128,14 +128,14 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
|
||||
|
||||
assert(str);
|
||||
|
||||
for (p = str; length;) {
|
||||
for (p = str; length > 0;) {
|
||||
int encoded_len, r;
|
||||
char32_t val;
|
||||
|
||||
encoded_len = utf8_encoded_valid_unichar(p);
|
||||
if (encoded_len < 0 ||
|
||||
(size_t) encoded_len > length)
|
||||
encoded_len = utf8_encoded_valid_unichar(p, length);
|
||||
if (encoded_len < 0)
|
||||
return false;
|
||||
assert(encoded_len > 0 && (size_t) encoded_len <= length);
|
||||
|
||||
r = utf8_encoded_to_unichar(p, &val);
|
||||
if (r < 0 ||
|
||||
@@ -159,7 +159,7 @@ char *utf8_is_valid(const char *str) {
|
||||
while (*p) {
|
||||
int len;
|
||||
|
||||
len = utf8_encoded_valid_unichar(p);
|
||||
len = utf8_encoded_valid_unichar(p, (size_t) -1);
|
||||
if (len < 0)
|
||||
return NULL;
|
||||
|
||||
@@ -181,7 +181,7 @@ char *utf8_escape_invalid(const char *str) {
|
||||
while (*str) {
|
||||
int len;
|
||||
|
||||
len = utf8_encoded_valid_unichar(str);
|
||||
len = utf8_encoded_valid_unichar(str, (size_t) -1);
|
||||
if (len > 0) {
|
||||
s = mempcpy(s, str, len);
|
||||
str += len;
|
||||
@@ -208,7 +208,7 @@ char *utf8_escape_non_printable(const char *str) {
|
||||
while (*str) {
|
||||
int len;
|
||||
|
||||
len = utf8_encoded_valid_unichar(str);
|
||||
len = utf8_encoded_valid_unichar(str, (size_t) -1);
|
||||
if (len > 0) {
|
||||
if (utf8_is_printable(str, len)) {
|
||||
s = mempcpy(s, str, len);
|
||||
@@ -452,17 +452,24 @@ static int utf8_unichar_to_encoded_len(char32_t unichar) {
|
||||
}
|
||||
|
||||
/* validate one encoded unicode char and return its length */
|
||||
int utf8_encoded_valid_unichar(const char *str) {
|
||||
int utf8_encoded_valid_unichar(const char *str, size_t length /* bytes */) {
|
||||
char32_t unichar;
|
||||
size_t len, i;
|
||||
int r;
|
||||
|
||||
assert(str);
|
||||
assert(length > 0);
|
||||
|
||||
/* We read until NUL, at most length bytes. (size_t) -1 may be used to disable the length check. */
|
||||
|
||||
len = utf8_encoded_expected_len(str[0]);
|
||||
if (len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Do we have a truncated multi-byte character? */
|
||||
if (len > length)
|
||||
return -EINVAL;
|
||||
|
||||
/* ascii is valid */
|
||||
if (len == 1)
|
||||
return 1;
|
||||
@@ -495,7 +502,7 @@ size_t utf8_n_codepoints(const char *str) {
|
||||
while (*str != 0) {
|
||||
int k;
|
||||
|
||||
k = utf8_encoded_valid_unichar(str);
|
||||
k = utf8_encoded_valid_unichar(str, (size_t) -1);
|
||||
if (k < 0)
|
||||
return (size_t) -1;
|
||||
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ char16_t *utf8_to_utf16(const char *s, size_t length);
|
||||
|
||||
size_t char16_strlen(const char16_t *s); /* returns the number of 16bit words in the string (not bytes!) */
|
||||
|
||||
int utf8_encoded_valid_unichar(const char *str);
|
||||
int utf8_encoded_valid_unichar(const char *str, size_t length);
|
||||
int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar);
|
||||
|
||||
static inline bool utf16_is_surrogate(char16_t c) {
|
||||
|
||||
Reference in New Issue
Block a user