From 49db03c384b63ba7a299263cdae63857fe46ef1f Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Fri, 24 Feb 2017 10:01:21 -0800 Subject: [PATCH] Fix for traceback when we encounter non-utf8 characters in diff We can diff non-utf8 files (as part of copy, for instance) but when we try to turn the bytes into text for display, the characters cause a traceback. Since diff output is only informational, we can replace those problematic bytes with replacement characters. We do not want to do this to other fields because those fields may be used inside of the playbook (for templating another variable or matching in a conditional). Fixes #21803 Fixes #21804 --- lib/ansible/executor/task_executor.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py index 09b22f91d6..f53ab14fc6 100644 --- a/lib/ansible/executor/task_executor.py +++ b/lib/ansible/executor/task_executor.py @@ -129,17 +129,26 @@ class TaskExecutor: if 'changed' not in res: res['changed'] = False - def _clean_res(res): + def _clean_res(res, errors='surrogate_or_strict'): if isinstance(res, UnsafeProxy): return res._obj elif isinstance(res, binary_type): - return to_text(res, errors='surrogate_or_strict') + return to_text(res, errors=errors) elif isinstance(res, dict): for k in res: - res[k] = _clean_res(res[k]) + try: + res[k] = _clean_res(res[k], errors=errors) + except UnicodeError: + if k == 'diff': + # If this is a diff, substitute a replacement character if the value + # is undecodable as utf8. (Fix #21804) + display.warning("We were unable to decode all characters, replaced some in an effort to return as much as possible") + res[k] = _clean_res(res[k], errors='surrogate_then_replace') + else: + raise elif isinstance(res, list): for idx,item in enumerate(res): - res[idx] = _clean_res(item) + res[idx] = _clean_res(item, errors=errors) return res display.debug("dumping result to json")