Skip to content

Commit

Permalink
Add xmlint as tool
Browse files Browse the repository at this point in the history
Closes #27
  • Loading branch information
priv-kweihmann committed Mar 5, 2019
1 parent a6d1278 commit b9c4787
Show file tree
Hide file tree
Showing 14 changed files with 238 additions and 3 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ On the other hand some static code analysis does not make any sense on an image-
* image-summary (aggregate all findings for package in an image) [image-summary]
* pylint (python) [pylint]
* shellcheck (shell) [shellcheck]
* xmlint (xml) [xmllint]

### Tools for all other recipes

Expand All @@ -46,6 +47,7 @@ On the other hand some static code analysis does not make any sense on an image-
* pysymbolcheck (check elf-files for used functions) [pysymcheck]
* oclint (c/c++/obj-c) [oclint]
* shellcheck (shell) [shellcheck]
* xmlint (xml) [xmllint]

each tool does have it's own benefits and flaws so don't be mad if you have 10k+ findings on the initial run.

Expand Down Expand Up @@ -196,6 +198,14 @@ n.a. this module does not need configuration, nor does it support suppression or
| SCA_BANDIT_EXTRA_SUPPRESS | Extra error-ids to be suppressed | space-separated-list | ""
| SCA_BANDIT_EXTRA_FATAL | Extra error-ids leading to build termination when found | space-separated-list | ""

### Available configuration for cpplint

| var | purpose | type | default |
| ------------- |:-------------:| -----:| -----:
| SCA_XMLLINT_EXTRA_SUPPRESS | Extra error-ids to be suppressed | space-separated-list | ""
| SCA_XMLLINT_EXTRA_FATAL | Extra error-ids leading to build termination when found | space-separated-list | ""
| SCA_XMLLINT_FILE_FILTER | List of file-extensions to be checked | space-separated-list | ".xml"

## Suppression and fatal-error
Every tool has the possibility to suppress some of the findings.
Besides that some findings could be configured to terminate the build, e.g. when a nullptr-dereference is found in C-code.
Expand Down
65 changes: 65 additions & 0 deletions classes/sca-conv-checkstyle-xmllint.bbclass
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
## This file contains the converter from raw
## cppcheck-format to checkstyle

inherit sca-conv-checkstyle-helper

def do_sca_conv_xmllint(d):
import os
import re
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
from xml.etree import ElementTree
from xml.dom import minidom

package_name = d.getVar("PN", True)
buildpath = d.getVar("SCA_SOURCES_DIR", True)

items = []
pattern = r"^(?P<file>.*):(?P<line>\d+):\s+(?P<id>.*)\s+:\s+(?P<msg>.*)"

class XmlLintItem():
File = ""
Line = ""
Column = "1"
Severity = "error"
Message = ""
ID = ""

if os.path.exists(d.getVar("SCA_RAW_RESULT")):
f = open(d.getVar("SCA_RAW_RESULT"), "r")
content = f.read()
f.close()

for m in re.finditer(pattern, content, re.MULTILINE):
try:
g = XmlLintItem()
filename = m.group("file")
if not os.path.isabs(filename):
filename = os.path.join(buildpath, filename)
g.File = filename
g.Line = m.group("line")
g.Message = "[Package:%s Tool:xmllint] %s" % (package_name, m.group("msg"))
g.ID = "xmllint.xmllint.%s" % m.group("id").replace(" ", "")
if g.Severity in checkstyle_allowed_warning_level(d) and not g.ID in get_suppress_entries(d):
items.append(g)
except:
pass

filenames = list(set([x.File for x in items]))

top = Element("checkstyle")
top.set("version", "4.3")

for _file in filenames:
_fe = SubElement(top, "file", { "name": _file })
for _fileE in [x for x in items if x.File == _file ]:
_fee = SubElement(_fe, "error", {
"column": _fileE.Column,
"line": _fileE.Line,
"message": _fileE.Message,
"severity": _fileE.Severity,
"source": _fileE.ID
})
try:
return checkstyle_prettify(d, top).decode("utf-8")
except:
return checkstyle_prettify(d, top)
2 changes: 1 addition & 1 deletion classes/sca-global.bbclass
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ SCA_WARNING_LEVEL ?= "warning"
SCA_ENABLE_IMAGE_SUMMARY ?= "1"

