summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHwankyu Jhun <h.jhun@samsung.com>2017-09-01 14:59:24 +0900
committerHwankyu Jhun <h.jhun@samsung.com>2017-09-04 08:19:58 +0900
commit54aad38ef5913e98edb05284eec10892c1bbb654 (patch)
tree0132cb1c1e528ded981245b06afe035e44842e90
parentb8d30ded257e23b9e70c5e63be47f103d5ed34ef (diff)
downloadbundle-54aad38ef5913e98edb05284eec10892c1bbb654.tar.gz
bundle-54aad38ef5913e98edb05284eec10892c1bbb654.tar.bz2
bundle-54aad38ef5913e98edb05284eec10892c1bbb654.zip
Fix keyval decode functions
- Adds byte size check to prevent buffer overflow - Fixes wrong pointer type Change-Id: I30a1b4ab25555327bac2a25861b247824efe7e85 Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
-rw-r--r--src/bundle.c30
-rwxr-xr-xsrc/keyval.c11
-rwxr-xr-xsrc/keyval.h3
-rwxr-xr-xsrc/keyval_array.c12
4 files changed, 46 insertions, 10 deletions
diff --git a/src/bundle.c b/src/bundle.c
index c766ee9..ac0725f 100644
--- a/src/bundle.c
+++ b/src/bundle.c
@@ -508,6 +508,7 @@ bundle *bundle_decode(const bundle_raw *r, const int data_size)
size_t bytes_read;
keyval_t *kv;
int type;
+ size_t byte_size;
if (r == NULL) {
set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
@@ -572,15 +573,17 @@ bundle *bundle_decode(const bundle_raw *r, const int data_size)
while (p_r < d_r + d_len - 1) {
kv = NULL; /* To get a new kv */
+ byte_size = d_r + d_len - 1 - p_r;
+ if (byte_size < sizeof(size_t))
+ break;
+
/* Find type, and use decode function according to type */
type = keyval_get_type_from_encoded_byte(p_r);
if (keyval_type_is_array(type)) {
bytes_read = keyval_array_decode(p_r,
- (keyval_array_t **)&kv,
- d_r + d_len - 1 - p_r);
+ (keyval_array_t **)&kv, byte_size);
} else {
- bytes_read = keyval_decode(p_r, &kv,
- d_r + d_len - 1 - p_r);
+ bytes_read = keyval_decode(p_r, &kv, byte_size);
}
if (kv)
@@ -670,6 +673,7 @@ bundle *bundle_decode_raw(const bundle_raw *r, const int data_size)
size_t bytes_read;
keyval_t *kv;
int type;
+ size_t byte_size;
if (r == NULL) {
set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
@@ -717,15 +721,17 @@ bundle *bundle_decode_raw(const bundle_raw *r, const int data_size)
while (p_r < d_r + d_len - 1) {
kv = NULL; /* To get a new kv */
+ byte_size = d_r + d_len - 1 - p_r;
+ if (byte_size < sizeof(size_t))
+ break;
+
/* Find type, and use decode function according to type */
type = keyval_get_type_from_encoded_byte(p_r);
if (keyval_type_is_array(type)) {
bytes_read = keyval_array_decode(p_r,
- (keyval_array_t **)&kv,
- d_r + d_len - 1 - p_r);
+ (keyval_array_t **)&kv, byte_size);
} else {
- bytes_read = keyval_decode(p_r, &kv,
- d_r + d_len - 1 - p_r);
+ bytes_read = keyval_decode(p_r, &kv, byte_size);
}
if (kv)
@@ -870,6 +876,13 @@ bundle *bundle_import_from_argv(int argc, char **argv)
return NULL;
}
+ if (byte_size < sizeof(size_t)) {
+ free(byte);
+ byte = NULL;
+ byte_size = 0;
+ continue;
+ }
+
type = keyval_get_type_from_encoded_byte(byte);
if (keyval_type_is_array(type)) {
if (keyval_array_decode(byte, &kva, byte_size) == 0) /* TODO: error! */
@@ -883,6 +896,7 @@ bundle *bundle_import_from_argv(int argc, char **argv)
free(byte);
byte = NULL;
+ byte_size = 0;
}
set_last_result(BUNDLE_ERROR_NONE);
diff --git a/src/keyval.c b/src/keyval.c
index ee069c2..8c7a42f 100755
--- a/src/keyval.c
+++ b/src/keyval.c
@@ -223,6 +223,7 @@ size_t keyval_decode(unsigned char *byte, keyval_t **kv, size_t byte_size)
size_t size;
void *val;
unsigned char *p = byte;
+ size_t encoded_size;
byte_len = *((size_t *)p);
@@ -246,6 +247,8 @@ size_t keyval_decode(unsigned char *byte, keyval_t **kv, size_t byte_size)
byte_size -= sz_keysize;
p += sz_keysize;
key = (char *)p;
+ if ((strlen(key) + 1) != keysize)
+ return 0;
if (byte_size < keysize)
return 0;
@@ -260,6 +263,12 @@ size_t keyval_decode(unsigned char *byte, keyval_t **kv, size_t byte_size)
byte_size -= sz_size;
p += sz_size;
val = (void *)p;
+
+ encoded_size = sz_byte_len + sz_type + sz_keysize + keysize +
+ sz_size + size;
+ if (encoded_size != byte_len)
+ return 0;
+
p += size;
if (kv)
@@ -274,7 +283,7 @@ int keyval_get_type_from_encoded_byte(unsigned char *byte)
unsigned char *p = byte;
int type;
- p += sz_byte_len;
+ p += sz_byte_len;
type = *((int *)p);
return type;
diff --git a/src/keyval.h b/src/keyval.h
index 4cf3b6b..1116b6b 100755
--- a/src/keyval.h
+++ b/src/keyval.h
@@ -38,7 +38,8 @@ typedef size_t (*keyval_method_encode_t)(
keyval_t *,
unsigned char **byte,
size_t *byte_len);
-typedef size_t (*keyval_method_decode_t)(unsigned char *byte, keyval_t **kv);
+typedef size_t (*keyval_method_decode_t)(unsigned char *byte, keyval_t **kv,
+ size_t byte_size);
struct keyval_method_collection_t {
keyval_method_free_t free;
diff --git a/src/keyval_array.c b/src/keyval_array.c
index db9d9c0..013531c 100755
--- a/src/keyval_array.c
+++ b/src/keyval_array.c
@@ -335,6 +335,8 @@ size_t keyval_array_decode(void *byte, keyval_array_t **kva, size_t byte_size)
void *array_val;
int i;
size_t elem_size = 0;
+ size_t sum_array_element_size = 0;
+ size_t encoded_size;
/* Get data */
byte_len = *((size_t *)p);
@@ -359,6 +361,8 @@ size_t keyval_array_decode(void *byte, keyval_array_t **kva, size_t byte_size)
byte_size -= sz_keysize;
p += sz_keysize;
key = (char *)p;
+ if ((strlen(key) + 1) != keysize)
+ return 0;
if (byte_size < keysize)
return 0;
@@ -380,6 +384,14 @@ size_t keyval_array_decode(void *byte, keyval_array_t **kva, size_t byte_size)
p += sizeof(size_t) * len;
array_val = (void *)p;
+ for (i = 0; i < len; ++i)
+ sum_array_element_size += array_element_size[i];
+
+ encoded_size = sz_byte_len + sz_type + sz_keysize + keysize +
+ sz_len + (sizeof(size_t) * len) sum_array_element_size;
+ if (encoded_size != byte_len)
+ return 0;
+
*kva = keyval_array_new(NULL, key, type, NULL, len);
for (i = 0; i < len; i++) {
elem_size += i ? array_element_size[i - 1] : 0;