sd-json: when parsing optionally insist top-level variant is object or array
Typically, the top-level JSON object has to be an object, in any json document we parse, hence let's add a simple way to enforce that. Make use of this in various places. (Note, various other JSON parsers insist on this logic right from the beginning, but I actually thinking making this insisting optional like this patch does it is the cleaner approach)
This commit is contained in:
committed by
Daan De Meyer
parent
bc6380ae07
commit
2c74a91cb8
@@ -861,6 +861,17 @@ manpages = [
|
||||
'sd_json_dispatch_variant',
|
||||
'sd_json_dispatch_variant_noref'],
|
||||
''],
|
||||
['sd_json_parse',
|
||||
'3',
|
||||
['SD_JSON_PARSE_MUST_BE_ARRAY',
|
||||
'SD_JSON_PARSE_MUST_BE_OBJECT',
|
||||
'SD_JSON_PARSE_SENSITIVE',
|
||||
'sd_json_parse_continue',
|
||||
'sd_json_parse_file',
|
||||
'sd_json_parse_file_at',
|
||||
'sd_json_parse_with_source',
|
||||
'sd_json_parse_with_source_continue'],
|
||||
''],
|
||||
['sd_listen_fds',
|
||||
'3',
|
||||
['SD_LISTEN_FDS_START', 'sd_listen_fds_with_names'],
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
|
||||
|
||||
<refentry id="sd_json_parse" xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<refentryinfo>
|
||||
<title>sd_json_parse</title>
|
||||
<productname>systemd</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>sd_json_parse</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>sd_json_parse</refname>
|
||||
<refname>sd_json_parse_continue</refname>
|
||||
<refname>sd_json_parse_with_source</refname>
|
||||
<refname>sd_json_parse_with_source_continue</refname>
|
||||
<refname>sd_json_parse_file</refname>
|
||||
<refname>sd_json_parse_file_at</refname>
|
||||
<refname>SD_JSON_PARSE_SENSITIVE</refname>
|
||||
<refname>SD_JSON_PARSE_MUST_BE_OBJECT</refname>
|
||||
<refname>SD_JSON_PARSE_MUST_BE_ARRAY</refname>
|
||||
|
||||
<refpurpose>Parse JSON strings and files into JSON variant objects</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <systemd/sd-json.h></funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_json_parse</function></funcdef>
|
||||
<paramdef>const char *<parameter>string</parameter></paramdef>
|
||||
<paramdef>sd_json_parse_flags_t <parameter>flags</parameter></paramdef>
|
||||
<paramdef>sd_json_variant **<parameter>ret</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_line</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_column</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_json_parse_continue</function></funcdef>
|
||||
<paramdef>const char **<parameter>p</parameter></paramdef>
|
||||
<paramdef>sd_json_parse_flags_t <parameter>flags</parameter></paramdef>
|
||||
<paramdef>sd_json_variant **<parameter>ret</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_line</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_column</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_json_parse_with_source</function></funcdef>
|
||||
<paramdef>const char *<parameter>string</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>source</parameter></paramdef>
|
||||
<paramdef>sd_json_parse_flags_t <parameter>flags</parameter></paramdef>
|
||||
<paramdef>sd_json_variant **<parameter>ret</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_line</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_column</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_json_parse_with_source_continue</function></funcdef>
|
||||
<paramdef>const char **<parameter>p</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>source</parameter></paramdef>
|
||||
<paramdef>sd_json_parse_flags_t <parameter>flags</parameter></paramdef>
|
||||
<paramdef>sd_json_variant **<parameter>ret</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_line</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_column</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_json_parse_file</function></funcdef>
|
||||
<paramdef>FILE *<parameter>f</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>path</parameter></paramdef>
|
||||
<paramdef>sd_json_parse_flags_t <parameter>flags</parameter></paramdef>
|
||||
<paramdef>sd_json_variant **<parameter>ret</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_line</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_column</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_json_parse_file_at</function></funcdef>
|
||||
<paramdef>FILE *<parameter>f</parameter></paramdef>
|
||||
<paramdef>int <parameter>dir_fd</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>path</parameter></paramdef>
|
||||
<paramdef>sd_json_parse_flags_t <parameter>flags</parameter></paramdef>
|
||||
<paramdef>sd_json_variant **<parameter>ret</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_line</parameter></paramdef>
|
||||
<paramdef>unsigned *<parameter>reterr_column</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><function>sd_json_parse()</function> parses the JSON string in <parameter>string</parameter> and
|
||||
returns the resulting JSON variant object in <parameter>ret</parameter>. The input must contain exactly
|
||||
one JSON value (object, array, string, number, boolean, or null); any trailing non-whitespace content
|
||||
after the first parsed value is considered an error.</para>
|
||||
|
||||
<para>If parsing fails, the <parameter>reterr_line</parameter> and <parameter>reterr_column</parameter>
|
||||
arguments are set to the line and column (both one-based) where the parse error occurred. One or both
|
||||
may be passed as <constant>NULL</constant> if the caller is not interested in error location
|
||||
information. On success, the return value is non-negative and <parameter>ret</parameter> is set to a
|
||||
newly allocated JSON variant object (which must be freed with
|
||||
<citerefentry><refentrytitle>sd_json_variant_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
when no longer needed). <parameter>ret</parameter> may be passed as <constant>NULL</constant>, in which
|
||||
case the input is validated but no object is returned.</para>
|
||||
|
||||
<para><function>sd_json_parse_continue()</function> is similar, but is intended for parsing a sequence of
|
||||
concatenated JSON values from a single input string. Instead of taking a <type>const char *</type> string
|
||||
directly, it takes a pointer to a <type>const char *</type> pointer. After each successful parse, the
|
||||
pointer is advanced past the consumed input, so that subsequent calls will parse the next JSON
|
||||
value. This is useful for parsing newline-delimited JSON (NDJSON) streams or similar concatenated JSON
|
||||
formats. Unlike <function>sd_json_parse()</function>, trailing content after the first JSON value is not
|
||||
considered an error — it is expected to be the beginning of the next value.</para>
|
||||
|
||||
<para><function>sd_json_parse_with_source()</function> and
|
||||
<function>sd_json_parse_with_source_continue()</function> are similar to
|
||||
<function>sd_json_parse()</function> and <function>sd_json_parse_continue()</function>, respectively, but
|
||||
take an additional <parameter>source</parameter> argument. This is a human-readable string (typically a
|
||||
file name or other origin identifier) that is attached to the parsed JSON variant object and can later be
|
||||
retrieved via
|
||||
<citerefentry><refentrytitle>sd_json_variant_get_source</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
|
||||
<parameter>source</parameter> is <constant>NULL</constant>, no source information is
|
||||
attached. <function>sd_json_parse()</function> and <function>sd_json_parse_continue()</function> are
|
||||
equivalent to calling their <function>_with_source</function> counterparts with
|
||||
<parameter>source</parameter> set to <constant>NULL</constant>.</para>
|
||||
|
||||
<para><function>sd_json_parse_file()</function> reads and parses a JSON value from a file. If the
|
||||
<parameter>f</parameter> argument is non-<constant>NULL</constant>, the JSON text is read from the
|
||||
specified <type>FILE</type> stream. If <parameter>f</parameter> is <constant>NULL</constant>, the file
|
||||
indicated by <parameter>path</parameter> is opened and read instead. The <parameter>path</parameter>
|
||||
argument serves a dual purpose: it is both used for opening the file (if <parameter>f</parameter> is
|
||||
<constant>NULL</constant>) and recorded as source information in the resulting JSON variant (see
|
||||
above).</para>
|
||||
|
||||
<para><function>sd_json_parse_file_at()</function> is similar to
|
||||
<function>sd_json_parse_file()</function>, but takes an additional <parameter>dir_fd</parameter> argument
|
||||
which specifies a file descriptor referring to the directory to resolve relative paths specified in
|
||||
<parameter>path</parameter> against. If set to <constant>AT_FDCWD</constant>, relative paths are resolved
|
||||
against the current working directory, which is the default behaviour of
|
||||
<function>sd_json_parse_file()</function>.</para>
|
||||
|
||||
<para>The <parameter>flags</parameter> argument is a bitmask of zero or more of the following
|
||||
flags:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><constant>SD_JSON_PARSE_SENSITIVE</constant></term>
|
||||
|
||||
<listitem><para>Marks the resulting JSON variant as "sensitive", indicating that it contains secret
|
||||
key material or similar confidential data. Sensitive variants are erased from memory when freed and
|
||||
are excluded from certain debug logging and introspection operations. See
|
||||
<citerefentry><refentrytitle>sd_json_variant_sensitive</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
for details.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SD_JSON_PARSE_MUST_BE_OBJECT</constant></term>
|
||||
|
||||
<listitem><para>Requires that the top-level JSON value be a JSON object (i.e. <literal>{…}</literal>).
|
||||
If the top-level value is an array, string, number, boolean, or null, parsing fails with
|
||||
<constant>-EINVAL</constant>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SD_JSON_PARSE_MUST_BE_ARRAY</constant></term>
|
||||
|
||||
<listitem><para>Requires that the top-level JSON value be a JSON array (i.e. <literal>[…]</literal>).
|
||||
If the top-level value is an object, string, number, boolean, or null, parsing fails with
|
||||
<constant>-EINVAL</constant>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>If both <constant>SD_JSON_PARSE_MUST_BE_OBJECT</constant> and
|
||||
<constant>SD_JSON_PARSE_MUST_BE_ARRAY</constant> are set, both objects and arrays are accepted, but
|
||||
non-container values (strings, numbers, booleans, null) are still refused.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para>On success, these functions return 0. On failure, they return a negative errno-style error
|
||||
code.</para>
|
||||
|
||||
<refsect2>
|
||||
<title>Errors</title>
|
||||
|
||||
<para>Returned errors may indicate the following problems:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><constant>-EINVAL</constant></term>
|
||||
|
||||
<listitem><para>The input is not valid JSON, the input contains trailing content after the parsed
|
||||
value (only for non-<function>_continue</function> variants), or a top-level type constraint
|
||||
specified via <constant>SD_JSON_PARSE_MUST_BE_OBJECT</constant> or
|
||||
<constant>SD_JSON_PARSE_MUST_BE_ARRAY</constant> was violated.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-ENODATA</constant></term>
|
||||
|
||||
<listitem><para>The input string is empty or <constant>NULL</constant>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-ENOMEM</constant></term>
|
||||
|
||||
<listitem><para>Memory allocation failed.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
<xi:include href="libsystemd-pkgconfig.xml" />
|
||||
|
||||
<refsect1>
|
||||
<title>History</title>
|
||||
<para><function>sd_json_parse()</function>,
|
||||
<function>sd_json_parse_continue()</function>,
|
||||
<function>sd_json_parse_with_source()</function>,
|
||||
<function>sd_json_parse_with_source_continue()</function>,
|
||||
<function>sd_json_parse_file()</function>, and
|
||||
<function>sd_json_parse_file_at()</function> were added in version 257.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
|
||||
<para><simplelist type="inline">
|
||||
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>sd-json</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>sd_json_variant_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>sd_json_variant_get_source</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>sd_json_dispatch</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
|
||||
</simplelist></para>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <linux/capability.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-json.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "analyze-verify-util.h"
|
||||
@@ -2919,7 +2920,7 @@ int verb_security(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
|
||||
unsigned line = 0, column = 0;
|
||||
if (arg_security_policy) {
|
||||
r = sd_json_parse_file(/* f= */ NULL, arg_security_policy, /* flags= */ 0, &policy, &line, &column);
|
||||
r = sd_json_parse_file(/* f= */ NULL, arg_security_policy, SD_JSON_PARSE_MUST_BE_OBJECT, &policy, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse '%s' at %u:%u: %m", arg_security_policy, line, column);
|
||||
} else {
|
||||
@@ -2931,7 +2932,7 @@ int verb_security(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
return r;
|
||||
|
||||
if (f) {
|
||||
r = sd_json_parse_file(f, pp, /* flags= */ 0, &policy, &line, &column);
|
||||
r = sd_json_parse_file(f, pp, SD_JSON_PARSE_MUST_BE_OBJECT, &policy, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "[%s:%u:%u] Failed to parse JSON policy: %m", pp, line, column);
|
||||
}
|
||||
|
||||
@@ -829,7 +829,7 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) {
|
||||
if (exe && pkgmeta_json) {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
|
||||
r = sd_json_parse(pkgmeta_json, 0, &v, NULL, NULL);
|
||||
r = sd_json_parse(pkgmeta_json, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0) {
|
||||
_cleanup_free_ char *esc = cescape(pkgmeta_json);
|
||||
log_warning_errno(r, "json_parse on \"%s\" failed, ignoring: %m", strnull(esc));
|
||||
|
||||
@@ -162,7 +162,7 @@ _public_ int cryptsetup_token_validate(
|
||||
|
||||
assert(json);
|
||||
|
||||
r = sd_json_parse(json, 0, &v, NULL, NULL);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return crypt_log_debug_errno(cd, r, "Could not parse " TOKEN_NAME " json object: %m.");
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ _public_ int cryptsetup_token_validate(
|
||||
sd_json_variant *w;
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
|
||||
r = sd_json_parse(json, 0, &v, NULL, NULL);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return crypt_log_debug_errno(cd, r, "Could not parse " TOKEN_NAME " json object: %m.");
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ _public_ int cryptsetup_token_open_pin(
|
||||
if (usrptr)
|
||||
params = *(systemd_tpm2_plugin_params *)usrptr;
|
||||
|
||||
r = sd_json_parse(json, 0, &v, NULL, NULL);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return crypt_log_debug_errno(cd, r, "Failed to parse token JSON data: %m");
|
||||
|
||||
@@ -186,7 +186,7 @@ _public_ void cryptsetup_token_dump(
|
||||
|
||||
assert(json);
|
||||
|
||||
r = sd_json_parse(json, 0, &v, NULL, NULL);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return (void) crypt_log_debug_errno(cd, r, "Failed to parse " TOKEN_NAME " JSON object: %m");
|
||||
|
||||
@@ -275,7 +275,7 @@ _public_ int cryptsetup_token_validate(
|
||||
|
||||
assert(json);
|
||||
|
||||
r = sd_json_parse(json, 0, &v, NULL, NULL);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return crypt_log_debug_errno(cd, r, "Could not parse " TOKEN_NAME " json object: %m");
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ int parse_luks2_fido2_data(
|
||||
assert(ret_cid_size);
|
||||
assert(ret_required);
|
||||
|
||||
r = sd_json_parse(json, 0, &v, NULL, NULL);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return crypt_log_error_errno(cd, r, "Failed to parse JSON token data: %m");
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ int parse_luks2_pkcs11_data(
|
||||
assert(ret_encrypted_key);
|
||||
assert(ret_encrypted_key_size);
|
||||
|
||||
r = sd_json_parse(json, 0, &v, NULL, NULL);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
+20
-7
@@ -758,7 +758,7 @@ static int inspect_home(sd_bus *bus, const char *name) {
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_SENSITIVE, &v, NULL, NULL);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_SENSITIVE|SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse JSON identity: %m");
|
||||
|
||||
@@ -1159,7 +1159,11 @@ static int acquire_new_home_record(sd_json_variant *input, UserRecord **ret) {
|
||||
|
||||
r = sd_json_parse_file(
|
||||
streq(arg_identity, "-") ? stdin : NULL,
|
||||
streq(arg_identity, "-") ? "<stdin>" : arg_identity, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
streq(arg_identity, "-") ? "<stdin>" : arg_identity,
|
||||
SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE,
|
||||
&v,
|
||||
&line,
|
||||
&column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse identity at %u:%u: %m", line, column);
|
||||
} else
|
||||
@@ -1667,7 +1671,7 @@ static int register_home_one(sd_bus *bus, FILE *f, const char *path) {
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
unsigned line = 0, column = 0;
|
||||
r = sd_json_parse_file(f, path, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
r = sd_json_parse_file(f, path, SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "[%s:%u:%u] Failed to parse user record: %m", path, line, column);
|
||||
|
||||
@@ -1785,7 +1789,11 @@ static int acquire_updated_home_record(
|
||||
|
||||
r = sd_json_parse_file(
|
||||
streq(arg_identity, "-") ? stdin : NULL,
|
||||
streq(arg_identity, "-") ? "<stdin>" : arg_identity, SD_JSON_PARSE_SENSITIVE, &json, &line, &column);
|
||||
streq(arg_identity, "-") ? "<stdin>" : arg_identity,
|
||||
SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE,
|
||||
&json,
|
||||
&line,
|
||||
&column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse identity at %u:%u: %m", line, column);
|
||||
|
||||
@@ -1822,7 +1830,12 @@ static int acquire_updated_home_record(
|
||||
if (incomplete)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EACCES), "Lacking rights to acquire user record including privileged metadata, can't update record.");
|
||||
|
||||
r = sd_json_parse(text, SD_JSON_PARSE_SENSITIVE, &json, NULL, NULL);
|
||||
r = sd_json_parse(
|
||||
text,
|
||||
SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE,
|
||||
&json,
|
||||
/* reterr_line= */ NULL,
|
||||
/* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse JSON identity: %m");
|
||||
|
||||
@@ -2569,7 +2582,7 @@ static int create_or_register_from_credentials(void) {
|
||||
/* f= */ NULL,
|
||||
fd,
|
||||
de->d_name,
|
||||
/* flags= */ 0,
|
||||
/* flags= */ SD_JSON_PARSE_MUST_BE_OBJECT,
|
||||
&identity,
|
||||
&line,
|
||||
&column);
|
||||
@@ -5135,7 +5148,7 @@ static int fallback_shell(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_SENSITIVE, &v, NULL, NULL);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_SENSITIVE|SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse JSON identity: %m");
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ int bus_message_read_secret(sd_bus_message *m, UserRecord **ret, sd_bus_error *e
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_SENSITIVE|SD_JSON_PARSE_MUST_BE_OBJECT, &v, &line, &column);
|
||||
if (r < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse JSON secret record at %u:%u: %m", line, column);
|
||||
|
||||
@@ -57,7 +57,7 @@ int bus_message_read_home_record(sd_bus_message *m, UserRecordLoadFlags flags, U
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_SENSITIVE|SD_JSON_PARSE_MUST_BE_OBJECT, &v, &line, &column);
|
||||
if (r < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse JSON identity record at %u:%u: %m", line, column);
|
||||
|
||||
|
||||
@@ -589,7 +589,7 @@ static int home_parse_worker_stdout(int _fd, UserRecord **ret) {
|
||||
}
|
||||
|
||||
unsigned line = 0, column = 0;
|
||||
r = sd_json_parse_file(f, "stdout", SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
r = sd_json_parse_file(f, "stdout", SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse identity at %u:%u: %m", line, column);
|
||||
|
||||
|
||||
@@ -406,9 +406,9 @@ static int manager_add_home_by_record(
|
||||
goto unlink_this_file;
|
||||
|
||||
unsigned line = 0, column = 0;
|
||||
r = sd_json_parse_file_at(NULL, dir_fd, fname, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
r = sd_json_parse_file_at(/* f= */ NULL, dir_fd, fname, SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse identity record at %s:%u%u: %m", fname, line, column);
|
||||
return log_error_errno(r, "Failed to parse identity record at %s:%u:%u: %m", fname, line, column);
|
||||
|
||||
if (sd_json_variant_is_blank_object(v))
|
||||
goto unlink_this_file;
|
||||
|
||||
@@ -887,7 +887,7 @@ static int luks_validate_home_record(
|
||||
return log_error_errno(r, "Failed to read LUKS token %i: %m", token);
|
||||
|
||||
unsigned line = 0, column = 0;
|
||||
r = sd_json_parse(text, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
r = sd_json_parse(text, SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse LUKS token JSON data %u:%u: %m", line, column);
|
||||
|
||||
@@ -940,7 +940,7 @@ static int luks_validate_home_record(
|
||||
|
||||
decrypted[decrypted_size] = 0;
|
||||
|
||||
r = sd_json_parse(decrypted, SD_JSON_PARSE_SENSITIVE, &rr, NULL, NULL);
|
||||
r = sd_json_parse(decrypted, SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE, &rr, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse decrypted JSON record, refusing.");
|
||||
|
||||
|
||||
+2
-2
@@ -571,7 +571,7 @@ static int read_identity_file(int root_fd, sd_json_variant **ret) {
|
||||
return log_oom();
|
||||
|
||||
unsigned line = 0, column = 0;
|
||||
r = sd_json_parse_file(identity_file, ".identity", SD_JSON_PARSE_SENSITIVE, ret, &line, &column);
|
||||
r = sd_json_parse_file(identity_file, ".identity", SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE, ret, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "[.identity:%u:%u] Failed to parse JSON data: %m", line, column);
|
||||
|
||||
@@ -2025,7 +2025,7 @@ static int run(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
unsigned line = 0, column = 0;
|
||||
r = sd_json_parse_file(json_file, json_path, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
r = sd_json_parse_file(json_file, json_path, SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "[%s:%u:%u] Failed to parse JSON data: %m", json_path, line, column);
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ static int acquire_user_record(
|
||||
fresh_data = true;
|
||||
}
|
||||
|
||||
r = sd_json_parse(json, /* flags= */ 0, &v, NULL, NULL);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return pam_syslog_errno(pamh, LOG_ERR, r, "Failed to parse JSON user record: %m");
|
||||
|
||||
|
||||
@@ -567,7 +567,7 @@ static int verb_show_status(int argc, char *argv[], uintptr_t _data, void *userd
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
r = sd_json_parse(text, 0, &v, NULL, NULL);
|
||||
r = sd_json_parse(text, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse JSON: %m");
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ int oci_pull_new(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pull_job_payload_as_json(PullJob *j, sd_json_variant **ret) {
|
||||
static int pull_job_payload_as_json_object(PullJob *j, sd_json_variant **ret) {
|
||||
int r;
|
||||
|
||||
assert(j);
|
||||
@@ -214,7 +214,7 @@ static int pull_job_payload_as_json(PullJob *j, sd_json_variant **ret) {
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
unsigned line = 0, column = 0;
|
||||
r = sd_json_parse((char*) j->payload.iov_base, /* flags= */ 0, &v, &line, &column);
|
||||
r = sd_json_parse((char*) j->payload.iov_base, SD_JSON_PARSE_MUST_BE_OBJECT, &v, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse JSON at position %u:%u: %m", line, column);
|
||||
|
||||
@@ -391,7 +391,7 @@ static int oci_pull_process_index(OciPull *i, PullJob *j) {
|
||||
* https://github.com/opencontainers/image-spec/blob/main/image-index.md */
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
r = pull_job_payload_as_json(j, &v);
|
||||
r = pull_job_payload_as_json_object(j, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -783,7 +783,7 @@ static int oci_pull_process_manifest(OciPull *i, PullJob *j) {
|
||||
* https://github.com/opencontainers/image-spec/blob/main/manifest.md */
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
r = pull_job_payload_as_json(j, &v);
|
||||
r = pull_job_payload_as_json_object(j, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -958,7 +958,7 @@ static int oci_pull_save_nspawn_settings(OciPull *i) {
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
unsigned line = 0, column = 0;
|
||||
r = sd_json_parse((char*) i->config.iov_base, /* flags= */ 0, &v, &line, &column);
|
||||
r = sd_json_parse((char*) i->config.iov_base, SD_JSON_PARSE_MUST_BE_OBJECT, &v, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse JSON config data at position %u:%u: %m", line, column);
|
||||
|
||||
@@ -1340,7 +1340,7 @@ static void oci_pull_job_on_finished_bearer_token(PullJob *j) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = pull_job_payload_as_json(j, &v);
|
||||
r = pull_job_payload_as_json_object(j, &v);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
|
||||
@@ -490,7 +490,7 @@ static int load_leases_file(int dir_fd, const char *path, SavedInfo *ret) {
|
||||
/* f= */ NULL,
|
||||
dir_fd,
|
||||
path,
|
||||
/* flags= */ 0,
|
||||
/* flags= */ SD_JSON_PARSE_MUST_BE_OBJECT,
|
||||
&v,
|
||||
/* reterr_line= */ NULL,
|
||||
/* ret_column= */ NULL);
|
||||
|
||||
@@ -3039,7 +3039,6 @@ static int json_parse_internal(
|
||||
int r;
|
||||
|
||||
assert_return(input, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
p = *input;
|
||||
|
||||
@@ -3111,12 +3110,16 @@ static int json_parse_internal(
|
||||
break;
|
||||
|
||||
case JSON_TOKEN_OBJECT_OPEN:
|
||||
|
||||
if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (n_stack == 1 && FLAGS_SET(flags, SD_JSON_PARSE_MUST_BE_ARRAY) && !FLAGS_SET(flags, SD_JSON_PARSE_MUST_BE_OBJECT)) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(stack, n_stack+1)) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
@@ -3168,6 +3171,11 @@ static int json_parse_internal(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (n_stack == 1 && !FLAGS_SET(flags, SD_JSON_PARSE_MUST_BE_ARRAY) && FLAGS_SET(flags, SD_JSON_PARSE_MUST_BE_OBJECT)) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(stack, n_stack+1)) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
@@ -3217,6 +3225,11 @@ static int json_parse_internal(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (n_stack == 1 && (flags & (SD_JSON_PARSE_MUST_BE_ARRAY|SD_JSON_PARSE_MUST_BE_OBJECT)) != 0) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_json_variant_new_string(&add, string);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
@@ -3240,6 +3253,11 @@ static int json_parse_internal(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (n_stack == 1 && (flags & (SD_JSON_PARSE_MUST_BE_ARRAY|SD_JSON_PARSE_MUST_BE_OBJECT)) != 0) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_json_variant_new_real(&add, value.real);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
@@ -3261,6 +3279,11 @@ static int json_parse_internal(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (n_stack == 1 && (flags & (SD_JSON_PARSE_MUST_BE_ARRAY|SD_JSON_PARSE_MUST_BE_OBJECT)) != 0) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_json_variant_new_integer(&add, value.integer);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
@@ -3282,6 +3305,11 @@ static int json_parse_internal(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (n_stack == 1 && (flags & (SD_JSON_PARSE_MUST_BE_ARRAY|SD_JSON_PARSE_MUST_BE_OBJECT)) != 0) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_json_variant_new_unsigned(&add, value.unsig);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
@@ -3303,6 +3331,11 @@ static int json_parse_internal(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (n_stack == 1 && (flags & (SD_JSON_PARSE_MUST_BE_ARRAY|SD_JSON_PARSE_MUST_BE_OBJECT)) != 0) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_json_variant_new_boolean(&add, value.boolean);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
@@ -3324,6 +3357,11 @@ static int json_parse_internal(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (n_stack == 1 && (flags & (SD_JSON_PARSE_MUST_BE_ARRAY|SD_JSON_PARSE_MUST_BE_OBJECT)) != 0) {
|
||||
r = -EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_json_variant_new_null(&add);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
@@ -3365,7 +3403,8 @@ done:
|
||||
assert(n_stack == 1);
|
||||
assert(stack[0].n_elements == 1);
|
||||
|
||||
*ret = sd_json_variant_ref(stack[0].elements[0]);
|
||||
if (ret)
|
||||
*ret = sd_json_variant_ref(stack[0].elements[0]);
|
||||
*input = p;
|
||||
r = 0;
|
||||
|
||||
|
||||
@@ -1009,14 +1009,14 @@ static int varlink_parse_message(sd_varlink *v) {
|
||||
|
||||
sz = e - begin + 1;
|
||||
|
||||
r = sd_json_parse(begin, 0, &v->current, NULL, NULL);
|
||||
r = sd_json_parse(begin, SD_JSON_PARSE_MUST_BE_OBJECT, &v->current, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (v->input_sensitive)
|
||||
explicit_bzero_safe(begin, sz);
|
||||
if (r < 0) {
|
||||
/* If we encounter a parse failure flush all data. We cannot possibly recover from this,
|
||||
* hence drop all buffered data now. */
|
||||
v->input_buffer_index = v->input_buffer_size = v->input_buffer_unscanned = 0;
|
||||
return varlink_log_errno(v, r, "Failed to parse JSON: %m");
|
||||
return varlink_log_errno(v, r, "Failed to parse JSON object: %m");
|
||||
}
|
||||
|
||||
if (v->input_sensitive) {
|
||||
|
||||
@@ -205,7 +205,7 @@ static int acquire_user_record(pam_handle_t *pamh, UserRecord **ret_record) {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
|
||||
/* Parse cached record */
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_SENSITIVE, &v, NULL, NULL);
|
||||
r = sd_json_parse(json, SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return pam_syslog_errno(pamh, LOG_ERR, r, "Failed to parse JSON user record: %m");
|
||||
|
||||
|
||||
@@ -820,13 +820,9 @@ static int build_policy_digest(bool sign) {
|
||||
assert(!strv_isempty(arg_phase));
|
||||
|
||||
if (arg_append) {
|
||||
r = sd_json_parse_file(NULL, arg_append, 0, &v, NULL, NULL);
|
||||
r = sd_json_parse_file(/* f= */ NULL, arg_append, SD_JSON_PARSE_MUST_BE_OBJECT, &v, /* reterr_line= */ NULL, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse '%s': %m", arg_append);
|
||||
|
||||
if (!sd_json_variant_is_object(v))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"File '%s' is not a valid JSON object, refusing.", arg_append);
|
||||
return log_error_errno(r, "Failed to parse JSON object '%s': %m", arg_append);
|
||||
}
|
||||
|
||||
/* When signing/building digest we only support JSON output */
|
||||
|
||||
@@ -181,7 +181,9 @@ int sd_json_variant_sort(sd_json_variant **v);
|
||||
int sd_json_variant_normalize(sd_json_variant **v);
|
||||
|
||||
__extension__ typedef enum _SD_ENUM_TYPE_S64(sd_json_parse_flags_t) {
|
||||
SD_JSON_PARSE_SENSITIVE = 1 << 0, /* mark variant as "sensitive", i.e. something containing secret key material or such */
|
||||
SD_JSON_PARSE_SENSITIVE = 1 << 0, /* mark variant as "sensitive", i.e. something containing secret key material or such */
|
||||
SD_JSON_PARSE_MUST_BE_OBJECT = 1 << 1, /* refuse parsing if top-level is not an object */
|
||||
SD_JSON_PARSE_MUST_BE_ARRAY = 1 << 2, /* refuse parsing if top-level is not an array */
|
||||
_SD_ENUM_FORCE_S64(JSON_PARSE_FLAGS)
|
||||
} sd_json_parse_flags_t;
|
||||
|
||||
|
||||
@@ -1588,4 +1588,46 @@ TEST(json_variant_compare) {
|
||||
test_json_variant_compare_one("{\"a\":\"b\",\"b\":\"c\"}", "{\"a\":\"b\"}", 1);
|
||||
}
|
||||
|
||||
TEST(must_be) {
|
||||
ASSERT_OK(sd_json_parse("null", /* flags= */ 0, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
ASSERT_ERROR(sd_json_parse("null", SD_JSON_PARSE_MUST_BE_OBJECT, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("null", SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("null", SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
|
||||
ASSERT_OK(sd_json_parse("true", /* flags= */ 0, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
ASSERT_ERROR(sd_json_parse("true", SD_JSON_PARSE_MUST_BE_OBJECT, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("true", SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("true", SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
|
||||
ASSERT_OK(sd_json_parse("\"foo\"", /* flags= */ 0, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
ASSERT_ERROR(sd_json_parse("\"foo\"", SD_JSON_PARSE_MUST_BE_OBJECT, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("\"foo\"", SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("\"foo\"", SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
|
||||
ASSERT_OK(sd_json_parse("4711", /* flags= */ 0, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
ASSERT_ERROR(sd_json_parse("4711", SD_JSON_PARSE_MUST_BE_OBJECT, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("4711", SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("4711", SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
|
||||
ASSERT_OK(sd_json_parse("-4711", /* flags= */ 0, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
ASSERT_ERROR(sd_json_parse("-4711", SD_JSON_PARSE_MUST_BE_OBJECT, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("-4711", SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("-4711", SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
|
||||
ASSERT_OK(sd_json_parse("-4.5", /* flags= */ 0, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
ASSERT_ERROR(sd_json_parse("-4.5", SD_JSON_PARSE_MUST_BE_OBJECT, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("-4.5", SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_ERROR(sd_json_parse("-4.5", SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
|
||||
ASSERT_OK(sd_json_parse("{}", /* flags= */ 0, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
ASSERT_OK(sd_json_parse("{}", SD_JSON_PARSE_MUST_BE_OBJECT, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
ASSERT_ERROR(sd_json_parse("{}", SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_OK(sd_json_parse("{}", SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
|
||||
ASSERT_OK(sd_json_parse("[]", /* flags= */ 0, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
ASSERT_ERROR(sd_json_parse("[]", SD_JSON_PARSE_MUST_BE_OBJECT, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL), EINVAL);
|
||||
ASSERT_OK(sd_json_parse("[]", SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
ASSERT_OK(sd_json_parse("[]", SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_MUST_BE_ARRAY, /* ret= */ NULL, /* reterr_line= */ NULL, /* reterr_column= */ NULL));
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
||||
@@ -1260,7 +1260,7 @@ static int load_credential_one(
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
unsigned line = 0, column = 0;
|
||||
r = sd_json_parse_file_at(NULL, credential_dir_fd, name, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
r = sd_json_parse_file_at(/* f= */ NULL, credential_dir_fd, name, SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse credential '%s' as JSON at %u:%u: %m", name, line, column);
|
||||
|
||||
@@ -1844,7 +1844,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
const char *fn = streq(optarg, "-") ? NULL : optarg;
|
||||
unsigned line = 0;
|
||||
r = sd_json_parse_file(fn ? NULL : stdin, fn ?: "<stdin>", SD_JSON_PARSE_SENSITIVE, &v, &line, /* reterr_column= */ NULL);
|
||||
r = sd_json_parse_file(fn ? NULL : stdin, fn ?: "<stdin>", SD_JSON_PARSE_MUST_BE_OBJECT|SD_JSON_PARSE_SENSITIVE, &v, &line, /* reterr_column= */ NULL);
|
||||
if (r < 0)
|
||||
return log_syntax(/* unit= */ NULL, LOG_ERR, fn ?: "<stdin>", line, r, "JSON parse failure.");
|
||||
|
||||
|
||||
@@ -682,14 +682,14 @@ static int verb_call(int argc, char *argv[], uintptr_t _data, void *userdata) {
|
||||
source = "<argv[4]>";
|
||||
|
||||
/* <argv[4]> is correct, as dispatch_verb() shifts arguments by one for the verb. */
|
||||
r = sd_json_parse_with_source(parameter, source, 0, &jp, &line, &column);
|
||||
r = sd_json_parse_with_source(parameter, source, SD_JSON_PARSE_MUST_BE_OBJECT, &jp, &line, &column);
|
||||
} else {
|
||||
if (isatty_safe(STDIN_FILENO) && !arg_quiet)
|
||||
log_notice("Expecting method call parameter JSON object on standard input. (Provide empty string or {} for no parameters.)");
|
||||
|
||||
source = "<stdin>";
|
||||
|
||||
r = sd_json_parse_file_at(stdin, AT_FDCWD, source, 0, &jp, &line, &column);
|
||||
r = sd_json_parse_file_at(stdin, AT_FDCWD, source, SD_JSON_PARSE_MUST_BE_OBJECT, &jp, &line, &column);
|
||||
}
|
||||
if (r < 0 && r != -ENODATA)
|
||||
return log_error_errno(r, "Failed to parse parameters at %s:%u:%u: %m", source, line, column);
|
||||
|
||||
@@ -253,7 +253,7 @@ static int load_firmware_data(const char *path, FirmwareData **ret) {
|
||||
r = sd_json_parse_file(
|
||||
/* f= */ NULL,
|
||||
path,
|
||||
/* flags= */ 0,
|
||||
/* flags= */ SD_JSON_PARSE_MUST_BE_OBJECT,
|
||||
&json,
|
||||
/* reterr_line= */ NULL,
|
||||
/* ret_column= */ NULL);
|
||||
|
||||
Reference in New Issue
Block a user