/
githubmirror
/
xmlsec
Обзор
Документация
Войти
/
githubmirror
/
xmlsec
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
apps/unit_tests/nodeset_unit_tests.c
473 строки
14 KB
lsh123
Fix minor issues from coverity run (#1208)
22 июн 2026, 19:49
Не верифицирован
22 июн 2026, 19:49
1faccc4
Код
Авторство
О чём код?
/** * XML Security Library (http://www.aleksey.com/xmlsec). * * This is free software; see the Copyright file in the source distribution for precise wording. * * Copyright (C) 2002-2026 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved. */ /** * @brief XML Security Library unit nodeset tests. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <libxml/parser.h> #include <libxml/tree.h> #include <libxml/xmlIO.h> /* must be included before any other xmlsec header */ #include "xmlsec_unit_tests.h" #include <xmlsec/nodeset.h> static xmlDocPtr nodesetTestParseDoc(const char* xml) { xmlDocPtr doc; xmlSecAssert2(xml != NULL, NULL); doc = xmlReadMemory(xml, (int)strlen(xml), "nodeset-test.xml", NULL, XML_PARSE_NONET); if(doc == NULL) { testLog("Error: failed to parse XML\n"); return(NULL); } return(doc); } static xmlNodePtr nodesetTestFindChild(xmlNodePtr parent, const xmlChar* name) { xmlNodePtr cur; xmlSecAssert2(parent != NULL, NULL); xmlSecAssert2(name != NULL, NULL); for(cur = parent->children; cur != NULL; cur = cur->next) { if((cur->type == XML_ELEMENT_NODE) && xmlStrEqual(cur->name, name)) { return(cur); } } return(NULL); } static xmlNodePtr nodesetTestFindChildByType(xmlNodePtr parent, xmlElementType type) { xmlNodePtr cur; xmlSecAssert2(parent != NULL, NULL); for(cur = parent->children; cur != NULL; cur = cur->next) { if(cur->type == type) { return(cur); } } return(NULL); } struct nodesetWalkStats { int total; int elements; int attributes; int namespaces; int text; }; static int nodesetTestWalkStatsCallback(xmlSecNodeSetPtr nset, xmlNodePtr cur, xmlNodePtr parent, void* data) { struct nodesetWalkStats* stats = (struct nodesetWalkStats*)data; (void)nset; (void)parent; xmlSecAssert2(cur != NULL, -1); xmlSecAssert2(stats != NULL, -1); ++stats->total; switch(cur->type) { case XML_ELEMENT_NODE: ++stats->elements; break; case XML_ATTRIBUTE_NODE: ++stats->attributes; break; case XML_NAMESPACE_DECL: ++stats->namespaces; break; case XML_TEXT_NODE: ++stats->text; break; default: break; } return(0); } static void test_xmlSecNodeSetCreate_destroy_doc_destroy(void) { xmlDocPtr doc; xmlNodePtr root; xmlNodeSetPtr nodes; xmlSecNodeSetPtr nset; testStart("xmlSecNodeSetCreate/xmlSecNodeSetDocDestroy/xmlSecNodeSetDestroy"); doc = xmlNewDoc(BAD_CAST "1.0"); if(doc == NULL) { testLog("Error: failed to create doc\n"); testFinishedFailure(); return; } root = xmlNewDocNode(doc, NULL, BAD_CAST "Root", NULL); if(root == NULL) { testLog("Error: failed to create root node\n"); xmlFreeDoc(doc); testFinishedFailure(); return; } xmlDocSetRootElement(doc, root); nodes = xmlXPathNodeSetCreate(root); if(nodes == NULL) { testLog("Error: failed to create XPath node set\n"); xmlFreeDoc(doc); testFinishedFailure(); return; } nset = xmlSecNodeSetCreate(doc, nodes, xmlSecNodeSetNormal); if(nset == NULL) { testLog("Error: failed to create xmlsec node set\n"); xmlXPathFreeNodeSet(nodes); xmlFreeDoc(doc); testFinishedFailure(); return; } if((nset->doc != doc) || (nset->nodes != nodes) || (nset->type != xmlSecNodeSetNormal) || (nset->destroyDoc != 0) || (nset->next != nset) || (nset->prev != nset)) { testLog("Error: xmlSecNodeSetCreate initialized fields incorrectly\n"); xmlSecNodeSetDestroy(nset); testFinishedFailure(); return; } xmlSecNodeSetDocDestroy(nset); if(nset->destroyDoc != 1) { testLog("Error: xmlSecNodeSetDocDestroy did not set destroyDoc flag\n"); xmlSecNodeSetDestroy(nset); testFinishedFailure(); return; } xmlSecNodeSetDestroy(nset); testFinishedSuccess(); } static void test_xmlSecNodeSetContains_null_nodeset_allows_node(void) { xmlDocPtr doc; xmlNodePtr root; testStart("xmlSecNodeSetContains accepts NULL node set"); doc = nodesetTestParseDoc("<Root/>"); if(doc == NULL) { testFinishedFailure(); return; } root = xmlDocGetRootElement(doc); if((root == NULL) || (xmlSecNodeSetContains(NULL, root, root->parent) != 1)) { testLog("Error: NULL node set should contain every node\n"); xmlFreeDoc(doc); testFinishedFailure(); return; } xmlFreeDoc(doc); testFinishedSuccess(); } static void test_xmlSecNodeSetGetChildren_without_comments_contains_subtree(void) { xmlDocPtr doc; xmlNodePtr root; xmlNodePtr child; xmlNodePtr grandchild; xmlNodePtr sibling; xmlNodePtr comment; xmlAttrPtr childAttr; xmlSecNodeSetPtr nset; testStart("xmlSecNodeSetGetChildren without comments contains subtree"); doc = nodesetTestParseDoc( "<Root keep=\"1\"><Child childAttr=\"2\">alpha<!--comment--><Grandchild grandAttr=\"3\"/></Child><Sibling/></Root>"); if(doc == NULL) { testFinishedFailure(); return; } root = xmlDocGetRootElement(doc); child = nodesetTestFindChild(root, BAD_CAST "Child"); grandchild = nodesetTestFindChild(child, BAD_CAST "Grandchild"); sibling = nodesetTestFindChild(root, BAD_CAST "Sibling"); comment = nodesetTestFindChildByType(child, XML_COMMENT_NODE); childAttr = (child != NULL) ? child->properties : NULL; nset = xmlSecNodeSetGetChildren(doc, child, 0, 0); if((child == NULL) || (grandchild == NULL) || (sibling == NULL) || (comment == NULL) || (childAttr == NULL) || (nset == NULL)) { testLog("Error: failed to prepare subtree test data\n"); xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedFailure(); return; } if((xmlSecNodeSetContains(nset, child, root) != 1) || (xmlSecNodeSetContains(nset, grandchild, child) != 1) || (xmlSecNodeSetContains(nset, (xmlNodePtr)childAttr, child) != 1) || (xmlSecNodeSetContains(nset, comment, child) != 0) || (xmlSecNodeSetContains(nset, sibling, root) != 0) || (xmlSecNodeSetContains(nset, root, root->parent) != 0)) { testLog("Error: xmlSecNodeSetGetChildren/xmlSecNodeSetContains returned unexpected results\n"); xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedFailure(); return; } xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedSuccess(); } static void test_xmlSecNodeSetGetChildren_invert_excludes_subtree(void) { xmlDocPtr doc; xmlNodePtr root; xmlNodePtr child; xmlNodePtr grandchild; xmlNodePtr sibling; xmlSecNodeSetPtr nset; testStart("xmlSecNodeSetGetChildren invert excludes subtree"); doc = nodesetTestParseDoc("<Root><Child><Grandchild/></Child><Sibling/></Root>"); if(doc == NULL) { testFinishedFailure(); return; } root = xmlDocGetRootElement(doc); child = nodesetTestFindChild(root, BAD_CAST "Child"); grandchild = nodesetTestFindChild(child, BAD_CAST "Grandchild"); sibling = nodesetTestFindChild(root, BAD_CAST "Sibling"); nset = xmlSecNodeSetGetChildren(doc, child, 1, 1); if((child == NULL) || (grandchild == NULL) || (sibling == NULL) || (nset == NULL)) { testLog("Error: failed to prepare invert test data\n"); xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedFailure(); return; } if((xmlSecNodeSetContains(nset, root, root->parent) != 1) || (xmlSecNodeSetContains(nset, sibling, root) != 1) || (xmlSecNodeSetContains(nset, child, root) != 0) || (xmlSecNodeSetContains(nset, grandchild, child) != 0)) { testLog("Error: inverted node set did not exclude subtree correctly\n"); xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedFailure(); return; } xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedSuccess(); } static void test_xmlSecNodeSetAdd_subtraction_removes_subtree(void) { xmlDocPtr doc; xmlNodePtr root; xmlNodePtr keep; xmlNodePtr drop; xmlNodePtr nested; xmlSecNodeSetPtr nset; xmlSecNodeSetPtr removed; testStart("xmlSecNodeSetAdd subtraction removes subtree"); doc = nodesetTestParseDoc("<Root><Keep/><Drop><Nested/></Drop></Root>"); if(doc == NULL) { testFinishedFailure(); return; } root = xmlDocGetRootElement(doc); keep = nodesetTestFindChild(root, BAD_CAST "Keep"); drop = nodesetTestFindChild(root, BAD_CAST "Drop"); nested = nodesetTestFindChild(drop, BAD_CAST "Nested"); nset = xmlSecNodeSetGetChildren(doc, root, 1, 0); removed = xmlSecNodeSetGetChildren(doc, drop, 1, 0); if((keep == NULL) || (drop == NULL) || (nested == NULL) || (nset == NULL) || (removed == NULL)) { testLog("Error: failed to prepare node set subtraction test\n"); xmlSecNodeSetDestroy(nset); xmlSecNodeSetDestroy(removed); xmlFreeDoc(doc); testFinishedFailure(); return; } if(xmlSecNodeSetAdd(nset, removed, xmlSecNodeSetSubtraction) != nset) { testLog("Error: xmlSecNodeSetAdd did not return the original list head\n"); xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedFailure(); return; } if((xmlSecNodeSetContains(nset, root, root->parent) != 1) || (xmlSecNodeSetContains(nset, keep, root) != 1) || (xmlSecNodeSetContains(nset, drop, root) != 0) || (xmlSecNodeSetContains(nset, nested, drop) != 0)) { testLog("Error: subtraction node set membership is incorrect\n"); xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedFailure(); return; } xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedSuccess(); } static void test_xmlSecNodeSetWalk_visits_elements_attributes_and_namespaces(void) { xmlDocPtr doc; xmlNodePtr root; xmlSecNodeSetPtr nset; struct nodesetWalkStats stats; int ret; testStart("xmlSecNodeSetWalk visits elements attributes and namespaces"); memset(&stats, 0, sizeof(stats)); doc = nodesetTestParseDoc("<p:Root xmlns:p=\"urn:test\" attr=\"1\"/>"); if(doc == NULL) { testFinishedFailure(); return; } root = xmlDocGetRootElement(doc); nset = xmlSecNodeSetGetChildren(doc, root, 1, 0); if((root == NULL) || (nset == NULL)) { testLog("Error: failed to prepare walk test data\n"); xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedFailure(); return; } ret = xmlSecNodeSetWalk(nset, nodesetTestWalkStatsCallback, &stats); if((ret < 0) || (stats.total != 3) || (stats.elements != 1) || (stats.attributes != 1) || (stats.namespaces != 1) || (stats.text != 0)) { testLog("Error: walk stats mismatch (ret=%d total=%d elem=%d attr=%d ns=%d text=%d)\n", ret, stats.total, stats.elements, stats.attributes, stats.namespaces, stats.text); xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedFailure(); return; } xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedSuccess(); } static void test_xmlSecNodeSetDumpTextNodes_preserves_document_order(void) { xmlDocPtr doc; xmlNodePtr root; xmlSecNodeSetPtr nset; xmlBufferPtr buffer; xmlOutputBufferPtr out; int ret; testStart("xmlSecNodeSetDumpTextNodes preserves document order"); doc = nodesetTestParseDoc("<Root><A>1</A><B>2</B><C><D>3</D></C></Root>"); if(doc == NULL) { testFinishedFailure(); return; } root = xmlDocGetRootElement(doc); nset = xmlSecNodeSetGetChildren(doc, root, 1, 0); buffer = xmlBufferCreate(); out = (buffer != NULL) ? xmlOutputBufferCreateBuffer(buffer, NULL) : NULL; if((root == NULL) || (nset == NULL) || (buffer == NULL) || (out == NULL)) { testLog("Error: failed to prepare dump text nodes test data\n"); if(out != NULL) { (void)xmlOutputBufferClose(out); } else if(buffer != NULL) { xmlBufferFree(buffer); } xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedFailure(); return; } ret = xmlSecNodeSetDumpTextNodes(nset, out); if((ret < 0) || (xmlOutputBufferFlush(out) < 0) || !xmlStrEqual(xmlBufferContent(buffer), BAD_CAST "123")) { testLog("Error: dump text nodes output mismatch (ret=%d, text='%s')\n", ret, (xmlBufferContent(buffer) != NULL) ? (const char*)xmlBufferContent(buffer) : "(null)"); xmlOutputBufferClose(out); xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedFailure(); return; } xmlOutputBufferClose(out); xmlSecNodeSetDestroy(nset); xmlFreeDoc(doc); testFinishedSuccess(); } int test_nodeset(void) { int success = 1; testGroupStart("xmlSecNodeSetCreate"); test_xmlSecNodeSetCreate_destroy_doc_destroy(); test_xmlSecNodeSetContains_null_nodeset_allows_node(); if(testGroupFinished() != 1) { success = 0; } testGroupStart("xmlSecNodeSetGetChildren"); test_xmlSecNodeSetGetChildren_without_comments_contains_subtree(); test_xmlSecNodeSetGetChildren_invert_excludes_subtree(); if(testGroupFinished() != 1) { success = 0; } testGroupStart("xmlSecNodeSetAdd"); test_xmlSecNodeSetAdd_subtraction_removes_subtree(); if(testGroupFinished() != 1) { success = 0; } testGroupStart("xmlSecNodeSetWalk"); test_xmlSecNodeSetWalk_visits_elements_attributes_and_namespaces(); test_xmlSecNodeSetDumpTextNodes_preserves_document_order(); if(testGroupFinished() != 1) { success = 0; } return(success); }