Check for null-termination of strings
[platform/core/base/bundle.git] / src / keyval.c
1 /*
2  * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * keyval.c
19  * Implementation of keyval object
20  */
21
22 #define _GNU_SOURCE
23 #include <stdlib.h>
24
25 #include "keyval_type.h"
26 #include "keyval.h"
27 #include "bundle_log.h"
28 #include "bundle.h"
29
30 static keyval_method_collection_t method = {
31         keyval_free,
32         keyval_compare,
33         keyval_get_encoded_size,
34         keyval_encode,
35         keyval_decode
36 };
37
38 keyval_t *keyval_new(keyval_t *kv, const char *key,
39                 const int type, const void *val, const size_t size)
40 {
41         int must_free_obj = kv ? 0 : 1;
42         char *str;
43
44         if (!kv) {
45                 kv = calloc(1, sizeof(keyval_t));
46                 if (!kv) {
47                         set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
48                         return NULL;
49                 }
50         }
51
52         if (kv->key) {
53                 keyval_free(kv, must_free_obj);
54                 return NULL;
55         }
56
57         kv->key = strdup(key);
58         if (!kv->key) {
59                 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
60                 keyval_free(kv, must_free_obj);
61                 return NULL;
62         }
63
64         kv->type = type;
65         kv->size = size;
66
67         if (size) {
68                 kv->val = calloc(1, size);
69                 if (!kv->val) {
70                         set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
71                         keyval_free(kv, must_free_obj);
72                         return NULL;
73                 }
74                 if (val) {
75                         memcpy(kv->val, val, size);
76                         if (type == BUNDLE_TYPE_STR) {
77                                 str = (char *)kv->val;
78                                 if (str[size - 1] != '\0')
79                                         str[size - 1] = '\0';
80                         }
81                 }
82         }
83
84         kv->method = &method;
85
86         return kv;
87 }
88
89 void keyval_free(keyval_t *kv, int do_free_object)
90 {
91         if (kv == NULL)
92                 return;
93
94         if (kv->key) {
95                 free(kv->key);
96                 kv->key = NULL;
97         }
98
99         if (kv->val != NULL) {
100                 free(kv->val);
101                 kv->val = NULL;
102         }
103
104         if (do_free_object)
105                 free(kv);
106
107         return;
108 }
109
110 int keyval_get_data(keyval_t *kv, int *type, void **val, size_t *size)
111 {
112         if (!kv)
113                 return BUNDLE_ERROR_INVALID_PARAMETER;
114
115         if (keyval_type_is_array(kv->type))
116                 return BUNDLE_ERROR_INVALID_PARAMETER;
117
118         if (type)
119                 *type = kv->type;
120         if (val)
121                 *val = kv->val;
122         if (size)
123                 *size = kv->size;
124
125         return 0;
126 }
127
128 /* LCOV_EXCL_START */
129 int keyval_compare(keyval_t *kv1, keyval_t *kv2)
130 {
131         if (!kv1 || !kv2)
132                 return -1;
133
134         if (strcmp(kv1->key, kv2->key) != 0)
135                 return 1;
136         if (kv1->type != kv2->type)
137                 return 1;
138         if (kv1->size != kv2->size)
139                 return 1;
140
141         if (kv1->val == NULL && kv2->val == NULL)
142                 return 0;
143         if (kv1->val == NULL || kv2->val == NULL)
144                 return 1;
145         if (memcmp(kv1->val, kv2->val, kv1->size) != 0)
146                 return 1;
147
148         return 0;
149 }
150 /* LCOV_EXCL_STOP */
151
152 size_t keyval_get_encoded_size(keyval_t *kv)
153 {
154         size_t encoded_size;
155
156         if (!kv)
157                 return 0;
158
159         encoded_size = sizeof(size_t)   /* total size */
160                 + sizeof(int)           /* type */
161                 + sizeof(size_t)        /* key size */
162                 + strlen(kv->key) + 1   /* key (+ null byte) */
163                 + sizeof(size_t)        /* size */
164                 + kv->size;             /* val */
165
166         return encoded_size;
167 }
168
169 /**
170  * encode a keyval to byte
171  *
172  * @pre                 kv must be valid.
173  * @post                byte must be freed.
174  * @param[in]   kv
175  * @param[out]  byte
176  * @param[out]  byte_len
177  * @return byte_len
178  */
179 size_t keyval_encode(keyval_t *kv, unsigned char **byte, size_t *byte_len)
180 {
181         static const size_t sz_type = sizeof(int);
182         static const size_t sz_keysize = sizeof(size_t);
183         size_t sz_key = strlen(kv->key) + 1;
184         static const size_t sz_size = sizeof(size_t);
185         size_t sz_val = kv->size;
186         unsigned char *p;
187
188         *byte_len = keyval_get_encoded_size(kv);
189
190         *byte = calloc(1, *byte_len);
191         if (!*byte)
192                 return 0;
193
194         p = *byte;
195
196         memcpy(p, byte_len, sizeof(size_t));
197         p += sizeof(size_t);
198         memcpy(p, &(kv->type), sz_type);
199         p += sz_type;
200         memcpy(p, &sz_key, sz_keysize);
201         p += sz_keysize;
202         memcpy(p, kv->key, sz_key);
203         p += sz_key;
204         memcpy(p, &(kv->size), sz_size);
205         p += sz_size;
206         memcpy(p, kv->val, sz_val);
207         p += sz_val;
208
209         return *byte_len;
210 }
211
212 /**
213  * decode a byte stream to a keyval
214  *
215  * @param[in]     byte  byte stream.
216  * @param[in|out] kv    keyval.
217  *                  If kv is NULL, new keyval_t object comes.
218  *                  If kv is not NULL, given kv is used. (No new kv is created.)
219  * @return        Number of bytes read from byte.
220  */
221 size_t keyval_decode(unsigned char *byte, keyval_t **kv, size_t byte_size)
222 {
223         static const size_t sz_byte_len = sizeof(size_t);
224         static const size_t sz_type = sizeof(int);
225         static const size_t sz_keysize = sizeof(size_t);
226         static const size_t sz_size = sizeof(size_t);
227         size_t byte_len;
228         int type;
229         size_t keysize;
230         char *key;
231         size_t size;
232         void *val;
233         unsigned char *p = byte;
234         size_t encoded_size;
235
236         byte_len = *((size_t *)p);
237
238         if (byte_size < sz_byte_len)
239                 return 0;
240
241         byte_size -= sz_byte_len;
242         p += sz_byte_len;
243         type = *((int *)p);
244
245         if (byte_size < sz_type)
246                 return 0;
247
248         byte_size -= sz_type;
249         p += sz_type;
250         keysize = *((size_t *)p);
251
252         if (byte_size < sz_keysize)
253                 return 0;
254
255         byte_size -= sz_keysize;
256         p += sz_keysize;
257         key = (char *)p;
258
259         if (byte_size < keysize)
260                 return 0;
261
262         if (!key || (strnlen(key, keysize) + 1) != keysize)
263                 return 0;
264
265         byte_size -= keysize;
266         p += keysize;
267         size = *((size_t *)p);
268
269         if (byte_size < sz_size)
270                 return 0;
271
272         byte_size -= sz_size;
273         p += sz_size;
274         val = (void *)p;
275
276         encoded_size = sz_byte_len + sz_type + sz_keysize + keysize +
277                 sz_size + size;
278         if (encoded_size != byte_len)
279                 return 0;
280
281         p += size;
282
283         if (kv)
284                 *kv = keyval_new(*kv, key, type, val, size);
285
286         return byte_len;
287 }
288
289 int keyval_get_type_from_encoded_byte(unsigned char *byte)
290 {
291         static const size_t sz_byte_len = sizeof(size_t);
292         unsigned char *p = byte;
293         int type;
294
295         p += sz_byte_len;
296         type = *((int *)p);
297
298         return type;
299 }