summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoofar <toofar@spalge.com>2023-08-29 17:59:19 +1200
committertoofar <toofar@spalge.com>2023-08-29 17:59:19 +1200
commite467adac9cf5db4d56797a5f968358713f990dcc (patch)
tree19e4043a76e3c9703f1610b7b476d37a06e86ba1
parent36d399dc29c7161fe801bc54ddf9dcba3ff6cd44 (diff)
parent51aa7abe548ccaec66f64b08c4bdc9a3fcdba67f (diff)
downloadqutebrowser-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.py17
-rw-r--r--tests/unit/keyinput/test_basekeyparser.py20
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