Bug 1429669 - Recursively check identifiers in schema validation. r=dustin
authorMike Hommey <mh+mozilla@glandium.org>
Thu, 11 Jan 2018 09:29:19 +0900
changeset 450679 8210a2bd7a4c1cdab9363a965c9470723bf19b2f
parent 450678 03f2c77c78c66b265b60dd9e93f2f4026d84d107
child 450680 2b09823ab0472a4db42beaa8f07f78d119bbc260
push id8531
push userryanvm@gmail.com
push dateFri, 12 Jan 2018 16:47:01 +0000
treeherdermozilla-beta@0bc627ade5a0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdustin
bugs1429669
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1429669 - Recursively check identifiers in schema validation. r=dustin The taskgraph.util.schema.check_schema function validates key names used in schemas, ensuring they are dashed lower-case. However, it currently assumes keys are either direct strings, Required or Optional entries, and either ignores or fails to recognize other patterns. For example, it ignores Any, and fails to recognize combinations like Required(Any(...)), which we're going to use in next patch.
taskcluster/taskgraph/util/schema.py
--- a/taskcluster/taskgraph/util/schema.py
+++ b/taskcluster/taskgraph/util/schema.py
@@ -156,26 +156,38 @@ WHITELISTED_SCHEMA_IDENTIFIERS = [
 
 def check_schema(schema):
     identifier_re = re.compile('^[a-z][a-z0-9-]*$')
 
     def whitelisted(path):
         return any(f(path) for f in WHITELISTED_SCHEMA_IDENTIFIERS)
 
     def iter(path, sch):
+        def check_identifier(path, k):
+            if k in (basestring, voluptuous.Extra):
+                pass
+            elif isinstance(k, basestring):
+                if not identifier_re.match(k) and not whitelisted(path):
+                    raise RuntimeError(
+                        'YAML schemas should use dashed lower-case identifiers, '
+                        'not {!r} @ {}'.format(k, path))
+            elif isinstance(k, (voluptuous.Optional, voluptuous.Required)):
+                check_identifier(path, k.schema)
+            elif isinstance(k, voluptuous.Any):
+                for v in k.validators:
+                    check_identifier(path, v)
+            elif not whitelisted(path):
+                raise RuntimeError(
+                    'Unexpected type in YAML schema: {} @ {}'.format(
+                        type(k).__name__, path))
+
         if isinstance(sch, collections.Mapping):
             for k, v in sch.iteritems():
                 child = "{}[{!r}]".format(path, k)
-                if isinstance(k, (voluptuous.Optional, voluptuous.Required)):
-                    k = str(k)
-                if isinstance(k, basestring):
-                    if not identifier_re.match(k) and not whitelisted(child):
-                        raise RuntimeError(
-                            'YAML schemas should use dashed lower-case identifiers, '
-                            'not {!r} @ {}'.format(k, child))
+                check_identifier(child, k)
                 iter(child, v)
         elif isinstance(sch, (list, tuple)):
             for i, v in enumerate(sch):
                 iter("{}[{}]".format(path, i), v)
         elif isinstance(sch, voluptuous.Any):
             for v in sch.validators:
                 iter(path, v)
     iter('schema', schema.schema)