Giter VIP home page Giter VIP logo

libyang's Introduction

libyang

BSD license Build Docs Coverity Scan Build Status codecov.io Fuzzing Status Ohloh Project Status

libyang is a YANG data modelling language parser and toolkit written (and providing API) in C. The library is used e.g. in libnetconf2, Netopeer2 or sysrepo projects.

Branches

The project uses 2 main branches master and devel. Other branches should not be cloned. In master there are files of the last official release. Any latest improvements and changes, which were tested at least briefly are found in devel. On every new release, devel is merged into master.

This means that when only stable official releases are to be used, either master can be used or specific releases downloaded. If all the latest bugfixes should be applied, devel branch is the one to be used. Note that whenever a new issue is created and it occurs on the master branch, the first response will likely be to use devel before any further provided support.

Migration from libyang version 1 or older

Look into the documentation and the section Transition Manual. That should help with basic migration and the ability to compile a project. But to actually make use of the new features, it is required to read through the whole documentation and the API.

Provided Features

  • Parsing (and validating) schemas in YANG format.
  • Parsing (and validating) schemas in YIN format.
  • Parsing, validating and printing instance data in XML format.
  • Parsing, validating and printing instance data in JSON format (RFC 7951).
  • Manipulation with the instance data.
  • Support for default values in the instance data (RFC 6243).
  • Support for YANG extensions.
  • Support for YANG Metadata (RFC 7952).
  • Support for YANG Schema Mount (RFC 8528).
  • Support for YANG Structure (RFC 8791).
  • yanglint - feature-rich YANG tool.

Current implementation covers YANG 1.0 (RFC 6020) as well as YANG 1.1 (RFC 7950).

Packages

Binary RPM or DEB packages of the latest release can be built locally using apkg, look into README in the distro directory.

Requirements

