From a1559e3f534fed31022a105d099b55e741db26e6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Oct 2018 14:42:24 +0200 Subject: [PATCH 01/11] json: use structured initialization all the way --- src/basic/json.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/basic/json.c b/src/basic/json.c index 426ed0328e2..cb005a16853 100644 --- a/src/basic/json.c +++ b/src/basic/json.c @@ -476,10 +476,9 @@ int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n) { *w = (JsonVariant) { .is_embedded = true, .parent = v, + .type = JSON_VARIANT_UNSIGNED, + .value.unsig = ((const uint8_t*) p)[i], }; - - w->type = JSON_VARIANT_UNSIGNED; - w->value.unsig = ((const uint8_t*) p)[i]; } *ret = v; @@ -499,7 +498,7 @@ int json_variant_new_array_strv(JsonVariant **ret, char **l) { return 0; } - v = new0(JsonVariant, n + 1); + v = new(JsonVariant, n + 1); if (!v) return -ENOMEM; @@ -512,9 +511,11 @@ int json_variant_new_array_strv(JsonVariant **ret, char **l) { JsonVariant *w = v + 1 + v->n_elements; size_t k; - w->is_embedded = true; - w->parent = v; - w->type = JSON_VARIANT_STRING; + *w = (JsonVariant) { + .is_embedded = true, + .parent = v, + .type = JSON_VARIANT_STRING, + }; k = strlen(l[v->n_elements]); From 92853e9bbe232ca1affcf3effd9194e985531fc4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Oct 2018 14:42:36 +0200 Subject: [PATCH 02/11] json: return a double when we shall return a double --- src/basic/json.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/json.c b/src/basic/json.c index cb005a16853..0a2a620c3bf 100644 --- a/src/basic/json.c +++ b/src/basic/json.c @@ -823,7 +823,7 @@ long double json_variant_real(JsonVariant *v) { mismatch: log_debug("Non-integer JSON variant requested as integer, returning 0."); - return 0; + return 0.0; } bool json_variant_is_negative(JsonVariant *v) { From 4ae7e4e5d892cd9d28493e4d2fe7ac9ee3ae383d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Oct 2018 14:42:43 +0200 Subject: [PATCH 03/11] json: avoid stack allocation of long strings in a recursive function Fixes: oss-fuzz#10908 https://oss-fuzz.com/v2/testcase-detail/5639441482252288 --- src/basic/json.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/basic/json.c b/src/basic/json.c index 0a2a620c3bf..ec2952c6da3 100644 --- a/src/basic/json.c +++ b/src/basic/json.c @@ -1344,10 +1344,15 @@ static int json_format(FILE *f, JsonVariant *v, unsigned flags, const char *pref if (n == 0) fputs("[]", f); else { + _cleanup_free_ char *joined = NULL; const char *prefix2; if (flags & JSON_FORMAT_PRETTY) { - prefix2 = strjoina(strempty(prefix), "\t"); + joined = strjoin(strempty(prefix), "\t"); + if (!joined) + return -ENOMEM; + + prefix2 = joined; fputs("[\n", f); } else { prefix2 = strempty(prefix); @@ -1395,10 +1400,15 @@ static int json_format(FILE *f, JsonVariant *v, unsigned flags, const char *pref if (n == 0) fputs("{}", f); else { + _cleanup_free_ char *joined = NULL; const char *prefix2; if (flags & JSON_FORMAT_PRETTY) { - prefix2 = strjoina(strempty(prefix), "\t"); + joined = strjoin(strempty(prefix), "\t"); + if (!joined) + return -ENOMEM; + + prefix2 = joined; fputs("{\n", f); } else { prefix2 = strempty(prefix); From a7efb030391547d01b4c0bcc5a296404decc75ab Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Oct 2018 14:49:50 +0200 Subject: [PATCH 04/11] json: slightly reorder JsonVariant Let's move things around a bit, so that the trailing unused whitespace within the structure due to padding is placed together, so that it is easier to use for new fields. (Found with pahole) --- src/basic/json.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/basic/json.c b/src/basic/json.c index ec2952c6da3..b6106498bb7 100644 --- a/src/basic/json.c +++ b/src/basic/json.c @@ -45,6 +45,10 @@ struct JsonVariant { JsonVariant *parent; }; + /* If this was parsed from some file or buffer, this stores where from, as well as the source line/column */ + JsonSource *source; + unsigned line, column; + JsonVariantType type:5; /* A marker whether this variant is embedded into in array/object or not. If true, the 'parent' pointer above @@ -59,10 +63,6 @@ struct JsonVariant { /* While comparing two arrays, we use this for marking what we already have seen */ bool is_marked:1; - /* If this was parsed from some file or buffer, this stores where from, as well as the source line/column */ - unsigned line, column; - JsonSource *source; - union { /* For simple types we store the value in-line. */ JsonValue value; From b2fa0d4fcab75f7012fc899dedfa68afeea9903c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Oct 2018 15:38:17 +0200 Subject: [PATCH 05/11] json: enforce a maximum nesting depth for json variants Simply as a safety precaution so that json objects we read are not arbitrary amounts deep, so that code that processes json objects recursively can't be easily exploited (by hitting stack limits). Follow-up for oss-fuzz#10908 (Nice is that we can accomodate for this counter without increasing the size of the JsonVariant object.) --- src/basic/json.c | 67 +++++++++++++++++++++++++++++++++----------- src/test/test-json.c | 34 ++++++++++++++++++++++ 2 files changed, 85 insertions(+), 16 deletions(-) diff --git a/src/basic/json.c b/src/basic/json.c index b6106498bb7..8bf190ed586 100644 --- a/src/basic/json.c +++ b/src/basic/json.c @@ -24,6 +24,12 @@ #include "terminal-util.h" #include "utf8.h" +/* Refuse putting together variants with a larger depth than 16K by default (as a protection against overflowing stacks + * if code processes JSON objects recursively. Note that we store the depth in an uint16_t, hence make sure this + * remains under 2^16. */ +#define DEPTH_MAX (16U*1024U) +assert_cc(DEPTH_MAX <= UINT16_MAX); + typedef struct JsonSource { /* When we parse from a file or similar, encodes the filename, to indicate the source of a json variant */ size_t n_ref; @@ -63,6 +69,9 @@ struct JsonVariant { /* While comparing two arrays, we use this for marking what we already have seen */ bool is_marked:1; + /* The current 'depth' of the JsonVariant, i.e. how many levels of member variants this has */ + uint16_t depth; + union { /* For simple types we store the value in-line. */ JsonValue value; @@ -158,6 +167,18 @@ static JsonVariant *json_variant_dereference(JsonVariant *v) { return json_variant_dereference(v->reference); } +static uint16_t json_variant_depth(JsonVariant *v) { + + v = json_variant_dereference(v); + if (!v) + return 0; + + if (json_variant_is_magic(v)) + return 0; + + return v->depth; +} + static JsonVariant *json_variant_normalize(JsonVariant *v) { /* Converts json variants to their normalized form, i.e. fully dereferenced and wherever possible converted to @@ -413,8 +434,7 @@ static void json_variant_copy_source(JsonVariant *v, JsonVariant *from) { } int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n) { - JsonVariant *v; - size_t i; + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; assert_return(ret, -EINVAL); if (n == 0) { @@ -430,22 +450,29 @@ int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n) { *v = (JsonVariant) { .n_ref = 1, .type = JSON_VARIANT_ARRAY, - .n_elements = n, }; - for (i = 0; i < n; i++) { - JsonVariant *w = v + 1 + i; + for (v->n_elements = 0; v->n_elements < n; v->n_elements++) { + JsonVariant *w = v + 1 + v->n_elements, + *c = array[v->n_elements]; + uint16_t d; + + d = json_variant_depth(c); + if (d >= DEPTH_MAX) /* Refuse too deep nesting */ + return -ELNRNG; + if (d >= v->depth) + v->depth = d + 1; *w = (JsonVariant) { .is_embedded = true, .parent = v, }; - json_variant_set(w, array[i]); - json_variant_copy_source(w, array[i]); + json_variant_set(w, c); + json_variant_copy_source(w, c); } - *ret = v; + *ret = TAKE_PTR(v); return 0; } @@ -468,6 +495,7 @@ int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n) { .n_ref = 1, .type = JSON_VARIANT_ARRAY, .n_elements = n, + .depth = 1, }; for (i = 0; i < n; i++) { @@ -505,6 +533,7 @@ int json_variant_new_array_strv(JsonVariant **ret, char **l) { *v = (JsonVariant) { .n_ref = 1, .type = JSON_VARIANT_ARRAY, + .depth = 1, }; for (v->n_elements = 0; v->n_elements < n; v->n_elements++) { @@ -536,8 +565,7 @@ int json_variant_new_array_strv(JsonVariant **ret, char **l) { } int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n) { - JsonVariant *v; - size_t i; + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; assert_return(ret, -EINVAL); if (n == 0) { @@ -554,22 +582,29 @@ int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n) { *v = (JsonVariant) { .n_ref = 1, .type = JSON_VARIANT_OBJECT, - .n_elements = n, }; - for (i = 0; i < n; i++) { - JsonVariant *w = v + 1 + i; + for (v->n_elements = 0; v->n_elements < n; v->n_elements++) { + JsonVariant *w = v + 1 + v->n_elements, + *c = array[v->n_elements]; + uint16_t d; + + d = json_variant_depth(c); + if (d >= DEPTH_MAX) /* Refuse too deep nesting */ + return -ELNRNG; + if (d >= v->depth) + v->depth = d + 1; *w = (JsonVariant) { .is_embedded = true, .parent = v, }; - json_variant_set(w, array[i]); - json_variant_copy_source(w, array[i]); + json_variant_set(w, c); + json_variant_copy_source(w, c); } - *ret = v; + *ret = TAKE_PTR(v); return 0; } diff --git a/src/test/test-json.c b/src/test/test-json.c index e145559ae90..bcf94b211c2 100644 --- a/src/test/test-json.c +++ b/src/test/test-json.c @@ -354,6 +354,38 @@ static void test_source(void) { printf("--- pretty end ---\n"); } +static void test_depth(void) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *k = NULL; + unsigned i; + int r; + + assert_se(json_variant_new_string(&k, "hallo") >= 0); + v = json_variant_ref(k); + + /* Let's verify that the maximum depth checks work */ + + for (i = 0;; i++) { + _cleanup_(json_variant_unrefp) JsonVariant *w = NULL; + + assert_se(i <= UINT16_MAX); + if (i & 1) + r = json_variant_new_array(&w, &v, 1); + else + r = json_variant_new_object(&w, (JsonVariant*[]) { k, v }, 2); + if (r == -ELNRNG) { + log_info("max depth at %u", i); + break; + } + + assert_se(r >= 0); + + json_variant_unref(v); + v = TAKE_PTR(w); + } + + json_variant_dump(v, 0, stdout, NULL); +} + int main(int argc, char *argv[]) { log_set_max_level(LOG_DEBUG); @@ -407,5 +439,7 @@ int main(int argc, char *argv[]) { test_source(); + test_depth(); + return 0; } From d77e781fd017946093bd71448e546cf59921ee22 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Oct 2018 15:59:21 +0200 Subject: [PATCH 06/11] json: when creating an object, insist that every second item is a string After all, those are the keys, which have to be keys. --- src/basic/json.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/basic/json.c b/src/basic/json.c index 8bf190ed586..72e8e115baf 100644 --- a/src/basic/json.c +++ b/src/basic/json.c @@ -589,6 +589,10 @@ int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n) { *c = array[v->n_elements]; uint16_t d; + if ((v->n_elements & 1) == 0 && + !json_variant_is_string(c)) + return -EINVAL; /* Every second one needs to be a string, as it is the key name */ + d = json_variant_depth(c); if (d >= DEPTH_MAX) /* Refuse too deep nesting */ return -ELNRNG; From 4fcb507a909c60d8568b17fc8a9dbb8c83029c01 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Oct 2018 16:21:21 +0200 Subject: [PATCH 07/11] json: minor optimization instead of comparing the magic JsonVariants one by one, let's simply compare that they lie within a specific range. --- src/basic/json-internal.h | 1 + src/basic/json.c | 13 ++++--------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/basic/json-internal.h b/src/basic/json-internal.h index 6d195eb672f..98e53ede10c 100644 --- a/src/basic/json-internal.h +++ b/src/basic/json-internal.h @@ -35,6 +35,7 @@ assert_cc(sizeof(JsonValue) == 16U); #define JSON_VARIANT_MAGIC_EMPTY_STRING ((JsonVariant*) 7) #define JSON_VARIANT_MAGIC_EMPTY_ARRAY ((JsonVariant*) 8) #define JSON_VARIANT_MAGIC_EMPTY_OBJECT ((JsonVariant*) 9) +#define _JSON_VARIANT_MAGIC_MAX ((JsonVariant*) 10) enum { /* JSON tokens */ JSON_TOKEN_END, diff --git a/src/basic/json.c b/src/basic/json.c index 72e8e115baf..f3db01eb993 100644 --- a/src/basic/json.c +++ b/src/basic/json.c @@ -140,15 +140,10 @@ static bool json_source_equal(JsonSource *a, JsonSource *b) { DEFINE_TRIVIAL_CLEANUP_FUNC(JsonSource*, json_source_unref); static bool json_variant_is_magic(const JsonVariant *v) { - return v == JSON_VARIANT_MAGIC_TRUE || - v == JSON_VARIANT_MAGIC_FALSE || - v == JSON_VARIANT_MAGIC_NULL || - v == JSON_VARIANT_MAGIC_ZERO_INTEGER || - v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || - v == JSON_VARIANT_MAGIC_ZERO_REAL || - v == JSON_VARIANT_MAGIC_EMPTY_STRING || - v == JSON_VARIANT_MAGIC_EMPTY_ARRAY || - v == JSON_VARIANT_MAGIC_EMPTY_OBJECT; + if (!v) + return false; + + return v < _JSON_VARIANT_MAGIC_MAX; } static JsonVariant *json_variant_dereference(JsonVariant *v) { From d520d519f0ad8c7bdc65e4cb375a23e37fffbedc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Oct 2018 16:46:38 +0200 Subject: [PATCH 08/11] json: add support for using static const strings directly as JsonVariant objects This is a nice little optimization when using static const strings: we can now use them directly as JsonVariant objecs, without any additional allocation. --- src/basic/json.c | 94 +++++++++++++++++++++++++++++++++----------- src/basic/json.h | 9 +++++ src/test/test-json.c | 9 +++-- 3 files changed, 86 insertions(+), 26 deletions(-) diff --git a/src/basic/json.c b/src/basic/json.c index f3db01eb993..c6e4ea6aa80 100644 --- a/src/basic/json.c +++ b/src/basic/json.c @@ -139,6 +139,23 @@ static bool json_source_equal(JsonSource *a, JsonSource *b) { DEFINE_TRIVIAL_CLEANUP_FUNC(JsonSource*, json_source_unref); +/* There are four kind of JsonVariant* pointers: + * + * 1. NULL + * 2. A 'regular' one, i.e. pointing to malloc() memory + * 3. A 'magic' one, i.e. one of the special JSON_VARIANT_MAGIC_XYZ values, that encode a few very basic values directly in the pointer. + * 4. A 'const string' one, i.e. a pointer to a const string. + * + * The four kinds of pointers can be discerned like this: + * + * Detecting #1 is easy, just compare with NULL. Detecting #3 is similarly easy: all magic pointers are below + * _JSON_VARIANT_MAGIC_MAX (which is pretty low, within the first memory page, which is special on Linux and other + * OSes, as it is a faulting page). In order to discern #2 and #4 we check the lowest bit. If it's off it's #2, + * otherwise #4. This makes use of the fact that malloc() will return "maximum aligned" memory, which definitely + * means the pointer is even. This means we can use the uneven pointers to reference static strings, as long as we + * make sure that all static strings used like this are aligned to 2 (or higher), and that we mask the bit on + * access. The JSON_VARIANT_STRING_CONST() macro encodes strings as JsonVariant* pointers, with the bit set. */ + static bool json_variant_is_magic(const JsonVariant *v) { if (!v) return false; @@ -146,6 +163,25 @@ static bool json_variant_is_magic(const JsonVariant *v) { return v < _JSON_VARIANT_MAGIC_MAX; } +static bool json_variant_is_const_string(const JsonVariant *v) { + + if (v < _JSON_VARIANT_MAGIC_MAX) + return false; + + /* A proper JsonVariant is aligned to whatever malloc() aligns things too, which is definitely not uneven. We + * hence use all uneven pointers as indicators for const strings. */ + + return (((uintptr_t) v) & 1) != 0; +} + +static bool json_variant_is_regular(const JsonVariant *v) { + + if (v < _JSON_VARIANT_MAGIC_MAX) + return false; + + return (((uintptr_t) v) & 1) == 0; +} + static JsonVariant *json_variant_dereference(JsonVariant *v) { /* Recursively dereference variants that are references to other variants */ @@ -153,7 +189,7 @@ static JsonVariant *json_variant_dereference(JsonVariant *v) { if (!v) return NULL; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) return v; if (!v->is_reference) @@ -168,7 +204,7 @@ static uint16_t json_variant_depth(JsonVariant *v) { if (!v) return 0; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) return 0; return v->depth; @@ -226,7 +262,7 @@ static JsonVariant *json_variant_conservative_normalize(JsonVariant *v) { if (!v) return NULL; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) return v; if (v->source || v->line > 0 || v->column > 0) @@ -420,7 +456,7 @@ static void json_variant_copy_source(JsonVariant *v, JsonVariant *from) { assert(v); assert(from); - if (json_variant_is_magic(from)) + if (!json_variant_is_regular(from)) return; v->line = from->line; @@ -610,7 +646,7 @@ int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n) { static void json_variant_free_inner(JsonVariant *v) { assert(v); - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) return; json_source_unref(v->source); @@ -631,7 +667,7 @@ static void json_variant_free_inner(JsonVariant *v) { JsonVariant *json_variant_ref(JsonVariant *v) { if (!v) return NULL; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) return v; if (v->is_embedded) @@ -647,7 +683,7 @@ JsonVariant *json_variant_ref(JsonVariant *v) { JsonVariant *json_variant_unref(JsonVariant *v) { if (!v) return NULL; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) return NULL; if (v->is_embedded) @@ -681,6 +717,13 @@ const char *json_variant_string(JsonVariant *v) { return ""; if (json_variant_is_magic(v)) goto mismatch; + if (json_variant_is_const_string(v)) { + uintptr_t p = (uintptr_t) v; + + assert((p & 1) != 0); + return (const char*) (p ^ 1U); + } + if (v->is_reference) return json_variant_string(v->reference); if (v->type != JSON_VARIANT_STRING) @@ -700,7 +743,7 @@ bool json_variant_boolean(JsonVariant *v) { return true; if (v == JSON_VARIANT_MAGIC_FALSE) return false; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) goto mismatch; if (v->type != JSON_VARIANT_BOOLEAN) goto mismatch; @@ -721,7 +764,7 @@ intmax_t json_variant_integer(JsonVariant *v) { v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || v == JSON_VARIANT_MAGIC_ZERO_REAL) return 0; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) goto mismatch; if (v->is_reference) return json_variant_integer(v->reference); @@ -769,7 +812,7 @@ uintmax_t json_variant_unsigned(JsonVariant *v) { v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || v == JSON_VARIANT_MAGIC_ZERO_REAL) return 0; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) goto mismatch; if (v->is_reference) return json_variant_integer(v->reference); @@ -817,7 +860,7 @@ long double json_variant_real(JsonVariant *v) { v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || v == JSON_VARIANT_MAGIC_ZERO_REAL) return 0.0; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) goto mismatch; if (v->is_reference) return json_variant_real(v->reference); @@ -867,7 +910,7 @@ bool json_variant_is_negative(JsonVariant *v) { v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || v == JSON_VARIANT_MAGIC_ZERO_REAL) return false; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) goto mismatch; if (v->is_reference) return json_variant_is_negative(v->reference); @@ -901,6 +944,9 @@ JsonVariantType json_variant_type(JsonVariant *v) { if (!v) return _JSON_VARIANT_TYPE_INVALID; + if (json_variant_is_const_string(v)) + return JSON_VARIANT_STRING; + if (v == JSON_VARIANT_MAGIC_TRUE || v == JSON_VARIANT_MAGIC_FALSE) return JSON_VARIANT_BOOLEAN; @@ -937,6 +983,10 @@ bool json_variant_has_type(JsonVariant *v, JsonVariantType type) { if (rt == type) return true; + /* If it's a const string, then it only can be a string, and if it is not, it's not */ + if (json_variant_is_const_string(v)) + return false; + /* All three magic zeroes qualify as integer, unsigned and as real */ if ((v == JSON_VARIANT_MAGIC_ZERO_INTEGER || v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || v == JSON_VARIANT_MAGIC_ZERO_REAL) && IN_SET(type, JSON_VARIANT_INTEGER, JSON_VARIANT_UNSIGNED, JSON_VARIANT_REAL, JSON_VARIANT_NUMBER)) @@ -980,7 +1030,7 @@ size_t json_variant_elements(JsonVariant *v) { if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY || v == JSON_VARIANT_MAGIC_EMPTY_OBJECT) return 0; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) goto mismatch; if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT)) goto mismatch; @@ -1000,7 +1050,7 @@ JsonVariant *json_variant_by_index(JsonVariant *v, size_t idx) { if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY || v == JSON_VARIANT_MAGIC_EMPTY_OBJECT) return NULL; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) goto mismatch; if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT)) goto mismatch; @@ -1025,7 +1075,7 @@ JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVaria goto not_found; if (v == JSON_VARIANT_MAGIC_EMPTY_OBJECT) goto not_found; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) goto mismatch; if (v->type != JSON_VARIANT_OBJECT) goto mismatch; @@ -1174,13 +1224,13 @@ int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *r assert_return(v, -EINVAL); if (ret_source) - *ret_source = json_variant_is_magic(v) || !v->source ? NULL : v->source->name; + *ret_source = json_variant_is_regular(v) && v->source ? v->source->name : NULL; if (ret_line) - *ret_line = json_variant_is_magic(v) ? 0 : v->line; + *ret_line = json_variant_is_regular(v) ? v->line : 0; if (ret_column) - *ret_column = json_variant_is_magic(v) ? 0 : v->column; + *ret_column = json_variant_is_regular(v) ? v->column : 0; return 0; } @@ -1191,7 +1241,7 @@ static int print_source(FILE *f, JsonVariant *v, unsigned flags, bool whitespace if (!FLAGS_SET(flags, JSON_FORMAT_SOURCE|JSON_FORMAT_PRETTY)) return 0; - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) return 0; if (!v->source && v->line == 0 && v->column == 0) @@ -1632,7 +1682,7 @@ static bool json_single_ref(JsonVariant *v) { /* Checks whether the caller is the single owner of the object, i.e. can get away with changing it */ - if (json_variant_is_magic(v)) + if (!json_variant_is_regular(v)) return false; if (v->is_embedded) @@ -1659,7 +1709,7 @@ static int json_variant_set_source(JsonVariant **v, JsonSource *source, unsigned if (source && column > source->max_column) source->max_column = column; - if (json_variant_is_magic(*v)) { + if (!json_variant_is_regular(*v)) { if (!source && line == 0 && column == 0) return 0; @@ -1683,7 +1733,7 @@ static int json_variant_set_source(JsonVariant **v, JsonSource *source, unsigned if (r < 0) return r; - assert(!json_variant_is_magic(w)); + assert(json_variant_is_regular(w)); assert(!w->is_embedded); assert(w->n_ref == 1); assert(!w->source); diff --git a/src/basic/json.h b/src/basic/json.h index 1f06fe22573..42be60e0554 100644 --- a/src/basic/json.h +++ b/src/basic/json.h @@ -270,5 +270,14 @@ int json_log_internal(JsonVariant *variant, int level, int error, const char *fi : -abs(_e); \ }) +#define JSON_VARIANT_STRING_CONST(x) _JSON_VARIANT_STRING_CONST(UNIQ, (x)) + +#define _JSON_VARIANT_STRING_CONST(xq, x) \ + ({ \ + __attribute__((aligned(2))) static const char UNIQ_T(json_string_const, xq)[] = (x); \ + assert((((uintptr_t) UNIQ_T(json_string_const, xq)) & 1) == 0); \ + (JsonVariant*) ((uintptr_t) UNIQ_T(json_string_const, xq) + 1); \ + }) + const char *json_variant_type_to_string(JsonVariantType t); JsonVariantType json_variant_type_from_string(const char *s); diff --git a/src/test/test-json.c b/src/test/test-json.c index bcf94b211c2..6a57f88882e 100644 --- a/src/test/test-json.c +++ b/src/test/test-json.c @@ -292,6 +292,7 @@ static void test_build(void) { JSON_BUILD_STRING(NULL), JSON_BUILD_NULL, JSON_BUILD_INTEGER(77), + JSON_BUILD_ARRAY(JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("foobar")), JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("zzz"))), JSON_BUILD_STRV(STRV_MAKE("one", "two", "three", "four")))) >= 0); assert_se(json_variant_format(a, 0, &s) >= 0); @@ -355,12 +356,11 @@ static void test_source(void) { } static void test_depth(void) { - _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *k = NULL; + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; unsigned i; int r; - assert_se(json_variant_new_string(&k, "hallo") >= 0); - v = json_variant_ref(k); + v = JSON_VARIANT_STRING_CONST("start"); /* Let's verify that the maximum depth checks work */ @@ -371,7 +371,7 @@ static void test_depth(void) { if (i & 1) r = json_variant_new_array(&w, &v, 1); else - r = json_variant_new_object(&w, (JsonVariant*[]) { k, v }, 2); + r = json_variant_new_object(&w, (JsonVariant*[]) { JSON_VARIANT_STRING_CONST("key"), v }, 2); if (r == -ELNRNG) { log_info("max depth at %u", i); break; @@ -384,6 +384,7 @@ static void test_depth(void) { } json_variant_dump(v, 0, stdout, NULL); + fputs("\n", stdout); } int main(int argc, char *argv[]) { From 7e61bd0f678dacdd470cc72b202d411cca3f20d9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Oct 2018 16:51:31 +0200 Subject: [PATCH 09/11] macro.h: include assert.h so that static_assert can be properly checked for For the definition of assert_cc() we try to use static_assert and check for it with "#ifdef". But that can only work if assert.h is imported before. Hence let's do so. --- src/basic/macro.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/basic/macro.h b/src/basic/macro.h index 63a8be440f2..14d49c1a1bf 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include #include #include #include From 085f3d6416c7af9247a76ca964f43a991574892f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Oct 2018 16:53:04 +0200 Subject: [PATCH 10/11] json: add an assert_cc() check that validates _JSON_VARIANT_MAGIC_MAX --- src/basic/json-internal.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/basic/json-internal.h b/src/basic/json-internal.h index 98e53ede10c..bf158bff0d4 100644 --- a/src/basic/json-internal.h +++ b/src/basic/json-internal.h @@ -37,6 +37,11 @@ assert_cc(sizeof(JsonValue) == 16U); #define JSON_VARIANT_MAGIC_EMPTY_OBJECT ((JsonVariant*) 9) #define _JSON_VARIANT_MAGIC_MAX ((JsonVariant*) 10) +/* This is only safe as long as we don't define more than 4K magic pointers, i.e. the page size of the simplest + * architectures we support. That's because we rely on the fact that malloc() will never allocate from the first memory + * page, as it is a faulting page for catching NULL pointer dereferences. */ +assert_cc((uintptr_t) _JSON_VARIANT_MAGIC_MAX < 4096U); + enum { /* JSON tokens */ JSON_TOKEN_END, JSON_TOKEN_COLON, From e413ec4a9da74c6915d496aff7360033a4546462 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 13 Oct 2018 12:41:34 +0200 Subject: [PATCH 11/11] fuzz: add test from oss-fuzz#10908 https://oss-fuzz.com/download?testcase_id=5639441482252288 --- test/fuzz/fuzz-json/crash-5639441482252288 | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 test/fuzz/fuzz-json/crash-5639441482252288 diff --git a/test/fuzz/fuzz-json/crash-5639441482252288 b/test/fuzz/fuzz-json/crash-5639441482252288 new file mode 100644 index 00000000000..c6cf59a51ee --- /dev/null +++ b/test/fuzz/fuzz-json/crash-5639441482252288 @@ -0,0 +1,9 @@ +[[],[],[ ],[[],[[],[[ ],[[],[],[],[[],[],[[ ],[],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]],[],[[],[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ + + + + + +[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],0]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] + +]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]