mirror of
https://github.com/systemd/systemd.git
synced 2025-01-10 05:18:17 +03:00
Merge pull request #23335 from keszybz/fuzz-json-more-coverage
More coverage in fuzz-json
This commit is contained in:
commit
97cda6e10f
@ -55,8 +55,8 @@ typedef void* (*mfree_func_t)(void *p);
|
||||
typeof(a)* _a = &(a); \
|
||||
typeof(b)* _b = &(b); \
|
||||
free(*_a); \
|
||||
(*_a) = (*_b); \
|
||||
(*_b) = NULL; \
|
||||
*_a = *_b; \
|
||||
*_b = NULL; \
|
||||
0; \
|
||||
})
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "env-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fuzz.h"
|
||||
#include "json.h"
|
||||
@ -10,18 +11,106 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
size_t out_size;
|
||||
_cleanup_fclose_ FILE *f = NULL, *g = NULL;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
int r;
|
||||
|
||||
/* Disable most logging if not running standalone */
|
||||
if (!getenv("SYSTEMD_LOG_LEVEL"))
|
||||
log_set_max_level(LOG_CRIT);
|
||||
|
||||
f = data_to_file(data, size);
|
||||
assert_se(f);
|
||||
|
||||
if (json_parse_file(f, NULL, 0, &v, NULL, NULL) < 0)
|
||||
r = json_parse_file(f, NULL, 0, &v, NULL, NULL);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "failed to parse input: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
g = open_memstream_unlocked(&out, &out_size);
|
||||
assert_se(g);
|
||||
if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0)
|
||||
assert_se(g = open_memstream_unlocked(&out, &out_size));
|
||||
|
||||
json_variant_dump(v, 0, g, NULL);
|
||||
json_variant_dump(v, JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR|JSON_FORMAT_SOURCE, g, NULL);
|
||||
json_variant_dump(v, 0, g ?: stdout, NULL);
|
||||
json_variant_dump(v, JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR|JSON_FORMAT_SOURCE, g ?: stdout, NULL);
|
||||
|
||||
bool sorted = json_variant_is_sorted(v);
|
||||
log_debug("json_variant_is_sorted: %s", yes_no(sorted));
|
||||
|
||||
r = json_variant_sort(&v);
|
||||
log_debug_errno(r, "json_variant_sort: %d/%m", r);
|
||||
|
||||
sorted = json_variant_is_sorted(v);
|
||||
log_debug("json_variant_is_sorted: %s", yes_no(sorted));
|
||||
assert_se(r < 0 || sorted);
|
||||
|
||||
bool normalized = json_variant_is_normalized(v);
|
||||
log_debug("json_variant_is_normalized: %s", yes_no(normalized));
|
||||
|
||||
r = json_variant_normalize(&v);
|
||||
log_debug_errno(r, "json_variant_normalize: %d/%m", r);
|
||||
|
||||
normalized = json_variant_is_normalized(v);
|
||||
log_debug("json_variant_is_normalized: %s", yes_no(normalized));
|
||||
assert_se(r < 0 || normalized);
|
||||
|
||||
double real = json_variant_real(v);
|
||||
log_debug("json_variant_real: %lf", real);
|
||||
|
||||
bool negative = json_variant_is_negative(v);
|
||||
log_debug("json_variant_is_negative: %s", yes_no(negative));
|
||||
|
||||
bool blank = json_variant_is_blank_object(v);
|
||||
log_debug("json_variant_is_blank_object: %s", yes_no(blank));
|
||||
|
||||
blank = json_variant_is_blank_array(v);
|
||||
log_debug("json_variant_is_blank_array: %s", yes_no(blank));
|
||||
|
||||
size_t elements = json_variant_elements(v);
|
||||
log_debug("json_variant_elements: %zu", elements);
|
||||
|
||||
for (size_t i = 0; i <= elements + 2; i++)
|
||||
(void) json_variant_by_index(v, i);
|
||||
|
||||
assert_se(json_variant_equal(v, v));
|
||||
assert_se(!json_variant_equal(v, NULL));
|
||||
assert_se(!json_variant_equal(NULL, v));
|
||||
|
||||
bool sensitive = json_variant_is_sensitive(v);
|
||||
log_debug("json_variant_is_sensitive: %s", yes_no(sensitive));
|
||||
|
||||
json_variant_sensitive(v);
|
||||
|
||||
sensitive = json_variant_is_sensitive(v);
|
||||
log_debug("json_variant_is_sensitive: %s", yes_no(sensitive));
|
||||
|
||||
const char *source;
|
||||
unsigned line, column;
|
||||
assert_se(json_variant_get_source(v, &source, &line, &column) == 0);
|
||||
log_debug("json_variant_get_source: %s:%u:%u", source ?: "-", line, column);
|
||||
|
||||
r = json_variant_set_field_string(&v, "a", "string-a");
|
||||
log_debug_errno(r, "json_set_field_string: %d/%m", r);
|
||||
|
||||
r = json_variant_set_field_integer(&v, "b", -12345);
|
||||
log_debug_errno(r, "json_set_field_integer: %d/%m", r);
|
||||
|
||||
r = json_variant_set_field_unsigned(&v, "c", 12345);
|
||||
log_debug_errno(r, "json_set_field_unsigned: %d/%m", r);
|
||||
|
||||
r = json_variant_set_field_boolean(&v, "d", false);
|
||||
log_debug_errno(r, "json_set_field_boolean: %d/%m", r);
|
||||
|
||||
r = json_variant_set_field_strv(&v, "e", STRV_MAKE("e-1", "e-2", "e-3"));
|
||||
log_debug_errno(r, "json_set_field_strv: %d/%m", r);
|
||||
|
||||
r = json_variant_filter(&v, STRV_MAKE("a", "b", "c", "d", "e"));
|
||||
log_debug_errno(r, "json_variant_filter: %d/%m", r);
|
||||
|
||||
/* I assume we can merge v with itself… */
|
||||
r = json_variant_merge(&v, v);
|
||||
log_debug_errno(r, "json_variant_merge: %d/%m", r);
|
||||
|
||||
r = json_variant_append_array(&v, v);
|
||||
log_debug_errno(r, "json_variant_append_array: %d/%m", r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -273,8 +273,8 @@ static JsonVariant *json_variant_formalize(JsonVariant *v) {
|
||||
|
||||
static JsonVariant *json_variant_conservative_formalize(JsonVariant *v) {
|
||||
|
||||
/* Much like json_variant_formalize(), but won't simplify if the variant has a source/line location attached to
|
||||
* it, in order not to lose context */
|
||||
/* Much like json_variant_formalize(), but won't simplify if the variant has a source/line location
|
||||
* attached to it, in order not to lose context */
|
||||
|
||||
if (!v)
|
||||
return NULL;
|
||||
@ -546,7 +546,7 @@ int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n) {
|
||||
|
||||
for (v->n_elements = 0; v->n_elements < n; v->n_elements++) {
|
||||
JsonVariant *w = v + 1 + v->n_elements,
|
||||
*c = array[v->n_elements];
|
||||
*c = array[v->n_elements];
|
||||
uint16_t d;
|
||||
|
||||
d = json_variant_depth(c);
|
||||
@ -574,9 +574,6 @@ int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n) {
|
||||
}
|
||||
|
||||
int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n) {
|
||||
JsonVariant *v;
|
||||
size_t i;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
if (n == 0) {
|
||||
*ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY;
|
||||
@ -584,7 +581,7 @@ int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n) {
|
||||
}
|
||||
assert_return(p, -EINVAL);
|
||||
|
||||
v = new(JsonVariant, n + 1);
|
||||
JsonVariant *v = new(JsonVariant, n + 1);
|
||||
if (!v)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -595,7 +592,7 @@ int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n) {
|
||||
.depth = 1,
|
||||
};
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
JsonVariant *w = v + 1 + i;
|
||||
|
||||
*w = (JsonVariant) {
|
||||
@ -693,7 +690,7 @@ int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n) {
|
||||
|
||||
for (v->n_elements = 0; v->n_elements < n; v->n_elements++) {
|
||||
JsonVariant *w = v + 1 + v->n_elements,
|
||||
*c = array[v->n_elements];
|
||||
*c = array[v->n_elements];
|
||||
uint16_t d;
|
||||
|
||||
if ((v->n_elements & 1) == 0) {
|
||||
@ -734,7 +731,6 @@ int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n) {
|
||||
}
|
||||
|
||||
static size_t json_variant_size(JsonVariant* v) {
|
||||
|
||||
if (!json_variant_is_regular(v))
|
||||
return 0;
|
||||
|
||||
@ -790,12 +786,9 @@ static void json_variant_free_inner(JsonVariant *v, bool force_sensitive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT)) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < v->n_elements; i++)
|
||||
if (IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT))
|
||||
for (size_t i = 0; i < v->n_elements; i++)
|
||||
json_variant_free_inner(v + 1 + i, sensitive);
|
||||
}
|
||||
|
||||
if (sensitive)
|
||||
explicit_bzero_safe(v, json_variant_size(v));
|
||||
@ -839,11 +832,9 @@ JsonVariant *json_variant_unref(JsonVariant *v) {
|
||||
}
|
||||
|
||||
void json_variant_unref_many(JsonVariant **array, size_t n) {
|
||||
size_t i;
|
||||
|
||||
assert(array || n == 0);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
for (size_t i = 0; i < n; i++)
|
||||
json_variant_unref(array[i]);
|
||||
}
|
||||
|
||||
@ -1218,8 +1209,6 @@ mismatch:
|
||||
}
|
||||
|
||||
JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key) {
|
||||
size_t i;
|
||||
|
||||
if (!v)
|
||||
goto not_found;
|
||||
if (!key)
|
||||
@ -1241,6 +1230,7 @@ JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVaria
|
||||
while (b > a) {
|
||||
JsonVariant *p;
|
||||
const char *f;
|
||||
size_t i;
|
||||
int c;
|
||||
|
||||
i = (a + b) / 2;
|
||||
@ -1264,7 +1254,7 @@ JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVaria
|
||||
}
|
||||
|
||||
/* The variant is not sorted, hence search for the field linearly */
|
||||
for (i = 0; i < v->n_elements; i += 2) {
|
||||
for (size_t i = 0; i < v->n_elements; i += 2) {
|
||||
JsonVariant *p;
|
||||
|
||||
p = json_variant_dereference(v + 1 + i);
|
||||
@ -1335,34 +1325,28 @@ bool json_variant_equal(JsonVariant *a, JsonVariant *b) {
|
||||
return true;
|
||||
|
||||
case JSON_VARIANT_ARRAY: {
|
||||
size_t i, n;
|
||||
|
||||
n = json_variant_elements(a);
|
||||
size_t n = json_variant_elements(a);
|
||||
if (n != json_variant_elements(b))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (size_t i = 0; i < n; i++)
|
||||
if (!json_variant_equal(json_variant_by_index(a, i), json_variant_by_index(b, i)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case JSON_VARIANT_OBJECT: {
|
||||
size_t i, n;
|
||||
|
||||
n = json_variant_elements(a);
|
||||
size_t n = json_variant_elements(a);
|
||||
if (n != json_variant_elements(b))
|
||||
return false;
|
||||
|
||||
/* Iterate through all keys in 'a' */
|
||||
for (i = 0; i < n; i += 2) {
|
||||
for (size_t i = 0; i < n; i += 2) {
|
||||
bool found = false;
|
||||
size_t j;
|
||||
|
||||
/* Match them against all keys in 'b' */
|
||||
for (j = 0; j < n; j += 2) {
|
||||
for (size_t j = 0; j < n; j += 2) {
|
||||
JsonVariant *key_b;
|
||||
|
||||
key_b = json_variant_by_index(b, j);
|
||||
@ -1470,16 +1454,14 @@ static int print_source(FILE *f, JsonVariant *v, JsonFormatFlags flags, bool whi
|
||||
DECIMAL_STR_MAX(unsigned) -1;
|
||||
|
||||
if (whitespace) {
|
||||
size_t i, n;
|
||||
size_t n = 1 + (v->source ? strlen(v->source->name) : 0) +
|
||||
((v->source && (v->line > 0 || v->column > 0)) ? 1 : 0) +
|
||||
(v->line > 0 ? w : 0) +
|
||||
(((v->source || v->line > 0) && v->column > 0) ? 1 : 0) +
|
||||
(v->column > 0 ? k : 0) +
|
||||
2;
|
||||
|
||||
n = 1 + (v->source ? strlen(v->source->name) : 0) +
|
||||
((v->source && (v->line > 0 || v->column > 0)) ? 1 : 0) +
|
||||
(v->line > 0 ? w : 0) +
|
||||
(((v->source || v->line > 0) && v->column > 0) ? 1 : 0) +
|
||||
(v->column > 0 ? k : 0) +
|
||||
2;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
for (size_t i = 0; i < n; i++)
|
||||
fputc(' ', f);
|
||||
} else {
|
||||
fputc('[', f);
|
||||
@ -1631,10 +1613,7 @@ static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const cha
|
||||
break;
|
||||
|
||||
case JSON_VARIANT_ARRAY: {
|
||||
size_t i, n;
|
||||
|
||||
n = json_variant_elements(v);
|
||||
|
||||
size_t n = json_variant_elements(v);
|
||||
if (n == 0)
|
||||
fputs("[]", f);
|
||||
else {
|
||||
@ -1653,7 +1632,7 @@ static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const cha
|
||||
fputc('[', f);
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
JsonVariant *e;
|
||||
|
||||
assert_se(e = json_variant_by_index(v, i));
|
||||
@ -1687,10 +1666,7 @@ static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const cha
|
||||
}
|
||||
|
||||
case JSON_VARIANT_OBJECT: {
|
||||
size_t i, n;
|
||||
|
||||
n = json_variant_elements(v);
|
||||
|
||||
size_t n = json_variant_elements(v);
|
||||
if (n == 0)
|
||||
fputs("{}", f);
|
||||
else {
|
||||
@ -1709,7 +1685,7 @@ static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const cha
|
||||
fputc('{', f);
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i += 2) {
|
||||
for (size_t i = 0; i < n; i += 2) {
|
||||
JsonVariant *e;
|
||||
|
||||
e = json_variant_by_index(v, i);
|
||||
@ -1826,7 +1802,7 @@ void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const cha
|
||||
int json_variant_filter(JsonVariant **v, char **to_remove) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
|
||||
_cleanup_free_ JsonVariant **array = NULL;
|
||||
size_t i, n = 0, k = 0;
|
||||
size_t n = 0, k = 0;
|
||||
int r;
|
||||
|
||||
assert(v);
|
||||
@ -1839,7 +1815,7 @@ int json_variant_filter(JsonVariant **v, char **to_remove) {
|
||||
if (strv_isempty(to_remove))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < json_variant_elements(*v); i += 2) {
|
||||
for (size_t i = 0; i < json_variant_elements(*v); i += 2) {
|
||||
JsonVariant *p;
|
||||
|
||||
p = json_variant_by_index(*v, i);
|
||||
@ -1871,9 +1847,7 @@ int json_variant_filter(JsonVariant **v, char **to_remove) {
|
||||
return r;
|
||||
|
||||
json_variant_propagate_sensitive(*v, w);
|
||||
|
||||
json_variant_unref(*v);
|
||||
*v = TAKE_PTR(w);
|
||||
JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
|
||||
|
||||
return (int) n;
|
||||
}
|
||||
@ -1881,7 +1855,7 @@ int json_variant_filter(JsonVariant **v, char **to_remove) {
|
||||
int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *value) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *field_variant = NULL, *w = NULL;
|
||||
_cleanup_free_ JsonVariant **array = NULL;
|
||||
size_t i, k = 0;
|
||||
size_t k = 0;
|
||||
int r;
|
||||
|
||||
assert(v);
|
||||
@ -1896,7 +1870,7 @@ int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *valu
|
||||
if (!json_variant_is_object(*v))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < json_variant_elements(*v); i += 2) {
|
||||
for (size_t i = 0; i < json_variant_elements(*v); i += 2) {
|
||||
JsonVariant *p;
|
||||
|
||||
p = json_variant_by_index(*v, i);
|
||||
@ -1942,9 +1916,7 @@ int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *valu
|
||||
return r;
|
||||
|
||||
json_variant_propagate_sensitive(*v, w);
|
||||
|
||||
json_variant_unref(*v);
|
||||
*v = TAKE_PTR(w);
|
||||
JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -2007,7 +1979,7 @@ int json_variant_set_field_strv(JsonVariant **v, const char *field, char **l) {
|
||||
int json_variant_merge(JsonVariant **v, JsonVariant *m) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *w = NULL;
|
||||
_cleanup_free_ JsonVariant **array = NULL;
|
||||
size_t v_elements, m_elements, i, k;
|
||||
size_t v_elements, m_elements, k;
|
||||
bool v_blank, m_blank;
|
||||
int r;
|
||||
|
||||
@ -2025,8 +1997,7 @@ int json_variant_merge(JsonVariant **v, JsonVariant *m) {
|
||||
return 0; /* nothing to do */
|
||||
|
||||
if (v_blank) {
|
||||
json_variant_unref(*v);
|
||||
*v = json_variant_ref(m);
|
||||
JSON_VARIANT_REPLACE(*v, json_variant_ref(m));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2040,7 +2011,7 @@ int json_variant_merge(JsonVariant **v, JsonVariant *m) {
|
||||
return -ENOMEM;
|
||||
|
||||
k = 0;
|
||||
for (i = 0; i < v_elements; i += 2) {
|
||||
for (size_t i = 0; i < v_elements; i += 2) {
|
||||
JsonVariant *u;
|
||||
|
||||
u = json_variant_by_index(*v, i);
|
||||
@ -2054,7 +2025,7 @@ int json_variant_merge(JsonVariant **v, JsonVariant *m) {
|
||||
array[k++] = json_variant_by_index(*v, i + 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < m_elements; i++)
|
||||
for (size_t i = 0; i < m_elements; i++)
|
||||
array[k++] = json_variant_by_index(m, i);
|
||||
|
||||
r = json_variant_new_object(&w, array, k);
|
||||
@ -2063,9 +2034,7 @@ int json_variant_merge(JsonVariant **v, JsonVariant *m) {
|
||||
|
||||
json_variant_propagate_sensitive(*v, w);
|
||||
json_variant_propagate_sensitive(m, w);
|
||||
|
||||
json_variant_unref(*v);
|
||||
*v = TAKE_PTR(w);
|
||||
JSON_VARIANT_REPLACE(*v, TAKE_PTR(w));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -2089,34 +2058,29 @@ int json_variant_append_array(JsonVariant **v, JsonVariant *element) {
|
||||
if (blank)
|
||||
r = json_variant_new_array(&nv, (JsonVariant*[]) { element }, 1);
|
||||
else {
|
||||
_cleanup_free_ JsonVariant **array = NULL;
|
||||
size_t i;
|
||||
|
||||
array = new(JsonVariant*, json_variant_elements(*v) + 1);
|
||||
_cleanup_free_ JsonVariant **array = new(JsonVariant*, json_variant_elements(*v) + 1);
|
||||
if (!array)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < json_variant_elements(*v); i++)
|
||||
size_t size = json_variant_elements(*v);
|
||||
for (size_t i = 0; i < size; i++)
|
||||
array[i] = json_variant_by_index(*v, i);
|
||||
|
||||
array[i] = element;
|
||||
array[size] = element;
|
||||
|
||||
r = json_variant_new_array(&nv, array, i + 1);
|
||||
r = json_variant_new_array(&nv, array, size + 1);
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
json_variant_propagate_sensitive(*v, nv);
|
||||
|
||||
json_variant_unref(*v);
|
||||
*v = TAKE_PTR(nv);
|
||||
JSON_VARIANT_REPLACE(*v, TAKE_PTR(nv));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int json_variant_strv(JsonVariant *v, char ***ret) {
|
||||
char **l = NULL;
|
||||
size_t n, i;
|
||||
bool sensitive;
|
||||
int r;
|
||||
|
||||
@ -2136,12 +2100,12 @@ int json_variant_strv(JsonVariant *v, char ***ret) {
|
||||
|
||||
sensitive = v->sensitive;
|
||||
|
||||
n = json_variant_elements(v);
|
||||
size_t n = json_variant_elements(v);
|
||||
l = new(char*, n+1);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
JsonVariant *e;
|
||||
|
||||
assert_se(e = json_variant_by_index(v, i));
|
||||
@ -2160,7 +2124,7 @@ int json_variant_strv(JsonVariant *v, char ***ret) {
|
||||
}
|
||||
}
|
||||
|
||||
l[i] = NULL;
|
||||
l[n] = NULL;
|
||||
*ret = TAKE_PTR(l);
|
||||
|
||||
return 0;
|
||||
@ -2279,8 +2243,9 @@ static int json_variant_set_source(JsonVariant **v, JsonSource *source, unsigned
|
||||
|
||||
assert(v);
|
||||
|
||||
/* Patch in source and line/column number. Tries to do this in-place if the caller is the sole referencer of
|
||||
* the object. If not, allocates a new object, possibly a surrogate for the original one */
|
||||
/* Patch in source and line/column number. Tries to do this in-place if the caller is the sole
|
||||
* referencer of the object. If not, allocates a new object, possibly a surrogate for the original
|
||||
* one */
|
||||
|
||||
if (!*v)
|
||||
return 0;
|
||||
@ -2323,8 +2288,7 @@ static int json_variant_set_source(JsonVariant **v, JsonSource *source, unsigned
|
||||
w->line = line;
|
||||
w->column = column;
|
||||
|
||||
json_variant_unref(*v);
|
||||
*v = w;
|
||||
JSON_VARIANT_REPLACE(*v, w);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -2847,7 +2811,7 @@ static int json_parse_internal(
|
||||
unsigned *column,
|
||||
bool continue_end) {
|
||||
|
||||
size_t n_stack = 1, i;
|
||||
size_t n_stack = 1;
|
||||
unsigned line_buffer = 0, column_buffer = 0;
|
||||
void *tokenizer_state = NULL;
|
||||
JsonStack *stack = NULL;
|
||||
@ -3186,7 +3150,7 @@ done:
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
for (i = 0; i < n_stack; i++)
|
||||
for (size_t i = 0; i < n_stack; i++)
|
||||
json_stack_release(stack + i);
|
||||
|
||||
free(stack);
|
||||
@ -3229,7 +3193,7 @@ int json_parse_file_at(FILE *f, int dir_fd, const char *path, JsonParseFlags fla
|
||||
|
||||
int json_buildv(JsonVariant **ret, va_list ap) {
|
||||
JsonStack *stack = NULL;
|
||||
size_t n_stack = 1, i;
|
||||
size_t n_stack = 1;
|
||||
int r;
|
||||
|
||||
assert_return(ret, -EINVAL);
|
||||
@ -3757,10 +3721,10 @@ int json_buildv(JsonVariant **ret, va_list ap) {
|
||||
|
||||
stack[n_stack++] = (JsonStack) {
|
||||
.expect = EXPECT_OBJECT_KEY,
|
||||
.n_suppress = current->n_suppress != 0 ? SIZE_MAX : 0, /* if we shall suppress the
|
||||
* new object, then we should
|
||||
* also suppress all object
|
||||
* members */
|
||||
.n_suppress = current->n_suppress != 0 ? SIZE_MAX : 0, /* If we shall suppress the
|
||||
* new object, then we should
|
||||
* also suppress all object
|
||||
* members. */
|
||||
};
|
||||
|
||||
break;
|
||||
@ -4128,9 +4092,9 @@ int json_buildv(JsonVariant **ret, va_list ap) {
|
||||
current->elements[current->n_elements++] = TAKE_PTR(add_more);
|
||||
}
|
||||
|
||||
/* If we are supposed to suppress items, let's subtract how many items where generated from that
|
||||
* counter. Except if the counter is SIZE_MAX, i.e. we shall suppress an infinite number of elements
|
||||
* on this stack level */
|
||||
/* If we are supposed to suppress items, let's subtract how many items where generated from
|
||||
* that counter. Except if the counter is SIZE_MAX, i.e. we shall suppress an infinite number
|
||||
* of elements on this stack level */
|
||||
if (current->n_suppress != SIZE_MAX) {
|
||||
if (current->n_suppress <= n_subtract) /* Saturated */
|
||||
current->n_suppress = 0;
|
||||
@ -4147,7 +4111,7 @@ done:
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
for (i = 0; i < n_stack; i++)
|
||||
for (size_t i = 0; i < n_stack; i++)
|
||||
json_stack_release(stack + i);
|
||||
|
||||
free(stack);
|
||||
@ -4231,8 +4195,7 @@ int json_log_internal(
|
||||
}
|
||||
|
||||
int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata) {
|
||||
const JsonDispatch *p;
|
||||
size_t i, n, m;
|
||||
size_t m;
|
||||
int r, done = 0;
|
||||
bool *found;
|
||||
|
||||
@ -4245,14 +4208,16 @@ int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallba
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (p = table, m = 0; p->name; p++)
|
||||
m = 0;
|
||||
for (const JsonDispatch *p = table; p->name; p++)
|
||||
m++;
|
||||
|
||||
found = newa0(bool, m);
|
||||
|
||||
n = json_variant_elements(v);
|
||||
for (i = 0; i < n; i += 2) {
|
||||
size_t n = json_variant_elements(v);
|
||||
for (size_t i = 0; i < n; i += 2) {
|
||||
JsonVariant *key, *value;
|
||||
const JsonDispatch *p;
|
||||
|
||||
assert_se(key = json_variant_by_index(v, i));
|
||||
assert_se(value = json_variant_by_index(v, i+1));
|
||||
@ -4326,7 +4291,7 @@ int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallba
|
||||
}
|
||||
}
|
||||
|
||||
for (p = table; p->name; p++) {
|
||||
for (const JsonDispatch *p = table; p->name; p++) {
|
||||
JsonDispatchFlags merged_flags = p->flags | flags;
|
||||
|
||||
if ((merged_flags & JSON_MANDATORY) && !found[p-table]) {
|
||||
@ -4524,14 +4489,10 @@ int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags
|
||||
}
|
||||
|
||||
int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||||
JsonVariant **p = userdata;
|
||||
|
||||
JsonVariant **p = ASSERT_PTR(userdata);
|
||||
assert(variant);
|
||||
assert(p);
|
||||
|
||||
json_variant_unref(*p);
|
||||
*p = json_variant_ref(variant);
|
||||
|
||||
JSON_VARIANT_REPLACE(*p, json_variant_ref(variant));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4620,8 +4581,8 @@ static int json_cmp_strings(const void *x, const void *y) {
|
||||
|
||||
int json_variant_sort(JsonVariant **v) {
|
||||
_cleanup_free_ JsonVariant **a = NULL;
|
||||
JsonVariant *n = NULL;
|
||||
size_t i, m;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *n = NULL;
|
||||
size_t m;
|
||||
int r;
|
||||
|
||||
assert(v);
|
||||
@ -4639,7 +4600,7 @@ int json_variant_sort(JsonVariant **v) {
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < m; i++)
|
||||
for (size_t i = 0; i < m; i++)
|
||||
a[i] = json_variant_by_index(*v, i);
|
||||
|
||||
qsort(a, m/2, sizeof(JsonVariant*)*2, json_cmp_strings);
|
||||
@ -4653,16 +4614,15 @@ int json_variant_sort(JsonVariant **v) {
|
||||
if (!n->sorted) /* Check if this worked. This will fail if there are multiple identical keys used. */
|
||||
return -ENOTUNIQ;
|
||||
|
||||
json_variant_unref(*v);
|
||||
*v = n;
|
||||
JSON_VARIANT_REPLACE(*v, TAKE_PTR(n));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int json_variant_normalize(JsonVariant **v) {
|
||||
_cleanup_free_ JsonVariant **a = NULL;
|
||||
JsonVariant *n = NULL;
|
||||
size_t i, j, m;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *n = NULL;
|
||||
size_t i, m;
|
||||
int r;
|
||||
|
||||
assert(v);
|
||||
@ -4680,10 +4640,11 @@ int json_variant_normalize(JsonVariant **v) {
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < m; i++) {
|
||||
for (i = 0; i < m; ) {
|
||||
a[i] = json_variant_ref(json_variant_by_index(*v, i));
|
||||
i++;
|
||||
|
||||
r = json_variant_normalize(a + i);
|
||||
r = json_variant_normalize(&a[i-1]);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
@ -4708,23 +4669,21 @@ int json_variant_normalize(JsonVariant **v) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
json_variant_unref(*v);
|
||||
*v = n;
|
||||
JSON_VARIANT_REPLACE(*v, TAKE_PTR(n));
|
||||
|
||||
r = 1;
|
||||
|
||||
finish:
|
||||
for (j = 0; j < i; j++)
|
||||
for (size_t j = 0; j < i; j++)
|
||||
json_variant_unref(a[j]);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
bool json_variant_is_normalized(JsonVariant *v) {
|
||||
|
||||
/* For now, let's consider anything containing numbers not expressible as integers as
|
||||
* non-normalized. That's because we cannot sensibly compare them due to accuracy issues, nor even
|
||||
* store them if they are too large. */
|
||||
/* For now, let's consider anything containing numbers not expressible as integers as non-normalized.
|
||||
* That's because we cannot sensibly compare them due to accuracy issues, nor even store them if they
|
||||
* are too large. */
|
||||
if (json_variant_is_real(v) && !json_variant_is_integer(v) && !json_variant_is_unsigned(v))
|
||||
return false;
|
||||
|
||||
@ -4754,7 +4713,6 @@ bool json_variant_is_sorted(JsonVariant *v) {
|
||||
}
|
||||
|
||||
int json_variant_unbase64(JsonVariant *v, void **ret, size_t *ret_size) {
|
||||
|
||||
if (!json_variant_is_string(v))
|
||||
return -EINVAL;
|
||||
|
||||
@ -4762,7 +4720,6 @@ int json_variant_unbase64(JsonVariant *v, void **ret, size_t *ret_size) {
|
||||
}
|
||||
|
||||
int json_variant_unhex(JsonVariant *v, void **ret, size_t *ret_size) {
|
||||
|
||||
if (!json_variant_is_string(v))
|
||||
return -EINVAL;
|
||||
|
||||
@ -4770,15 +4727,15 @@ int json_variant_unhex(JsonVariant *v, void **ret, size_t *ret_size) {
|
||||
}
|
||||
|
||||
static const char* const json_variant_type_table[_JSON_VARIANT_TYPE_MAX] = {
|
||||
[JSON_VARIANT_STRING] = "string",
|
||||
[JSON_VARIANT_INTEGER] = "integer",
|
||||
[JSON_VARIANT_STRING] = "string",
|
||||
[JSON_VARIANT_INTEGER] = "integer",
|
||||
[JSON_VARIANT_UNSIGNED] = "unsigned",
|
||||
[JSON_VARIANT_REAL] = "real",
|
||||
[JSON_VARIANT_NUMBER] = "number",
|
||||
[JSON_VARIANT_BOOLEAN] = "boolean",
|
||||
[JSON_VARIANT_ARRAY] = "array",
|
||||
[JSON_VARIANT_OBJECT] = "object",
|
||||
[JSON_VARIANT_NULL] = "null",
|
||||
[JSON_VARIANT_REAL] = "real",
|
||||
[JSON_VARIANT_NUMBER] = "number",
|
||||
[JSON_VARIANT_BOOLEAN] = "boolean",
|
||||
[JSON_VARIANT_ARRAY] = "array",
|
||||
[JSON_VARIANT_OBJECT] = "object",
|
||||
[JSON_VARIANT_NULL] = "null",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(json_variant_type, JsonVariantType);
|
||||
|
@ -82,6 +82,14 @@ JsonVariant *json_variant_ref(JsonVariant *v);
|
||||
JsonVariant *json_variant_unref(JsonVariant *v);
|
||||
void json_variant_unref_many(JsonVariant **array, size_t n);
|
||||
|
||||
#define JSON_VARIANT_REPLACE(v, q) \
|
||||
do { \
|
||||
typeof(v)* _v = &(v); \
|
||||
typeof(q) _q = (q); \
|
||||
json_variant_unref(*_v); \
|
||||
*_v = _q; \
|
||||
} while(0)
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref);
|
||||
|
||||
const char *json_variant_string(JsonVariant *v);
|
||||
|
1
test/fuzz/fuzz-json/leak-normalize-fail
Normal file
1
test/fuzz/fuzz-json/leak-normalize-fail
Normal file
@ -0,0 +1 @@
|
||||
[7E73]
|
1
test/fuzz/fuzz-json/leak-normalize-object
Normal file
1
test/fuzz/fuzz-json/leak-normalize-object
Normal file
@ -0,0 +1 @@
|
||||
[7,7,7,7,{"":7,"":7,"^t":7,"-":7},2777,7,7,7,3]
|
1
test/fuzz/fuzz-json/leak-sort
Normal file
1
test/fuzz/fuzz-json/leak-sort
Normal file
@ -0,0 +1 @@
|
||||
{"":2,"":6,"-":7}
|
Loading…
Reference in New Issue
Block a user