chiark / gitweb /
VercodeOperation: only allow simple math expresssions and %c
authorHans-Christoph Steiner <hans@eds.org>
Fri, 2 Mar 2018 11:50:48 +0000 (12:50 +0100)
committerHans-Christoph Steiner <hans@eds.org>
Mon, 5 Mar 2018 08:45:58 +0000 (09:45 +0100)
fdroidserver/checkupdates.py
fdroidserver/common.py
fdroidserver/lint.py
tests/lint.TestCase

index d919c72b11a8cbba405065651bf9dc68ad332549..0a4f6e27af114bf1d2ad46e3945bc9cfcebd18dd 100644 (file)
@@ -429,6 +429,9 @@ def checkupdates_app(app):
         msg = 'Invalid update check method'
 
     if version and vercode and app.VercodeOperation:
+        if not common.VERCODE_OPERATION_RE.match(app.VercodeOperation):
+            raise MetaDataException(_('Invalid VercodeOperation: {field}')
+                                    .format(field=app.VercodeOperation))
         oldvercode = str(int(vercode))
         op = app.VercodeOperation.replace("%c", oldvercode)
         vercode = str(eval(op))
index 93a6945f825aa16470d3860125d54bac729fdbd8..cf1d92035f9473f42b221ca6b9ad5e461c24149b 100644 (file)
@@ -61,6 +61,8 @@ from .asynchronousfilereader import AsynchronousFileReader
 # has to be manually set in test_aapt_version()
 MINIMUM_AAPT_VERSION = '26.0.0'
 
+VERCODE_OPERATION_RE = re.compile(r'^([ 0-9/*+-]|%c)+$')
+
 # A signature block file with a .DSA, .RSA, or .EC extension
 CERT_PATH_REGEX = re.compile(r'^META-INF/.*\.(DSA|EC|RSA)$')
 APK_NAME_REGEX = re.compile(r'^([a-zA-Z][\w.]*)_(-?[0-9]+)_?([0-9a-f]{7})?\.apk')
index ed86e29ad32473e5ffc48a76689f6576a6d5afc1..a40ffffe3b2266da074d0275ceccd4bb9e3e3ca8 100644 (file)
@@ -222,6 +222,11 @@ def check_update_check_data_url(app):
                     yield _('UpdateCheckData must use HTTPS URL: {url}').format(url=url)
 
 
+def check_vercode_operation(app):
+    if app.VercodeOperation and not common.VERCODE_OPERATION_RE.match(app.VercodeOperation):
+        yield _('Invalid VercodeOperation: {field}').format(field=app.VercodeOperation)
+
+
 def check_ucm_tags(app):
     lastbuild = get_lastbuild(app.builds)
     if (lastbuild is not None
@@ -529,6 +534,7 @@ def main():
         app_check_funcs = [
             check_regexes,
             check_update_check_data_url,
+            check_vercode_operation,
             check_ucm_tags,
             check_char_limits,
             check_old_links,
index ad9f0514f1791c46b228389200a7cc50c5b2747e..28d539a0563ad32bb666bc7de233cf7a2c32c3e4 100755 (executable)
@@ -19,6 +19,7 @@ if localmodule not in sys.path:
 
 import fdroidserver.common
 import fdroidserver.lint
+import fdroidserver.metadata
 
 
 class LintTest(unittest.TestCase):
@@ -69,6 +70,52 @@ class LintTest(unittest.TestCase):
             logging.debug(warn)
         self.assertTrue(anywarns)
 
+    def test_check_vercode_operation(self):
+        config = dict()
+        fdroidserver.common.fill_config_defaults(config)
+        fdroidserver.common.config = config
+        fdroidserver.lint.config = config
+
+        app = fdroidserver.metadata.App()
+        app.Name = 'Bad App'
+        app.Summary = 'We pwn you'
+        app.Description = 'These are some back'
+
+        good_fields = [
+            '6%c',
+            '%c - 1',
+            '%c + 10',
+            '%c*10',
+            '%c*10 + 3',
+            '%c*10 + 8',
+            '%c + 2 ',
+            '%c + 3',
+            '%c + 7',
+        ]
+        bad_fields = [
+            'open("/etc/passwd")',
+            '%C + 1',
+            '%%c * 123',
+            '123 + %%',
+            '%c % 7',
+        ]
+
+        anywarns = False
+        for good in good_fields:
+            app.VercodeOperation = good
+            for warn in fdroidserver.lint.check_vercode_operation(app):
+                anywarns = True
+                logging.debug(warn)
+            self.assertFalse(anywarns)
+
+        for bad in bad_fields:
+            anywarns = False
+            app.VercodeOperation = bad
+            for warn in fdroidserver.lint.check_vercode_operation(app):
+                anywarns = True
+                logging.debug(warn)
+            self.assertTrue(anywarns)
+
 
 if __name__ == "__main__":
     parser = optparse.OptionParser()