Make config files obey the utf-8 input rule

When we read files from disk we always want to read them as bytes and
then convert them to text ourselves.  This gives us greater control over
what encodings are used, what to do in case of errors decoding the bytes
to text, and better resilience against problems on both Python 2 and
Python 3.

If we left it up to Python to do this, on Python2, this could mean
that config values end up as bytes (leading to tracebacks elsewhere in
the code).  In Python3, it could traceback if the user's locale did not
match with the encoding of the ini file or config files could be decoded
as the user's locale encoding instead of as utf-8.
pull/41415/head
Toshio Kuratomi 7 years ago
parent 30da71d880
commit 204fc7becf

@ -8,6 +8,7 @@ import os
import sys import sys
import tempfile import tempfile
import io
from collections import namedtuple from collections import namedtuple
from yaml import load as yaml_load from yaml import load as yaml_load
@ -19,7 +20,7 @@ except ImportError:
from ansible.config.data import ConfigData from ansible.config.data import ConfigData
from ansible.errors import AnsibleOptionsError, AnsibleError from ansible.errors import AnsibleOptionsError, AnsibleError
from ansible.module_utils.six import string_types from ansible.module_utils.six import PY3, string_types
from ansible.module_utils.six.moves import configparser from ansible.module_utils.six.moves import configparser
from ansible.module_utils._text import to_text, to_bytes, to_native from ansible.module_utils._text import to_text, to_bytes, to_native
from ansible.module_utils.parsing.convert_bool import boolean from ansible.module_utils.parsing.convert_bool import boolean
@ -215,8 +216,17 @@ class ConfigManager(object):
if cfile is not None: if cfile is not None:
if ftype == 'ini': if ftype == 'ini':
self._parsers[cfile] = configparser.ConfigParser() self._parsers[cfile] = configparser.ConfigParser()
with open(cfile, 'rb') as f:
try: try:
self._parsers[cfile].read(cfile) cfg_text = to_text(f.read(), errors='surrogate_or_strict')
except UnicodeError:
raise AnsibleOptionsError("Error reading config file(%s) because the config file was not utf8 encoded: %s" % (cfile, to_native(e)))
try:
if PY3:
self._parsers[cfile].read_string(cfg_text)
else:
cfg_file = io.StringIO(cfg_text)
self._parsers[cfile].readfp(cfg_file)
except configparser.Error as e: except configparser.Error as e:
raise AnsibleOptionsError("Error reading config file (%s): %s" % (cfile, to_native(e))) raise AnsibleOptionsError("Error reading config file (%s): %s" % (cfile, to_native(e)))
# FIXME: this should eventually handle yaml config files # FIXME: this should eventually handle yaml config files

Loading…
Cancel
Save