forked from mirrors/gecko-dev
Bug 1651731: [lint] Only allow files that are typically executable to have shebang lines override permission check; r=linter-reviewers,sylvestre
Differential Revision: https://phabricator.services.mozilla.com/D82949
This commit is contained in:
parent
51a23a4ba2
commit
2244b1cc7c
11 changed files with 83 additions and 44 deletions
|
|
@ -52,10 +52,7 @@ config/windows-h-.*.h
|
|||
tools/clang-tidy/test/.*
|
||||
|
||||
# We are testing the incorrect formatting.
|
||||
tools/lint/test/files/file-whitespace/
|
||||
|
||||
# Test reformatting
|
||||
tools/lint/test/files/clang-format/
|
||||
tools/lint/test/files/
|
||||
|
||||
# Contains an XML definition and formatting would break the layout
|
||||
widget/gtk/MPRISInterfaceDescription.h
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ This linter verifies if a file has unnecessary permissions.
|
|||
If a file has execution permissions (+x), file-perm will
|
||||
generate a warning.
|
||||
|
||||
It will ignore files starting with ``#!`` (Python or node scripts).
|
||||
It will ignore files starting with ``#!`` for types of files
|
||||
that typically have shebang lines (such as python, node or
|
||||
shell scripts).
|
||||
|
||||
This linter does not have any affect on Windows.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ file-perm:
|
|||
- .cpp
|
||||
- .h
|
||||
- .html
|
||||
- .js
|
||||
- .jsm
|
||||
- .jsx
|
||||
- .m
|
||||
|
|
@ -22,3 +21,15 @@ file-perm:
|
|||
- 'tools/lint/file-perm/**'
|
||||
type: external
|
||||
payload: file-perm:lint
|
||||
|
||||
maybe-shebang-file-perm:
|
||||
description: "File permission check for files that might have `#!` header."
|
||||
include:
|
||||
- .
|
||||
allow-shebang: true
|
||||
extensions:
|
||||
- .js
|
||||
support-files:
|
||||
- 'tools/lint/file-perm/**'
|
||||
type: external
|
||||
payload: file-perm:lint
|
||||
|
|
|
|||
|
|
@ -8,10 +8,9 @@ import platform
|
|||
from mozlint import result
|
||||
from mozlint.pathutils import expand_exclusions
|
||||
|
||||
results = []
|
||||
|
||||
|
||||
def lint(paths, config, fix=None, **lintargs):
|
||||
results = []
|
||||
|
||||
if platform.system() == "Windows":
|
||||
# Windows doesn't have permissions in files
|
||||
|
|
@ -21,13 +20,14 @@ def lint(paths, config, fix=None, **lintargs):
|
|||
files = list(expand_exclusions(paths, config, lintargs["root"]))
|
||||
for f in files:
|
||||
if os.access(f, os.X_OK):
|
||||
with open(f, "r+") as content:
|
||||
# Some source files have +x permissions
|
||||
line = content.readline()
|
||||
if line.startswith("#!"):
|
||||
# Check if the file doesn't start with a shebang
|
||||
# if it does, not a warning
|
||||
continue
|
||||
if config.get("allow-shebang"):
|
||||
with open(f, "r+") as content:
|
||||
# Some source files have +x permissions
|
||||
line = content.readline()
|
||||
if line.startswith("#!"):
|
||||
# Check if the file doesn't start with a shebang
|
||||
# if it does, not a warning
|
||||
continue
|
||||
|
||||
if fix:
|
||||
# We want to fix it, do it and leave
|
||||
|
|
|
|||
|
|
@ -20,7 +20,39 @@ sys.path.insert(0, lintdir)
|
|||
logger = logging.getLogger("mozlint")
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def pytest_generate_tests(metafunc):
|
||||
"""Finds, loads and returns the config for the linter name specified by the
|
||||
LINTER global variable in the calling module.
|
||||
|
||||
This implies that each test file (that uses this fixture) should only be
|
||||
used to test a single linter. If no LINTER variable is defined, the test
|
||||
will fail.
|
||||
"""
|
||||
if "config" in metafunc.fixturenames:
|
||||
if not hasattr(metafunc.module, "LINTER"):
|
||||
pytest.fail(
|
||||
"'config' fixture used from a module that didn't set the LINTER variable"
|
||||
)
|
||||
|
||||
name = metafunc.module.LINTER
|
||||
config_path = os.path.join(lintdir, "{}.yml".format(name))
|
||||
parser = Parser(build.topsrcdir)
|
||||
configs = parser.parse(config_path)
|
||||
config_names = {config["name"] for config in configs}
|
||||
|
||||
marker = metafunc.definition.get_closest_marker("lint_config")
|
||||
if marker:
|
||||
config_name = marker.kwargs["name"]
|
||||
if config_name not in config_names:
|
||||
pytest.fail(f"lint config {config_name} not present in {name}.yml")
|
||||
configs = [
|
||||
config for config in configs if config["name"] == marker.kwargs["name"]
|
||||
]
|
||||
|
||||
ids = [config["name"] for config in configs]
|
||||
metafunc.parametrize("config", configs, ids=ids)
|
||||
|
||||
|
||||
def root(request):
|
||||
"""Return the root directory for the files of the linter under test.
|
||||
|
||||
|
|
@ -50,27 +82,6 @@ def paths(root):
|
|||
return _inner
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def config(request):
|
||||
"""Finds, loads and returns the config for the linter name specified by the
|
||||
LINTER global variable in the calling module.
|
||||
|
||||
This implies that each test file (that uses this fixture) should only be
|
||||
used to test a single linter. If no LINTER variable is defined, the test
|
||||
will fail.
|
||||
"""
|
||||
if not hasattr(request.module, "LINTER"):
|
||||
pytest.fail(
|
||||
"'config' fixture used from a module that didn't set the LINTER variable"
|
||||
)
|
||||
|
||||
name = request.module.LINTER
|
||||
config_path = os.path.join(lintdir, "{}.yml".format(name))
|
||||
parser = Parser(build.topsrcdir)
|
||||
# TODO Don't assume one linter per yaml file
|
||||
return parser.parse(config_path)[0]
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def run_setup(config):
|
||||
"""Make sure that if the linter named in the LINTER global variable has a
|
||||
|
|
@ -111,7 +122,7 @@ def lint(config, root):
|
|||
|
||||
ret = defaultdict(list)
|
||||
for r in results:
|
||||
ret[r.path].append(r)
|
||||
ret[r.relpath].append(r)
|
||||
return ret
|
||||
|
||||
return wrapper
|
||||
|
|
|
|||
2
tools/lint/test/files/file-perm/no-shebang/bad-shebang.c
Executable file
2
tools/lint/test/files/file-perm/no-shebang/bad-shebang.c
Executable file
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/bash
|
||||
int main() { return 0; }
|
||||
|
|
@ -1,22 +1,38 @@
|
|||
from __future__ import absolute_import, print_function
|
||||
|
||||
import pytest
|
||||
|
||||
import mozunit
|
||||
|
||||
LINTER = "file-perm"
|
||||
|
||||
|
||||
@pytest.mark.lint_config(name="file-perm")
|
||||
def test_lint_file_perm(lint, paths):
|
||||
results = lint(paths())
|
||||
results = lint(paths("no-shebang"), collapse_results=True)
|
||||
print(results)
|
||||
assert len(results) == 2
|
||||
|
||||
assert results.keys() == {
|
||||
"no-shebang/bad.c",
|
||||
"no-shebang/bad-shebang.c",
|
||||
}
|
||||
|
||||
for path, issues in results.items():
|
||||
for issue in issues:
|
||||
assert "permissions on a source" in issue.message
|
||||
assert issue.level == "error"
|
||||
|
||||
|
||||
@pytest.mark.lint_config(name="maybe-shebang-file-perm")
|
||||
def test_lint_shebang_file_perm(config, lint, paths):
|
||||
results = lint(paths("maybe-shebang"))
|
||||
print(results)
|
||||
assert len(results) == 1
|
||||
|
||||
assert "permissions on a source" in results[0].message
|
||||
assert results[0].level == "error"
|
||||
assert results[0].relpath == "bad.c"
|
||||
|
||||
assert "permissions on a source" in results[1].message
|
||||
assert results[1].level == "error"
|
||||
assert results[1].relpath == "bad.js"
|
||||
assert results[0].relpath == "maybe-shebang/bad.js"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Reference in a new issue