From: Hwankyu Jhun Date: Fri, 1 Sep 2017 05:59:24 +0000 (+0900) Subject: Fix keyval decode functions X-Git-Tag: accepted/tizen/4.0/unified/20170905.175330~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=54aad38ef5913e98edb05284eec10892c1bbb654;p=platform%2Fcore%2Fbase%2Fbundle.git Fix keyval decode functions - Adds byte size check to prevent buffer overflow - Fixes wrong pointer type Change-Id: I30a1b4ab25555327bac2a25861b247824efe7e85 Signed-off-by: Hwankyu Jhun --- 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;