1 /*
2  * This file Copyright (C) 2008-2014 Mnemosyne LLC
3  *
4  * It may be used under the GNU GPL versions 2 or 3
5  * or any future license endorsed by Mnemosyne LLC.
6  *
7  */
8 
9 #if defined(HAVE_USELOCALE) && (!defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 700)
10 #undef _XOPEN_SOURCE
11 #define _XOPEN_SOURCE 700
12 #endif
13 
14 #if defined(HAVE_USELOCALE) && !defined(_GNU_SOURCE)
15 #define _GNU_SOURCE
16 #endif
17 
18 #include <errno.h>
19 #include <stdlib.h> /* strtod(), realloc(), qsort() */
20 #include <string.h>
21 
22 #ifdef _WIN32
23 #include <share.h>
24 #endif
25 
26 #include <locale.h> /* setlocale() */
27 
28 #if defined(HAVE_USELOCALE) && defined(HAVE_XLOCALE_H)
29 #include <xlocale.h>
30 #endif
31 
32 #include <event2/buffer.h>
33 
34 #define __LIBTRANSMISSION_VARIANT_MODULE__
35 
36 #include "transmission.h"
37 #include "ConvertUTF.h"
38 #include "error.h"
39 #include "file.h"
40 #include "log.h"
41 #include "tr-assert.h"
42 #include "utils.h" /* tr_new(), tr_free() */
43 #include "variant.h"
44 #include "variant-common.h"
45 
46 /* don't use newlocale/uselocale on old versions of uClibc because they're buggy.
47  * https://trac.transmissionbt.com/ticket/6006 */
48 #if defined(__UCLIBC__) && !TR_UCLIBC_CHECK_VERSION(0, 9, 34)
49 #undef HAVE_USELOCALE
50 #endif
51 
52 /**
53 ***
54 **/
55 
56 struct locale_context
57 {
58 #ifdef HAVE_USELOCALE
59     locale_t new_locale;
60     locale_t old_locale;
61 #else
62 #if defined(HAVE__CONFIGTHREADLOCALE) && defined(_ENABLE_PER_THREAD_LOCALE)
63     int old_thread_config;
64 #endif
65     int category;
66     char old_locale[128];
67 #endif
68 };
69 
use_numeric_locale(struct locale_context * context,char const * locale_name)70 static void use_numeric_locale(struct locale_context* context, char const* locale_name)
71 {
72 #ifdef HAVE_USELOCALE
73 
74     context->new_locale = newlocale(LC_NUMERIC_MASK, locale_name, NULL);
75     context->old_locale = uselocale(context->new_locale);
76 
77 #else
78 
79 #if defined(HAVE__CONFIGTHREADLOCALE) && defined(_ENABLE_PER_THREAD_LOCALE)
80     context->old_thread_config = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
81 #endif
82 
83     context->category = LC_NUMERIC;
84     tr_strlcpy(context->old_locale, setlocale(context->category, NULL), sizeof(context->old_locale));
85     setlocale(context->category, locale_name);
86 
87 #endif
88 }
89 
restore_locale(struct locale_context * context)90 static void restore_locale(struct locale_context* context)
91 {
92 #ifdef HAVE_USELOCALE
93 
94     uselocale(context->old_locale);
95     freelocale(context->new_locale);
96 
97 #else
98 
99     setlocale(context->category, context->old_locale);
100 
101 #if defined(HAVE__CONFIGTHREADLOCALE) && defined(_ENABLE_PER_THREAD_LOCALE)
102     _configthreadlocale(context->old_thread_config);
103 #endif
104 
105 #endif
106 }
107 
108 /***
109 ****
110 ***/
111 
tr_variantIsContainer(tr_variant const * v)112 static bool tr_variantIsContainer(tr_variant const* v)
113 {
114     return tr_variantIsList(v) || tr_variantIsDict(v);
115 }
116 
tr_variantIsSomething(tr_variant const * v)117 static bool tr_variantIsSomething(tr_variant const* v)
118 {
119     return tr_variantIsContainer(v) || tr_variantIsInt(v) || tr_variantIsString(v) || tr_variantIsReal(v) ||
120         tr_variantIsBool(v);
121 }
122 
tr_variantInit(tr_variant * v,char type)123 void tr_variantInit(tr_variant* v, char type)
124 {
125     v->type = type;
126     memset(&v->val, 0, sizeof(v->val));
127 }
128 
129 /***
130 ****
131 ***/
132 
133 static struct tr_variant_string const STRING_INIT =
134 {
135     .type = TR_STRING_TYPE_QUARK,
136     .quark = TR_KEY_NONE,
137     .len = 0,
138     .str.str = ""
139 };
140 
tr_variant_string_clear(struct tr_variant_string * str)141 static void tr_variant_string_clear(struct tr_variant_string* str)
142 {
143     if (str->type == TR_STRING_TYPE_HEAP)
144     {
145         tr_free((char*)(str->str.str));
146     }
147 
148     *str = STRING_INIT;
149 }
150 
151 /* returns a const pointer to the variant's string */
tr_variant_string_get_string(struct tr_variant_string const * str)152 static char const* tr_variant_string_get_string(struct tr_variant_string const* str)
153 {
154     char const* ret;
155 
156     switch (str->type)
157     {
158     case TR_STRING_TYPE_BUF:
159         ret = str->str.buf;
160         break;
161 
162     case TR_STRING_TYPE_HEAP:
163         ret = str->str.str;
164         break;
165 
166     case TR_STRING_TYPE_QUARK:
167         ret = str->str.str;
168         break;
169 
170     default:
171         ret = NULL;
172     }
173 
174     return ret;
175 }
176 
tr_variant_string_set_quark(struct tr_variant_string * str,tr_quark const quark)177 static void tr_variant_string_set_quark(struct tr_variant_string* str, tr_quark const quark)
178 {
179     tr_variant_string_clear(str);
180 
181     str->type = TR_STRING_TYPE_QUARK;
182     str->quark = quark;
183     str->str.str = tr_quark_get_string(quark, &str->len);
184 }
185 
tr_variant_string_set_string(struct tr_variant_string * str,char const * bytes,size_t len)186 static void tr_variant_string_set_string(struct tr_variant_string* str, char const* bytes, size_t len)
187 {
188     tr_variant_string_clear(str);
189 
190     if (bytes == NULL)
191     {
192         len = 0;
193     }
194     else if (len == TR_BAD_SIZE)
195     {
196         len = strlen(bytes);
197     }
198 
199     if (len < sizeof(str->str.buf))
200     {
201         str->type = TR_STRING_TYPE_BUF;
202         memcpy(str->str.buf, bytes, len);
203         str->str.buf[len] = '\0';
204         str->len = len;
205     }
206     else
207     {
208         char* tmp = tr_new(char, len + 1);
209         memcpy(tmp, bytes, len);
210         tmp[len] = '\0';
211         str->type = TR_STRING_TYPE_HEAP;
212         str->str.str = tmp;
213         str->len = len;
214     }
215 }
216 
217 /***
218 ****
219 ***/
220 
getStr(tr_variant const * v)221 static inline char const* getStr(tr_variant const* v)
222 {
223     TR_ASSERT(tr_variantIsString(v));
224 
225     return tr_variant_string_get_string(&v->val.s);
226 }
227 
dictIndexOf(tr_variant const * dict,tr_quark const key)228 static int dictIndexOf(tr_variant const* dict, tr_quark const key)
229 {
230     if (tr_variantIsDict(dict))
231     {
232         for (size_t i = 0; i < dict->val.l.count; ++i)
233         {
234             if (dict->val.l.vals[i].key == key)
235             {
236                 return (int)i;
237             }
238         }
239     }
240 
241     return -1;
242 }
243 
tr_variantDictFind(tr_variant * dict,tr_quark const key)244 tr_variant* tr_variantDictFind(tr_variant* dict, tr_quark const key)
245 {
246     int const i = dictIndexOf(dict, key);
247 
248     return i < 0 ? NULL : dict->val.l.vals + i;
249 }
250 
tr_variantDictFindType(tr_variant * dict,tr_quark const key,int type,tr_variant ** setme)251 static bool tr_variantDictFindType(tr_variant* dict, tr_quark const key, int type, tr_variant** setme)
252 {
253     *setme = tr_variantDictFind(dict, key);
254     return tr_variantIsType(*setme, type);
255 }
256 
tr_variantListSize(tr_variant const * list)257 size_t tr_variantListSize(tr_variant const* list)
258 {
259     return tr_variantIsList(list) ? list->val.l.count : 0;
260 }
261 
tr_variantListChild(tr_variant * v,size_t i)262 tr_variant* tr_variantListChild(tr_variant* v, size_t i)
263 {
264     tr_variant* ret = NULL;
265 
266     if (tr_variantIsList(v) && i < v->val.l.count)
267     {
268         ret = v->val.l.vals + i;
269     }
270 
271     return ret;
272 }
273 
tr_variantListRemove(tr_variant * list,size_t i)274 bool tr_variantListRemove(tr_variant* list, size_t i)
275 {
276     bool removed = false;
277 
278     if (tr_variantIsList(list) && i < list->val.l.count)
279     {
280         removed = true;
281         tr_variantFree(&list->val.l.vals[i]);
282         tr_removeElementFromArray(list->val.l.vals, i, sizeof(tr_variant), list->val.l.count);
283         --list->val.l.count;
284     }
285 
286     return removed;
287 }
288 
tr_variantGetInt(tr_variant const * v,int64_t * setme)289 bool tr_variantGetInt(tr_variant const* v, int64_t* setme)
290 {
291     bool success = false;
292 
293     if (tr_variantIsInt(v))
294     {
295         if (setme != NULL)
296         {
297             *setme = v->val.i;
298         }
299 
300         success = true;
301     }
302 
303     if (!success && tr_variantIsBool(v))
304     {
305         if (setme != NULL)
306         {
307             *setme = v->val.b ? 1 : 0;
308         }
309 
310         success = true;
311     }
312 
313     return success;
314 }
315 
tr_variantGetStr(tr_variant const * v,char const ** setme,size_t * len)316 bool tr_variantGetStr(tr_variant const* v, char const** setme, size_t* len)
317 {
318     bool const success = tr_variantIsString(v);
319 
320     if (success)
321     {
322         *setme = getStr(v);
323     }
324 
325     if (len != NULL)
326     {
327         *len = success ? v->val.s.len : 0;
328     }
329 
330     return success;
331 }
332 
tr_variantGetRaw(tr_variant const * v,uint8_t const ** setme_raw,size_t * setme_len)333 bool tr_variantGetRaw(tr_variant const* v, uint8_t const** setme_raw, size_t* setme_len)
334 {
335     bool const success = tr_variantIsString(v);
336 
337     if (success)
338     {
339         *setme_raw = (uint8_t*)getStr(v);
340         *setme_len = v->val.s.len;
341     }
342 
343     return success;
344 }
345 
tr_variantGetBool(tr_variant const * v,bool * setme)346 bool tr_variantGetBool(tr_variant const* v, bool* setme)
347 {
348     char const* str;
349     bool success = false;
350 
351     if (tr_variantIsBool(v))
352     {
353         *setme = v->val.b;
354         success = true;
355     }
356 
357     if (!success && tr_variantIsInt(v))
358     {
359         if (v->val.i == 0 || v->val.i == 1)
360         {
361             *setme = v->val.i != 0;
362             success = true;
363         }
364     }
365 
366     if (!success && tr_variantGetStr(v, &str, NULL))
367     {
368         if (strcmp(str, "true") == 0 || strcmp(str, "false") == 0)
369         {
370             *setme = strcmp(str, "true") == 0;
371             success = true;
372         }
373     }
374 
375     return success;
376 }
377 
tr_variantGetReal(tr_variant const * v,double * setme)378 bool tr_variantGetReal(tr_variant const* v, double* setme)
379 {
380     bool success = false;
381 
382     if (tr_variantIsReal(v))
383     {
384         *setme = v->val.d;
385         success = true;
386     }
387 
388     if (!success && tr_variantIsInt(v))
389     {
390         *setme = v->val.i;
391         success = true;
392     }
393 
394     if (!success && tr_variantIsString(v))
395     {
396         char* endptr;
397         struct locale_context locale_ctx;
398         double d;
399 
400         /* the json spec requires a '.' decimal point regardless of locale */
401         use_numeric_locale(&locale_ctx, "C");
402         d = strtod(getStr(v), &endptr);
403         restore_locale(&locale_ctx);
404 
405         if (getStr(v) != endptr && *endptr == '\0')
406         {
407             *setme = d;
408             success = true;
409         }
410     }
411 
412     return success;
413 }
414 
tr_variantDictFindInt(tr_variant * dict,tr_quark const key,int64_t * setme)415 bool tr_variantDictFindInt(tr_variant* dict, tr_quark const key, int64_t* setme)
416 {
417     tr_variant* child = tr_variantDictFind(dict, key);
418     return tr_variantGetInt(child, setme);
419 }
420 
tr_variantDictFindBool(tr_variant * dict,tr_quark const key,bool * setme)421 bool tr_variantDictFindBool(tr_variant* dict, tr_quark const key, bool* setme)
422 {
423     tr_variant* child = tr_variantDictFind(dict, key);
424     return tr_variantGetBool(child, setme);
425 }
426 
tr_variantDictFindReal(tr_variant * dict,tr_quark const key,double * setme)427 bool tr_variantDictFindReal(tr_variant* dict, tr_quark const key, double* setme)
428 {
429     tr_variant* child = tr_variantDictFind(dict, key);
430     return tr_variantGetReal(child, setme);
431 }
432 
tr_variantDictFindStr(tr_variant * dict,tr_quark const key,char const ** setme,size_t * len)433 bool tr_variantDictFindStr(tr_variant* dict, tr_quark const key, char const** setme, size_t* len)
434 {
435     tr_variant* child = tr_variantDictFind(dict, key);
436     return tr_variantGetStr(child, setme, len);
437 }
438 
tr_variantDictFindList(tr_variant * dict,tr_quark const key,tr_variant ** setme)439 bool tr_variantDictFindList(tr_variant* dict, tr_quark const key, tr_variant** setme)
440 {
441     return tr_variantDictFindType(dict, key, TR_VARIANT_TYPE_LIST, setme);
442 }
443 
tr_variantDictFindDict(tr_variant * dict,tr_quark const key,tr_variant ** setme)444 bool tr_variantDictFindDict(tr_variant* dict, tr_quark const key, tr_variant** setme)
445 {
446     return tr_variantDictFindType(dict, key, TR_VARIANT_TYPE_DICT, setme);
447 }
448 
tr_variantDictFindRaw(tr_variant * dict,tr_quark const key,uint8_t const ** setme_raw,size_t * setme_len)449 bool tr_variantDictFindRaw(tr_variant* dict, tr_quark const key, uint8_t const** setme_raw, size_t* setme_len)
450 {
451     tr_variant* child = tr_variantDictFind(dict, key);
452     return tr_variantGetRaw(child, setme_raw, setme_len);
453 }
454 
455 /***
456 ****
457 ***/
458 
tr_variantInitRaw(tr_variant * v,void const * src,size_t byteCount)459 void tr_variantInitRaw(tr_variant* v, void const* src, size_t byteCount)
460 {
461     tr_variantInit(v, TR_VARIANT_TYPE_STR);
462     tr_variant_string_set_string(&v->val.s, src, byteCount);
463 }
464 
tr_variantInitQuark(tr_variant * v,tr_quark const q)465 void tr_variantInitQuark(tr_variant* v, tr_quark const q)
466 {
467     tr_variantInit(v, TR_VARIANT_TYPE_STR);
468     tr_variant_string_set_quark(&v->val.s, q);
469 }
470 
tr_variantInitStr(tr_variant * v,void const * str,size_t len)471 void tr_variantInitStr(tr_variant* v, void const* str, size_t len)
472 {
473     tr_variantInit(v, TR_VARIANT_TYPE_STR);
474     tr_variant_string_set_string(&v->val.s, str, len);
475 }
476 
tr_variantInitBool(tr_variant * v,bool value)477 void tr_variantInitBool(tr_variant* v, bool value)
478 {
479     tr_variantInit(v, TR_VARIANT_TYPE_BOOL);
480     v->val.b = value != 0;
481 }
482 
tr_variantInitReal(tr_variant * v,double value)483 void tr_variantInitReal(tr_variant* v, double value)
484 {
485     tr_variantInit(v, TR_VARIANT_TYPE_REAL);
486     v->val.d = value;
487 }
488 
tr_variantInitInt(tr_variant * v,int64_t value)489 void tr_variantInitInt(tr_variant* v, int64_t value)
490 {
491     tr_variantInit(v, TR_VARIANT_TYPE_INT);
492     v->val.i = value;
493 }
494 
tr_variantInitList(tr_variant * v,size_t reserve_count)495 void tr_variantInitList(tr_variant* v, size_t reserve_count)
496 {
497     tr_variantInit(v, TR_VARIANT_TYPE_LIST);
498     tr_variantListReserve(v, reserve_count);
499 }
500 
containerReserve(tr_variant * v,size_t count)501 static void containerReserve(tr_variant* v, size_t count)
502 {
503     TR_ASSERT(tr_variantIsContainer(v));
504 
505     size_t const needed = v->val.l.count + count;
506 
507     if (needed > v->val.l.alloc)
508     {
509         /* scale the alloc size in powers-of-2 */
510         size_t n = v->val.l.alloc != 0 ? v->val.l.alloc : 8;
511 
512         while (n < needed)
513         {
514             n *= 2U;
515         }
516 
517         v->val.l.vals = tr_renew(tr_variant, v->val.l.vals, n);
518         v->val.l.alloc = n;
519     }
520 }
521 
tr_variantListReserve(tr_variant * list,size_t count)522 void tr_variantListReserve(tr_variant* list, size_t count)
523 {
524     TR_ASSERT(tr_variantIsList(list));
525 
526     containerReserve(list, count);
527 }
528 
tr_variantInitDict(tr_variant * v,size_t reserve_count)529 void tr_variantInitDict(tr_variant* v, size_t reserve_count)
530 {
531     tr_variantInit(v, TR_VARIANT_TYPE_DICT);
532     tr_variantDictReserve(v, reserve_count);
533 }
534 
tr_variantDictReserve(tr_variant * dict,size_t reserve_count)535 void tr_variantDictReserve(tr_variant* dict, size_t reserve_count)
536 {
537     TR_ASSERT(tr_variantIsDict(dict));
538 
539     containerReserve(dict, reserve_count);
540 }
541 
tr_variantListAdd(tr_variant * list)542 tr_variant* tr_variantListAdd(tr_variant* list)
543 {
544     TR_ASSERT(tr_variantIsList(list));
545 
546     containerReserve(list, 1);
547 
548     tr_variant* child = &list->val.l.vals[list->val.l.count++];
549     child->key = 0;
550     tr_variantInit(child, TR_VARIANT_TYPE_INT);
551 
552     return child;
553 }
554 
tr_variantListAddInt(tr_variant * list,int64_t val)555 tr_variant* tr_variantListAddInt(tr_variant* list, int64_t val)
556 {
557     tr_variant* child = tr_variantListAdd(list);
558     tr_variantInitInt(child, val);
559     return child;
560 }
561 
tr_variantListAddReal(tr_variant * list,double val)562 tr_variant* tr_variantListAddReal(tr_variant* list, double val)
563 {
564     tr_variant* child = tr_variantListAdd(list);
565     tr_variantInitReal(child, val);
566     return child;
567 }
568 
tr_variantListAddBool(tr_variant * list,bool val)569 tr_variant* tr_variantListAddBool(tr_variant* list, bool val)
570 {
571     tr_variant* child = tr_variantListAdd(list);
572     tr_variantInitBool(child, val);
573     return child;
574 }
575 
tr_variantListAddStr(tr_variant * list,char const * val)576 tr_variant* tr_variantListAddStr(tr_variant* list, char const* val)
577 {
578     tr_variant* child = tr_variantListAdd(list);
579     tr_variantInitStr(child, val, TR_BAD_SIZE);
580     return child;
581 }
582 
tr_variantListAddQuark(tr_variant * list,tr_quark const val)583 tr_variant* tr_variantListAddQuark(tr_variant* list, tr_quark const val)
584 {
585     tr_variant* child = tr_variantListAdd(list);
586     tr_variantInitQuark(child, val);
587     return child;
588 }
589 
tr_variantListAddRaw(tr_variant * list,void const * val,size_t len)590 tr_variant* tr_variantListAddRaw(tr_variant* list, void const* val, size_t len)
591 {
592     tr_variant* child = tr_variantListAdd(list);
593     tr_variantInitRaw(child, val, len);
594     return child;
595 }
596 
tr_variantListAddList(tr_variant * list,size_t reserve_count)597 tr_variant* tr_variantListAddList(tr_variant* list, size_t reserve_count)
598 {
599     tr_variant* child = tr_variantListAdd(list);
600     tr_variantInitList(child, reserve_count);
601     return child;
602 }
603 
tr_variantListAddDict(tr_variant * list,size_t reserve_count)604 tr_variant* tr_variantListAddDict(tr_variant* list, size_t reserve_count)
605 {
606     tr_variant* child = tr_variantListAdd(list);
607     tr_variantInitDict(child, reserve_count);
608     return child;
609 }
610 
tr_variantDictAdd(tr_variant * dict,tr_quark const key)611 tr_variant* tr_variantDictAdd(tr_variant* dict, tr_quark const key)
612 {
613     TR_ASSERT(tr_variantIsDict(dict));
614 
615     containerReserve(dict, 1);
616 
617     tr_variant* val = dict->val.l.vals + dict->val.l.count++;
618     tr_variantInit(val, TR_VARIANT_TYPE_INT);
619     val->key = key;
620 
621     return val;
622 }
623 
dictFindOrAdd(tr_variant * dict,tr_quark const key,int type)624 static tr_variant* dictFindOrAdd(tr_variant* dict, tr_quark const key, int type)
625 {
626     tr_variant* child;
627 
628     /* see if it already exists, and if so, try to reuse it */
629     if ((child = tr_variantDictFind(dict, key)) != NULL)
630     {
631         if (!tr_variantIsType(child, type))
632         {
633             tr_variantDictRemove(dict, key);
634             child = NULL;
635         }
636         else if (child->type == TR_VARIANT_TYPE_STR)
637         {
638             tr_variant_string_clear(&child->val.s);
639         }
640     }
641 
642     /* if it doesn't exist, create it */
643     if (child == NULL)
644     {
645         child = tr_variantDictAdd(dict, key);
646     }
647 
648     return child;
649 }
650 
tr_variantDictAddInt(tr_variant * dict,tr_quark const key,int64_t val)651 tr_variant* tr_variantDictAddInt(tr_variant* dict, tr_quark const key, int64_t val)
652 {
653     tr_variant* child = dictFindOrAdd(dict, key, TR_VARIANT_TYPE_INT);
654     tr_variantInitInt(child, val);
655     return child;
656 }
657 
tr_variantDictAddBool(tr_variant * dict,tr_quark const key,bool val)658 tr_variant* tr_variantDictAddBool(tr_variant* dict, tr_quark const key, bool val)
659 {
660     tr_variant* child = dictFindOrAdd(dict, key, TR_VARIANT_TYPE_BOOL);
661     tr_variantInitBool(child, val);
662     return child;
663 }
664 
tr_variantDictAddReal(tr_variant * dict,tr_quark const key,double val)665 tr_variant* tr_variantDictAddReal(tr_variant* dict, tr_quark const key, double val)
666 {
667     tr_variant* child = dictFindOrAdd(dict, key, TR_VARIANT_TYPE_REAL);
668     tr_variantInitReal(child, val);
669     return child;
670 }
671 
tr_variantDictAddQuark(tr_variant * dict,tr_quark const key,tr_quark const val)672 tr_variant* tr_variantDictAddQuark(tr_variant* dict, tr_quark const key, tr_quark const val)
673 {
674     tr_variant* child = dictFindOrAdd(dict, key, TR_VARIANT_TYPE_STR);
675     tr_variantInitQuark(child, val);
676     return child;
677 }
678 
tr_variantDictAddStr(tr_variant * dict,tr_quark const key,char const * val)679 tr_variant* tr_variantDictAddStr(tr_variant* dict, tr_quark const key, char const* val)
680 {
681     tr_variant* child = dictFindOrAdd(dict, key, TR_VARIANT_TYPE_STR);
682     tr_variantInitStr(child, val, TR_BAD_SIZE);
683     return child;
684 }
685 
tr_variantDictAddRaw(tr_variant * dict,tr_quark const key,void const * src,size_t len)686 tr_variant* tr_variantDictAddRaw(tr_variant* dict, tr_quark const key, void const* src, size_t len)
687 {
688     tr_variant* child = dictFindOrAdd(dict, key, TR_VARIANT_TYPE_STR);
689     tr_variantInitRaw(child, src, len);
690     return child;
691 }
692 
tr_variantDictAddList(tr_variant * dict,tr_quark const key,size_t reserve_count)693 tr_variant* tr_variantDictAddList(tr_variant* dict, tr_quark const key, size_t reserve_count)
694 {
695     tr_variant* child = tr_variantDictAdd(dict, key);
696     tr_variantInitList(child, reserve_count);
697     return child;
698 }
699 
tr_variantDictAddDict(tr_variant * dict,tr_quark const key,size_t reserve_count)700 tr_variant* tr_variantDictAddDict(tr_variant* dict, tr_quark const key, size_t reserve_count)
701 {
702     tr_variant* child = tr_variantDictAdd(dict, key);
703     tr_variantInitDict(child, reserve_count);
704     return child;
705 }
706 
tr_variantDictSteal(tr_variant * dict,tr_quark const key,tr_variant * value)707 tr_variant* tr_variantDictSteal(tr_variant* dict, tr_quark const key, tr_variant* value)
708 {
709     tr_variant* child = tr_variantDictAdd(dict, key);
710     *child = *value;
711     child->key = key;
712     tr_variantInit(value, value->type);
713     return child;
714 }
715 
tr_variantDictRemove(tr_variant * dict,tr_quark const key)716 bool tr_variantDictRemove(tr_variant* dict, tr_quark const key)
717 {
718     bool removed = false;
719     int const i = dictIndexOf(dict, key);
720 
721     if (i >= 0)
722     {
723         int const last = dict->val.l.count - 1;
724 
725         tr_variantFree(&dict->val.l.vals[i]);
726 
727         if (i != last)
728         {
729             dict->val.l.vals[i] = dict->val.l.vals[last];
730         }
731 
732         --dict->val.l.count;
733 
734         removed = true;
735     }
736 
737     return removed;
738 }
739 
740 /***
741 ****  BENC WALKING
742 ***/
743 
744 struct KeyIndex
745 {
746     char const* keystr;
747     tr_variant* val;
748 };
749 
compareKeyIndex(void const * va,void const * vb)750 static int compareKeyIndex(void const* va, void const* vb)
751 {
752     struct KeyIndex const* a = va;
753     struct KeyIndex const* b = vb;
754 
755     return strcmp(a->keystr, b->keystr);
756 }
757 
758 struct SaveNode
759 {
760     tr_variant const* v;
761     tr_variant* sorted;
762     size_t childIndex;
763     bool isVisited;
764 };
765 
nodeConstruct(struct SaveNode * node,tr_variant const * v,bool sort_dicts)766 static void nodeConstruct(struct SaveNode* node, tr_variant const* v, bool sort_dicts)
767 {
768     node->isVisited = false;
769     node->childIndex = 0;
770 
771     if (sort_dicts && tr_variantIsDict(v))
772     {
773         /* make node->sorted a sorted version of this dictionary */
774 
775         size_t const n = v->val.l.count;
776         struct KeyIndex* tmp = tr_new(struct KeyIndex, n);
777 
778         for (size_t i = 0; i < n; i++)
779         {
780             tmp[i].val = v->val.l.vals + i;
781             tmp[i].keystr = tr_quark_get_string(tmp[i].val->key, NULL);
782         }
783 
784         qsort(tmp, n, sizeof(struct KeyIndex), compareKeyIndex);
785 
786         node->sorted = tr_new(tr_variant, 1);
787         tr_variantInitDict(node->sorted, n);
788 
789         for (size_t i = 0; i < n; ++i)
790         {
791             node->sorted->val.l.vals[i] = *tmp[i].val;
792         }
793 
794         node->sorted->val.l.count = n;
795 
796         tr_free(tmp);
797 
798         v = node->sorted;
799     }
800     else
801     {
802         node->sorted = NULL;
803     }
804 
805     node->v = v;
806 }
807 
nodeDestruct(struct SaveNode * node)808 static void nodeDestruct(struct SaveNode* node)
809 {
810     TR_ASSERT(node != NULL);
811 
812     if (node->sorted != NULL)
813     {
814         tr_free(node->sorted->val.l.vals);
815         tr_free(node->sorted);
816     }
817 }
818 
819 /**
820  * This function's previous recursive implementation was
821  * easier to read, but was vulnerable to a smash-stacking
822  * attack via maliciously-crafted data. (#667)
823  */
tr_variantWalk(tr_variant const * v,struct VariantWalkFuncs const * walkFuncs,void * user_data,bool sort_dicts)824 void tr_variantWalk(tr_variant const* v, struct VariantWalkFuncs const* walkFuncs, void* user_data, bool sort_dicts)
825 {
826     int stackSize = 0;
827     int stackAlloc = 64;
828     struct SaveNode* stack = tr_new(struct SaveNode, stackAlloc);
829 
830     nodeConstruct(&stack[stackSize++], v, sort_dicts);
831 
832     while (stackSize > 0)
833     {
834         struct SaveNode* node = &stack[stackSize - 1];
835         tr_variant const* v;
836 
837         if (!node->isVisited)
838         {
839             v = node->v;
840             node->isVisited = true;
841         }
842         else if (tr_variantIsContainer(node->v) && node->childIndex < node->v->val.l.count)
843         {
844             int const index = node->childIndex;
845             ++node->childIndex;
846 
847             v = node->v->val.l.vals + index;
848 
849             if (tr_variantIsDict(node->v))
850             {
851                 tr_variant tmp;
852                 tr_variantInitQuark(&tmp, v->key);
853                 walkFuncs->stringFunc(&tmp, user_data);
854             }
855         }
856         else /* done with this node */
857         {
858             if (tr_variantIsContainer(node->v))
859             {
860                 walkFuncs->containerEndFunc(node->v, user_data);
861             }
862 
863             --stackSize;
864             nodeDestruct(node);
865             continue;
866         }
867 
868         if (v != NULL)
869         {
870             switch (v->type)
871             {
872             case TR_VARIANT_TYPE_INT:
873                 walkFuncs->intFunc(v, user_data);
874                 break;
875 
876             case TR_VARIANT_TYPE_BOOL:
877                 walkFuncs->boolFunc(v, user_data);
878                 break;
879 
880             case TR_VARIANT_TYPE_REAL:
881                 walkFuncs->realFunc(v, user_data);
882                 break;
883 
884             case TR_VARIANT_TYPE_STR:
885                 walkFuncs->stringFunc(v, user_data);
886                 break;
887 
888             case TR_VARIANT_TYPE_LIST:
889                 if (v == node->v)
890                 {
891                     walkFuncs->listBeginFunc(v, user_data);
892                 }
893                 else
894                 {
895                     if (stackAlloc == stackSize)
896                     {
897                         stackAlloc *= 2;
898                         stack = tr_renew(struct SaveNode, stack, stackAlloc);
899                     }
900 
901                     nodeConstruct(&stack[stackSize++], v, sort_dicts);
902                 }
903 
904                 break;
905 
906             case TR_VARIANT_TYPE_DICT:
907                 if (v == node->v)
908                 {
909                     walkFuncs->dictBeginFunc(v, user_data);
910                 }
911                 else
912                 {
913                     if (stackAlloc == stackSize)
914                     {
915                         stackAlloc *= 2;
916                         stack = tr_renew(struct SaveNode, stack, stackAlloc);
917                     }
918 
919                     nodeConstruct(&stack[stackSize++], v, sort_dicts);
920                 }
921 
922                 break;
923 
924             default:
925                 /* did caller give us an uninitialized val? */
926                 tr_logAddError("%s", _("Invalid metadata"));
927                 break;
928             }
929         }
930     }
931 
932     tr_free(stack);
933 }
934 
935 /****
936 *****
937 ****/
938 
freeDummyFunc(tr_variant const * v UNUSED,void * buf UNUSED)939 static void freeDummyFunc(tr_variant const* v UNUSED, void* buf UNUSED)
940 {
941 }
942 
freeStringFunc(tr_variant const * v,void * unused UNUSED)943 static void freeStringFunc(tr_variant const* v, void* unused UNUSED)
944 {
945     tr_variant_string_clear(&((tr_variant*)v)->val.s);
946 }
947 
freeContainerEndFunc(tr_variant const * v,void * unused UNUSED)948 static void freeContainerEndFunc(tr_variant const* v, void* unused UNUSED)
949 {
950     tr_free(v->val.l.vals);
951 }
952 
953 static struct VariantWalkFuncs const freeWalkFuncs =
954 {
955     freeDummyFunc,
956     freeDummyFunc,
957     freeDummyFunc,
958     freeStringFunc,
959     freeDummyFunc,
960     freeDummyFunc,
961     freeContainerEndFunc
962 };
963 
tr_variantFree(tr_variant * v)964 void tr_variantFree(tr_variant* v)
965 {
966     if (tr_variantIsSomething(v))
967     {
968         tr_variantWalk(v, &freeWalkFuncs, NULL, false);
969     }
970 }
971 
972 /***
973 ****
974 ***/
975 
tr_variantListCopy(tr_variant * target,tr_variant const * src)976 static void tr_variantListCopy(tr_variant* target, tr_variant const* src)
977 {
978     int i = 0;
979     tr_variant const* val;
980 
981     while ((val = tr_variantListChild((tr_variant*)src, i)) != NULL)
982     {
983         if (tr_variantIsBool(val))
984         {
985             bool boolVal = false;
986             tr_variantGetBool(val, &boolVal);
987             tr_variantListAddBool(target, boolVal);
988         }
989         else if (tr_variantIsReal(val))
990         {
991             double realVal = 0;
992             tr_variantGetReal(val, &realVal);
993             tr_variantListAddReal(target, realVal);
994         }
995         else if (tr_variantIsInt(val))
996         {
997             int64_t intVal = 0;
998             tr_variantGetInt(val, &intVal);
999             tr_variantListAddInt(target, intVal);
1000         }
1001         else if (tr_variantIsString(val))
1002         {
1003             size_t len;
1004             char const* str;
1005             tr_variantGetStr(val, &str, &len);
1006             tr_variantListAddRaw(target, str, len);
1007         }
1008         else if (tr_variantIsDict(val))
1009         {
1010             tr_variantMergeDicts(tr_variantListAddDict(target, 0), val);
1011         }
1012         else if (tr_variantIsList(val))
1013         {
1014             tr_variantListCopy(tr_variantListAddList(target, 0), val);
1015         }
1016         else
1017         {
1018             tr_logAddError("tr_variantListCopy skipping item");
1019         }
1020 
1021         ++i;
1022     }
1023 }
1024 
tr_variantDictSize(tr_variant const * dict)1025 static size_t tr_variantDictSize(tr_variant const* dict)
1026 {
1027     return tr_variantIsDict(dict) ? dict->val.l.count : 0;
1028 }
1029 
tr_variantDictChild(tr_variant * dict,size_t n,tr_quark * key,tr_variant ** val)1030 bool tr_variantDictChild(tr_variant* dict, size_t n, tr_quark* key, tr_variant** val)
1031 {
1032     TR_ASSERT(tr_variantIsDict(dict));
1033 
1034     bool success = false;
1035 
1036     if (tr_variantIsDict(dict) && n < dict->val.l.count)
1037     {
1038         *key = dict->val.l.vals[n].key;
1039         *val = dict->val.l.vals + n;
1040         success = true;
1041     }
1042 
1043     return success;
1044 }
1045 
tr_variantMergeDicts(tr_variant * target,tr_variant const * source)1046 void tr_variantMergeDicts(tr_variant* target, tr_variant const* source)
1047 {
1048     TR_ASSERT(tr_variantIsDict(target));
1049     TR_ASSERT(tr_variantIsDict(source));
1050 
1051     size_t const sourceCount = tr_variantDictSize(source);
1052 
1053     tr_variantDictReserve(target, sourceCount + tr_variantDictSize(target));
1054 
1055     for (size_t i = 0; i < sourceCount; ++i)
1056     {
1057         tr_quark key;
1058         tr_variant* val;
1059         tr_variant* t;
1060 
1061         if (tr_variantDictChild((tr_variant*)source, i, &key, &val))
1062         {
1063             if (tr_variantIsBool(val))
1064             {
1065                 bool boolVal;
1066                 tr_variantGetBool(val, &boolVal);
1067                 tr_variantDictAddBool(target, key, boolVal);
1068             }
1069             else if (tr_variantIsReal(val))
1070             {
1071                 double realVal = 0;
1072                 tr_variantGetReal(val, &realVal);
1073                 tr_variantDictAddReal(target, key, realVal);
1074             }
1075             else if (tr_variantIsInt(val))
1076             {
1077                 int64_t intVal = 0;
1078                 tr_variantGetInt(val, &intVal);
1079                 tr_variantDictAddInt(target, key, intVal);
1080             }
1081             else if (tr_variantIsString(val))
1082             {
1083                 size_t len;
1084                 char const* str;
1085                 tr_variantGetStr(val, &str, &len);
1086                 tr_variantDictAddRaw(target, key, str, len);
1087             }
1088             else if (tr_variantIsDict(val) && tr_variantDictFindDict(target, key, &t))
1089             {
1090                 tr_variantMergeDicts(t, val);
1091             }
1092             else if (tr_variantIsList(val))
1093             {
1094                 if (tr_variantDictFind(target, key) == NULL)
1095                 {
1096                     tr_variantListCopy(tr_variantDictAddList(target, key, tr_variantListSize(val)), val);
1097                 }
1098             }
1099             else if (tr_variantIsDict(val))
1100             {
1101                 tr_variant* target_dict = tr_variantDictFind(target, key);
1102 
1103                 if (target_dict == NULL)
1104                 {
1105                     target_dict = tr_variantDictAddDict(target, key, tr_variantDictSize(val));
1106                 }
1107 
1108                 if (tr_variantIsDict(target_dict))
1109                 {
1110                     tr_variantMergeDicts(target_dict, val);
1111                 }
1112             }
1113             else
1114             {
1115                 tr_logAddDebug("tr_variantMergeDicts skipping \"%s\"", tr_quark_get_string(key, NULL));
1116             }
1117         }
1118     }
1119 }
1120 
1121 /***
1122 ****
1123 ***/
1124 
tr_variantToBuf(tr_variant const * v,tr_variant_fmt fmt)1125 struct evbuffer* tr_variantToBuf(tr_variant const* v, tr_variant_fmt fmt)
1126 {
1127     struct locale_context locale_ctx;
1128     struct evbuffer* buf = evbuffer_new();
1129 
1130     /* parse with LC_NUMERIC="C" to ensure a "." decimal separator */
1131     use_numeric_locale(&locale_ctx, "C");
1132 
1133     evbuffer_expand(buf, 4096); /* alloc a little memory to start off with */
1134 
1135     switch (fmt)
1136     {
1137     case TR_VARIANT_FMT_BENC:
1138         tr_variantToBufBenc(v, buf);
1139         break;
1140 
1141     case TR_VARIANT_FMT_JSON:
1142         tr_variantToBufJson(v, buf, false);
1143         break;
1144 
1145     case TR_VARIANT_FMT_JSON_LEAN:
1146         tr_variantToBufJson(v, buf, true);
1147         break;
1148     }
1149 
1150     /* restore the previous locale */
1151     restore_locale(&locale_ctx);
1152     return buf;
1153 }
1154 
tr_variantToStr(tr_variant const * v,tr_variant_fmt fmt,size_t * len)1155 char* tr_variantToStr(tr_variant const* v, tr_variant_fmt fmt, size_t* len)
1156 {
1157     struct evbuffer* buf = tr_variantToBuf(v, fmt);
1158     return evbuffer_free_to_str(buf, len);
1159 }
1160 
tr_variantToFile(tr_variant const * v,tr_variant_fmt fmt,char const * filename)1161 int tr_variantToFile(tr_variant const* v, tr_variant_fmt fmt, char const* filename)
1162 {
1163     char* tmp;
1164     tr_sys_file_t fd;
1165     int err = 0;
1166     char* real_filename;
1167     tr_error* error = NULL;
1168 
1169     /* follow symlinks to find the "real" file, to make sure the temporary
1170      * we build with tr_sys_file_open_temp() is created on the right partition */
1171     if ((real_filename = tr_sys_path_resolve(filename, NULL)) != NULL)
1172     {
1173         filename = real_filename;
1174     }
1175 
1176     /* if the file already exists, try to move it out of the way & keep it as a backup */
1177     tmp = tr_strdup_printf("%s.tmp.XXXXXX", filename);
1178     fd = tr_sys_file_open_temp(tmp, &error);
1179 
1180     if (fd != TR_BAD_SYS_FILE)
1181     {
1182         uint64_t nleft;
1183 
1184         /* save the variant to a temporary file */
1185         {
1186             struct evbuffer* buf = tr_variantToBuf(v, fmt);
1187             char const* walk = (char const*)evbuffer_pullup(buf, -1);
1188             nleft = evbuffer_get_length(buf);
1189 
1190             while (nleft > 0)
1191             {
1192                 uint64_t n;
1193 
1194                 if (!tr_sys_file_write(fd, walk, nleft, &n, &error))
1195                 {
1196                     err = error->code;
1197                     break;
1198                 }
1199 
1200                 nleft -= n;
1201                 walk += n;
1202             }
1203 
1204             evbuffer_free(buf);
1205         }
1206 
1207         tr_sys_file_close(fd, NULL);
1208 
1209         if (nleft > 0)
1210         {
1211             tr_logAddError(_("Couldn't save temporary file \"%1$s\": %2$s"), tmp, error->message);
1212             tr_sys_path_remove(tmp, NULL);
1213             tr_error_free(error);
1214         }
1215         else
1216         {
1217             tr_error_clear(&error);
1218 
1219             if (tr_sys_path_rename(tmp, filename, &error))
1220             {
1221                 tr_logAddInfo(_("Saved \"%s\""), filename);
1222             }
1223             else
1224             {
1225                 err = error->code;
1226                 tr_logAddError(_("Couldn't save file \"%1$s\": %2$s"), filename, error->message);
1227                 tr_sys_path_remove(tmp, NULL);
1228                 tr_error_free(error);
1229             }
1230         }
1231     }
1232     else
1233     {
1234         err = error->code;
1235         tr_logAddError(_("Couldn't save temporary file \"%1$s\": %2$s"), tmp, error->message);
1236         tr_error_free(error);
1237     }
1238 
1239     tr_free(tmp);
1240     tr_free(real_filename);
1241     return err;
1242 }
1243 
1244 /***
1245 ****
1246 ***/
1247 
tr_variantFromFile(tr_variant * setme,tr_variant_fmt fmt,char const * filename,tr_error ** error)1248 bool tr_variantFromFile(tr_variant* setme, tr_variant_fmt fmt, char const* filename, tr_error** error)
1249 {
1250     bool ret = false;
1251     uint8_t* buf;
1252     size_t buflen;
1253 
1254     buf = tr_loadFile(filename, &buflen, error);
1255 
1256     if (buf != NULL)
1257     {
1258         if (tr_variantFromBuf(setme, fmt, buf, buflen, filename, NULL) == 0)
1259         {
1260             ret = true;
1261         }
1262         else
1263         {
1264             tr_error_set_literal(error, 0, _("Unable to parse file content"));
1265         }
1266 
1267         tr_free(buf);
1268     }
1269 
1270     return ret;
1271 }
1272 
tr_variantFromBuf(tr_variant * setme,tr_variant_fmt fmt,void const * buf,size_t buflen,char const * optional_source,char const ** setme_end)1273 int tr_variantFromBuf(tr_variant* setme, tr_variant_fmt fmt, void const* buf, size_t buflen, char const* optional_source,
1274     char const** setme_end)
1275 {
1276     int err;
1277     struct locale_context locale_ctx;
1278 
1279     /* parse with LC_NUMERIC="C" to ensure a "." decimal separator */
1280     use_numeric_locale(&locale_ctx, "C");
1281 
1282     switch (fmt)
1283     {
1284     case TR_VARIANT_FMT_JSON:
1285     case TR_VARIANT_FMT_JSON_LEAN:
1286         err = tr_jsonParse(optional_source, buf, buflen, setme, setme_end);
1287         break;
1288 
1289     default /* TR_VARIANT_FMT_BENC */:
1290         err = tr_variantParseBenc(buf, (char const*)buf + buflen, setme, setme_end);
1291         break;
1292     }
1293 
1294     /* restore the previous locale */
1295     restore_locale(&locale_ctx);
1296     return err;
1297 }
1298