Minor tweaks to get a clean compile in C++

29 views
Skip to first unread message

Moz Le

unread,
Nov 6, 2019, 11:17:05 PM11/6/19
to Jansson users
I can't readily generate proper patches because I've done horrible things to the code to get it included in my project. Here's a couple of modifications to 2.12 that I am pretty sure are also valid C, and slightly clean up the code:

Modern C++ demands that printing pointers be done only after casting to void:

static int loop_check(hashtable_t *parents, const json_t *json, char *key, size_t key_size)
 {
-    snprintf(key, key_size, "%p", json);
+    snprintf(key, key_size, "%p", (void *) json);


This is only used in the conditionally defined code that follows so should be moved in with it:

static uint32_t buf_to_uint32(char *data) 

#if !defined(_WIN32) && defined(USE_URANDOM)



You print one buffer into a same-size buffer with extra context and while it might be valid the compiler complains because it doesn't know that. I went with added context, others might prefer ...TEXT_WITH_CONTEXT = 200 or whatever:

#define JSON_ERROR_TEXT_LENGTH    160
+#define JSON_ERROR_CONTEXT_LENGTH  80
 #define JSON_ERROR_SOURCE_LENGTH   80



@@ -114,9 +114,9 @@ static void error_set(json_error_t *error, const lex_t *lex,
         if(saved_text && saved_text[0])
         {
             if(lex->saved_text.length <= 20) {
-                snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH,
+                snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH + JSON_ERROR_CONTEXT_LENGTH,
                          "%s near '%s'", msg_text, saved_text);
-                msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+                msg_with_context[JSON_ERROR_TEXT_LENGTH + JSON_ERROR_CONTEXT_LENGTH - 1] = '\0';
                 result = msg_with_context;
             }
         }
@@ -131,9 +131,9 @@ static void error_set(json_error_t *error, const lex_t *lex,
                 result = msg_text;
             }
             else {
-                snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH,
+                snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH + JSON_ERROR_CONTEXT_LENGTH,
                          "%s near end of file", msg_text);
-                msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+                msg_with_context[JSON_ERROR_TEXT_LENGTH + JSON_ERROR_CONTEXT_LENGTH - 1] = '\0';
                 result = msg_with_context;
             }
         }


I'm chasing some memory issues which block on the clang memory sanitizer complaining about me passing std::string.c_str() values into json_string and json_dump. I think that's legal, but I'm using the buffer+size versions because they work (because passing string.c_str(),string.length() is fine). And I'm struggling to get debug info, so included the code directly in my program (now I get debug info 50% of the time rather than 0%). Anyway, now I get dumps like this and can start trying to make a test case that reproduces the problem. The current JSON file is ~12kB and that's a bit unreasonable:

