Skip to content

Commit c6d7b67

Browse files
TartyThomas Dehghani
and
Thomas Dehghani
authored
fix(serializer): Add support for byterray and memoryview built-in types (#1833)
Both `bytearray` and `memoryview` built-in types weren't explicitly mentioned in the serializer logic, and as they are subtyping Sequence, this led their instances to be enumerated upon, and to be output as a list of bytes, byte per byte. In the case of `memoryview`, this could also lead to a segmentation fault if the memory referenced was already freed and unavailable to the process by then. By explicitly adding them as seralizable types, bytearray will be decoded as a string just like bytes, and memoryview will use its __repr__ method instead. Close GH-1829 Co-authored-by: Thomas Dehghani <thomas.dehghani@imc.com>
1 parent 20c25f2 commit c6d7b67

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

sentry_sdk/_compat.py

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
number_types = (int, long, float) # noqa
2727
int_types = (int, long) # noqa
2828
iteritems = lambda x: x.iteritems() # noqa: B301
29+
binary_sequence_types = (bytearray, memoryview)
2930

3031
def implements_str(cls):
3132
# type: (T) -> T
@@ -44,6 +45,7 @@ def implements_str(cls):
4445
number_types = (int, float) # type: Tuple[type, type]
4546
int_types = (int,)
4647
iteritems = lambda x: x.items()
48+
binary_sequence_types = (bytes, bytearray, memoryview)
4749

4850
def implements_str(x):
4951
# type: (T) -> T

sentry_sdk/serializer.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,14 @@
1515

1616
import sentry_sdk.utils
1717

18-
from sentry_sdk._compat import text_type, PY2, string_types, number_types, iteritems
18+
from sentry_sdk._compat import (
19+
text_type,
20+
PY2,
21+
string_types,
22+
number_types,
23+
iteritems,
24+
binary_sequence_types,
25+
)
1926

2027
from sentry_sdk._types import MYPY
2128

@@ -47,15 +54,15 @@
4754
# https://github.com/python/cpython/blob/master/Lib/collections/__init__.py#L49
4855
from collections import Mapping, Sequence, Set
4956

50-
serializable_str_types = string_types
57+
serializable_str_types = string_types + binary_sequence_types
5158

5259
else:
5360
# New in 3.3
5461
# https://docs.python.org/3/library/collections.abc.html
5562
from collections.abc import Mapping, Sequence, Set
5663

5764
# Bytes are technically not strings in Python 3, but we can serialize them
58-
serializable_str_types = (str, bytes)
65+
serializable_str_types = string_types + binary_sequence_types
5966

6067

6168
# Maximum length of JSON-serialized event payloads that can be safely sent
@@ -350,7 +357,7 @@ def _serialize_node_impl(
350357
if should_repr_strings:
351358
obj = safe_repr(obj)
352359
else:
353-
if isinstance(obj, bytes):
360+
if isinstance(obj, bytes) or isinstance(obj, bytearray):
354361
obj = obj.decode("utf-8", "replace")
355362

356363
if not isinstance(obj, string_types):

tests/test_serializer.py

+20
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import re
12
import sys
23
import pytest
34

@@ -62,6 +63,25 @@ def test_bytes_serialization_repr(message_normalizer):
6263
assert result == r"b'abc123\x80\xf0\x9f\x8d\x95'"
6364

6465

66+
def test_bytearray_serialization_decode(message_normalizer):
67+
binary = bytearray(b"abc123\x80\xf0\x9f\x8d\x95")
68+
result = message_normalizer(binary, should_repr_strings=False)
69+
assert result == "abc123\ufffd\U0001f355"
70+
71+
72+
@pytest.mark.xfail(sys.version_info < (3,), reason="Known safe_repr bugs in Py2.7")
73+
def test_bytearray_serialization_repr(message_normalizer):
74+
binary = bytearray(b"abc123\x80\xf0\x9f\x8d\x95")
75+
result = message_normalizer(binary, should_repr_strings=True)
76+
assert result == r"bytearray(b'abc123\x80\xf0\x9f\x8d\x95')"
77+
78+
79+
def test_memoryview_serialization_repr(message_normalizer):
80+
binary = memoryview(b"abc123\x80\xf0\x9f\x8d\x95")
81+
result = message_normalizer(binary, should_repr_strings=False)
82+
assert re.match(r"^<memory at 0x\w+>$", result)
83+
84+
6585
def test_serialize_sets(extra_normalizer):
6686
result = extra_normalizer({1, 2, 3})
6787
assert result == [1, 2, 3]

0 commit comments

Comments
 (0)