commit:     18e21c8082f37816cedb6b0621264364f5568673
Author:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Thu Aug  3 19:25:05 2023 +0000
Commit:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Wed Aug 30 15:36:15 2023 +0000
URL:        
https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=18e21c80

GlobDistdir: check for glob usage with DISTDIR

Resolves: https://github.com/pkgcore/pkgcheck/issues/605
Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>

 src/pkgcheck/checks/codingstyle.py                 | 34 ++++++++++++++++++++++
 .../standalone/GlobCheck/GlobDistdir/expected.json |  3 ++
 .../GlobCheck/GlobDistdir/GlobDistdir-0.ebuild     | 15 ++++++++++
 3 files changed, 52 insertions(+)

diff --git a/src/pkgcheck/checks/codingstyle.py 
b/src/pkgcheck/checks/codingstyle.py
index c99a8eca..0e2188db 100644
--- a/src/pkgcheck/checks/codingstyle.py
+++ b/src/pkgcheck/checks/codingstyle.py
@@ -1363,3 +1363,37 @@ class NonPosixCheck(Check):
             call_name = pkg.node_str(call_node.child_by_field_name("name"))
             if call_name in ("head", "tail"):
                 yield from self.check_head_tail(pkg, call_node, call_name)
+
+
+class GlobDistdir(results.LineResult, results.Warning):
+    """Filename expansion with ``${DISTDIR}`` is unsafe.
+
+    Filename expansion could accidentally match irrelevant files in
+    ``${DISTDIR}``, e.g. from other packages or other versions of the
+    same package.
+    """
+
+    @property
+    def desc(self):
+        return f"line {self.lineno}: unsafe filename expansion used with 
DISTDIR: {self.line}"
+
+
+class GlobCheck(Check):
+    """Scan ebuilds for unsafe glob usage."""
+
+    _source = sources.EbuildParseRepoSource
+    known_results = frozenset({GlobDistdir})
+
+    def __init__(self, options, **kwargs):
+        super().__init__(options, **kwargs)
+        self.glob_query = bash.query('(concatenation (word) @word (.match? 
@word "[*?]")) @usage')
+
+    def feed(self, pkg):
+        for node, capture in self.glob_query.captures(pkg.tree.root_node):
+            if capture == "usage":
+                for var_node, _ in bash.var_query.captures(node):
+                    var_name = pkg.node_str(var_node)
+                    if var_name == "DISTDIR":
+                        lineno, _colno = node.start_point
+                        yield GlobDistdir(line=pkg.node_str(node), 
lineno=lineno + 1, pkg=pkg)
+                        break

diff --git a/testdata/data/repos/standalone/GlobCheck/GlobDistdir/expected.json 
b/testdata/data/repos/standalone/GlobCheck/GlobDistdir/expected.json
new file mode 100644
index 00000000..56e00b6c
--- /dev/null
+++ b/testdata/data/repos/standalone/GlobCheck/GlobDistdir/expected.json
@@ -0,0 +1,3 @@
+{"__class__": "GlobDistdir", "category": "GlobCheck", "package": 
"GlobDistdir", "version": "0", "line": "\"${DISTDIR}\"/foo-*.bar", "lineno": 7}
+{"__class__": "GlobDistdir", "category": "GlobCheck", "package": 
"GlobDistdir", "version": "0", "line": 
"\"${DISTDIR}\"/\"${DISTDIR}\"/foo-?.bar", "lineno": 8}
+{"__class__": "GlobDistdir", "category": "GlobCheck", "package": 
"GlobDistdir", "version": "0", "line": "\"${DISTDIR}\"/foo-?-*.bar", "lineno": 
9}

diff --git 
a/testdata/repos/standalone/GlobCheck/GlobDistdir/GlobDistdir-0.ebuild 
b/testdata/repos/standalone/GlobCheck/GlobDistdir/GlobDistdir-0.ebuild
new file mode 100644
index 00000000..a0480fa7
--- /dev/null
+++ b/testdata/repos/standalone/GlobCheck/GlobDistdir/GlobDistdir-0.ebuild
@@ -0,0 +1,15 @@
+DESCRIPTION="Ebuild with unsafe glob around DISTDIR"
+HOMEPAGE="https://github.com/pkgcore/pkgcheck";
+SLOT="0"
+LICENSE="BSD"
+
+src_install() {
+       doins "${DISTDIR}"/foo-*.bar # bad
+       doins "${DISTDIR}"/"${DISTDIR}"/foo-?.bar # bad
+       doins "${DISTDIR}"/foo-?-*.bar # bad
+
+       doins "${T}"/foo-*.bar # not unsafe dir
+       doins "${DISTDIR}"/foo-1.bar # no glob
+       doins "${DISTDIR}"/"foo-*.bar" # quoted
+       doins "${DISTDIR}"/'foo-*.bar' # quoted
+}

Reply via email to