#! /usr/bin/python # # SPDX-License-Identifier: Apache-2.0 # Zephyr's Twister library # # pylint: disable=unused-import # # Set of code that other projects can also import to do things on # Zephyr's sanity check testcases. import logging import yaml try: # Use the C LibYAML parser if available, rather than the Python parser. # It's much faster. from yaml import CLoader as Loader from yaml import CSafeLoader as SafeLoader from yaml import CDumper as Dumper except ImportError: from yaml import Loader, SafeLoader, Dumper log = logging.getLogger("scl") class EmptyYamlFileException(Exception): pass # # def yaml_load(filename): """ Safely load a YAML document Follows recommendations from https://security.openstack.org/guidelines/dg_avoid-dangerous-input-parsing-libraries.html. :param str filename: filename to load :raises yaml.scanner: On YAML scan issues :raises: any other exception on file access errors :return: dictionary representing the YAML document """ try: with open(filename, 'r', encoding='utf-8') as f: return yaml.load(f, Loader=SafeLoader) except yaml.scanner.ScannerError as e: # For errors parsing schema.yaml mark = e.problem_mark cmark = e.context_mark log.error("%s:%d:%d: error: %s (note %s context @%s:%d:%d %s)", mark.name, mark.line, mark.column, e.problem, e.note, cmark.name, cmark.line, cmark.column, e.context) raise # If pykwalify is installed, then the validate function will work -- # otherwise, it is a stub and we'd warn about it. try: import pykwalify.core # Don't print error messages yourself, let us do it logging.getLogger("pykwalify.core").setLevel(50) def _yaml_validate(data, schema): if not schema: return c = pykwalify.core.Core(source_data=data, schema_data=schema) c.validate(raise_exception=True) except ImportError as e: log.warning("can't import pykwalify; won't validate YAML (%s)", e) def _yaml_validate(data, schema): pass def yaml_load_verify(filename, schema): """ Safely load a testcase/sample yaml document and validate it against the YAML schema, returning in case of success the YAML data. :param str filename: name of the file to load and process :param dict schema: loaded YAML schema (can load with :func:`yaml_load`) # 'document.yaml' contains a single YAML document. :raises yaml.scanner.ScannerError: on YAML parsing error :raises pykwalify.errors.SchemaError: on Schema violation error """ # 'document.yaml' contains a single YAML document. y = yaml_load(filename) if not y: raise EmptyYamlFileException('No data in YAML file: %s' % filename) _yaml_validate(y, schema) return y