diff --git a/fdroidserver/scanner.py b/fdroidserver/scanner.py index f1cc171d..034d4f3c 100644 --- a/fdroidserver/scanner.py +++ b/fdroidserver/scanner.py @@ -146,15 +146,17 @@ def scan_source(build_dir, build=metadata.Build()): return False def ignoreproblem(what, path_in_build_dir): - logging.info('Ignoring %s at %s' % (what, path_in_build_dir)) + msg = ('Ignoring %s at %s' % (what, path_in_build_dir)) + logging.info(msg) if json_per_build is not None: - json_per_build['infos'].append([what, path_in_build_dir]) + json_per_build['infos'].append([msg, path_in_build_dir]) return 0 def removeproblem(what, path_in_build_dir, filepath): - logging.info('Removing %s at %s' % (what, path_in_build_dir)) + msg = ('Removing %s at %s' % (what, path_in_build_dir)) + logging.info(msg) if json_per_build is not None: - json_per_build['infos'].append([what, path_in_build_dir]) + json_per_build['infos'].append([msg, path_in_build_dir]) os.remove(filepath) return 0 @@ -229,7 +231,12 @@ def scan_source(build_dir, build=metadata.Build()): path_in_build_dir = os.path.relpath(filepath, build_dir) _ignored, ext = common.get_extension(path_in_build_dir) - if ext == 'a': + if curfile in ('gradle-wrapper.jar', 'gradlew', 'gradlew.bat'): + removeproblem(curfile, path_in_build_dir, filepath) + elif ext == 'apk': + removeproblem(_('Android APK file'), path_in_build_dir, filepath) + + elif ext == 'a': count += handleproblem(_('static library'), path_in_build_dir, filepath) elif ext == 'aar': count += handleproblem(_('Android AAR library'), path_in_build_dir, filepath) @@ -237,16 +244,10 @@ def scan_source(build_dir, build=metadata.Build()): count += handleproblem(_('Java compiled class'), path_in_build_dir, filepath) elif ext == 'so': count += handleproblem(_('shared library'), path_in_build_dir, filepath) - elif ext == 'apk': - removeproblem(_('Android APK file'), path_in_build_dir, filepath) - elif ext == 'jar': for name in suspects_found(curfile): count += handleproblem('usual suspect \'%s\'' % name, path_in_build_dir, filepath) - if curfile == 'gradle-wrapper.jar': - removeproblem('gradle-wrapper.jar', path_in_build_dir, filepath) - else: - count += handleproblem('JAR file', path_in_build_dir, filepath) + count += handleproblem(_('Java JAR file'), path_in_build_dir, filepath) elif ext == 'java': if not os.path.isfile(filepath): diff --git a/tests/scanner.TestCase b/tests/scanner.TestCase index 6bb74f9a..fc10a8af 100755 --- a/tests/scanner.TestCase +++ b/tests/scanner.TestCase @@ -5,10 +5,12 @@ import inspect import logging import optparse import os +import shutil import sys import tempfile import textwrap import unittest +import uuid from unittest import mock localmodule = os.path.realpath( @@ -80,6 +82,82 @@ class ScannerTest(unittest.TestCase): i += 1 self.assertEqual(count, i) + def test_scan_source_file_types(self): + """Build product files are not allowed, test they are detected""" + testdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name, dir=self.tmpdir) + os.chdir(testdir) + + fdroidserver.scanner.config = None + fdroidserver.scanner.options = mock.Mock() + fdroidserver.scanner.options.json = True + + keep = [ + 'arg.jar', + 'ascii.out', + 'baz.so', + 'sqlcipher.aar', + 'static.a', + ] + remove = [ + 'gradle-wrapper.jar', + 'gradlew', + 'gradlew.bat', + ] + for f in keep + remove: + with open(f, 'w') as fp: + fp.write('placeholder') + self.assertTrue(os.path.exists(f)) + binaries = [ + 'binary.out', + 'fake.png', + 'snippet.png', + ] + with open('binary.out', 'wb') as fp: + fp.write(b'\x00\x00') + fp.write(uuid.uuid4().bytes) + shutil.copyfile('binary.out', 'fake.png') + os.chmod('fake.png', 0o755) + os.system('ls -l binary.out') + with open('snippet.png', 'wb') as fp: + fp.write(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\x00' + b'\x000\x08\x06\x00\x00\x00W\x02\xf9\x87\x00\x00\x00\x04sB' + b'IT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\tpHYs\x00\x00\n' + b'a\x00\x00\na\x01\xfc\xccJ%\x00\x00\x00\x19tEXtSoftware') + os.chmod('snippet.png', 0o755) + os.system('ls -l fake.png') + + count = fdroidserver.scanner.scan_source(testdir) + self.assertEqual(5, count, 'there should be this many errors') + + for f in keep + binaries: + self.assertTrue(os.path.exists(f), f + ' should still be there') + for f in remove: + self.assertFalse(os.path.exists(f), f + ' should have been removed') + + files = dict() + for section in ('errors', 'infos', 'warnings'): + files[section] = [] + for msg, f in fdroidserver.scanner.json_per_build[section]: + files[section].append(f) + + self.assertFalse('ascii.out' in files['errors'], + 'an ASCII .out file is not an error') + self.assertFalse('snippet.png' in files['errors'], + 'an executable valid image is not an error') + + self.assertTrue('arg.jar' in files['errors'], 'all JAR files are errors') + self.assertTrue('baz.so' in files['errors'], 'all .so files are errors') + self.assertTrue('binary.out' in files['errors'], 'a binary .out file is an error') + self.assertTrue('sqlcipher.aar' in files['errors'], 'all AAR files are errors') + self.assertTrue('static.a' in files['errors'], 'all .a files are errors') + + self.assertTrue('fake.png' in files['warnings'], + 'a random binary that is executable that is not an image is a warning') + + for f in remove: + self.assertTrue(f in files['infos'], + f + ' should be removed with an info message') + def test_build_local_scanner(self): """`fdroid build` calls scanner functions, test them here""" testdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name, dir=self.tmpdir)