From 9c2052febe494ca5fe8e3fef7996fd2c2c736785 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20=C4=8Cern=C3=BD?= <jcerny@redhat.com>
Date: Wed, 2 Nov 2022 09:04:25 +0100
Subject: [PATCH] Don't emit items if XPath doesn't match
This commit fixes the behavior of the xmlfilecontent probe in situation
when the XPath query in xmlfilecontent_object doesn't match any node in
the given XML file and the query returns an empty node set. Currently,
in this situation, we emit an item in which we add an empty value_of
element. However, this value_of element has its datatype attribute set
to an empty string, which is invalid according to the OVAL schema. When
we try to make the OVAL results valid, we face the problem that it isn't
clear what should be the value of the datatype attribute for empty
elements. But as we can realize the XPath doesn't match anything means
that the requested object doesn't exist on the system, so a better
behavior would be to not produce a xmlfilecontent54_item. That is
consistent with eg. situation when a regular expression matched nothing
in textfilecontent54_object. This commit therefore stops the item
generation in this situation.
This commit also extends the existing test to cover the situation
of XPath queries for nonexistent element and nonexistent attribute.
Fixes: #1890, rhbz#2138884, rhbz#2139060
---
.../probes/independent/xmlfilecontent_probe.c | 5 +--
.../test_xmlfilecontent_probe.sh | 6 +++
.../test_xmlfilecontent_probe.xml | 38 +++++++++++++++++++
3 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/src/OVAL/probes/independent/xmlfilecontent_probe.c b/src/OVAL/probes/independent/xmlfilecontent_probe.c
index 6c70b359ba..5d56afa0d4 100644
--- a/src/OVAL/probes/independent/xmlfilecontent_probe.c
+++ b/src/OVAL/probes/independent/xmlfilecontent_probe.c
@@ -296,10 +296,9 @@ static int process_file(const char *prefix, const char *path, const char *filena
node_cnt = nodes->nodeNr;
dD("node_cnt: %d.", node_cnt);
- if (node_cnt == 0) {
- probe_item_setstatus(item, SYSCHAR_STATUS_DOES_NOT_EXIST);
- probe_item_ent_add(item, "value_of", NULL, NULL);
- probe_itement_setstatus(item, "value_of", 1, SYSCHAR_STATUS_DOES_NOT_EXIST);
+ if (node_cnt <= 0) {
+ ret = -5;
+ goto cleanup;
} else {
node_tab = nodes->nodeTab;
for (i = 0; i < node_cnt; ++i) {
diff --git a/tests/probes/xmlfilecontent/test_xmlfilecontent_probe.sh b/tests/probes/xmlfilecontent/test_xmlfilecontent_probe.sh
index e3c56a8606..68138dad75 100755
--- a/tests/probes/xmlfilecontent/test_xmlfilecontent_probe.sh
+++ b/tests/probes/xmlfilecontent/test_xmlfilecontent_probe.sh
@@ -6,9 +6,15 @@ set -e -o pipefail
cp $srcdir/example.xml /tmp/
result=$(mktemp)
$OSCAP oval eval --results $result $srcdir/test_xmlfilecontent_probe.xml
+# Even if OSCAP_FULL_VALIDATION is set, an invalid OVAL result doesn't cause
+# the "oscap oval eval" to return a non-zero value, so let's run validation
+# as a separate command
+$OSCAP oval validate "$result"
assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:1" and @result="true"]'
assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:2" and @result="true"]'
assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:3" and @result="true"]'
assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:4" and @result="true"]'
assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:5" and @result="true"]'
+assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:6" and @result="true"]'
+assert_exists 1 '/oval_results/results/system/definitions/definition[@definition_id="oval:x:def:7" and @result="true"]'
rm -f $result
\ No newline at end of file
diff --git a/tests/probes/xmlfilecontent/test_xmlfilecontent_probe.xml b/tests/probes/xmlfilecontent/test_xmlfilecontent_probe.xml
index 3350df0c49..0a9708d4b6 100644
--- a/tests/probes/xmlfilecontent/test_xmlfilecontent_probe.xml
+++ b/tests/probes/xmlfilecontent/test_xmlfilecontent_probe.xml
@@ -66,6 +66,30 @@
<criterion test_ref="oval:x:tst:5" comment="test"/>
</criteria>
</definition>
+ <definition class="compliance" version="1" id="oval:x:def:6">
+ <metadata>
+ <title>A simple test OVAL for xmlfilecontent test - check nonexisting attribute</title>
+ <description>x</description>
+ <affected family="unix">
+ <platform>x</platform>
+ </affected>
+ </metadata>
+ <criteria>
+ <criterion test_ref="oval:x:tst:6" comment="test"/>
+ </criteria>
+ </definition>
+ <definition class="compliance" version="1" id="oval:x:def:7">
+ <metadata>
+ <title>A simple test OVAL for xmlfilecontent test - check nonexisting element</title>
+ <description>x</description>
+ <affected family="unix">
+ <platform>x</platform>
+ </affected>
+ </metadata>
+ <criteria>
+ <criterion test_ref="oval:x:tst:7" comment="test"/>
+ </criteria>
+ </definition>
</definitions>
<tests>
@@ -89,6 +113,12 @@
<ind:object object_ref="oval:x:obj:5"/>
<ind:state state_ref="oval:x:ste:5"/>
</ind:xmlfilecontent_test>
+ <ind:xmlfilecontent_test id="oval:x:tst:6" version="1" comment="test an xpath expression" check="all" check_existence="none_exist">
+ <ind:object object_ref="oval:x:obj:6"/>
+ </ind:xmlfilecontent_test>
+ <ind:xmlfilecontent_test id="oval:x:tst:7" version="1" comment="test an xpath expression" check="all" check_existence="none_exist">
+ <ind:object object_ref="oval:x:obj:7"/>
+ </ind:xmlfilecontent_test>
</tests>
<objects>
@@ -112,6 +142,14 @@
<ind:filepath>/tmp/example.xml</ind:filepath>
<ind:xpath>//*[@regid="mycoyote.com"]/@name</ind:xpath>
</ind:xmlfilecontent_object>
+ <ind:xmlfilecontent_object id="oval:x:obj:6" version="1" comment="xpath query">
+ <ind:filepath>/tmp/example.xml</ind:filepath>
+ <ind:xpath>/SoftwareIdentity/@thisattributedoesnotexist</ind:xpath>
+ </ind:xmlfilecontent_object>
+ <ind:xmlfilecontent_object id="oval:x:obj:7" version="1" comment="xpath query">
+ <ind:filepath>/tmp/example.xml</ind:filepath>
+ <ind:xpath>/SoftwareIdentity/thiselementdoesnotexist</ind:xpath>
+ </ind:xmlfilecontent_object>
</objects>
<states>