diff --git a/awx/main/tests/unit/utils/test_common.py b/awx/main/tests/unit/utils/test_common.py index 0f50bac6b1..fa4a038037 100644 --- a/awx/main/tests/unit/utils/test_common.py +++ b/awx/main/tests/unit/utils/test_common.py @@ -44,6 +44,16 @@ def test_parse_yaml_or_json(input_, output): assert common.parse_yaml_or_json(input_) == output +def test_recursive_vars_not_allowed(): + rdict = {} + rdict['a'] = rdict + # YAML dumper will use a tag to give recursive data + data = yaml.dump(rdict, default_flow_style=False) + with pytest.raises(ParseError) as exc: + common.parse_yaml_or_json(data, silent_failure=False) + assert 'Circular reference detected' in str(exc) + + class TestParserExceptions: @staticmethod diff --git a/awx/main/utils/common.py b/awx/main/utils/common.py index 13ff87e956..a024e7d649 100644 --- a/awx/main/utils/common.py +++ b/awx/main/utils/common.py @@ -630,8 +630,16 @@ def parse_yaml_or_json(vars_str, silent_failure=True): vars_dict = yaml.safe_load(vars_str) # Can be None if '---' if vars_dict is None: - return {} + vars_dict = {} validate_vars_type(vars_dict) + if not silent_failure: + # is valid YAML, check that it is compatible with JSON + try: + json.dumps(vars_dict) + except (ValueError, TypeError, AssertionError) as json_err2: + raise ParseError(_( + 'Variables not compatible with JSON standard (error: {json_error})').format( + json_error=str(json_err2))) except (yaml.YAMLError, TypeError, AttributeError, AssertionError) as yaml_err: if silent_failure: return {}