Skip to content

wrong empty handling in RPCs #30

@jktjkt

Description

@jktjkt

As reported in #27, trying to set a leaf within a prepare context fails:

/> prepare /ietf-netconf:get-config
(prepare: /ietf-netconf:get-config) > set source/candidate 
(prepare: /ietf-netconf:get-config) > exec

Here's the BT which eventually throws:

(gdb) bt
#0  lyplg_type_store_empty (ctx=ctx@entry=0x513000017180, type=<optimized out>, value=0x7ffff477aac0, value_len=7, options=0, UNUSED_format=<optimized out>, UNUSED_prefix_data=<optimized out>, hints=1011, UNUSED_ctx_node=<optimized out>, storage=0x50800007c8d8, UNUSED_unres=<optimized out>, err=0x7ffff44c9420)
    at /home/jkt/work/cesnet/gerrit/github/CESNET/libyang/src/plugins_types/empty.c:54
#1  0x00007ffff690f46c in lyd_value_store (ctx=<optimized out>, val=<optimized out>, type=<optimized out>, value=<optimized out>, value_len=<optimized out>, is_utf8=<optimized out>, store_only=<optimized out>, dynamic=<optimized out>, format=<optimized out>, prefix_data=<optimized out>, hints=<optimized out>, ctx_node=<optimized out>, 
    incomplete=<optimized out>) at /home/jkt/work/cesnet/gerrit/github/CESNET/libyang/src/tree_data_common.c:535
#2  0x00007ffff6926c89 in lyd_create_term (schema=schema@entry=0x50c0000a4b00, value=value@entry=0x7ffff477aac0 "[empty]", value_len=value_len@entry=7, is_utf8=is_utf8@entry=0 '\000', store_only=store_only@entry=0 '\000', dynamic=dynamic@entry=0x0, format=LY_VALUE_JSON, prefix_data=0x0, hints=1011, incomplete=0x0, node=0x7ffff477b510)
    at /home/jkt/work/cesnet/gerrit/github/CESNET/libyang/src/tree_data_new.c:71
