{"action":"created","issue":{"url":"https://api.github.com/repos/CESNET/libnetconf/issues/75","labels_url":"https://api.github.com/repos/CESNET/libnetconf/issues/75/labels{/name}","comments_url":"https://api.github.com/repos/CESNET/libnetconf/issues/75/comments","events_url":"https://api.github.com/repos/CESNET/libnetconf/issues/75/events","html_url":"https://github.com/CESNET/libnetconf/issues/75","id":93983837,"number":75,"title":"Filter bug in ncxml_subtree_filter()","user":{"login":"classcwnd","id":3356405,"avatar_url":"https://avatars.githubusercontent.com/u/3356405?v=3","gravatar_id":"","url":"https://api.github.com/users/classcwnd","html_url":"https://github.com/classcwnd","followers_url":"https://api.github.com/users/classcwnd/followers","following_url":"https://api.github.com/users/classcwnd/following{/other_user}","gists_url":"https://api.github.com/users/classcwnd/gists{/gist_id}","starred_url":"https://api.github.com/users/classcwnd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/classcwnd/subscriptions","organizations_url":"https://api.github.com/users/classcwnd/orgs","repos_url":"https://api.github.com/users/classcwnd/repos","events_url":"https://api.github.com/users/classcwnd/events{/privacy}","received_events_url":"https://api.github.com/users/classcwnd/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":8,"created_at":"2015-07-09T07:58:49Z","updated_at":"2015-07-09T10:54:19Z","closed_at":null,"body":"I found there is bug in libnetconf ncxml_subtree_filter. I list the input message and output message at end of the email: \r\ninput.txt: input message, to get ospf-area-entry 0.0.0.57 and 0.0.0.59.\r\noutput_1.txt: intermediate output message returned from our code to libnetconf, ospf-area-entry 0.0.0.57 and 0.0.0.59 are gotten successfully.   \r\nOutput_2.txt: output message filtered by libnetconf, ospf-area-entry 0.0.0.59 is removed in ncxml_subtree_filter.\r\n\r\nI analyzed function ncxml_subtree_filter, there is logic error in below code, The code compares config_node (run-time data in this example) with filter_node, config_node is removed if it’s not consistent with filter_node. Current behavior is: \r\n1.\tCompare config_node 0.0.0.57 with filter_node 0.0.0.57, they are consistent; \r\n2.\tCompare config_node 0.0.0.59 with filter_node 0.0.0.57, they are inconsistent, so config_node 0.0.0.59 is removed. \r\n\r\nFor each config_node, the code always search filter_node from the beginning. If name and namespace of config_node and filter_node are the same, then the code will compare the config_node and filter_node. \r\nIn this example, it compares config_node 0.0.0.59 with filter_node 0.0.0.57, because the \"name\", \"ns\" and \"attr\" are the same, and filter_node->children->type != XML_TEXT_NODE, so it uses children of filter_node 0.0.0.57 to call ncxml_subtree_filter recursively.\r\nBut config_node->children(i.e. 0.0.0.59) and filter_node->children (i.e. 0.0.0.57)are different, so it removes config_node 0.0.0.59. \r\nActually it should loop through all filter_node before removing config_node. \r\n\r\nCould you please take a look at this issue? \r\n\r\n```\r\n/* select and remove all unwanted nodes */\r\nconfig_node = config;\r\nwhile (config_node) {\r\n         /* init */\r\n         sibling_in = 0;\r\n\r\n         /* go to the first filter sibing node */\r\n         filter_node = filter;\r\n         /* pass all filter sibling nodes */\r\n         while (filter_node) {\r\n                   if (!strcmp((char *) filter_node->name, (char *) config_node->name) &&\r\n                                     !nc_nscmp(filter_node, config_node) && !attrcmp(filter_node, config_node)) {\r\n                            /* content match node check */\r\n                            if (filter_node->children && (filter_node->children->type == XML_TEXT_NODE) && !xmlIsBlankNode(filter_node->children) &&\r\n                                             config_node->children && (config_node->children->type == XML_TEXT_NODE) && !xmlIsBlankNode(config_node->children)) {\r\n                                     /* get filter's text node content ignoring whitespaces */\r\n                                     if ((content2 = nc_clrwspace((char *) filter_node->children->content)) == NULL ||\r\n                                                     (content1 = nc_clrwspace((char *) config_node->children->content)) == NULL) {\r\n                                               free(content1);\r\n                                               free(content2);\r\n                                               /* internal error - memory allocation failed, do not continue! */\r\n                                               return 0;\r\n                                     }\r\n                                     if (strcmp(content1, content2) != 0) {\r\n                                               free(content1);\r\n                                               free(content2);\r\n                                               filter_node = filter_node->next;\r\n                                               continue;\r\n                                     }\r\n                                     free(content1);\r\n                                     free(content2);\r\n                            }\r\n                            sibling_in = 1;\r\n                            break;\r\n                   }\r\n                   filter_node = filter_node->next;\r\n         }\r\n         content1 = NULL;\r\n\r\n         /* if this config node is not in filter, remove it */\r\n         if (sibling_selection && !sibling_in) {\r\n                   delete = config_node;\r\n                   config_node = config_node->next;\r\n                   xmlUnlinkNode(delete);\r\n                   xmlFreeNode(delete);\r\n         } else {\r\n                   /* recursively process subtree filter */\r\n                   if (filter_node && filter_node->children && (filter_node->children->type == XML_ELEMENT_NODE) && config_node->children && (config_node->children->type == XML_ELEMENT_NODE)) {\r\n                            sibling_in = ncxml_subtree_filter(config_node->children, filter_node->children);\r\n                   }\r\n                   if (sibling_selection && sibling_in == 0) {\r\n                            /* subtree is not a content of the filter output */\r\n                            delete = config_node;\r\n\r\n                            /* remeber where to go next */\r\n                            config_node = config_node->next;\r\n\r\n                            /* and remove unwanted subtree */\r\n                            xmlUnlinkNode(delete);\r\n                            xmlFreeNode(delete);\r\n                   } else {\r\n                            /* go to the next sibling */\r\n                            config_node = config_node->next;\r\n                   }\r\n         }\r\n}\r\n```\r\n\r\ninput.txt: input message, to get ospf-area-entry 0.0.0.57 and 0.0.0.59.\r\n```\r\n  <econfig:contexts-state xmlns=\"urn:ietf:params:xml:ns:yang:my-config\">\r\n    <ctx:context xmlns=\"urn:ietf:params:xml:ns:yang:context-state\">\r\n      <ctx:context-name>local</ctx:context-name>\r\n      <ctx:router>\r\n        <ospf:ospf xmlns=\"urn:ietf:params:xml:ns:yang:ospf-state\">\r\n          <ospf:ospf-state-instance-id>201</ospf:ospf-state-instance-id>\r\n          <ospf:ospf-area-entry>\r\n            <ospf:ospf-area-id>0.0.0.57</ospf:ospf-area-id>\r\n          </ospf:ospf-area-entry>\r\n          <ospf:ospf-area-entry>\r\n            <ospf:ospf-area-id>0.0.0.59</ospf:ospf-area-id>\r\n          </ospf:ospf-area-entry>\r\n        </ospf:ospf>\r\n      </ctx:router>\r\n    </ctx:context>\r\n  </econfig:contexts-state> \r\n```  \r\noutput_1.txt: intermediate output message returned from our code to libnetconf, ospf-area-entry 0.0.0.57 and 0.0.0.59 are gotten successfully.\r\n```\r\n  <econfig:contexts-state xmlns=\"urn:ietf:params:xml:ns:yang:my-config\" xmlns:econfig=\"urn:ietf:params:xml:ns:yang:my-config\" xmlns:ctx=\"urn:ietf:params:xml:ns:yang:context-state\" xmlns:ospf=\"urn:ietf:params:xml:ns:yang:ospf-state\">\r\n    <ctx:context xmlns=\"urn:ietf:params:xml:ns:yang:context-state\">\r\n      <ctx:context-name>local</ctx:context-name>\r\n      <ctx:router>\r\n        <ospf:ospf xmlns=\"urn:ietf:params:xml:ns:yang:ospf-state\">\r\n          <ospf:ospf-state-instance-id>201</ospf:ospf-state-instance-id>\r\n          <ospf:ospf-area-entry>\r\n            <ospf:ospf-area-id>0.0.0.57</ospf:ospf-area-id>\r\n            <ospf:ospf-spf-runs>3</ospf:ospf-spf-runs>\r\n            <ospf:ospf-area-bdr-rtr-count>0</ospf:ospf-area-bdr-rtr-count>\r\n            <ospf:ospf-as-bdr-rtr-count>0</ospf:ospf-as-bdr-rtr-count>\r\n            <ospf:ospf-area-lsa-count>1</ospf:ospf-area-lsa-count>\r\n            <ospf:ospf-area-lsa-cksum-sum>cceb</ospf:ospf-area-lsa-cksum-sum>\r\n            <ospf:ospf-area-nssa-translator-state>disabled</ospf:ospf-area-nssa-translator-state>\r\n            <ospf:ospf-area-nssa-translator-events>0</ospf:ospf-area-nssa-translator-events>\r\n          </ospf:ospf-area-entry>\r\n          <ospf:ospf-area-entry>\r\n            <ospf:ospf-area-id>0.0.0.59</ospf:ospf-area-id>\r\n            <ospf:ospf-spf-runs>3</ospf:ospf-spf-runs>\r\n            <ospf:ospf-area-bdr-rtr-count>0</ospf:ospf-area-bdr-rtr-count>\r\n            <ospf:ospf-as-bdr-rtr-count>0</ospf:ospf-as-bdr-rtr-count>\r\n            <ospf:ospf-area-lsa-count>1</ospf:ospf-area-lsa-count>\r\n            <ospf:ospf-area-lsa-cksum-sum>ceea</ospf:ospf-area-lsa-cksum-sum>\r\n            <ospf:ospf-area-nssa-translator-state>disabled</ospf:ospf-area-nssa-translator-state>\r\n            <ospf:ospf-area-nssa-translator-events>0</ospf:ospf-area-nssa-translator-events>\r\n          </ospf:ospf-area-entry>\r\n        </ospf:ospf>\r\n      </ctx:router>\r\n    </ctx:context>\r\n  </econfig:contexts-state> \r\n```  \r\nOutput_2.txt: output message filtered by libnetconf, ospf-area-entry 0.0.0.59 is removed in ncxml_subtree_filter.\r\n```\r\n  <econfig:contexts-state xmlns=\"urn:ietf:params:xml:ns:yang:my-config\" xmlns:econfig=\"urn:ietf:params:xml:ns:yang:my-config\" xmlns:ctx=\"urn:ietf:params:xml:ns:yang:context-state\" xmlns:ospf=\"urn:ietf:params:xml:ns:yang:ospf-state\">\r\n    <ctx:context xmlns=\"urn:ietf:params:xml:ns:yang:context-state\">\r\n      <ctx:context-name>local</ctx:context-name>\r\n      <ctx:router>\r\n        <ospf:ospf xmlns=\"urn:ietf:params:xml:ns:yang:ospf-state\">\r\n          <ospf:ospf-state-instance-id>201</ospf:ospf-state-instance-id>\r\n          <ospf:ospf-area-entry>\r\n            <ospf:ospf-area-id>0.0.0.57</ospf:ospf-area-id>\r\n            <ospf:ospf-spf-runs>3</ospf:ospf-spf-runs>\r\n            <ospf:ospf-area-bdr-rtr-count>0</ospf:ospf-area-bdr-rtr-count>\r\n            <ospf:ospf-as-bdr-rtr-count>0</ospf:ospf-as-bdr-rtr-count>\r\n            <ospf:ospf-area-lsa-count>1</ospf:ospf-area-lsa-count>\r\n            <ospf:ospf-area-lsa-cksum-sum>cceb</ospf:ospf-area-lsa-cksum-sum>\r\n            <ospf:ospf-area-nssa-translator-state>disabled</ospf:ospf-area-nssa-translator-state>\r\n            <ospf:ospf-area-nssa-translator-events>0</ospf:ospf-area-nssa-translator-events>\r\n          </ospf:ospf-area-entry>\r\n        </ospf:ospf>\r\n      </ctx:router>\r\n    </ctx:context>\r\n  </econfig:contexts-state>\r\n```"},"comment":{"url":"https://api.github.com/repos/CESNET/libnetconf/issues/comments/119908090","html_url":"https://github.com/CESNET/libnetconf/issues/75#issuecomment-119908090","issue_url":"https://api.github.com/repos/CESNET/libnetconf/issues/75","id":119908090,"user":{"login":"rkrejci","id":6471899,"avatar_url":"https://avatars.githubusercontent.com/u/6471899?v=3","gravatar_id":"","url":"https://api.github.com/users/rkrejci","html_url":"https://github.com/rkrejci","followers_url":"https://api.github.com/users/rkrejci/followers","following_url":"https://api.github.com/users/rkrejci/following{/other_user}","gists_url":"https://api.github.com/users/rkrejci/gists{/gist_id}","starred_url":"https://api.github.com/users/rkrejci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rkrejci/subscriptions","organizations_url":"https://api.github.com/users/rkrejci/orgs","repos_url":"https://api.github.com/users/rkrejci/repos","events_url":"https://api.github.com/users/rkrejci/events{/privacy}","received_events_url":"https://api.github.com/users/rkrejci/received_events","type":"User","site_admin":false},"created_at":"2015-07-09T10:54:19Z","updated_at":"2015-07-09T10:54:19Z","body":"What is your running datastore content, before you edit-config it?"}}