## List of overall available modules
SCA_AVAILABLE_MODULES = "bandit bitbake clang cppcheck cpplint cve-check eslint flint gcc kconfighard oclint pylint shellcheck"
SCA_AVAILABLE_MODULES = "bandit bitbake clang cppcheck cpplint cve-check eslint flint gcc kconfighard oclint pylint shellcheck xmllint"

inherit sca-conv-checkstyle-helper

Expand Down
2 changes: 1 addition & 1 deletion classes/sca-on-image.bbclass
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
inherit sca-global

SCA_PACKAGE_LICENSE_FILTER = "CLOSED"
SCA_ENABLED_MODULES ?= "bandit bitbake eslint pylint shellcheck"
SCA_ENABLED_MODULES ?= "bandit bitbake eslint pylint shellcheck xmllint"
SCA_SOURCES_DIR ?= "${IMAGE_ROOTFS}"

SCA_MODE = "image"
Expand Down
2 changes: 1 addition & 1 deletion classes/sca-on-recipe.bbclass
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
inherit sca-global
inherit sca-license-filter

SCA_ENABLED_MODULES ?= "bandit bitbake cve-check clang eslint flint cpplint cppcheck gcc kconfighard pylint pysymcheck oclint shellcheck"
SCA_ENABLED_MODULES ?= "bandit bitbake cve-check clang eslint flint cpplint cppcheck gcc kconfighard pylint pysymcheck oclint shellcheck xmllint"
SCA_SOURCES_DIR ?= "${B}"

SCA_MODE = "recipe"
Expand Down
65 changes: 65 additions & 0 deletions classes/sca-xmllint-core.bbclass
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
inherit sca-conv-checkstyle-xmllint
inherit sca-license-filter
inherit sca-helper

SCA_XMLLINT_EXTRA_SUPPRESS ?= ""
SCA_XMLLINT_EXTRA_FATAL ?= ""
## File extension filter list (whitespace separated)
SCA_XMLLINT_FILE_FILTER ?= ".c .cpp .h .hpp"

DEPENDS += "libxml2-native"

python do_sca_xmllint_core() {
import os
import subprocess
import json

d.setVar("SCA_EXTRA_SUPPRESS", d.getVar("SCA_XMLLINT_EXTRA_SUPPRESS"))
d.setVar("SCA_EXTRA_FATAL", d.getVar("SCA_XMLLINT_EXTRA_FATAL"))
d.setVar("SCA_SUPRESS_FILE", os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "xmllint-{}-suppress".format(d.getVar("SCA_MODE"))))
d.setVar("SCA_FATAL_FILE", os.path.join(d.getVar("STAGING_DATADIR_NATIVE"), "xmllint-{}-fatal".format(d.getVar("SCA_MODE"))))

_supress = get_suppress_entries(d)
_fatal = get_fatal_entries(d)

_args = ["xmllint"]
_args += ["--noout"]
_args += ["--valid"]

_files = get_files_by_extention(d, d.getVar("SCA_SOURCES_DIR"), d.getVar("SCA_XMLLINT_FILE_FILTER"), sca_filter_by_license(d))
cmd_output = ""
if any(_files):
_args += _files
try:
cmd_output = subprocess.check_output(_args, universal_newlines=True)
except subprocess.CalledProcessError as e:
cmd_output = e.stdout or ""

result_raw_file = os.path.join(d.getVar("T"), "sca_raw_xmllint.txt")
d.setVar("SCA_RAW_RESULT", result_raw_file)
with open(result_raw_file, "w") as o:
o.write(cmd_output)

xml_output = do_sca_conv_xmllint(d)
result_file = os.path.join(d.getVar("T"), "sca_checkstyle_xmllint.xml")
d.setVar("SCA_RESULT_FILE", result_file)
with open(result_file, "w") as o:
o.write(xml_output)

## Evaluate
_warnings = get_warnings_from_result(d)
_fatals = get_fatal_from_result(d, "xmllint.", _fatal)
_errors = get_errors_from_result(d)

warn_log = []
if any(_warnings):
warn_log.append("{} warning(s)".format(len(_warnings)))
if any(_errors):
warn_log.append("{} error(s)".format(len(_errors)))
if warn_log and should_emit_to_console(d):
bb.warn("SCA has found {}".format(",".join(warn_log)))