#3  0x00007ffff69442ef in lyd_new_path_ (parent=0x5070000ab200, ctx=0x513000017180, ext=<optimized out>, path=<optimized out>, value=<optimized out>, value_len=7, value_type=<optimized out>, options=<optimized out>, new_parent=<optimized out>, new_node=<optimized out>) at /home/jkt/work/cesnet/gerrit/github/CESNET/libyang/src/tree_data_new.c:1857
#4  0x00007ffff6940583 in lyd_new_path (parent=<optimized out>, ctx=<optimized out>, path=<optimized out>, value=<optimized out>, options=32, node=<optimized out>) at /home/jkt/work/cesnet/gerrit/github/CESNET/libyang/src/tree_data_new.c:1919
#5  0x00007ffff7eb7a7a in libyang::impl::newPath (node=<optimized out>, ctx=<optimized out>, refs=..., path="/ietf-netconf:get-config/source/candidate", value=..., options=std::optional = {...}) at /home/jkt/work/cesnet/gerrit/CzechLight/libyang-cpp/src/utils/newPath.cpp:20
#6  0x00007ffff7e37087 in libyang::DataNode::newPath (this=<optimized out>, path=..., value=..., options=...) at /home/jkt/work/cesnet/gerrit/CzechLight/libyang-cpp/src/DataNode.cpp:264
#7  0x000055555599a899 in treeToRpcInput (ctx=..., path=..., in=...) at /home/jkt/work/cesnet/gerrit/CzechLight/netconf-cli/src/libyang_utils.cpp:130
#8  0x000055555578d427 in SysrepoAccess::execute (this=0x50b000007e20, path=..., input=...) at /home/jkt/work/cesnet/gerrit/CzechLight/netconf-cli/src/sysrepo_access.cpp:175
#9  0x000055555579cd58 in ProxyDatastore::execute[abi:cxx11]() (this=0x7ffff4a00350) at /home/jkt/work/cesnet/gerrit/CzechLight/netconf-cli/src/proxy_datastore.cpp:81
#10 0x00005555558da0d0 in Interpreter::operator() (this=0x7ffff4a00a90, exec=...) at /home/jkt/work/cesnet/gerrit/CzechLight/netconf-cli/src/interpreter.cpp:279
#11 0x000055555577a82e in boost::apply_visitor<Interpreter, boost::variant<boost::detail::variant::over_sequence<boost::mpl::l_item<mpl_::long_<18l>, cancel_, boost::mpl::l_item<mpl_::long_<17l>, cd_, boost::mpl::l_item<mpl_::long_<16l>, commit_, boost::mpl::l_item<mpl_::long_<15l>, copy_, boost::mpl::l_item<mpl_::long_<14l>, create_, boost::mpl::l_item<mpl_::long_<13l>, delete_, boost::mpl::l_item<mpl_::long_<12l>, describe_, boost::mpl::l_item<mpl_::long_<11l>, discard_, boost::mpl::l_item<mpl_::long_<10l>, dump_, boost::mpl::l_item<mpl_::long_<9l>, exec_, boost::mpl::l_item<mpl_::long_<8l>, get_, boost::mpl::l_item<mpl_::long_<7l>, help_, boost::mpl::l_item<mpl_::long_<6l>, ls_, boost::mpl::l_item<mpl_::long_<5l>, move_, boost::mpl::l_item<mpl_::long_<4l>, prepare_, boost::mpl::l_item<mpl_::long_<3l>, quit_, boost::mpl::l_item<mpl_::long_<2l>, set_, boost::mpl::l_item<mpl_::long_<1l>, switch_, boost::mpl::l_end> > > > > > > > > > > > > > > > > > >>&>(Interpreter const&, boost::variant<boost::detail::variant::over_sequence<boost::mpl::l_item<mpl_::long_<18l>, cancel_, boost::mpl::l_item<mpl_::long_<17l>, cd_, boost::mpl::l_item<mpl_::long_<16l>, commit_, boost::mpl::l_item<mpl_::long_<15l>, copy_, boost::mpl::l_item<mpl_::long_<14l>, create_, boost::mpl::l_item<mpl_::long_<13l>, delete_, boost::mpl::l_item<mpl_::long_<12l>, describe_, boost::mpl::l_item<mpl_::long_<11l>, discard_, boost::mpl::l_item<mpl_::long_<10l>, dump_, boost::mpl::l_item<mpl_::long_<9l>, exec_, boost::mpl::l_item<mpl_::long_<8l>, get_, boost::mpl::l_item<mpl_::long_<7l>, help_, boost::mpl::l_item<mpl_::long_<6l>, ls_, boost::mpl::l_item<mpl_::long_<5l>, move_, boost::mpl::l_item<mpl_::long_<4l>, prepare_, boost::mpl::l_item<mpl_::long_<3l>, quit_, boost::mpl::l_item<mpl_::long_<2l>, set_, boost::mpl::l_item<mpl_::long_<1l>, switch_, boost::mpl::l_end> > > > > > > > > > > > > > > > > > >>&) (visitor=..., visitable=...) at include/boost/variant/detail/apply_visitor_unary.hpp:68
#12 main (argc=<optimized out>, argv=<optimized out>) at /home/jkt/work/cesnet/gerrit/CzechLight/netconf-cli/src/cli.cpp:299

The root cause is in the implementation of leafDataToStringVisitor which encodes an instance of YANG's empty type into a string [empty]. This was probably done so in an attempt at being user-friendly, but this thing is used not just in the get command for printing retrieved leaf values, but also in other contexts:

  • As reported in Unable to display candidate datastore content #27, it's used in the ProxyDatastore::execute to build a temporary DataNode tree.
  • It's used in ast_path.cpp's pathToDataString(), and therefore for (e.g.) XPaths which contain list key values (right? and is it used for XPaths in general?)
  • When moving data, it's used as an anchor to specify where to move the value relative in a list or a list-instance.
  • As a result, the code in sysrepo_access.cpp, netconf_access.cpp and yang_access.cpp has some special handling of their setLeaf methods for instances of the empty_ class.

Maybe we should get rid of that special [empty] pretty-printing? Or should we be more careful and clearly separate "pretty printing" from "YANG canonical value printing"?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions