X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=blobmsg.c;h=d87d60728fcdd89c6df32a2c818b1a2325c7ce81;hb=12bda4bdb1971385fd787737e8eec5a2eeb0deed;hp=7cd0934600deac2f92c98a59cbc51cfa434a25a0;hpb=b0e21553ae8c58d5db8103a0ea4d6095c6e4fe07;p=project%2Flibubox.git diff --git a/blobmsg.c b/blobmsg.c index 7cd0934..d87d607 100644 --- a/blobmsg.c +++ b/blobmsg.c @@ -25,54 +25,36 @@ static const int blob_type[__BLOBMSG_TYPE_LAST] = { [BLOBMSG_TYPE_UNSPEC] = BLOB_ATTR_BINARY, }; -static uint16_t -blobmsg_namelen(const struct blobmsg_hdr *hdr) -{ - return be16_to_cpu(hdr->namelen); -} - bool blobmsg_check_attr(const struct blob_attr *attr, bool name) { return blobmsg_check_attr_len(attr, name, blob_raw_len(attr)); } -static bool blobmsg_check_name(const struct blob_attr *attr, size_t len, bool name) +static bool blobmsg_check_name(const struct blob_attr *attr, bool name) { - char *limit = (char *) attr + len; const struct blobmsg_hdr *hdr; + uint16_t namelen; - hdr = blob_data(attr); - if (name && !hdr->namelen) + if (!blob_is_extended(attr)) + return !name; + + if (blob_len(attr) < sizeof(struct blobmsg_hdr)) return false; - if ((char *) hdr->name + blobmsg_namelen(hdr) > limit) + 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; return true; } -static const char* blobmsg_check_data(const struct blob_attr *attr, size_t len, size_t *data_len) -{ - char *limit = (char *) attr + len; - const char *data; - - *data_len = blobmsg_data_len(attr); - if (*data_len > blob_raw_len(attr)) - return NULL; - - data = blobmsg_data(attr); - if (data + *data_len > limit) - return NULL; - - return data; -} - bool blobmsg_check_attr_len(const struct blob_attr *attr, bool name, size_t len) { const char *data; @@ -82,7 +64,11 @@ bool blobmsg_check_attr_len(const struct blob_attr *attr, bool name, size_t len) if (len < sizeof(struct blob_attr)) return false; - if (!blobmsg_check_name(attr, len, name)) + 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); @@ -92,9 +78,8 @@ bool blobmsg_check_attr_len(const struct blob_attr *attr, bool name, size_t len) if (!blob_type[id]) return true; - data = blobmsg_check_data(attr, len, &data_len); - if (!data) - return false; + data = blobmsg_data(attr); + data_len = blobmsg_data_len(attr); return blob_check_type(data, data_len, blob_type[id]); } @@ -104,16 +89,18 @@ 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 len) +int blobmsg_check_array_len(const struct blob_attr *attr, int type, + size_t blob_len) { struct blob_attr *cur; + size_t rem; bool name; int size = 0; if (type > BLOBMSG_TYPE_LAST) return -1; - if (!blobmsg_check_attr_len(attr, false, len)) + if (!blobmsg_check_attr_len(attr, false, blob_len)) return -1; switch (blobmsg_type(attr)) { @@ -127,11 +114,11 @@ int blobmsg_check_array_len(const struct blob_attr *attr, int type, size_t len) return -1; } - __blobmsg_for_each_attr(cur, attr, len) { + blobmsg_for_each_attr(cur, attr, rem) { if (type != BLOBMSG_TYPE_UNSPEC && blobmsg_type(cur) != type) return -1; - if (!blobmsg_check_attr_len(cur, name, len)) + if (!blobmsg_check_attr_len(cur, name, rem)) return -1; size++; @@ -176,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; @@ -197,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_len(attr, true, len)) - return -1; + if (blobmsg_namelen(hdr) != pslen[i]) + continue; if (tb[i]) continue; @@ -246,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) @@ -293,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); - sbuf = blobmsg_alloc_string_buffer(buf, name, len + 1); + if (len < 0) + return -1; + + sbuf = blobmsg_alloc_string_buffer(buf, name, len); 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; @@ -321,6 +328,7 @@ blobmsg_alloc_string_buffer(struct blob_buf *buf, const char *name, unsigned int struct blob_attr *attr; void *data_dest; + maxlen++; attr = blobmsg_new(buf, BLOBMSG_TYPE_STRING, name, maxlen, &data_dest); if (!attr) return NULL; @@ -336,7 +344,7 @@ blobmsg_realloc_string_buffer(struct blob_buf *buf, unsigned int maxlen) { struct blob_attr *attr = blob_next(buf->head); int offset = attr_to_offset(buf, blob_next(buf->head)) + blob_pad_len(attr) - BLOB_COOKIE; - int required = maxlen - (buf->buflen - offset); + int required = maxlen + 1 - (buf->buflen - offset); if (required <= 0) goto out;