From 869b7c0d9d28c7fb7db6be910045bcffd3e25424 Mon Sep 17 00:00:00 2001 From: Simon McVittie <smcv@collabora.com> Date: Tue, 23 Mar 2021 13:32:15 +0000 Subject: [PATCH] inspect-library: Don't print non-ASCII as nonsense codepoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we pass a (signed) char to a varargs function, it's promoted to (signed) int by the default argument promotions (resulting in padding on the left by copying the sign bit); but then %x interprets it as an unsigned int. The practical result is that for anything over 0x7f, for example 0xAB, we interpret the high bit as the sign bit and pad with "1" bits, turning 0xAB into 0xFFFFFFAB. \uFFFFFFAB is not allowed as an escaped JSON character (because Unicode stops at U+10FFFF) so parsing fails. Note that this change does not result in strings with non-ASCII content being interpreted *correctly*: we are effectively taking the bytestring from the OS and decoding it as though it was ISO-8859-1, so if a file's path includes U+00C7 LATIN CAPITAL_LETTER C WITH CEDILLA (`Ç`), encoded as 0xC3 0x87 on disk (assuming a UTF-8 environment), it will go into the JSON document as \u00C3\u0087 instead of the correct \u00C7. Fixing this would require either a considerably more complex implementation of inspect-library, or an output format that is based on bytestrings rather than JSON. Partially addresses https://github.com/ValveSoftware/steam-runtime/issues/385 and https://gitlab.steamos.cloud/steamrt/steam-runtime-tools/-/issues/69. Signed-off-by: Simon McVittie <smcv@collabora.com> --- helpers/inspect-library.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/helpers/inspect-library.c b/helpers/inspect-library.c index 22c8c9e97..a627985f3 100644 --- a/helpers/inspect-library.c +++ b/helpers/inspect-library.c @@ -485,11 +485,11 @@ main (int argc, static void print_json_string_content (const char *s) { - const char *p; + const unsigned char *p; - for (p = s; *p != '\0'; p++) + for (p = (const unsigned char *) s; *p != '\0'; p++) { - if (*p == '"' || *p == '\\' || *p <= 0x1F) + if (*p == '"' || *p == '\\' || *p <= 0x1F || *p >= 0x80) printf ("\\u%04x", *p); else printf ("%c", *p); -- GitLab