diff options
author | toofar <toofar@spalge.com> | 2023-08-29 17:59:19 +1200 |
---|---|---|
committer | toofar <toofar@spalge.com> | 2023-08-29 17:59:19 +1200 |
commit | e467adac9cf5db4d56797a5f968358713f990dcc (patch) | |
tree | 19e4043a76e3c9703f1610b7b476d37a06e86ba1 | |
parent | 36d399dc29c7161fe801bc54ddf9dcba3ff6cd44 (diff) | |
parent | 51aa7abe548ccaec66f64b08c4bdc9a3fcdba67f (diff) | |
download | qutebrowser-e467adac9cf5db4d56797a5f968358713f990dcc.tar.gz qutebrowser-e467adac9cf5db4d56797a5f968358713f990dcc.zip |
Merge pull request #7834 from pylbrecht/purrr
Enforce digit limit (4300) on Count values passed by keypresses to avoid
segfaults due to cats sleeping on numpads.
-rw-r--r-- | qutebrowser/keyinput/basekeyparser.py | 17 | ||||
-rw-r--r-- | tests/unit/keyinput/test_basekeyparser.py | 20 |
2 files changed, 33 insertions, 4 deletions
diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py index 8c8ca4613..df6b66f7f 100644 --- a/qutebrowser/keyinput/basekeyparser.py +++ b/qutebrowser/keyinput/basekeyparser.py @@ -7,13 +7,14 @@ import string import types import dataclasses +import traceback from typing import Mapping, MutableMapping, Optional, Sequence from qutebrowser.qt.core import QObject, pyqtSignal from qutebrowser.qt.gui import QKeySequence, QKeyEvent from qutebrowser.config import config -from qutebrowser.utils import log, usertypes, utils +from qutebrowser.utils import log, usertypes, utils, message from qutebrowser.keyinput import keyutils @@ -189,7 +190,7 @@ class BaseKeyParser(QObject): passthrough=self.passthrough, supports_count=self._supports_count) - def _debug_log(self, message: str) -> None: + def _debug_log(self, msg: str) -> None: """Log a message to the debug log if logging is active. Args: @@ -198,7 +199,7 @@ class BaseKeyParser(QObject): if self._do_log: prefix = '{} for mode {}: '.format(self.__class__.__name__, self._mode.name) - log.keyboard.debug(prefix + message) + log.keyboard.debug(prefix + msg) def _match_key(self, sequence: keyutils.KeySequence) -> MatchResult: """Try to match a given keystring with any bound keychain. @@ -315,7 +316,15 @@ class BaseKeyParser(QObject): assert result.command is not None self._debug_log("Definitive match for '{}'.".format( result.sequence)) - count = int(self._count) if self._count else None + + try: + count = int(self._count) if self._count else None + except ValueError as err: + message.error(f"Failed to parse count: {err}", + stack=traceback.format_exc()) + self.clear_keystring() + return + self.clear_keystring() self.execute(result.command, count) elif result.match_type == QKeySequence.SequenceMatch.PartialMatch: diff --git a/tests/unit/keyinput/test_basekeyparser.py b/tests/unit/keyinput/test_basekeyparser.py index 68239d4b4..ec7c225bf 100644 --- a/tests/unit/keyinput/test_basekeyparser.py +++ b/tests/unit/keyinput/test_basekeyparser.py @@ -4,6 +4,9 @@ """Tests for BaseKeyParser.""" +import logging +import re +import sys from unittest import mock from qutebrowser.qt.core import Qt @@ -342,3 +345,20 @@ def test_respect_config_when_matching_counts(keyparser, config_stub): assert not keyparser._sequence assert not keyparser._count + + +def test_count_limit_exceeded(handle_text, keyparser, caplog): + try: + max_digits = sys.get_int_max_str_digits() + except AttributeError: + pytest.skip('sys.get_int_max_str_digits() not available') + + keys = (max_digits + 1) * [Qt.Key.Key_1] + + with caplog.at_level(logging.ERROR): + handle_text(keyparser, *keys, Qt.Key.Key_B, Qt.Key.Key_A) + + pattern = re.compile(r"^Failed to parse count: Exceeds the limit .* for integer string conversion: .*") + assert any(pattern.fullmatch(msg) for msg in caplog.messages) + assert not keyparser._sequence + assert not keyparser._count |