Uninitialized bytes in __interceptor_memchr at offset 0 inside [0x701000000050, 11)
==17893==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x10e8a9d in parse_object /builds/chris/listener/Listener/../jansson/src/load.c:717:13 /// if (memchr(key, '\0', len)) {
    #1 0x10e76bc in parse_value /builds/chris/listener/Listener/../jansson/src/load.c:860:20
    #2 0x10e696e in parse_json /builds/chris/listener/Listener/../jansson/src/load.c:897:14
    #3 0x10e6cb0 in json_loadf /builds/chris/listener/Listener/../jansson/src/load.c:1029:14
    #4 0xf3a54d in digiflex::ConfigurationFile::LoadConfig(digiflex::Configuration&, bool*) /builds/chris/listener/Listener/../common/ConfigurationFile.cpp:70:29
    #5 0x12eb216 in UpdateRedisConfig(char*) /builds/chris/listener/Listener/main.cpp:362:14
    #6 0x12eb96c in main /builds/chris/listener/Listener/main.cpp:413:5
    #7 0x7fbca932f812 in __libc_start_main (/lib64/libc.so.6+0x23812)
    #8 0xdaa26d in _start (/code/listener/listener-new+0xdaa26d)

  Uninitialized value was created by a heap allocation
    #0 0xdb2e83 in malloc /llvm-project/compiler-rt/lib/msan/msan_interceptors.cpp:925:3
    #1 0x10e8e51 in jsonp_malloc /builds/chris/listener/Listener/../jansson/src/memory.c:28:12
    #2 0x10e7b20 in lex_scan_string /builds/chris/listener/Listener/../jansson/src/load.c:389:9
    #3 0x10e72d4 in lex_scan /builds/chris/listener/Listener/../jansson/src/load.c:620:9
    #4 0x10e8a11 in parse_object /builds/chris/listener/Listener/../jansson/src/load.c:700:5
    #5 0x10e76bc in parse_value /builds/chris/listener/Listener/../jansson/src/load.c:860:20
    #6 0x10e696e in parse_json /builds/chris/listener/Listener/../jansson/src/load.c:897:14
    #7 0x10e6cb0 in json_loadf /builds/chris/listener/Listener/../jansson/src/load.c:1029:14
    #8 0xf3a54d in digiflex::ConfigurationFile::LoadConfig(digiflex::Configuration&, bool*) /builds/chris/listener/Listener/../common/ConfigurationFile.cpp:70:29
    #9 0x12eb216 in UpdateRedisConfig(char*) /builds/chris/listener/Listener/main.cpp:362:14
    #10 0x12eb96c in main /builds/chris/listener/Listener/main.cpp:413:5
    #11 0x7fbca932f812 in __libc_start_main (/lib64/libc.so.6+0x23812)

SUMMARY: MemorySanitizer: use-of-uninitialized-value /builds/chris/listener/Listener/../jansson/src/load.c:717:13 in parse_object

Moz Le

unread,
Nov 6, 2019, 11:58:24 PM11/6/19
to Jansson users

Ok, the smallest sample code I have makes clang MemorySanitizer unhappy. I'm not sure how to fix this, it's into the parser somewhere (line numbers are the same as above but got via addr2line since the raw output doesn't have them)

To build the key things are (although you could leave out all the -W flags)
CXXFLAGS=-g3 -pthread -Og -Wall -Wformat=2 -Wno-variadic-macros -Wcast-align -Wno-vla -Wextra -fsanitize=memory -fPIE -fno-omit-frame-pointer -fsanitize-memory-track-origins

and linker needs -fsanitize=memory

#include <stdio.h>
#include <jansson.h>

const char *STRINGS[] = {
    "{\n"
    "    \"Server Name\": \"ChrisDev\",\n"
    "}\n",
};

bool LoadJsonString(const std::string &jsonStr) {
    json_error_t error;
    json_t * root = json_loads(jsonStr.c_str(), JSON_REJECT_DUPLICATES, &error);
    if (root) {
        char * buf = json_dumps(root, JSON_INDENT(4));
        if (buf) {
            printf("%s\n", buf);
            free(buf);
            return true;
        } else {
            printf("failed to dump\n");
        }
    } else {
        printf("failed to load\n");

    }
    return false;
}

// ok, that's brutal:
//[chrismz@localhost scratch]$ addr2line -e dem 0x49f750 /home/chrismz/scratch/jansson_memory_test/jansson/load.c:717
//[chrismz@localhost scratch]$ addr2line -e dem 0x49e392 /home/chrismz/scratch/jansson_memory_test/jansson/load.c:860
//[chrismz@localhost scratch]$ addr2line -e dem 0x49d62e /home/chrismz/scratch/jansson_memory_test/jansson/load.c:897
//[chrismz@localhost scratch]$ addr2line -e dem 0x49d143 /home/chrismz/scratch/jansson_memory_test/jansson/load.c:957
//[chrismz@localhost scratch]$ addr2line -e dem 0x4a67d5 /home/chrismz/scratch/jansson_memory_test/main.cpp:50

int main(void) {
    LoadJsonString(STRINGS[0]);
    return 0;
}
Reply all
Reply to author
Forward
0 new messages