Skip to content

Commit

Permalink
output: Fix json encoding bug
Browse files Browse the repository at this point in the history
Fixed a nasty bug where JSON output validation was failing for
`/proc/mounts` entries containing backslash characters.

For example,

```bash
$ grep crypt /proc/mounts
tmpfs /run/credentials/systemd-cryptsetup@luks\134x2d3d322d7f\134x2d2f4f\134x2d45b1\134x2db73a\134x2d67ad0deff428.service tmpfs ro,seclabel,nosuid,nodev,noexec,relatime,nosymfollow,size=1024k,nr_inodes=1024,mode=700,inode64,noswap 0 0
```

The mount directory was encoded literally such that the JSON output
resulting from `procenv --format json` was invalid (since backslashes
need to be escaped in JSON).

The problem was not limited to JSON and was caused by two issues:

- The string value passed to `section_open()` and `container_open()`
  being used literally, rather than being encoded like all other string
  values.

- The translation table in `output.c` was not escaping the backslashes
  "enough" (moar backslashes please! :)

Signed-off-by: James O. D. Hunt <[email protected]>
  • Loading branch information
jamesodhunt committed Jan 1, 2025
1 parent 0e31aac commit 13d110b
Showing 1 changed file with 36 additions and 7 deletions.
43 changes: 36 additions & 7 deletions src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ static TranslateTable translate_table[] = {
{
{
{ L"\\\"", L'"' },
{ L"\\\\", L'\\' },

// Yes, this is crazy, but necessary!
{ L"\\\\\\\\", L'\\' },

/* XXX: the hack! */
{ NULL, L'\0' },
Expand Down Expand Up @@ -355,6 +357,21 @@ object_close (int retain)
}
}

pstring *
name_to_wide_name(const char *name)
{
pstring *encoded_name = NULL;

encoded_name = char_to_pstring (name);
if (! encoded_name)
die ("failed to convert string to pstring");

if (encode_string (&encoded_name) < 0)
die ("failed to encode name");

return encoded_name;
}

/**
* section_open:
*
Expand All @@ -368,30 +385,36 @@ section_open (const char *name)
assert (name);
common_assert ();

pstring *encoded_name = NULL;

encoded_name = name_to_wide_name(name);

change_element (ELEMENT_TYPE_SECTION_OPEN);

switch (output_format) {

case OUTPUT_FORMAT_TEXT:
wappendf (&doc, L"%s:", name);
wappendf (&doc, L"%ls:", encoded_name->buf);
break;

case OUTPUT_FORMAT_CRUMB:
add_breadcrumb (name);
break;

case OUTPUT_FORMAT_JSON:
wappendf (&doc, L"\"%s\" : {", name);
wappendf (&doc, L"\"%ls\" : {", encoded_name->buf);
break;

case OUTPUT_FORMAT_XML:
wappendf (&doc, L"<section name=\"%s\">", name);
wappendf (&doc, L"<section name=\"%ls\">", encoded_name->buf);
break;

default:
assert_not_reached ();
break;
}

pstring_free(encoded_name);
}

void
Expand Down Expand Up @@ -440,30 +463,36 @@ container_open (const char *name)
assert (name);
common_assert ();

pstring *encoded_name = NULL;

encoded_name = name_to_wide_name(name);

change_element (ELEMENT_TYPE_CONTAINER_OPEN);

switch (output_format) {

case OUTPUT_FORMAT_TEXT:
wappendf (&doc, L"%s:", name);
wappendf (&doc, L"%ls:", encoded_name->buf);
break;

case OUTPUT_FORMAT_CRUMB:
add_breadcrumb (name);
break;

case OUTPUT_FORMAT_JSON:
wappendf (&doc, L"\"%s\" : [", name);
wappendf (&doc, L"\"%ls\" : [", encoded_name->buf);
break;

case OUTPUT_FORMAT_XML:
wappendf (&doc, L"<container name=\"%s\">", name);
wappendf (&doc, L"<container name=\"%ls\">", encoded_name->buf);
break;

default:
assert_not_reached ();
break;
}

pstring_free(encoded_name);
}

/**
Expand Down

0 comments on commit 13d110b

Please sign in to comment.