CESNET / libyang

YANG data modeling language library
BSD 3-Clause "New" or "Revised" License
368 stars 292 forks source link

Null pointer access when parsing json data with meta attributes #2246

Closed peckato1 closed 4 months ago

peckato1 commented 5 months ago

Hello, I was experimenting a bit with parsing meta attributes. The following code results in load of null pointer of type 'struct lyd_node *' reported by ubsan.

Tested with libyang c7ef85597

#include <assert.h>
#include <libyang/libyang.h>

auto MOD = R"(
module example {
  yang-version 1.1;
  namespace "http://example.tld/example";
  prefix ex;

  container two-leafs {
    leaf a { type string; }
    leaf b { type string; }
  }
}
)";

auto INPUT = R"({
  "example:a": "another-a-value",
  "@example:a": {
    "ietf-netconf:operation": "replace"
  }
}
)";

int main()
{
    ly_log_level(LY_LLDBG);

    ly_ctx* ctx;
    assert(ly_ctx_new(nullptr, 0, &ctx) == LY_SUCCESS);

    struct ly_in* inMod;
    lys_module* mod;
    assert(ly_in_new_memory(MOD, &inMod) == LY_SUCCESS);
    assert(lys_parse(ctx, inMod, LYS_IN_YANG, nullptr, &mod) == LY_SUCCESS);
    assert(mod);

    struct ly_in* inData;
    assert(ly_in_new_memory(INPUT, &inData) == LY_SUCCESS);

    lyd_node *newParent, *newNode;
    lyd_new_path2(nullptr, ctx, "/example:two-leafs", nullptr, 0, LYD_ANYDATA_JSON, 0, &newParent, &newNode);

    assert(lyd_parse_data(ctx, newNode, inData, LYD_JSON, LYD_PARSE_STRICT | LYD_PARSE_ONLY | LYD_PARSE_NO_STATE, 0, nullptr) == LY_SUCCESS);

    ly_in_free(inData, false);
    ly_in_free(inMod, false);
    lyd_free_all(newParent);
    ly_ctx_destroy(ctx);
}
libyang[2]: Searching for "ietf-inet-types" in "/home/tomas/zdrojaky/cesnet/tmp".
libyang[2]: Newer revision than "ietf-inet-types@2013-07-15" not found, using this as the latest revision.
libyang[2]: Searching for "ietf-yang-types" in "/home/tomas/zdrojaky/cesnet/tmp".
libyang[2]: Newer revision than "ietf-yang-types@2013-07-15" not found, using this as the latest revision.
/home/tomas/zdrojaky/cesnet/libyang/src/parser_json.c:1196:9: runtime error: load of null pointer of type 'struct lyd_node *'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/tomas/zdrojaky/cesnet/libyang/src/parser_json.c:1196:9 in 
AddressSanitizer:DEADLYSIGNAL
=================================================================
==2663458==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x71a9ae2436e2 bp 0x7ffe23a801c0 sp 0x7ffe23a7fde0 T0)
==2663458==The signal is caused by a READ memory access.
==2663458==Hint: address points to the zero page.
    #0 0x71a9ae2436e2 in lydjson_parse_attribute /home/tomas/zdrojaky/cesnet/libyang/src/parser_json.c:1196:9
    #1 0x71a9ae235316 in lydjson_subtree_r /home/tomas/zdrojaky/cesnet/libyang/src/parser_json.c:1667:13
    #2 0x71a9ae230945 in lyd_parse_json /home/tomas/zdrojaky/cesnet/libyang/src/parser_json.c:1881:13
    #3 0x71a9ae136768 in lyd_parse /home/tomas/zdrojaky/cesnet/libyang/src/tree_data.c:132:13
    #4 0x71a9ae13795a in lyd_parse_data /home/tomas/zdrojaky/cesnet/libyang/src/tree_data.c:222:12
    #5 0x5d99f322a346 in main /home/tomas/zdrojaky/cesnet/tmp/test.cpp:44:5
    #6 0x71a9ad639c87  (/usr/lib/libc.so.6+0x25c87) (BuildId: 32a656aa5562eece8c59a585f5eacd6cf5e2307b)
    #7 0x71a9ad639d4b in __libc_start_main (/usr/lib/libc.so.6+0x25d4b) (BuildId: 32a656aa5562eece8c59a585f5eacd6cf5e2307b)
    #8 0x5d99f30f0124 in _start (/home/tomas/zdrojaky/cesnet/tmp/a.out+0x2c124) (BuildId: 984e6e1d58a9167542ae5ce8b561300776341abf)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/tomas/zdrojaky/cesnet/libyang/src/parser_json.c:1196:9 in lydjson_parse_attribute
==2663458==ABORTING
michalvasko commented 5 months ago

Thanks, fixed.

PS: Your attempts to transform C++ to C are appreciated but they are not fully successful :) (but much easier to finish than to start from a C++ code).