Add debugging attributes to `ssh_agent.TrailingDataError`
Marco Ricci

Marco Ricci commited on 2025-12-27 14:43:35
Zeige 1 geänderte Dateien mit 23 Einfügungen und 2 Löschungen.


The old implementation did not record *which* trailing data we were
seeing, on the grounds that well-behaved SSH agents would not send any
trailing data anyway (i.e., that this error condition was a failsafe).
However, while implementing Windows named pipe support, I observed
Pageant sporadically returning malformed responses that trigger this
error.  Without actually recording the trailing data, it is hard to
understand whether this is Pageant's fault (unlikely) or ours (more
likely), and specifically, whether we're implementing the protocol
incorrectly (unlikely), or rather the communication channel (much more
likely).  So the `TrailingDataError` class now optionally records the
actual raw response and the trailing data portion that caused the error,
to aid debugging.
... ...
@@ -36,8 +36,27 @@ HEAD_LEN = 4
36 36
 class TrailingDataError(RuntimeError):
37 37
     """The result contained trailing data."""
38 38
 
39
-    def __init__(self) -> None:
39
+    def __init__(
40
+        self, raw: bytes | bytearray = b"", trailing: bytes | bytearray = b""
41
+    ) -> None:
40 42
         super().__init__("Overlong response from SSH agent")
43
+        self.raw = bytes(raw)
44
+        self.trailing = bytes(trailing)
45
+
46
+    def __str__(self) -> str:  # pragma: no cover [debug]
47
+        if self.raw or self.trailing:
48
+            return (
49
+                f"Overlong response from SSH agent: "
50
+                f"raw = {self.raw!r}, trailing = {self.trailing!r}"
51
+            )
52
+        return super().__str__()
53
+
54
+    def __repr__(self) -> str:  # pragma: no cover [debug]
55
+        """"""  # noqa: D419
56
+        return (
57
+            f"{self.__class__.__name__}"
58
+            f"(raw={self.raw!r}, trailing={self.trailing!r})"
59
+        )
41 60
 
42 61
 
43 62
 class SSHAgentFailedError(RuntimeError):
... ...
@@ -575,7 +594,9 @@ class SSHAgentClient:
575 594
             # Both `key` and `comment` are not wrapped as SSH strings.
576 595
             keys.append(_types.SSHKeyCommentPair(key, comment))
577 596
         if response_stream:
578
-            raise TrailingDataError
597
+            raise TrailingDataError(
598
+                raw=response, trailing=bytes(response_stream)
599
+            )
579 600
         return keys
580 601
 
581 602
     def sign(
582 603