common BUGFIX out-of-bounds errors
diff --git a/src/common.c b/src/common.c
index 25e19f1..a434235 100644
--- a/src/common.c
+++ b/src/common.c
@@ -47,12 +47,8 @@
char *
ly_strnchr(const char *s, int c, size_t len)
{
- for ( ; *s != (char)c; ++s, --len) {
- if ((*s == '\0') || (!len)) {
- return NULL;
- }
- }
- return (char *)s;
+ for ( ; len && (*s != (char)c); ++s, --len) {}
+ return len ? (char *)s : NULL;
}
int
@@ -332,7 +328,7 @@
size_t len = 0;
const char *ptr = str;
- while (*ptr && (size_t)(ptr - str) < bytes) {
+ while (((size_t)(ptr - str) < bytes) && *ptr) {
++len;
ptr += utf8_char_length_table[((unsigned char)(*ptr))];
}
@@ -441,60 +437,81 @@
LY_ERR
ly_parse_int(const char *val_str, size_t val_len, int64_t min, int64_t max, int base, int64_t *ret)
{
- char *strptr;
+ LY_ERR rc = LY_SUCCESS;
+ char *ptr, *str;
int64_t i;
LY_CHECK_ARG_RET(NULL, val_str, val_str[0], val_len, LY_EINVAL);
- /* convert to 64-bit integer, all the redundant characters are handled */
- errno = 0;
- strptr = NULL;
+ /* duplicate the value */
+ str = strndup(val_str, val_len);
+ LY_CHECK_RET(!str, LY_EMEM);
- /* parse the value */
- i = strtoll(val_str, &strptr, base);
- if (errno || (strptr == val_str)) {
- return LY_EVALID;
+ /* parse the value to avoid accessing following bytes */
+ errno = 0;
+ i = strtoll(str, &ptr, base);
+ if (errno || (ptr == str)) {
+ /* invalid string */
+ rc = LY_EVALID;
} else if ((i < min) || (i > max)) {
- return LY_EDENIED;
- } else if (strptr && *strptr) {
- while (isspace(*strptr)) {
- ++strptr;
+ /* invalid number */
+ rc = LY_EDENIED;
+ } else if (*ptr) {
+ while (isspace(*ptr)) {
+ ++ptr;
}
- if (*strptr && (strptr < val_str + val_len)) {
- return LY_EVALID;
+ if (*ptr) {
+ /* invalid characters after some number */
+ rc = LY_EVALID;
}
}
- *ret = i;
- return LY_SUCCESS;
+ /* cleanup */
+ free(str);
+ if (!rc) {
+ *ret = i;
+ }
+ return rc;
}
LY_ERR
ly_parse_uint(const char *val_str, size_t val_len, uint64_t max, int base, uint64_t *ret)
{
- char *strptr;
+ LY_ERR rc = LY_SUCCESS;
+ char *ptr, *str;
uint64_t u;
- LY_CHECK_ARG_RET(NULL, val_str, val_str[0], LY_EINVAL);
+ LY_CHECK_ARG_RET(NULL, val_str, val_str[0], val_len, LY_EINVAL);
+ /* duplicate the value to avoid accessing following bytes */
+ str = strndup(val_str, val_len);
+ LY_CHECK_RET(!str, LY_EMEM);
+
+ /* parse the value */
errno = 0;
- strptr = NULL;
- u = strtoull(val_str, &strptr, base);
- if (errno || (strptr == val_str)) {
- return LY_EVALID;
- } else if ((u > max) || (u && (val_str[0] == '-'))) {
- return LY_EDENIED;
- } else if (strptr && *strptr) {
- while (isspace(*strptr)) {
- ++strptr;
+ u = strtoull(str, &ptr, base);
+ if (errno || (ptr == str)) {
+ /* invalid string */
+ rc = LY_EVALID;
+ } else if ((u > max) || (u && (str[0] == '-'))) {
+ /* invalid number */
+ rc = LY_EDENIED;
+ } else if (*ptr) {
+ while (isspace(*ptr)) {
+ ++ptr;
}
- if (*strptr && (strptr < val_str + val_len)) {
- return LY_EVALID;
+ if (*ptr) {
+ /* invalid characters after some number */
+ rc = LY_EVALID;
}
}
- *ret = u;
- return LY_SUCCESS;
+ /* cleanup */
+ free(str);
+ if (!rc) {
+ *ret = u;
+ }
+ return rc;
}
/**
diff --git a/src/plugins_types.c b/src/plugins_types.c
index b227d2e..9ea7fcb 100644
--- a/src/plugins_types.c
+++ b/src/plugins_types.c
@@ -459,8 +459,8 @@
memset(&valcopy[len], '0', fraction_digits);
}
- ret_val = lyplg_type_parse_int("decimal64", LY_BASE_DEC, INT64_C(-9223372036854775807) - INT64_C(1), INT64_C(9223372036854775807),
- valcopy, len, &d, err);
+ ret_val = lyplg_type_parse_int("decimal64", LY_BASE_DEC, INT64_C(-9223372036854775807) - INT64_C(1),
+ INT64_C(9223372036854775807), valcopy, size - 1, &d, err);
if (!ret_val && ret) {
*ret = d;
}