Unix Build Requirements

  • C compiler
  • cmake >= 2.8.12
  • libpcre2 >= 10.21 (including devel package)
    • note, that PCRE is supposed to be compiled with unicode support (configure's options --enable-utf and --enable-unicode-properties)

Optional

  • doxygen (for generating documentation)
  • cmocka >= 1.0.1 (for tests)
  • valgrind (for enhanced testing)
  • gcov (for code coverage)
  • lcov (for code coverage)
  • genhtml (for code coverage)

Unix Runtime Requirements

  • libpcre2 >= 10.21

Windows Build Requirements

The Windows version does not support plugins, and the yanglint works in a non-interactive mode only. On Windows, all YANG date-and-time values are first converted to UTC (if TZ offset was specified), and then returned with "unspecified timezone".

Building

$ mkdir build; cd build
$ cmake ..
$ make
# make install

Useful CMake Options

Changing Compiler

Set CC variable:

$ CC=/usr/bin/clang cmake ..

Changing Install Path

To change the prefix where the library, headers and any other files are installed, set CMAKE_INSTALL_PREFIX variable:

$ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr ..

Default prefix is /usr/local.

Build Modes

There are two build modes:

  • Release. This generates library for the production use without any debug information.
  • Debug. This generates library with the debug information and disables optimization of the code.

The Debug mode is currently used as the default one. to switch to the Release mode, enter at the command line:

$ cmake -D CMAKE_BUILD_TYPE:String="Release" ..

Changing Extensions Plugins Directory

As for YANG extensions, libyang allows loading extension plugins. By default, the directory to store the plugins is LIBDIR/libyang. To change it, use the following cmake option with the value specifying the desired directory:

$ cmake -DPLUGINS_DIR:PATH=`pwd`"/src/extensions/" ..

The directory path can be also changed runtime via environment variable, e.g.:

$ LIBYANG_EXTENSIONS_PLUGINS_DIR=`pwd`/my/relative/path yanglint

Note that plugins are not available on Windows.

Optimizations

Whenever the latest revision of a schema is supposed to be loaded (import without specific revision), it is performed in the standard way, the first time. By default, every other time when the latest revision of the same schema is needed, the one initially loaded is reused. If you know this can cause problems meaning the latest available revision of a schema can change during operation, you can force libyang to always search for the schema anew by:

$ cmake -DENABLE_LATEST_REVISIONS=OFF ..

CMake Notes

Note that, with CMake, if you want to change the compiler or its options after you already ran CMake, you need to clear its cache first - the most simple way to do it is to remove all content from the 'build' directory.

Usage

All libyang functions are available via the main header:

#include <libyang/libyang.h>

To compile your program with libyang, it is necessary to link it with libyang using the following linker parameters:

-lyang

Note, that it may be necessary to call ldconfig(8) after library installation and if the library was installed into a non-standard path, the path to libyang must be specified to the linker. To help with setting all the compiler's options, there is libyang.pc file for pkg-config(1) available in the source tree. The file is installed with the library.

If you are using cmake in you project, it is also possible to use the provided FindLibYANG.cmake file to detect presence of the libyang library in the system.

Bindings

There are no bindings for other languages directly in this project but they are available separately.

yanglint

libyang project includes a feature-rich tool called yanglint(1) for validation and conversion of the schemas and YANG modeled data. The source codes are located at /tools/lint and can be used to explore how an application is supposed to use the libyang library. yanglint(1) binary as well as its man page are installed together with the library itself.

There is also README describing some examples of using yanglint.

Tests

libyang includes several tests built with cmocka. The tests can be found in tests subdirectory and they are designed for checking library functionality after code changes. Additional regression tests done with a corpus of fuzzing inputs that previously caused crashes are done. Those are available in tests/fuzz and are built automatically with the cmocka unit tests.

The tests are by default built in the Debug build mode by running

$ make

In case of the Release mode, the tests are not built by default (it requires additional dependency), but they can be enabled via cmake option:

$ cmake -DENABLE_TESTS=ON ..

Note that if the necessary cmocka headers are not present in the system include paths, tests are not available despite the build mode or cmake's options.

Tests can be run by the make's test target:

$ make test

Perf

There is a performance measurement tool included that prints information about the time required to execute common use-cases of working with YANG instance data.

To enable this test, use an option and to get representative results, enable Release build type:

$ cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_PERF_TESTS=ON ..

and to run the test with seeing its output run:

$ make
$ ctest -V -R ly_perf

Code Coverage

Based on the tests run, it is possible to generate code coverage report. But it must be enabled and these commands are needed to generate the report:

$ cmake -DENABLE_COVERAGE=ON ..
$ make
$ make coverage

Fuzzing

Multiple YANG fuzzing targets and fuzzing instructions are available in the tests/fuzz directory.

All of the targets can be fuzzed with LLVM's LibFuzzer and AFL, and new targets can easily be added. Asciinema examples which describe the fuzzing setup for both AFL (https://asciinema.org/a/311060) and LibFuzzer (https://asciinema.org/a/311035) are available.

libyang's People

Contributors

choppsv1 avatar dajvid avatar ekinzie avatar fredgan avatar haititi avatar hugeping avatar idryzhov avatar irfanhaslanded avatar jakubman1 avatar jktjkt avatar jruzicka-nic avatar jvijtiuk avatar lepici avatar lucoliva avatar michalvasko avatar mwinter-osr avatar nextlitete avatar oerdnj avatar olivier-matz-6wind avatar optimden avatar radek-isa avatar rkrejci avatar rwestphal avatar spellingmistake avatar steweg avatar syyyr avatar ton31337 avatar vjardin avatar wesl-ee avatar zhangtaog avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libyang's Issues

list can not be created with LYD_PATH_OPT_UPDATE option

lyd_new_path requires value argument to be passed with LYD_PATH_OPT_UPDATE flags even for list.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libyang/libyang.h>

int main(int argc, char **argv)
{
   struct ly_ctx *ctx = ly_ctx_new(".");
   const struct lys_module *module = ly_ctx_load_module(ctx, "test-module", NULL);
   struct lyd_node *node = lyd_new_path(NULL, ctx, "/test-module:list[key='abc']", NULL, LYD_PATH_OPT_UPDATE);
   if (NULL == node) {
        puts("Fail");
   }
   lyd_free_withsiblings(node);
   ly_ctx_destroy(ctx, NULL);
   return 0;
}

crash by parsing edit-config RPC

Netopeer 2 crashes in libyang by parsing following edit-config RPC:

     <rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
       <edit-config>
         <target>
           <running/>
         </target>
         <config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
           <dnsmasq xmlns="urn:ietf:params:xml:ns:yang:dnsmasq-cfg">
             <dhcp-server>
               <dhcp-pool xc:operation="delete">
                 <start-addr>192.168.1.150</start-addr>
                 <end-addr>192.168.1.160</end-addr>
               </dhcp-pool>
             </dhcp-server>
           </dnsmasq>
         </config>
       </edit-config>
     </rpc>

YANG: https://github.com/sysrepo/dnsmasq-sysrepo/blob/master/cfg/dnsmasq-cfg.yang

backtrace:

#0  __strcmp_ssse3 () at ../sysdeps/x86_64/multiarch/../strcmp.S:209
#1  0x00007ffff793d1e7 in xml_parse_data (ctx=0x6234c0, xml=0x7fffec0017a0, schema_parent=0x0, parent=0x7fffec0019b0, prev=0x0, options=8, unres=0x7fffec001680, result=0x7ffff4f6a670)
    at /home/rasto/libraries/libyang/src/parser_xml.c:257
#2  0x00007ffff793ddfc in xml_parse_data (ctx=0x6234c0, xml=0x7fffec001750, schema_parent=0x0, parent=0x7fffec001640, prev=0x0, options=8, unres=0x7fffec001680, result=0x7ffff4f6a740)
    at /home/rasto/libraries/libyang/src/parser_xml.c:443
#3  0x00007ffff793ddfc in xml_parse_data (ctx=0x6234c0, xml=0x7fffec0016d0, schema_parent=0x0, parent=0x0, prev=0x0, options=8, unres=0x7fffec001680, result=0x7ffff4f6a7f0)
    at /home/rasto/libraries/libyang/src/parser_xml.c:443
#4  0x00007ffff793e34e in lyd_parse_xml (ctx=0x6234c0, root=0x7ffff4f6a950, options=8) at /home/rasto/libraries/libyang/src/parser_xml.c:555
#5  0x0000000000408606 in op_editconfig (rpc=0x7fffec002720, ncs=0x69a550) at /home/rasto/libraries/Netopeer2/server/operations.c:1444
#6  0x00007ffff76f0c52 in nc_send_reply (session=0x69a550, rpc=0x7fffec0026e0) at /home/rasto/libraries/libnetconf2/src/session_server.c:879
#7  0x00007ffff76f12fe in nc_ps_poll (ps=0x699bd0, timeout=500) at /home/rasto/libraries/libnetconf2/src/session_server.c:1060
#8  0x000000000040457f in process_loop (arg=0x0) at /home/rasto/libraries/Netopeer2/server/main.c:379
#9  0x00007ffff7bc4182 in start_thread (arg=0x7ffff4f6b700) at pthread_create.c:312
#10 0x00007ffff71a347d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

XPath /module:*//* doesn't match all nodes

Yang schema:

module test-module {
  namespace "urn:ietf:params:xml:ns:yang:test-module";
  prefix tm;

  organization "organization";
  description
    "example yang module";
  contact
    "[email protected]";

  list user {
    ordered-by user;
    config true;

    key "name";

    leaf name {
        type string;
    }
    leaf type {
        type string;
    }
  }

   leaf top-level-default {
    type string;
    default "default value";
  }
}

Data:

<user xmlns="urn:ietf:params:xml:ns:yang:test-module">
  <name>nameD</name>
  <type>TypeD</type>
</user>

Run "lyd_get_node" with xpath "/test-module://" and you will get only:

<user xmlns="urn:ietf:params:xml:ns:yang:test-module">
  <name>nameD</name>
</user>

What is probably happening is that the leaf "type" is actually included in the matching set at one point inside the moveto_node() function, but iteration later it is removed here:

(xpath.c:3924)
 if (!replaced) {
   /* no match */
   set_remove_node(set, i);
 }

I believe that the fix could be:

diff --git a/src/xpath.c b/src/xpath.c
index b6fed68..9d94cc5 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -3820,7 +3820,7 @@ moveto_node_add(struct lyxp_set *set, struct lyd_node *node, uint32_t pos, uint3
         set->val.nodes[*i].pos = pos;
         *replaced = 1;
     } else {
-        set_insert_node(set, node, pos, LYXP_NODE_ELEM, set->used);
+        set_insert_node(set, node, pos, LYXP_NODE_ELEM, *i);
     }

     ++(*
```i);



yanglint parse error for "reference"

Hi,

When I add a yin file, it reports following error:

> add [email protected]
libyang[0]: Parser fails around the line 24.
libyang[0]: Invalid value "text" of "reference".

We have following statement in line 24 of [email protected]. It seems that libyang doesn't support reference. Is that a limitation or bug of libyang?

     24    <reference>
     25       <text/>
     26     </reference>

The yang model is writen as following:

revision "2015-11-23" {
description
"rfc6020";
reference
"";

}

Thanks,
Yu

revision-date is incorrectly parsed in YANG format

RFC 6020 specifies revision-date as < a string that matches the rule date-arg >, but it seems that YANG parser in libyang parses it as identifier. So, the following statement

include sub-a-one {
    revision-date "2016-02-02";
}

generates invalid keyword error

libyang[0]: Invalid keyword ""2016-02-02"".

while

include sub-a-one {
    revision-date 2016-02-02;
}

is ok. Revision date in module's revision seems to be parsed correctly.

lyd_parse_fd crashes by empty file

lyd_parse_fd crashes by attempt to load an empty file (e.g. created with touch):

Program received signal SIGBUS, Bus error.
0x00007ffff73375d5 in lyxml_parse_mem (ctx=0x634150, data=0x7ffff7ff4000 <error: Cannot access memory at address 0x7ffff7ff4000>, options=1) at /home/rasto/libraries/libyang/src/xml.c:1113
1113        while (*c) {
(gdb) bt
#0  0x00007ffff73375d5 in lyxml_parse_mem (ctx=0x634150, data=0x7ffff7ff4000 <error: Cannot access memory at address 0x7ffff7ff4000>, options=1) at /home/rasto/libraries/libyang/src/xml.c:1113
#1  0x00007ffff735d701 in lyd_parse_ (ctx=0x634150, parent=0x0, data=0x7ffff7ff4000 <error: Cannot access memory at address 0x7ffff7ff4000>, format=LYD_XML, options=257)
    at /home/rasto/libraries/libyang/src/tree_data.c:59
#2  0x00007ffff735d8fc in lyd_parse_data_ (ctx=0x634150, data=0x7ffff7ff4000 <error: Cannot access memory at address 0x7ffff7ff4000>, format=LYD_XML, options=257, ap=0x7fffffffd9a8)
    at /home/rasto/libraries/libyang/src/tree_data.c:101
#3  0x00007ffff735db77 in lyd_parse_fd (ctx=0x634150, fd=3, format=LYD_XML, options=257) at /home/rasto/libraries/libyang/src/tree_data.c:142

My libyang version is 0.8.43 (current version in master branch).

lyd_validate crashes

1, crash with LYD_OPT_NOAUTODEL

#include <stdio.h>
#include <stdlib.h>
#include <libyang/libyang.h>

int main(int argc, char **argv)
{
   struct ly_ctx *ctx = ly_ctx_new(".");
   const struct lys_module *module =ly_ctx_load_module(ctx, "test-module", NULL);
   struct lyd_node *root = NULL;
   root = lyd_new(NULL, module, "interface");
   lyd_new_leaf(root, module, "ifType", "ethernet");
   lyd_validate(&root, LYD_OPT_STRICT  | LYD_OPT_NOAUTODEL | LYD_OPT_CONFIG);
   FILE *out = fopen("out", "w");
   lyd_print_file(out, root, LYD_XML, LYP_FORMAT);
   lyd_free(root);
   fclose(out);
   ly_ctx_destroy(ctx, NULL);
   return 0;
}

test-module needed by code snippet.

2, lyd_validate crashes also when empty data tree is passed

memleak in yang_read_node

New memleak appeared in libyang v. 0.9.74:

==18490== 800 bytes in 4 blocks are definitely lost in loss record 3 of 10
==18490== at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18490== by 0x56B7DE9: yang_read_node (parser_yang.c:469)
==18490== by 0x56A7C64: yyparse (parser_yang_bis.c:4646)
==18490== by 0x56BD032: yang_parse (parser_yang.c:2114)
==18490== by 0x56BD14F: yang_parse_mem (parser_yang.c:2137)
==18490== by 0x56BD285: yang_read_module (parser_yang.c:2169)
==18490== by 0x56BFC7C: lys_parse_mem_ (tree_schema.c:1065)
==18490== by 0x56C00B7: lys_parse_fd (tree_schema.c:1169)
==18490== by 0x56BFE98: lys_parse_path (tree_schema.c:1125)

SIGSEGV with leafreaf in typedef

Libyang crashes with segmentation fault, when it parse leafref in ietf-interfaces

node = parent_node->module->data;

#0  0x00007ffff7b754bc in resolve_path_arg_schema (
    path=0x61b740 "/ietf-interfaces:interfaces/ietf-interfaces:interface/ietf-interfaces:name", 
    parent_node=0x0, first=1, line=54, ret=0x61b620)
    at /home/lukas/playground/libyang/src/resolve.c:2407
#1  0x00007ffff7b77e57 in resolve_unres_schema_item (mod=0x61b520, item=0x61b5f8, 
    type=UNRES_TYPE_LEAFREF, str_snode=0x0, unres=0x6090f0, first=1, line=54)
    at /home/lukas/playground/libyang/src/resolve.c:3575
#2  0x00007ffff7b7874d in unres_schema_add_node (mod=0x61b520, unres=0x6090f0, item=0x61b5f8, 
    type=UNRES_TYPE_LEAFREF, snode=0x0, line=54) at /home/lukas/playground/libyang/src/resolve.c:3813
#3  0x00007ffff7b84066 in fill_yin_type (module=0x61b520, parent=0x0, yin=0x6134f0, type=0x61b5f8, 
    unres=0x6090f0) at /home/lukas/playground/libyang/src/parser_yin.c:975
#4  0x00007ffff7b77ead in resolve_unres_schema_item (mod=0x61b520, item=0x61b5f8, 
    type=UNRES_TYPE_DER, str_snode=0x0, unres=0x6090f0, first=1, line=54)
    at /home/lukas/playground/libyang/src/resolve.c:3588
#5  0x00007ffff7b7874d in unres_schema_add_node (mod=0x61b520, unres=0x6090f0, item=0x61b5f8, 
    type=UNRES_TYPE_DER, snode=0x0, line=54) at /home/lukas/playground/libyang/src/resolve.c:3813
#6  0x00007ffff7b84c6d in fill_yin_typedef (module=0x61b520, parent=0x0, yin=0x613960, 
    tpdf=0x61b5d0, unres=0x6090f0) at /home/lukas/playground/libyang/src/parser_yin.c:1185
#7  0x00007ffff7b94796 in read_sub_module (module=0x61b520, yin=0x60e090, unres=0x6090f0)
    at /home/lukas/playground/libyang/src/parser_yin.c:5302
#8  0x00007ffff7b954cf in yin_read_module (ctx=0x603010, 
    data=0x7ffff7ff3000 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module name=\"ietf-interfaces\"\n        xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n        xmlns:if=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"\n        xmlns:yan"..., implement=1, unres=0x6090f0)
    at /home/lukas/playground/libyang/src/parser_yin.c:5508
#9  0x00007ffff7b9b691 in lys_parse_data (ctx=0x603010, 
    data=0x7ffff7ff3000 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module name=\"ietf-interfaces\"\n        xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n        xmlns:if=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"\n        xmlns:yan"..., format=LYS_IN_YIN)
    at /home/lukas/playground/libyang/src/tree_schema.c:1091
#10 0x00007ffff7b9ba85 in lys_parse_fd (ctx=0x603010, fd=3, format=LYS_IN_YIN)

Function to free whole datatree

I would like to suggest including a function that frees whole data tree including siblings. It doesn't make difference if there is only one node at root level, however if there are multiple nodes it would be handy. Currently, you can read data tree by one function call but you have to use loop to free it.

Example:

module example-module {
   namespace "urn:ietf:params:xml:ns:yang:example";
   prefix ie; 

   organization "organization";
   description  "example yang module";
   contact      "[email protected]";

   container container {
      config true;
      list list {
         leaf leaf {
            type string;
         }
         leaf key1 {
            type string;
         }
         key "key1";
      }   
   }   
   leaf-list number{
      type uint16;
   }   
}
FILE *data = fopen("example-module.data","r"); 

struct lyd_node *data_tree = lyd_parse_fd(ctx, fileno(data), LYD_XML, 0); 
fclose(data); 
lyd_free(data_tree); /*This causes MEMLEAK if data contains container and leaflist*/

My suggestion:

/**
 * Free the subtree and its siblings.
 * @param [in] root
 */
void lyd_free_datatree(struct lyd_node *root){
    struct lyd_node *next = NULL;
    while(NULL != root){
        next = root->next;
        lyd_free(root);
        root = next;
    }
}

(The function name could be also lyd_free_with_siblings.)

What do you think? Or is there something I've overlooked?

Question: Milestones of libyang

Hi,
Very nice to see this C based YANG parser. Could you please disclose some information about milestone or roadmap ? Is libyang stable/ready to use ?

Thank you so much.

Cleanup section in xml_parse_data() overwrites ly_errno

When parsing file content with lyd_parse_fd() which contains an invalid leaf value, the function returns NULL in *result as expected but also leaves ly_errno set to LY_SUCCESS as if the file was empty.

The problem is that the cleanup section in xml_parse_data() overwrites ly_errno:

Watchpoint 8: *(ly_errno_location())

Old value = LY_EVALID
New value = LY_SUCCESS
lyd_unlink (node=0x64a1f0) at tree_data.c:2123
2123 ly_errno = LY_SUCCESS;
(gdb) bt
#0 lyd_unlink (node=0x64a1f0) at tree_data.c:2123
#1 lyd_free (node=0x64a1f0) at tree_data.c:2482
#2 lyd_free (node=0x647ad0) at tree_data.c:2456
#3 xml_parse_data (ctx=0x60d420, xml=0x633ce0, schema_parent=0x0, parent=0x6471e0, prev=0x0, options=257, unres=0x64a130, result=0x7fffffffa608)

at parser_xml.c:490

I suppose that the value of ly_errno should be locally saved at the beginning of the cleanup section and restored just before the return statement.

lyd_diff invalid write

There is an invalid write in case of created node.

26: ==16231== Thread 4:
26: ==16231== Invalid write of size 8
26: ==16231== at 0x4C2F793: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
26: ==16231== by 0x58E7258: lyd_diff (tree_data.c:2082)
26: ==16231== by 0x4A96F0: dm_commit_notify (data_manager.c:2603)
26: ==16231== by 0x48F1E0: rp_dt_commit (rp_dt_edit.c:705)
26: ==16231== by 0x47AEBC: rp_commit_req_process (request_processor.c:622)
26: ==16231== by 0x472F49: rp_msg_dispatch (request_processor.c:1223)
26: ==16231== by 0x470687: rp_worker_thread_execute (request_processor.c:1366)
26: ==16231== by 0x504A183: start_thread (pthread_create.c:312)
26: ==16231== by 0x5C3837C: clone (clone.S:111)
26: ==16231== Address 0x9e3aa70 is 0 bytes inside a block of size 4 alloc'd
26: ==16231== at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
26: ==16231== by 0x58E73E2: lyd_diff_init_difflist (tree_data.c:1635)
26: ==16231== by 0x58E621E: lyd_diff (tree_data.c:1728)
26: ==16231== by 0x4A96F0: dm_commit_notify (data_manager.c:2603)
26: ==16231== by 0x48F1E0: rp_dt_commit (rp_dt_edit.c:705)
26: ==16231== by 0x47AEBC: rp_commit_req_process (request_processor.c:622)
26: ==16231== by 0x472F49: rp_msg_dispatch (request_processor.c:1223)
26: ==16231== by 0x470687: rp_worker_thread_execute (request_processor.c:1366)
26: ==16231== by 0x504A183: start_thread (pthread_create.c:312)
26: ==16231== by 0x5C3837C: clone (clone.S:111)

I think that in this condition there should be != operator instead.

Memory leak

 #include <stdio.h>
 #include <stdlib.h>
 #include <libyang/libyang.h>

 int main(int argc, char **argv)
 {
     struct ly_ctx *ctx = ly_ctx_new(".");
     ly_ctx_destroy(ctx, NULL);
 }

==23495== HEAP SUMMARY:
==23495== in use at exit: 4 bytes in 1 blocks
==23495== total heap usage: 1,536 allocs, 1,535 frees, 149,576 bytes allocated
==23495==
==23495== 4 bytes in 1 blocks are still reachable in loss record 1 of 1
==23495== at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23495== by 0x4E44502: ly_errno_location (common.c:58)
==23495== by 0x4E5F970: lyxml_parse_mem (xml.c:1131)
==23495== by 0x4E85CE4: yin_read_module (parser_yin.c:5300)
==23495== by 0x4E901BC: lys_parse_mem (tree_schema.c:1057)
==23495== by 0x4E4607E: ly_ctx_new (context.c:87)
==23495== by 0x400705: main (main.c:7)
==23495==
==23495== LEAK SUMMARY:
==23495== definitely lost: 0 bytes in 0 blocks
==23495== indirectly lost: 0 bytes in 0 blocks
==23495== possibly lost: 0 bytes in 0 blocks
==23495== still reachable: 4 bytes in 1 blocks
==23495== suppressed: 0 bytes in 0 blocks
==23495==

Missing NULL-check for elem1 in lyd_diff

Used a very small yang module with one container only:

  container netconf-supported  {
    presence true;

    leaf rfc {
      type int32;
    }
  }

Then called lyd_diff to compare:

<netconf-supported xmlns="urn:ietf:params:xml:ns:yang:test-module">
</netconf-supported>

vs. this tree:

<netconf-supported xmlns="urn:ietf:params:xml:ns:yang:test-module">
    <rfc>3241</rfc>
</netconf-supported>

The program crashed with SIGSEGV:

(gdb) bt
#0  0x00007fb70a15d537 in lyd_diff (first=0x6caa00, second=0x6caf90, options=0) at tree_data.c:1775
#1  0x0000000000404d14 in srcfg_import_running_datastore (ly_ctx=0x66e410, new_data_tree=0x6caf90, module_name=0x7ffd14402065 "test-module", locked=false)
    at sysrepocfg.c:514
#2  0x0000000000405ef2 in srcfg_import_datastore (ly_ctx=0x66e410, fd_in=11, module_name=0x7ffd14402065 "test-module", datastore=SRCFG_STORE_RUNNING, format=LYD_XML, locked=false)
    at sysrepocfg.c:648
#3  0x0000000000407bc4 in srcfg_edit_operation (module_name=0x7ffd14402065 "test-module", datastore=SRCFG_STORE_RUNNING, format=LYD_XML, editor=0x7ffd14402db4 "vim", keep=false)
    at sysrepocfg.c:926
#4  0x000000000040878a in main (argc=1, argv=0x7ffd144007e8) at sysrepocfg.c:1221
(gdb) print elem1
$1 = (struct lyd_node *) 0x0

Memory leak - data tree with top level siblings

#include <stdio.h>
#include <stdlib.h>
#include <libyang/libyang.h>

int main(int argc, char **argv)
{
    struct ly_ctx *ctx = ly_ctx_new(".");

    if (NULL == ly_ctx_load_module(ctx, "test-module", NULL)){
        puts("load module failed");
        return 1;
    }   
    struct lyd_node *data = lyd_parse_path(ctx, "test-module.data", LYD_XML, 0); 
    if (NULL == data){
        puts("load data failed");
        return 1;
    }   
    lyd_free_withsiblings(data);

    ly_ctx_destroy(ctx, NULL);
    return 0;
}

test-module.data

<main xmlns="urn:ietf:params:xml:ns:yang:test-module">
  <enum>maybe</enum>
  <raw>SGVsbG8gd29ybGQh</raw>
  <options>strict recursive</options>
  <dec64>9.85</dec64>
  <i8>8</i8>
  <i16>16</i16>
  <i32>32</i32>
  <i64>64</i64>
  <ui8>8</ui8>
  <ui16>16</ui16>
  <ui32>32</ui32>
  <ui64>64</ui64>
  <empty/>
  <boolean>true</boolean>
  <string>str</string>
  <id_ref>id_1</id_ref>
  <numbers>1</numbers>
  <numbers>2</numbers>
  <numbers>42</numbers>
</main>
<list xmlns="urn:ietf:params:xml:ns:yang:test-module">
  <key>k2</key>
  <id_ref>id_2</id_ref>
  <union>infinity</union>
</list>
<list xmlns="urn:ietf:params:xml:ns:yang:test-module">
  <key>k1</key>
  <id_ref>id_1</id_ref>
  <union>42</union>
  <wireless/>
</list>

test-module.yin

<?xml version="1.0" encoding="UTF-8"?>
<module name="test-module"
        xmlns="urn:ietf:params:xml:ns:yang:yin:1"
        xmlns:tm="urn:ietf:params:xml:ns:yang:test-module">
  <namespace uri="urn:ietf:params:xml:ns:yang:test-module"/>
  <prefix value="tm"/>
  <organization>
    <text>organization</text>
  </organization>
  <description>
    <text>example yang module</text>
  </description>
  <contact>
    <text>[email protected]</text>
  </contact>
  <container name="main">
    <leaf name="enum">
      <type name="enumeration">
        <enum name="yes">
          <value value="1"/>
        </enum>
        <enum name="no">
          <value value="2"/>
        </enum>
        <enum name="maybe">
          <value value="3"/>
        </enum>
      </type>
    </leaf>
    <leaf name="options">
      <type name="bits">
        <bit name="strict"/>
        <bit name="recursive"/>
        <bit name="logging"/>
      </type>
    </leaf>
    <leaf name="raw">
      <type name="binary"/>
    </leaf>
    <leaf name="dec64">
      <type name="decimal64">
        <fraction-digits value="2"/>
      </type>
    </leaf>
    <leaf name="i8">
      <type name="int8"/>
    </leaf>
    <leaf name="i16">
      <type name="int16"/>
    </leaf>
    <leaf name="i32">
      <type name="int32"/>
    </leaf>
    <leaf name="i64">
      <type name="int64"/>
    </leaf>
    <leaf name="ui8">
      <type name="uint8"/>
    </leaf>
    <leaf name="ui16">
      <type name="uint16"/>
    </leaf>
    <leaf name="ui32">
      <type name="uint32"/>
    </leaf>
    <leaf name="ui64">
      <type name="uint64"/>
    </leaf>
    <leaf name="empty">
      <type name="empty"/>
    </leaf>
    <leaf name="boolean">
      <type name="boolean"/>
    </leaf>
    <leaf name="string">
      <type name="string"/>
    </leaf>
    <leaf name="id_ref">
      <type name="identityref">
        <base name="base_id"/>
      </type>
    </leaf>
    <leaf-list name="numbers">
      <type name="uint8"/>
    </leaf-list>
  </container>
  <identity name="base_id"/>
  <identity name="id_1">
    <base name="base_id"/>
  </identity>
  <identity name="id_2">
    <base name="base_id"/>
  </identity>
  <list name="list">
    <key value="key"/>
    <leaf name="key">
      <type name="string"/>
    </leaf>
    <leaf name="id_ref">
      <type name="identityref">
        <base name="base_id"/>
      </type>
    </leaf>
    <leaf name="union">
      <type name="union">
        <type name="uint8"/>
        <type name="enumeration">
          <enum name="infinity"/>
        </type>
      </type>
    </leaf>
    <container name="wireless">
      <presence value="wireless is enabled"/>
      <leaf name="vendor_name">
        <type name="string"/>
      </leaf>
    </container>
  </list>
</module>

Unable to build libyang on FreeBSD

$ cc -v
FreeBSD clang version 3.4.1 (tags/RELEASE_34/dot1-final 208032) 20140512
Target: x86_64-unknown-freebsd10.1
Thread model: posix

2 warnings generated.
[ 33%] Building C object CMakeFiles/yang.dir/src/parser_yin.c.o
[ 37%] Building C object CMakeFiles/yang.dir/src/parser_xml.c.o
[ 40%] Building C object CMakeFiles/yang.dir/src/parser_json.c.o
[ 44%] Building C object CMakeFiles/yang.dir/src/tree_schema.c.o
[ 48%] Building C object CMakeFiles/yang.dir/src/tree_data.c.o
/usr/home/rasto/lib/libyang/src/tree_data.c:360:5: warning: implicit declaration of function 'asprintf' is invalid in C99 [-Wimplicit-function-declaration]
asprintf(&xml, "<%s>%s</%s>", schema->name, (val_xml ? val_xml : ""), schema->name);
^
1 warning generated.
[ 51%] Building C object CMakeFiles/yang.dir/src/printer.c.o
[ 55%] Building C object CMakeFiles/yang.dir/src/xpath.c.o
/usr/home/rasto/lib/libyang/src/xpath.c:842:13: warning: implicit declaration of function 'asprintf' is invalid in C99 [-Wimplicit-function-declaration]
asprintf(&str_num, "%lld", (long long)set->value.num);
^
1 warning generated.
[ 59%] Building C object CMakeFiles/yang.dir/src/printer_yang.c.o
[ 62%] Building C object CMakeFiles/yang.dir/src/printer_xml.c.o
[ 66%] Building C object CMakeFiles/yang.dir/src/printer_tree.c.o
[ 70%] Building C object CMakeFiles/yang.dir/src/printer_info.c.o
[ 74%] Building C object CMakeFiles/yang.dir/src/printer_json.c.o
[ 77%] Building C object CMakeFiles/yang.dir/src/yang_types.c.o
[ 81%] Linking C shared library libyang.so
/usr/bin/ld: /usr/bin/../lib/libprofile_rt.a: No such file: No such file or directory
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error code 1

Stop.
make[2]: stopped in /usr/home/rasto/lib/libyang/build
*** Error code 1

Stop.
make[1]: stopped in /usr/home/rasto/lib/libyang/build
*** Error code 1

Stop.
make: stopped in /usr/home/rasto/lib/libyang/build

ly_ctx_get_node find relative node in choice

ly_ctx_get_node does not return requested node in choice

#include <stdio.h>
#include <stdlib.h>
#include <libyang/libyang.h>

int main(int argc, char **argv)
{

   struct ly_ctx *ctx = ly_ctx_new(".");
   const struct lys_module *module = ly_ctx_load_module(ctx, "ietf-interfaces", NULL);
   module = ly_ctx_load_module(ctx, "ietf-ip", NULL);
   /* matching schema node for:
    * /ietf-interfaces:interfaces/interface[name='eth0']/ietf-ip:ipv4/address[ip='192.168.2.100']/prefix-length */
   const struct lys_node *sch_node = ly_ctx_get_node(ctx, NULL, "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address");
   const struct lys_node *choice = sch_node->child->next;
   printf("%s -> %s\n", choice->name, choice->child->name);
   const struct lys_node *match = ly_ctx_get_node(ctx, choice, "prefix-length");
  /* Relative node IS NOT FOUND */
   if (NULL == match) {
        puts("Not found");
   }
   ly_ctx_destroy(ctx, NULL);
   return 0;
}

yangs used can be found here

lyd_diff+lyd_path returns invalid xpath (wrong namespace)

Used yang model: ietf-interfaces (https://github.com/sysrepo/sysrepo/blob/master/examples/yang/ietf-interfaces%402014-05-08.yang), which has the list "interface" augmented by ietf-ip (https://github.com/sysrepo/sysrepo/blob/master/examples/yang/ietf-ip%402014-06-16.yang).

Then I called lyd_diff on this tree:

<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
  <interface>
    <name>eth1</name>
    <enabled>true</enabled>
    <description>Ethernet 1</description>
    <type>ethernetCsmacd</type>
  </interface>
</interfaces>

vs. this tree:

<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
  <interface>
    <name>eth1</name>
    <enabled>true</enabled>
    <description>Ethernet 1</description>
    <type>ethernetCsmacd</type>
    <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
      <enabled>true</enabled>
      <mtu>1500</mtu>
      <address>
        <ip>10.10.1.5</ip>
        <prefix-length>16</prefix-length>
      </address>
    </ipv4>
  </interface>
</interfaces>

As expected, the difference is of type LYD_DIFF_CREATED and lyd_difflist::second points to the container ipv4. However, calling lyd_path on this node (or on some of its descendants) reveals that the namespace for the "interface" list is incorrectly set to "ietf-ip" (should be "ietf-interfaces"):
/ietf-interfaces:interfaces/ietf-ip:interface[name='eth1']/ietf-ip:ipv4

For this reason ly_ctx_get_node for this xpath returns NULL and the error message is:
libyang: Schema node not found.

mem leak in lyd_validate

12: ==29854== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1
12: ==29854== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
12: ==29854== by 0x5BB3889: strndup (strndup.c:45)
12: ==29854== by 0x58DD99F: lyd_wd_top (tree_data.c:3524)
12: ==29854== by 0x58DE1E6: lyd_defaults_add_unres (tree_data.c:3739)
12: ==29854== by 0x58DA1D3: lyd_validate (tree_data.c:1961)
12: ==29854== by 0x4472E7: dm_validate_rpc (data_manager.c:2584)
12: ==29854== by 0x40EAD2: dm_rpc_test (dm_test.c:473)
12: ==29854== by 0x4E3D175: cmocka_run_one_test_or_fixture (cmocka.c:2534)
12: ==29854== by 0x4E3D422: cmocka_run_one_tests (cmocka.c:2642)
12: ==29854== by 0x4E3D834: _cmocka_run_group_tests (cmocka.c:2757)
12: ==29854== by 0x40EBB4: main (dm_test.c:501)

I think buf_backup duplicated here is not freed probably here

lyd_new_leaf overwrites node in choice

If a leaf from diffrent choice alternative is added it overwrites previously added node and validation passes.

#include <stdio.h>
#include <stdlib.h>
#include <libyang/libyang.h>

int main(int argc, char **argv)
{
   struct ly_ctx *ctx = ly_ctx_new(".");
   const struct lys_module *module =ly_ctx_load_module(ctx, "test-module", NULL);
   struct lyd_node *root = NULL;
   root = lyd_new(NULL, module, "transfer");
   lyd_new_leaf(root, module, "interval", "15");
   lyd_new_leaf(root, module, "daily", ""); /*ADDING THIS NODE SHOULD CAUSE VALIDATION ERR*/
   if (0 == lyd_validate(&root, LYD_OPT_STRICT | LYD_OPT_NOAUTODEL |LYD_OPT_CONFIG)) {
        puts("Validation passes, but it should fail");
   }

   FILE *out = fopen("out", "w");
   lyd_print_file(out, root, LYD_XML, LYP_FORMAT);
   lyd_free(root);
   fclose(out);
   ly_ctx_destroy(ctx, NULL);
   return 0;
}

test-module needed by code snippet.

Valgrid complains about jump depending on unintialized value

dflt member of lyd_node is not intialized after node duplication. Replacing malloc by calloc in lyd_dup should fix it.

libyang version: 0.9.65

18: ==15173== Conditional jump or move depends on uninitialised value(s)
18: ==15173==    at 0x58F859A: xml_print_attrs (printer_xml.c:125)
18: ==15173==    by 0x58F8F82: xml_print_list (printer_xml.c:317)
18: ==15173==    by 0x58F93B5: xml_print_node (printer_xml.c:389)
18: ==15173==    by 0x58F8DF9: xml_print_container (printer_xml.c:292)
18: ==15173==    by 0x58F9357: xml_print_node (printer_xml.c:380)
18: ==15173==    by 0x58F943F: xml_print_data (printer_xml.c:407)
18: ==15173==    by 0x58DE5D7: lyd_print_ (printer.c:339)
18: ==15173==    by 0x58DE6BF: lyd_print_fd (printer.c:377)

set->size not cleared in ly_set_clean

A program using lyd_diff crashed with SIGSEGV:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007fb1fe370f0e in ly_set_add (set=0x1037550, node=0x1028330) at tree_data.c:3704
3704        set->set.g[set->number++] = node;
[Current thread is 1 (Thread 0x7fb1fec36700 (LWP 16761))]
(gdb) bt
#0  0x00007fb1fe370f0e in ly_set_add (set=0x1037550, node=0x1028330) at tree_data.c:3704
#1  0x00007fb1fe36baa6 in lyd_diff_compare (first=0x1028330, second=0x1027730, diff=0x104e1a0, size=0x7ffc5e1f10e0, i=0x7ffc5e1f10e8, matchset=0x1037550, ordset_keys=0x104ae00, ordset=0x104ade0)
    at tree_data.c:1516
#2  0x00007fb1fe36c4dc in lyd_diff (first=0x3a676e61, second=0x793a736e3a6c6d78, options=0) at tree_data.c:1766
#3  0x0000000000404cb2 in srcfg_import_running_datastore (ly_ctx=0xff1410, new_data_tree=0x104d470, module_name=0x7ffc5e1f9049 "ietf-interfaces", locked=false)
    at sysrepocfg.c:506
#4  0x0000000000405e97 in srcfg_import_datastore (ly_ctx=0xff1410, fd_in=11, module_name=0x7ffc5e1f9049 "ietf-interfaces", datastore=SRCFG_STORE_RUNNING, format=LYD_XML, locked=false)
    at sysrepocfg.c:643
#5  0x0000000000407bfa in srcfg_edit_operation (module_name=0x7ffc5e1f9049 "ietf-interfaces", datastore=SRCFG_STORE_RUNNING, format=LYD_XML, editor=0x7ffc5e1f9db4 "vim", keep=false)
    at sysrepocfg.c:926
#6  0x00000000004087c0 in main (argc=1, argv=0x7ffc5e1f7638) at sysrepocfg.c:1222
(gdb) print set->number 
$1 = 1
(gdb) print set->size
$2 = 8
(gdb) print set->set.g
$3 = (void **) 0x0

The crash is avoided if "set->size = 0;" is added to the ly_set_clean function.

Segmentation fault when using yanglint add models

Hi,

I use yanglint to add models, first it reports Module name "ianaift" refers to an unknown module.
But ianaift is iana-if-type.yin which is added before. I think it is an issue.

Then when I add [email protected], coredump happens.
Please have a look.

The models.tar is attached.
models.zip

[email protected] 
[email protected] gdb /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/build/yanglint
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/build/yanglint...done.
(gdb) r
Starting program: /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/build/yanglint 
[Thread debugging using libthread_db enabled]
> add [email protected]
> add iana-if-type.yin
> add [email protected]
> add [email protected]
> add [email protected]
> add [email protected]
> add [email protected]
libyang[0]: Parser fails around the line 36.
libyang[0]: Module name "ianaift" refers to an unknown module.
> add [email protected]
*** glibc detected *** /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/build/yanglint: malloc(): memory corruption (fast): 0x0000000000628710 ***

Program received signal SIGSEGV, Segmentation fault.
malloc_consolidate (av=0x34ec98fe80) at malloc.c:5196
5196          nextsize = chunksize(nextchunk);
Missing separate debuginfos, use: debuginfo-install pcre-7.8-6.el6.x86_64
(gdb) [email protected]
Undefined command: "ericsson-interfaces-dev-ipos".  Try "help".
(gdb) bt
#0  malloc_consolidate (av=0x34ec98fe80) at malloc.c:5196
#1  0x00000034ec679405 in _int_malloc (av=0x34ec98fe80, bytes=<value optimized out>) at malloc.c:4406
#2  0x00000034ec67a626 in __libc_calloc (n=<value optimized out>, elem_size=<value optimized out>) at malloc.c:4096
#3  0x00000034ebe0ad2f in _dl_new_object (realname=0x65a6b0 "/lib64/libgcc_s.so.1", libname=0x34ec75593e "libgcc_s.so.1", type=2, 
    loader=0x0, mode=-1879048191, nsid=0) at dl-object.c:77
#4  0x00000034ebe071be in _dl_map_object_from_fd (name=0x34ec75593e "libgcc_s.so.1", fd=5, fbp=0x7fffffffc000, 
    realname=0x65a6b0 "/lib64/libgcc_s.so.1", loader=0x0, l_type=2, mode=-1879048191, stack_endp=0x7fffffffc348, nsid=0) at dl-load.c:972
#5  0x00000034ebe0837a in _dl_map_object (loader=0x0, name=0x34ec75593e "libgcc_s.so.1", type=2, trace_mode=0, mode=<value optimized out>, 
    nsid=<value optimized out>) at dl-load.c:2271
#6  0x00000034ebe12a44 in dl_open_worker (a=0x7fffffffc570) at dl-open.c:227
#7  0x00000034ebe0e1b6 in _dl_catch_error (objname=0x7fffffffc5c0, errstring=0x7fffffffc5b8, mallocedp=0x7fffffffc5cf, 
    operate=0x34ebe12920 <dl_open_worker>, args=0x7fffffffc570) at dl-error.c:178
#8  0x00000034ebe124fa in _dl_open (file=0x34ec75593e "libgcc_s.so.1", mode=-2147483647, caller_dlopen=0x0, nsid=-2, argc=1, 
    argv=<value optimized out>, env=0x7fffffffda08) at dl-open.c:569
#9  0x00000034ec726e10 in do_dlopen (ptr=<value optimized out>) at dl-libc.c:86
#10 0x00000034ebe0e1b6 in _dl_catch_error (objname=0x7fffffffc780, errstring=0x7fffffffc778, mallocedp=0x7fffffffc78f, 
    operate=0x34ec726dd0 <do_dlopen>, args=0x7fffffffc760) at dl-error.c:178
#11 0x00000034ec726f67 in dlerror_run (name=<value optimized out>, mode=<value optimized out>) at dl-libc.c:47
#12 __libc_dlopen_mode (name=<value optimized out>, mode=<value optimized out>) at dl-libc.c:160
#13 0x00000034ec6feb25 in init () at ../sysdeps/ia64/backtrace.c:53
#14 0x00000034ece0cd33 in pthread_once () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S:104
#15 0x00000034ec6fec54 in __backtrace (array=<value optimized out>, size=64) at ../sysdeps/ia64/backtrace.c:104
#16 0x00000034ec67084b in __libc_message (do_abort=2, fmt=0x34ec758ac0 "*** glibc detected *** %s: %s: 0x%s ***\n")
    at ../sysdeps/unix/sysv/linux/libc_fatal.c:178
#17 0x00000034ec676166 in malloc_printerr (action=3, str=0x34ec758e70 "malloc(): memory corruption (fast)", ptr=<value optimized out>)
---Type <return> to continue, or q <return> to quit---

uninitialized value(s) in dict_insert

valgrind-3.11.0 reports conditional jump or move being dependent on uninitialized value(s) in dict_insert. Example stack-traces:

==17367== Conditional jump or move depends on uninitialised value(s)
==17367== at 0x4C33CF2: _memcmp_sse4_1 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17367== by 0x58854E0: dict_insert (dict.c:176)
==17367== by 0x58857B5: lydict_insert_zc (dict.c:255)
==17367== by 0x5895A45: lyxml_parse_elem (xml.c:1038)
==17367== by 0x589596E: lyxml_parse_elem (xml.c:1022)
==17367== by 0x589596E: lyxml_parse_elem (xml.c:1022)
==17367== by 0x589596E: lyxml_parse_elem (xml.c:1022)
==17367== by 0x5895EDE: lyxml_parse_mem (xml.c:1151)
==17367== by 0x58AF55A: yin_read_module (parser_yin.c:5082)
==17367== by 0x58D1467: lys_parse_mem
(tree_schema.c:1077)
==17367== by 0x58D14F2: lys_parse_mem (tree_schema.c:1094)
==17367== by 0x5882C31: ly_ctx_new (context.c:92)


==17367== Conditional jump or move depends on uninitialised value(s)
==17367== at 0x4C33CF2: _memcmp_sse4_1 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17367== by 0x58854E0: dict_insert (dict.c:176)
==17367== by 0x5885745: lydict_insert (dict.c:239)
==17367== by 0x589BF25: read_yin_subnode (parser_yin.c:86)
==17367== by 0x58A4A5E: read_yin_common (parser_yin.c:2437)
==17367== by 0x589F2BC: fill_yin_typedef (parser_yin.c:941)
==17367== by 0x58AE949: read_sub_module (parser_yin.c:4894)
==17367== by 0x58AF720: yin_read_module (parser_yin.c:5110)
==17367== by 0x58D1467: lys_parse_mem
(tree_schema.c:1077)
==17367== by 0x58D14F2: lys_parse_mem (tree_schema.c:1094)
==17367== by 0x5882C31: ly_ctx_new (context.c:92)

YANG parser crash

Second test of data/test_parse_print, which is commented out for now causes a crash during YANG model parsing.

loading one module multiple times

If a module is loaded a second time, after its parsing is finished it is thrown away, but all augments and deviations are applied, which results in a crash sooner or later.

memleak in lyd_get_node (lyxp_eval)

New memleak found after recent libyang update:

==30894== 14 bytes in 1 blocks are definitely lost in loss record 1 of 1
==30894== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30894== by 0x5BB4839: strdup (strdup.c:42)
==30894== by 0x58E3B01: parse_expr (xpath.c:1997)
==30894== by 0x58EE994: lyxp_eval (xpath.c:6699)
==30894== by 0x58DC24C: lyd_get_node (tree_data.c:2807

Can be replicated using sysrepo's rp_dt_edit_test.

lyd_insert_after sets prev/next pointers incorrectly

The program creates node in order l1, l2, l3 and the tries to adjust the order to be l2, l1, l3.

#include <stdio.h>
#include <stdlib.h>
#include <libyang/libyang.h>

int main(int argc, char **argv)
{
    struct ly_ctx *ctx = ly_ctx_new(".");
    const struct lys_module *test_module = ly_ctx_load_module(ctx, "test-module", NULL);

    if (NULL == test_module){
        puts("load module failed");
        return 1;
    }   

    struct lyd_node *l1 = lyd_new(NULL, test_module, "list");
    lyd_new_leaf(l1, test_module, "key", "A");

    struct lyd_node *l2 = lyd_new(NULL, test_module, "list");
    lyd_new_leaf(l2, test_module, "key", "B");


    struct lyd_node *l3 = lyd_new(NULL, test_module, "list");
    lyd_new_leaf(l3, test_module, "key", "C");

    lyd_insert_after(l1, l2);
    lyd_insert_after(l2, l3);

    /* ERROR*/
    lyd_insert_after(l2, l1); 

   /* THIS WORK as expected
    lyd_insert_before(l1, l2); */

    lyd_free_withsiblings(l1);

    ly_ctx_destroy(ctx, NULL);
    return 0;
}

It might be related to the fact that reordered nodes has no parent (top-level nodes)

The program sets pointer like this:
incorrect

The expected state(in comment):
expected

test-module.yang

module test-module {
  namespace "urn:ietf:params:xml:ns:yang:test-module";
  prefix tm;

  organization "organization";
  description
    "example yang module";

  list list {
    key "key";
    leaf key {
      type string;
    }
  }
}

Dumping data tree

I've read/validated some data, and am trying to dump the data-tree into a file.

I read the initial data from file and register with the context:

lyd_parse(yctx, buf, LYD_XML, LYD_OPT_STRICT);

Then at a later point I try to dump the data:

struct lyd_node *root;
File *file;

root = ly_ctx_info(yctx);
file = fopen("/tmp/dummy", "w+");
lyd_print(file, root, LYD_XML);

I get the following error while trying to write the file:

libyang[0]: Internal error (/home/odluser/dev/devel/libyang/src/printer_xml.c:305).

288 switch (node->schema->nodetype) {
(gdb)
305 LOGINT;
(gdb) print node->schema->name
$1 = 0x60a910 "module"
(gdb)

The node is listed as "GROUPING" and the node schema name is "module". This causes the print function to break .. how do I dump the entire data tree? Any help would be greatly appreciated!

lyd_print doesn't work

Calling lyd_print() dumps the loaded schemas not the data:

<libyang>
  <modules>
    <module>
      <name>ietf-inet-types</name>
      <revision>2013-07-15</revision>
      <namespace>urn:ietf:params:xml:ns:yang:ietf-inet-types</namespace>
      <conformance>implement</conformance>
    </module>
    <module>
      <name>ietf-yang-types</name>
      <revision>2013-07-15</revision>
      <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-types</namespace>
      <conformance>implement</conformance>
    </module>
    <module>
      <name>ietf-yang-library</name>
      <revision>2015-07-03</revision>
      <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace>
      <conformance>implement</conformance>
    </module>
    <module-set-id>4</module-set-id>
  </modules>
</libyang>

How do I dump/parse/access the data which was added via lyd_parse()

Create data tree with augment

Hi,
I am trying to create a data tree for a module which is augmented by another one. I've tried to use lyd_new_leaf but it doesn't work. What is the correct way to create data tree with augment?

root = lyd_new_leaf(NULL, module, "size", "8");

node =  lyd_new(NULL, module, "item");
lyd_new_leaf(node, module, "name", value);

lyd_insert_after(root, node);

module = ly_ctx_get_module(ctx, "info-module", NULL);
if(NULL == module){
      puts("info module not found");
}   
struct lyd_node *augment = lyd_new_leaf(node, module, "info", "asdfafa"); /* RETURNS NULL*/

used YANG modules:

module small-module {
  namespace "urn:ietf:params:xml:ns:yang:small-module";
  prefix sm;

  organization "organization";
  description
    "example yang module";
  contact
    "[email protected]";

  container item{
    leaf name {
      type string;
    }
  }

  leaf size {
    type int8;
  }
}
module info-module {
  namespace "urn:ietf:params:xml:ns:yang:info";
  prefix ie;
  import small-module {
    prefix sm;
  }

  organization "organization";
  description
    "example yang module";
  contact
    "[email protected]";

  augment "/sm:item" {
    leaf info {
      type string;
    }
  }
}

thanks
Lukas

Handle nodes with "status obsolete" statement

Hi,

In function read_yin_common(...), the "status" statement is parsed. If a node's status is "obsolete", its flag is set to LYS_STATUS_OBSLT.
According to RFC6020, "obsolete" means the definition is obsolete and SHOULD NOT be implemented and/or can be removed from implementations.
But I don't find any operation or validation are done for the obsoleted node. It is handled as normal node.Shouldn't the obsoleted node be treated as an unsupported node? Just similar with a node defined by if-feature and the feature is disabled.

Thanks,
Wei

Header files installation

I tried cmake, make and make install but only shared object (with links) was installed.
Is it planed to install header files into standard path? I expect so...
Should I create a patch?

memleak in YANG parser

After switching schema format from YIN to YANG, valgrind reports following memleak in lys_parse_path after destroying of the libyang context:

==16554== 510 bytes in 51 blocks are definitely lost in loss record 1 of 1
==16554== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16554== by 0x5BB3839: strdup (strdup.c:42)
==16554== by 0x58BE697: yyparse (parser_yang_bis.c:7652)
==16554== by 0x58CBD6A: yang_parse (parser_yang.c:2149)
==16554== by 0x58CBE87: yang_parse_mem (parser_yang.c:2172)
==16554== by 0x58CBFBD: yang_read_module (parser_yang.c:2203)
==16554== by 0x58CE8F8: lys_parse_mem_ (tree_schema.c:1065)
==16554== by 0x58CED33: lys_parse_fd (tree_schema.c:1169)
==16554== by 0x58CEB14: lys_parse_path (tree_schema.c:1125)

libyang v. 0.9.70

cmake failure

Hi all,

I can't use cmake with following errors, how can I resolve it? thanks!

[email protected] cmake ..
-- The C compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Looking for include files CMAKE_HAVE_PTHREAD_H
-- Looking for include files CMAKE_HAVE_PTHREAD_H - found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Found PCRE: /usr/lib64/libpcre.so
CMake Error at CMakeLists.txt:109 (string):
  string does not recognize sub-command FIND


-- Found Doxygen: /tools/swdev/bin/doxygen
-- Could NOT find CMocka  (missing:  CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIR)
-- Configuring incomplete, errors occurred!

yanglint print tree of augment-module does NOT work

I added some modules and found the model tree of augment module can not be printed out. Is this normal? I am afraid that the augment models are not added successfully.
The models.tar was uploaded in #22
Following are the log of my steps.
ietf-interfaces & ericsson-contexts-ipos are main models, and ericsson-context-ipos & ericsson-interfaces-ext-ipos are augment models.

(gdb) r
Starting program: /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/build/yanglint 
[Thread debugging using libthread_db enabled]
> add [email protected]
> add iana-if-type.yin
> add [email protected]
> add [email protected]
> add [email protected]
> print -f tree ericsson-contexts-ipos
module: ericsson-contexts-ipos
   +--rw contexts
   |  +--rw service
   |  |  +--rw multiple-contexts?       boolean <true>
   |  |  +--rw inter-context-routing?   empty
   |  |  +--rw load-balance
   |  |     +--rw ip
   |  |     |  +--rw (ip)?
   |  |     |     +--:(layer-3)
   |  |     |     |  +--rw layer-3?       empty
   |  |     |     +--:(layer-4)
   |  |     |     |  +--rw layer-4?       empty
   |  |     |     +--:(source-only)
   |  |     |        +--rw source-only?   empty
   |  |     +--rw link-group
   |  |        +--rw (link-group)?
   |  |           +--:(layer-3)
   |  |           |  +--rw layer-3?       empty
   |  |           +--:(layer-4)
   |  |           |  +--rw layer-4?       empty
   |  |           +--:(source-only)
   |  |              +--rw source-only?   empty
   |  +--rw system!
   |  |  +--rw lacp
   |  |     +--rw priority?   uint16
   |  |     +--rw mac-addr?   ietf-yang-types:mac-address
   |  +--rw ctxipos:context* [context-name]
   |  |  +--rw ctxipos:context-name     string
   |  |  +--rw ctxipos:vpn-rd?          string
   |  |  +--rw ctxipos:ippm!
   |  |  |  +--rw ctxipos:twamp-light
   |  |  +--rw ctxipos:description?     string
   |  |  +--rw ctxipos:subscriber
   |  |  |  +--rw ctxipos:name* [name]
   |  |  |  |  +--rw ctxipos:name              string
   |  |  |  |  +--rw ctxipos:ipv6!
   |  |  |  |  |  +--rw ctxipos:nd-profile    string
   |  |  |  |  +--rw ctxipos:forward-policy!
   |  |  |  |     +--rw ctxipos:pol-name    string
   |  |  |  |     +--rw ctxipos:in          empty
   |  |  |  +--rw ctxipos:profile* [profile]
   |  |  |     +--rw ctxipos:profile           string
   |  |  |     +--rw ctxipos:ipv6!
   |  |  |     |  +--rw ctxipos:nd-profile    string
   |  |  |     +--rw ctxipos:forward-policy!
   |  |  |        +--rw ctxipos:pol-name    string
   |  |  |        +--rw ctxipos:in          empty
   |  |  +--rw ctxipos:route-map* [route-map]
   |  |  |  +--rw ctxipos:route-map      string
   |  |  |  +--rw ctxipos:description?   string
   |  |  +--rw ctxipos:router
   |  |  |  +--rw ctxipos:msdp?              empty
   |  |  +--rw ctxipos:ospf3-maximum!
   |  |  |  +--rw (ctxipos:ospf3-maximum)?
   |  |  |     +--:(ctxipos:paths)
   |  |  |     |  +--rw ctxipos:paths?               uint8
   |  |  |     +--:(ctxipos:neighbor-exchange)
   |  |  |        +--rw ctxipos:neighbor-exchange?   uint32
   |  |  +--rw ctxipos:ip
   |  |  +--rw ctxipos:ipv6
   |  +--rw ctxipos:dot1q* [profile]
   |     +--rw ctxipos:profile        string
   |     +--rw ctxipos:description?   string
   +--ro contexts-state
> print -f tree ericsson-context-ipos
module: ericsson-context-ipos
> 
> 
> 
> 
> 
> print -f tree ericsson-interfaces-ext-ipos
module: ericsson-interfaces-ext-ipos
> print -f tree ericsson-context
ericsson-contexts-ipos  ericsson-context-ipos 

Incorrect enforcement of unique statement

It seems that libyang enforces the unique statement defined in the YANG model below incorrectly.

YANG model:
https://github.com/mbj4668/pyang/blob/master/doc/tutorial/examples/turing-machine.yang

Data:

  <turing-machine xmlns="http://example.net/turing-machine">
    <transition-function>
      <delta>
        <label>left summand</label>
        <input>
          <state>1</state>
          <symbol>2</symbol>
        </input>
      </delta>
      <delta>
        <label>right summand</label>
        <input>
          <state>3</state>
          <symbol>4</symbol>
        </input>
      </delta>
    </transition-function>
  </turing-machine>

Error from libyang's lyd_parse_fd function : Instances of "delta" list are not unique..

My libyang version is 0.8.51

Validation does not catch missing mandatory leaf

Missing mandatory leaf is not detected in a sibling subtree by lyd_validate function. However, invalid data can not be loaded by lyd_parse_path.
libyang version 0.8.54

#include <stdio.h>
#include <stdlib.h>
#include <libyang/libyang.h>

#define XPATH "/ietf-interfaces:interfaces/interface[name='gigaeth0']/ietf-ip:ipv6/address[ip='fe80::ab8']/prefix-length"


int main(int argc, char **argv)
{
   /* create context load module*/
   struct ly_ctx *ctx = ly_ctx_new(".");
   lys_parse_path(ctx, "iana-if-type.yin", LYS_IN_YIN);
   const struct lys_module *module = lys_parse_path(ctx, "[email protected]", LYS_IN_YIN);
   if (NULL == module) {
      return 1;
   }

   /* load data file*/
   struct lyd_node *root = lyd_parse_path(ctx, "data.xml", LYD_XML, LYD_OPT_STRICT | LYD_OPT_CONFIG);
   if (NULL == root || 0 != lyd_validate(&root, LYD_OPT_STRICT | LYD_OPT_NOAUTODEL | LYD_OPT_CONFIG)){
      puts("Validation failed");
      return 2;
   }

   /* remove mandatory element */
   struct ly_set *set = lyd_get_node(root, XPATH);
   if (NULL == set || set->number < 1){
      return 3;
   }
   lyd_unlink(set->set.d[0]);
   lyd_free(set->set.d[0]);

   /* VALIDATION SHOULD FAIL !!!*/
   if (0 != lyd_validate(&root, LYD_OPT_STRICT | LYD_OPT_NOAUTODEL | LYD_OPT_CONFIG)){
      puts("Validation failed");
      return 4;
   }

   /* write invalid content */   
   FILE *f = fopen("out.xml", "w");
   if (NULL == f) {
     return 5;
   }
   if (0 != lyd_print_file(f, root, LYD_XML, LYP_WITHSIBLINGS | LYP_FORMAT)){
      return 6;
   }

   /* unable to load "valid" written content */
   struct lyd_node *edited = lyd_parse_path(ctx, "out.xml", LYD_XML, LYD_OPT_STRICT | LYD_OPT_CONFIG);
   if (NULL == edited){
      puts("Error");
      return 7;
   }

   ly_set_free(set);
   lyd_free_withsiblings(root);
   ly_ctx_destroy(ctx, NULL);
   return 0;

}

data.xml

<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
  <interface>
    <name>eth0</name>
    <description>Ethernet 0</description>
    <type>ethernetCsmacd</type>
    <enabled>true</enabled>
    <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
      <enabled>true</enabled>
      <mtu>1500</mtu>
      <address>
        <ip>192.168.2.100</ip>
        <prefix-length>24</prefix-length>
      </address>
    </ipv4>
  </interface>
  <interface>
    <name>eth1</name>
    <description>Ethernet 1</description>
    <type>ethernetCsmacd</type>
    <enabled>true</enabled>
    <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
      <enabled>true</enabled>
      <mtu>1500</mtu>
      <address>
        <ip>10.10.1.5</ip>
        <prefix-length>16</prefix-length>
      </address>
    </ipv4>
  </interface>
  <interface>
    <name>gigaeth0</name>
    <description>GigabitEthernet 0</description>
    <type>ethernetCsmacd</type>
    <enabled>false</enabled>
    <ipv6 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
      <address>
        <ip>fe80::ab8</ip>
        <prefix-length>64</prefix-length>
      </address>
    </ipv6>
  </interface>
</interfaces>

Used .yin files can be found here

Segmentation fault of yanglint validation with examples

> add ietf-netconf-acm.yin
> data data-malformed-xml.xml
libyang[0]: Parser fails around the line 12.
libyang[0]: Mixed opening (nam) and closing (rule) element tags.

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7dc3fd6 in lyd_validate (node=0x0, options=0)
    at /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/src/tree_data.c:700
700         for (i = 0; i < ctx->models.used; i++) {
Missing separate debuginfos, use: debuginfo-install pcre-7.8-6.el6.x86_64
(gdb) bt
#0  0x00007ffff7dc3fd6 in lyd_validate (node=0x0, options=0)
    at /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/src/tree_data.c:700
#1  0x00007ffff7db7a19 in lyd_parse_xml (ctx=0x60a010, root=0x7fffffffd8e0, options=0)
    at /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/src/parser_xml.c:439
#2  0x00007ffff7dc26e2 in lyd_parse_ (ctx=0x60a010, parent=0x0, 
    data=0x7ffff7d88000 "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n<nacm xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-acm\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n    <rule-list>\n      <name>almigh"..., format=LYD_XML, options=0)
    at /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/src/tree_data.c:68
#3  0x00007ffff7dc28ad in lyd_parse_data_ (ctx=0x60a010, 
    data=0x7ffff7d88000 "<data xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n<nacm xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-acm\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n    <rule-list>\n      <name>almigh"..., format=LYD_XML, options=0, 
    ap=0x7fffffffd990) at /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/src/tree_data.c:106
#4  0x00007ffff7dc2b89 in lyd_parse_fd (ctx=0x60a010, fd=3, format=LYD_XML, options=0)
    at /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/src/tree_data.c:147
#5  0x00007ffff7dc2d44 in lyd_parse_path (ctx=0x60a010, path=0x610475 "data-malformed-xml.xml", format=LYD_XML, options=0)
    at /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/src/tree_data.c:174
#6  0x0000000000403242 in cmd_data (arg=0x610d80 "data data-malformed-xml.xml")
    at /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/tools/lint/commands.c:470
#7  0x0000000000402104 in main () at /project/swbuild82/eyyuppg/libnetconf/integration/new4/netopeer/libyang/tools/lint/main.c:91
(gdb) 

lyd_wd_add issues

  1. validation fails because lyd_wd_add adds default nodes even if they are disbled by if-feature
    libyang[0]: Unknown element "create-temporary-addresses". (path: /ietf-interfaces:interfaces/ietf-ip:interface[name='gigaeth0']/ietf-ip:ipv6/autoconf/create-temporary-addresses)
  2. if you comment out lyd_parse_path part lyd_wd_add tries to add something strange
    libyang[0]: Creating default element "ietf-interfaces:name" failed. (path: /ietf-interfaces:interfaces/interface[name='gigaeth0'])
#include <stdio.h>
#include <stdlib.h>
#include <libyang/libyang.h>

int main(int argc, char **argv)
{
   struct ly_ctx *ctx = ly_ctx_new(".");
   const struct lys_module *module = ly_ctx_load_module(ctx, "ietf-interfaces", NULL);
   module = ly_ctx_load_module(ctx, "ietf-ip", NULL);
   module = ly_ctx_load_module(ctx, "iana-if-type", NULL);

#if 1
   struct lyd_node *data = lyd_parse_path(ctx, "ietf-interfaces.startup", LYD_XML, LYD_OPT_CONFIG);
   if (NULL == data) {
           return 2;
   }
#endif

   struct lyd_node *root = NULL, *node = NULL;
   root = lyd_new_path(NULL, ctx, "/ietf-interfaces:interfaces/interface[name='gigaeth0']/type", "ethernetCsmacd", 0);
   node = lyd_new_path(root, ctx, "/ietf-interfaces:interfaces/interface[name='gigaeth0']/ietf-ip:ipv6/address[ip='fe80::ab8']/prefix-length", "64", 0);
   if (NULL == root || node == NULL) {
        return 3;
   }

   FILE *f = fopen("out.xml", "w");
   lyd_print_file(f, root, LYD_XML, LYP_FORMAT);
   fclose(f);

   lyd_wd_add(ctx, &root, LYD_WD_IMPL_TAG);
   if (0 != lyd_validate(&root, LYD_OPT_CONFIG | LYD_OPT_STRICT | LYD_OPT_NOAUTODEL)) {
        return 4;
   }
   lyd_free_withsiblings(root);
   ly_ctx_destroy(ctx, NULL);
   return 0;
}

Used yangs can be found here

ietf-interfaces.startup

<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
  <interface>
    <name>eth0</name>
    <description>Ethernet 0</description>
    <type>ethernetCsmacd</type>
    <enabled>true</enabled>
    <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
      <enabled>true</enabled>
      <mtu>1500</mtu>
      <address>
        <ip>192.168.2.100</ip>
        <prefix-length>24</prefix-length>
      </address>
    </ipv4>
  </interface>
</interfaces>

Build error on FreeBSD

This build error is from devel branch, but the same issue is present also in master:

[ 2%] Building C object CMakeFiles/yang.dir/src/common.c.o
/home/rasto/tmp/libyang/src/common.c:54:17: error: use of undeclared identifier 'ly_err_main'
if (ptr != &ly_err_main) {
^
1 error generated.
*** Error code 1

The content of ly_err_free function should be probably wrapped into #ifdef linux.

Examples of yanglint data validation does NOT work

I found following validation examples does not report validation errors:
Please help to fix them.

[Thread debugging using libthread_db enabled]
> clear
> add ietf-netconf-acm.yin
> #### State information in config XML
> data -x edit config-unknown-element.xml
> ##### Missing required element in NETCONF data
> data data-missing-key.xml
> 

lyd_new_path does not duplicate the value if the node is updated

The argument value passed to lyd_new_path is not duplicated, after free invalid value is printed.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libyang/libyang.h>

int main(int argc, char **argv)
{
   struct ly_ctx *ctx = ly_ctx_new(".");
   const struct lys_module *module = ly_ctx_load_module(ctx, "test-module", NULL);
   char *value = strdup("abc");
   struct lyd_node *container = lyd_new(NULL, module, "main");
   lyd_new_path(container, ctx, "/test-module:main/string", value, 0);
   struct lyd_node *node = lyd_new_path(container, ctx, "/test-module:main/string", value, LYD_PATH_OPT_UPDATE);
   printf("%s\n", ((struct lyd_node_leaf_list *) node)->value.string);
   free(value);
   printf("%s\n", ((struct lyd_node_leaf_list *) node)->value.string);  /* INVALID VALUE IS PRINTED*/
   lyd_free_withsiblings(container);
   ly_ctx_destroy(ctx, NULL);
   return 0;
}

test-module.yin

ly_ctx_load_module crashes with invalid revision argument

when invalid revision argument and existing module_name are passed ly_ctx_load_module program crashes.

Example:
example-module.yin is in search path

const struct lys_module *module = ly_ctx_load_module(ctx, "example-module", "2016-08-08");

How does libyang do cross-datastore validation?

I added following models, and do validation for datastore.xml, but got below errors, is this normal or a bug? From my point, it is a right datastore and shall not report error.
Attached datastore.xml
models.tar

> clear
> add [email protected]
> add iana-if-type.yin
> add [email protected]
> add [email protected]
> data datastore.xml
libyang[0]: Parser fails around the line 7.
libyang[0]: Unknown element "contexts".
libyang[0]: There are unresolved data items left.
Failed to parse data.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.