Skip to content

Commit

Permalink
Merge pull request #61 from mbengit/sanitizelogmessages
Browse files Browse the repository at this point in the history
Sanitize log message text
  • Loading branch information
mbengit authored Apr 26, 2023
2 parents f251940 + 1359b5d commit 3a94157
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[run]
omit=qpylib/__init__.py

[report]
fail_under=100
6 changes: 5 additions & 1 deletion qpylib/log_qpylib.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def log(message, level):
log_function = LOG_LEVEL_TO_FUNCTION.get(level.upper())
if not log_function:
raise ValueError("Unknown level: '{0}'".format(level))
log_function(message)
log_function(_sanitize(message))

def set_log_level(level='INFO'):
if not QLOGGER:
Expand All @@ -81,6 +81,10 @@ def _default_log_level():
def _log_file_location():
return app_qpylib.get_log_path('app.log')

def _sanitize(message):
# Use repr to suppress \t, \n, \r, and strip the surrounding quotes added by repr.
return repr(message)[1:-1]

def _generate_handlers(syslog_enabled):
handlers = []

Expand Down
2 changes: 2 additions & 0 deletions qpylib/qpylib.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ def create_log(syslog_enabled=True):

def log(message, level='INFO'):
''' Logs a message at the given level, which defaults to INFO.
Within the message string, any control characters such as tab
and newline will be suppressed.
Level values: DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL.
EXCEPTION is ERROR plus extra exception details.
Raises RuntimeError if logging was not previously initialised
Expand Down
9 changes: 9 additions & 0 deletions test/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,15 @@ def test_log_with_bad_level_raises_error(info_threshold, tmpdir):
with pytest.raises(ValueError, match="Unknown level: 'BAD'"):
qpylib.log('hello', 'BAD')

def test_message_with_control_chars(info_threshold, tmpdir):
log_path = os.path.join(tmpdir.strpath, 'app.log')
with patch('qpylib.log_qpylib._log_file_location') as mock_log_location:
mock_log_location.return_value = log_path
qpylib.create_log()
qpylib.log('This \r should all \n be on %0a one \t line')
verify_log_file_content(log_path, [
{'level': 'INFO', 'text': 'This \\r should all \\n be on %0a one \\t line'}])

def test_all_log_levels_with_manifest_info_threshold(info_threshold, tmpdir):
log_path = os.path.join(tmpdir.strpath, 'app.log')
with patch('qpylib.log_qpylib._log_file_location') as mock_log_location:
Expand Down

0 comments on commit 3a94157

Please sign in to comment.