X-Git-Url: http://git.openwrt.org/?p=project%2Flibubox.git;a=blobdiff_plain;f=blobmsg.c;h=93172abb8c63289884cc6cd09e010fb47600dd1f;hp=1a8b783e9ba92b35aff2b1a3ad6912a903b704e1;hb=551d75b5662cccd0466b990d58136bdf799a804d;hpb=4dfd24ed88c4d721d2b26d478b9ada86395d0554 diff --git a/blobmsg.c b/blobmsg.c index 1a8b783..93172ab 100644 --- a/blobmsg.c +++ b/blobmsg.c @@ -25,52 +25,84 @@ static const int blob_type[__BLOBMSG_TYPE_LAST] = { [BLOBMSG_TYPE_UNSPEC] = BLOB_ATTR_BINARY, }; -static uint16_t -blobmsg_namelen(const struct blobmsg_hdr *hdr) +bool blobmsg_check_attr(const struct blob_attr *attr, bool name) { - return be16_to_cpu(hdr->namelen); + return blobmsg_check_attr_len(attr, name, blob_raw_len(attr)); } -bool blobmsg_check_attr(const struct blob_attr *attr, bool name) +static bool blobmsg_check_name(const struct blob_attr *attr, bool name) { const struct blobmsg_hdr *hdr; - const char *data; - size_t len; - int id; + uint16_t namelen; + + if (!blob_is_extended(attr)) + return !name; if (blob_len(attr) < sizeof(struct blobmsg_hdr)) return false; - hdr = (void *) attr->data; - if (!hdr->namelen && name) + hdr = (const struct blobmsg_hdr *)blob_data(attr); + if (name && !hdr->namelen) return false; - if (blobmsg_namelen(hdr) > blob_len(attr) - sizeof(struct blobmsg_hdr)) + namelen = blobmsg_namelen(hdr); + if (blob_len(attr) < (size_t)blobmsg_hdrlen(namelen)) return false; - if (hdr->name[blobmsg_namelen(hdr)] != 0) + if (hdr->name[namelen] != 0) return false; - id = blob_id(attr); - len = blobmsg_data_len(attr); - data = blobmsg_data(attr); + return true; +} + +bool blobmsg_check_attr_len(const struct blob_attr *attr, bool name, size_t len) +{ + const char *data; + size_t data_len; + int id; + if (len < sizeof(struct blob_attr)) + return false; + + data_len = blob_raw_len(attr); + if (data_len < sizeof(struct blob_attr) || data_len > len) + return false; + + if (!blobmsg_check_name(attr, name)) + return false; + + id = blob_id(attr); if (id > BLOBMSG_TYPE_LAST) return false; if (!blob_type[id]) return true; - return blob_check_type(data, len, blob_type[id]); + data = blobmsg_data(attr); + data_len = blobmsg_data_len(attr); + + return blob_check_type(data, data_len, blob_type[id]); } int blobmsg_check_array(const struct blob_attr *attr, int type) +{ + return blobmsg_check_array_len(attr, type, blob_raw_len(attr)); +} + +int blobmsg_check_array_len(const struct blob_attr *attr, int type, + size_t blob_len) { struct blob_attr *cur; - bool name; size_t rem; + bool name; int size = 0; + if (type > BLOBMSG_TYPE_LAST) + return -1; + + if (!blobmsg_check_attr_len(attr, false, blob_len)) + return -1; + switch (blobmsg_type(attr)) { case BLOBMSG_TYPE_TABLE: name = true; @@ -86,7 +118,7 @@ int blobmsg_check_array(const struct blob_attr *attr, int type) if (type != BLOBMSG_TYPE_UNSPEC && blobmsg_type(cur) != type) return -1; - if (!blobmsg_check_attr(cur, name)) + if (!blobmsg_check_attr_len(cur, name, rem)) return -1; size++; @@ -100,6 +132,11 @@ bool blobmsg_check_attr_list(const struct blob_attr *attr, int type) return blobmsg_check_array(attr, type) >= 0; } +bool blobmsg_check_attr_list_len(const struct blob_attr *attr, int type, size_t len) +{ + return blobmsg_check_array_len(attr, type, len) >= 0; +} + int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len, struct blob_attr **tb, void *data, unsigned int len) { @@ -112,7 +149,7 @@ int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len, blob_id(attr) != policy[i].type) continue; - if (!blobmsg_check_attr(attr, false)) + if (!blobmsg_check_attr_len(attr, false, len)) return -1; if (tb[i]) @@ -126,11 +163,10 @@ int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len, return 0; } - int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len, struct blob_attr **tb, void *data, unsigned int len) { - struct blobmsg_hdr *hdr; + const struct blobmsg_hdr *hdr; struct blob_attr *attr; uint8_t *pslen; int i; @@ -147,20 +183,31 @@ int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len, } __blob_for_each_attr(attr, data, len) { + if (!blobmsg_check_attr_len(attr, false, len)) + return -1; + + if (!blob_is_extended(attr)) + continue; + hdr = blob_data(attr); for (i = 0; i < policy_len; i++) { if (!policy[i].name) continue; if (policy[i].type != BLOBMSG_TYPE_UNSPEC && + policy[i].type != BLOBMSG_CAST_INT64 && blob_id(attr) != policy[i].type) continue; - if (blobmsg_namelen(hdr) != pslen[i]) + if (policy[i].type == BLOBMSG_CAST_INT64 && + (blob_id(attr) != BLOBMSG_TYPE_INT64 && + blob_id(attr) != BLOBMSG_TYPE_INT32 && + blob_id(attr) != BLOBMSG_TYPE_INT16 && + blob_id(attr) != BLOBMSG_TYPE_INT8)) continue; - if (!blobmsg_check_attr(attr, true)) - return -1; + if (blobmsg_namelen(hdr) != pslen[i]) + continue; if (tb[i]) continue; @@ -196,7 +243,10 @@ blobmsg_new(struct blob_buf *buf, int type, const char *name, int payload_len, v attr->id_len |= be32_to_cpu(BLOB_ATTR_EXTENDED); hdr = blob_data(attr); hdr->namelen = cpu_to_be16(namelen); - strcpy((char *) hdr->name, (const char *)name); + + memcpy(hdr->name, name, namelen); + hdr->name[namelen] = '\0'; + pad_end = *data = blobmsg_data(attr); pad_start = (char *) &hdr->name[namelen]; if (pad_start < pad_end) @@ -243,10 +293,17 @@ int blobmsg_vprintf(struct blob_buf *buf, const char *name, const char *format, len = vsnprintf(&cbuf, sizeof(cbuf), format, arg2); va_end(arg2); + if (len < 0) + return -1; + sbuf = blobmsg_alloc_string_buffer(buf, name, len + 1); if (!sbuf) return -1; - ret = vsprintf(sbuf, format, arg); + + ret = vsnprintf(sbuf, len + 1, format, arg); + if (ret < 0) + return -1; + blobmsg_add_string_buffer(buf); return ret;