Check for null-termination of strings
[platform/core/base/bundle.git] / src / keyval.c
index 5397f90..d49be0e 100755 (executable)
@@ -1,10 +1,5 @@
 /*
- * bundle
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
- * Jaeho Lee <jaeho81.lee@samsung.com>
+ * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
-
 /**
  * keyval.c
  * Implementation of keyval object
  */
 
+#define _GNU_SOURCE
+#include <stdlib.h>
+
 #include "keyval_type.h"
 #include "keyval.h"
 #include "bundle_log.h"
-#include <stdlib.h>
-#include <errno.h>
-extern int errno;
+#include "bundle.h"
 
 static keyval_method_collection_t method = {
        keyval_free,
@@ -41,117 +35,133 @@ static keyval_method_collection_t method = {
        keyval_decode
 };
 
-keyval_t *
-keyval_new(keyval_t *kv, const char *key, const int type, const void *val, const size_t size)
+keyval_t *keyval_new(keyval_t *kv, const char *key,
+               const int type, const void *val, const size_t size)
 {
-       int must_free_obj;
-       must_free_obj = kv ? 0 : 1;
+       int must_free_obj = kv ? 0 : 1;
+       char *str;
 
-       if(!kv) {       
+       if (!kv) {
                kv = calloc(1, sizeof(keyval_t));
-               if(!kv) {
-                       //errno = ENOMEM;       // set by calloc
+               if (!kv) {
+                       set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
                        return NULL;
                }
        }
 
-       // key
-       if(kv->key) {
+       if (kv->key) {
                keyval_free(kv, must_free_obj);
                return NULL;
        }
+
        kv->key = strdup(key);
-       if(!kv->key) {
-               //errno = ENOMEM;       // set by strdup
+       if (!kv->key) {
+               set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
                keyval_free(kv, must_free_obj);
                return NULL;
        }
 
-       // elementa of primitive types
        kv->type = type;
        kv->size = size;
-       
-       if(size) {
-               kv->val = calloc(1, size);              // allocate memory unconditionally !
-               if(!kv->val) {
-                       errno = ENOMEM;
-                       keyval_free(kv, 1);
+
+       if (size) {
+               kv->val = calloc(1, size);
+               if (!kv->val) {
+                       set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
+                       keyval_free(kv, must_free_obj);
                        return NULL;
                }
-               if(val) {
+               if (val) {
                        memcpy(kv->val, val, size);
+                       if (type == BUNDLE_TYPE_STR) {
+                               str = (char *)kv->val;
+                               if (str[size - 1] != '\0')
+                                       str[size - 1] = '\0';
+                       }
                }
        }
 
-       // Set methods
        kv->method = &method;
 
        return kv;
 }
 
-void
-keyval_free(keyval_t *kv, int do_free_object)
+void keyval_free(keyval_t *kv, int do_free_object)
 {
-       //int i;
+       if (kv == NULL)
+               return;
 
-       if(NULL == kv) return;
-
-       if(kv->key) { 
+       if (kv->key) {
                free(kv->key);
                kv->key = NULL;
        }
 
-       if(NULL != kv->val) {
+       if (kv->val != NULL) {
                free(kv->val);
                kv->val = NULL;
        }
 
-       if(do_free_object) free(kv);
+       if (do_free_object)
+               free(kv);
 
        return;
 }
 
-int
-keyval_get_data(keyval_t *kv, int *type, void **val, size_t *size)
+int keyval_get_data(keyval_t *kv, int *type, void **val, size_t *size)
 {
-       if(!kv) return -EINVAL;
-       if(keyval_type_is_array(kv->type)) return -EINVAL;
+       if (!kv)
+               return BUNDLE_ERROR_INVALID_PARAMETER;
+
+       if (keyval_type_is_array(kv->type))
+               return BUNDLE_ERROR_INVALID_PARAMETER;
 
-       if(type) *type = kv->type;
-       if(val) *val = kv->val;
-       if(size) *size = kv->size;
+       if (type)
+               *type = kv->type;
+       if (val)
+               *val = kv->val;
+       if (size)
+               *size = kv->size;
 
        return 0;
 }
 
-int
-keyval_compare(keyval_t *kv1, keyval_t *kv2)
+/* LCOV_EXCL_START */
+int keyval_compare(keyval_t *kv1, keyval_t *kv2)
 {
-       if(!kv1 || !kv2) return -1;
-
-       if(0 != strcmp(kv1->key, kv2->key)) return 1;
-       if(kv1->type != kv2->type) return 1;
-       if(kv1->size != kv2->size) return 1;
-
-       if(kv1->val == NULL && kv2->val == NULL) return 0;
-       if(kv1->val == NULL || kv2->val == NULL) return 1;
-       if(0 != memcmp(kv1->val, kv2->val, kv1->size)) return 1;
+       if (!kv1 || !kv2)
+               return -1;
+
+       if (strcmp(kv1->key, kv2->key) != 0)
+               return 1;
+       if (kv1->type != kv2->type)
+               return 1;
+       if (kv1->size != kv2->size)
+               return 1;
+
+       if (kv1->val == NULL && kv2->val == NULL)
+               return 0;
+       if (kv1->val == NULL || kv2->val == NULL)
+               return 1;
+       if (memcmp(kv1->val, kv2->val, kv1->size) != 0)
+               return 1;
 
        return 0;
 }
+/* LCOV_EXCL_STOP */
 
-size_t
-keyval_get_encoded_size(keyval_t *kv)
+size_t keyval_get_encoded_size(keyval_t *kv)
 {
-       if(!kv) return 0;
+       size_t encoded_size;
 
-       size_t encoded_size 
-               = sizeof(size_t) // total size
-               + sizeof(int)   // type
-               + sizeof(size_t) // key size
-               + strlen(kv->key) + 1   // key (+ null byte)
-               + sizeof(size_t)        // size
-               + kv->size;                     // val
+       if (!kv)
+               return 0;
+
+       encoded_size = sizeof(size_t)   /* total size */
+               + sizeof(int)           /* type */
+               + sizeof(size_t)        /* key size */
+               + strlen(kv->key) + 1   /* key (+ null byte) */
+               + sizeof(size_t)        /* size */
+               + kv->size;             /* val */
 
        return encoded_size;
 }
@@ -166,36 +176,35 @@ keyval_get_encoded_size(keyval_t *kv)
  * @param[out] byte_len
  * @return byte_len
  */
-size_t
-keyval_encode(keyval_t *kv, unsigned char **byte, size_t *byte_len)
+size_t keyval_encode(keyval_t *kv, unsigned char **byte, size_t *byte_len)
 {
-       /*
-        * type
-        * key size
-        * key
-        * val size
-        * val
-        */
-
        static const size_t sz_type = sizeof(int);
        static const size_t sz_keysize = sizeof(size_t);
        size_t sz_key = strlen(kv->key) + 1;
        static const size_t sz_size = sizeof(size_t);
        size_t sz_val = kv->size;
+       unsigned char *p;
 
        *byte_len = keyval_get_encoded_size(kv);
 
        *byte = calloc(1, *byte_len);
-       if(!*byte) return 0;
-
-       unsigned char *p = *byte;
-       
-       memcpy(p, byte_len, sizeof(size_t)); p += sizeof(size_t);
-       memcpy(p, &(kv->type), sz_type); p += sz_type;
-       memcpy(p, &sz_key, sz_keysize); p += sz_keysize;
-       memcpy(p, kv->key, sz_key); p += sz_key;
-       memcpy(p, &(kv->size), sz_size); p += sz_size;
-       memcpy(p, kv->val, sz_val); p += sz_val;
+       if (!*byte)
+               return 0;
+
+       p = *byte;
+
+       memcpy(p, byte_len, sizeof(size_t));
+       p += sizeof(size_t);
+       memcpy(p, &(kv->type), sz_type);
+       p += sz_type;
+       memcpy(p, &sz_key, sz_keysize);
+       p += sz_keysize;
+       memcpy(p, kv->key, sz_key);
+       p += sz_key;
+       memcpy(p, &(kv->size), sz_size);
+       p += sz_size;
+       memcpy(p, kv->val, sz_val);
+       p += sz_val;
 
        return *byte_len;
 }
@@ -209,40 +218,82 @@ keyval_encode(keyval_t *kv, unsigned char **byte, size_t *byte_len)
  *                  If kv is not NULL, given kv is used. (No new kv is created.)
  * @return        Number of bytes read from byte.
  */
-size_t
-keyval_decode(unsigned char *byte, keyval_t **kv)
+size_t keyval_decode(unsigned char *byte, keyval_t **kv, size_t byte_size)
 {
        static const size_t sz_byte_len = sizeof(size_t);
        static const size_t sz_type = sizeof(int);
        static const size_t sz_keysize = sizeof(size_t);
        static const size_t sz_size = sizeof(size_t);
-
+       size_t byte_len;
+       int type;
+       size_t keysize;
+       char *key;
+       size_t size;
+       void *val;
        unsigned char *p = byte;
+       size_t encoded_size;
 
-       size_t byte_len = *((size_t *)p); p += sz_byte_len;
-       int type = *((int *)p); p += sz_type;
-       size_t keysize = *((size_t *)p); p += sz_keysize;
-       char *key = (char *)p; p += keysize;
-       size_t size = *((size_t *)p); p += sz_size;
-       void *val = (void *)p; p += size;
+       byte_len = *((size_t *)p);
 
-       if(kv) *kv = keyval_new(*kv, key, type, val, size);     // If *kv != NULL, use given kv
+       if (byte_size < sz_byte_len)
+               return 0;
+
+       byte_size -= sz_byte_len;
+       p += sz_byte_len;
+       type = *((int *)p);
+
+       if (byte_size < sz_type)
+               return 0;
+
+       byte_size -= sz_type;
+       p += sz_type;
+       keysize = *((size_t *)p);
+
+       if (byte_size < sz_keysize)
+               return 0;
+
+       byte_size -= sz_keysize;
+       p += sz_keysize;
+       key = (char *)p;
+
+       if (byte_size < keysize)
+               return 0;
+
+       if (!key || (strnlen(key, keysize) + 1) != keysize)
+               return 0;
+
+       byte_size -= keysize;
+       p += keysize;
+       size = *((size_t *)p);
+
+       if (byte_size < sz_size)
+               return 0;
+
+       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)
+               *kv = keyval_new(*kv, key, type, val, size);
 
        return byte_len;
 }
 
-
-int
-keyval_get_type_from_encoded_byte(unsigned char *byte)
+int keyval_get_type_from_encoded_byte(unsigned char *byte)
 {
-       // skip total size (== sizeof(size_t))
        static const size_t sz_byte_len = sizeof(size_t);
+       unsigned char *p = byte;
+       int type;
 
-       unsigned char *p=byte;
-        p += sz_byte_len;
-       int type = *((int *)p);
-       return type; 
+       p += sz_byte_len;
+       type = *((int *)p);
 
-       //return (int )*(byte + sizeof(size_t));
+       return type;
 }
-