if any(_fatals):
bb.build.exec_func(d.getVar("SCA_DEPLOY_TASK"), d)
bb.error("SCA has following fatal errors: {}".format("\n".join(_fatals)))
}
30 changes: 30 additions & 0 deletions classes/sca-xmllint-image.bbclass
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
inherit sca-helper
inherit sca-global
inherit sca-xmllint-core
inherit sca-conv-checkstyle-helper

SCA_DEPLOY_TASK = "do_sca_deploy_xmllint_image"

python do_sca_deploy_xmllint_image() {
import os
import shutil

os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "xmllint", "raw"), exist_ok=True)
os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "xmllint", "checkstyle"), exist_ok=True)

raw_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "xmllint", "raw", "{}-{}.txt".format(d.getVar("PN"), d.getVar("PV")))
cs_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "xmllint", "checkstyle", "{}-{}.xml".format(d.getVar("PN"), d.getVar("PV")))
src_raw = os.path.join(d.getVar("T"), "sca_raw_xmllint.tt")
src_conv = os.path.join(d.getVar("T"), "sca_checkstyle_xmllint.xml")
if os.path.exists(src_raw):
shutil.copy(src_raw, raw_target)
if os.path.exists(src_conv):
shutil.copy(src_conv, cs_target)
if os.path.exists(cs_target):
do_sca_export_sources(d, cs_target)
}

addtask do_sca_xmllint_core before do_image_complete after do_image
addtask do_sca_deploy_xmllint_image before do_image_complete after do_sca_xmllint_core

DEPENDS += "sca-image-xmllint-rules-native"
29 changes: 29 additions & 0 deletions classes/sca-xmllint-recipe.bbclass
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
inherit sca-helper
inherit sca-global
inherit sca-xmllint-core

SCA_DEPLOY_TASK = "do_sca_deploy_xmllint_recipe"

python do_sca_deploy_xmllint_recipe() {
import os
import shutil

os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "xmllint", "raw"), exist_ok=True)
os.makedirs(os.path.join(d.getVar("SCA_EXPORT_DIR"), "xmllint", "checkstyle"), exist_ok=True)

raw_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "xmllint", "raw", "{}-{}.txt".format(d.getVar("PN"), d.getVar("PV")))
cs_target = os.path.join(d.getVar("SCA_EXPORT_DIR"), "xmllint", "checkstyle", "{}-{}.xml".format(d.getVar("PN"), d.getVar("PV")))
src_raw = os.path.join(d.getVar("T"), "sca_raw_xmllint.txt")
src_conv = os.path.join(d.getVar("T"), "sca_checkstyle_xmllint.xml")
if os.path.exists(src_raw):
shutil.copy(src_raw, raw_target)
if os.path.exists(src_conv):
shutil.copy(src_conv, cs_target)
if os.path.exists(cs_target):
do_sca_export_sources(d, cs_target)
}

addtask do_sca_xmllint_core before do_install after do_compile
addtask do_sca_deploy_xmllint_recipe before do_package after do_sca_xmllint_core

DEPENDS += "sca-recipe-xmllint-rules-native"
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
SUMMARY = "Ruleset for xmllint"
DESCRIPTION = " Rules to configure how xmllint is affecting the build"

SRC_URI = "file://suppress \
file://fatal"

LICENSE ?= "BSD-2-Clause"
LIC_FILES_CHKSUM ?= "file://${COMMON_LICENSE_DIR}/BSD-2-Clause;md5=8bef8e6712b1be5aa76af1ebde9d6378"

inherit native

do_install() {
install -d "${D}${datadir}"
install "${WORKDIR}/suppress" "${D}${datadir}/xmllint-image-suppress"
install "${WORKDIR}/fatal" "${D}${datadir}/xmllint-image-fatal"
}

FILES_${PN} = "${datadir}/**"
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
SUMMARY = "Ruleset for xmllint"
DESCRIPTION = " Rules to configure how xmllint is affecting the build"

SRC_URI = "file://suppress \
file://fatal"

LICENSE ?= "BSD-2-Clause"
LIC_FILES_CHKSUM ?= "file://${COMMON_LICENSE_DIR}/BSD-2-Clause;md5=8bef8e6712b1be5aa76af1ebde9d6378"

inherit native

do_install() {
install -d "${D}${datadir}"
install "${WORKDIR}/suppress" "${D}${datadir}/xmllint-recipe-suppress"
install "${WORKDIR}/fatal" "${D}${datadir}/xmllint-recipe-fatal"
}

FILES_${PN} = "${datadir}/**"

0 comments on commit b9c4787

Please sign in to comment.