From 4f1c4e68dd4f9ce77458fc816c499f8e9a14a96a Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 20 May 2026 10:27:32 +0200 Subject: [PATCH 1/6] fix(serializer): Do not __iter__ arbitrary sequences --- sentry_sdk/serializer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/serializer.py b/sentry_sdk/serializer.py index f9afbe8fd0..98b3725585 100644 --- a/sentry_sdk/serializer.py +++ b/sentry_sdk/serializer.py @@ -1,6 +1,6 @@ import math import sys -from collections.abc import Mapping, Sequence, Set +from collections.abc import Mapping from datetime import datetime from typing import TYPE_CHECKING @@ -53,7 +53,7 @@ def add_global_repr_processor(processor: "ReprProcessor") -> None: global_repr_processors.append(processor) -sequence_types: "List[type]" = [Sequence, Set] +sequence_types: "List[type]" = [tuple, list, set] def add_repr_sequence_type(ty: type) -> None: From 0251841a17946ed61cb0b7f552cc30158b16e61e Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 20 May 2026 10:50:27 +0200 Subject: [PATCH 2/6] add frozenset --- sentry_sdk/serializer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/serializer.py b/sentry_sdk/serializer.py index 98b3725585..99097f425e 100644 --- a/sentry_sdk/serializer.py +++ b/sentry_sdk/serializer.py @@ -53,7 +53,7 @@ def add_global_repr_processor(processor: "ReprProcessor") -> None: global_repr_processors.append(processor) -sequence_types: "List[type]" = [tuple, list, set] +sequence_types: "List[type]" = [tuple, list, set, frozenset] def add_repr_sequence_type(ty: type) -> None: From 29fc6478c8af9736fdbcbfc94dc1f7f4cbe5e3fd Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 20 May 2026 11:03:10 +0200 Subject: [PATCH 3/6] bytes --- sentry_sdk/serializer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/serializer.py b/sentry_sdk/serializer.py index 99097f425e..78b8b51937 100644 --- a/sentry_sdk/serializer.py +++ b/sentry_sdk/serializer.py @@ -53,7 +53,7 @@ def add_global_repr_processor(processor: "ReprProcessor") -> None: global_repr_processors.append(processor) -sequence_types: "List[type]" = [tuple, list, set, frozenset] +sequence_types: "List[type]" = [tuple, list, set, frozenset, bytes] def add_repr_sequence_type(ty: type) -> None: From 254c780d01c85abe3ef075d625f27f2a5e4b4f73 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 20 May 2026 11:25:23 +0200 Subject: [PATCH 4/6] test --- tests/test_serializer.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 9d75f73d96..9e3534b3ad 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -180,3 +180,39 @@ def test_max_value_length(body_normalizer): result = body_normalizer(data, max_value_length=max_value_length) assert len(result["key"]) == max_value_length + + +def test_serialize_local_vars(): + # This was added to make sure we don't try to iterate over instances of + # custom classes with an __iter__ method due to potential side effects + class Custom: + def __init__(self, items): + self.items = items + + def __len__(self): + return self.items.__len__() + + def __getitem__(self, item): + return self.items.__getitem__(item) + + def __iter__(self): + raise ValueError + + local_vars = { + "str": "123", + "bytes": b"123", + "list": [1, 2, 3], + "set": {1, 2, 3}, + "frozenset": frozenset([1, 2, 3]), + "custom": Custom([1, 2, 3]), + } + + result = serialize(local_vars, is_vars=True) + assert result["str"] == "'123'" + assert result["bytes"] == "b'123'" + assert result["list"] == ["1", "2", "3"] + assert result["set"] == ["1", "2", "3"] + assert result["frozenset"] == ["1", "2", "3"] + assert result["custom"].startswith( + ".Custom object at" + ) From bffd71ce48cebfa7d6f252765508248383a3c428 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 20 May 2026 12:32:50 +0200 Subject: [PATCH 5/6] remove bytes, add array --- sentry_sdk/serializer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sentry_sdk/serializer.py b/sentry_sdk/serializer.py index 78b8b51937..405ea6f105 100644 --- a/sentry_sdk/serializer.py +++ b/sentry_sdk/serializer.py @@ -1,5 +1,6 @@ import math import sys +from array import array from collections.abc import Mapping from datetime import datetime from typing import TYPE_CHECKING @@ -53,7 +54,7 @@ def add_global_repr_processor(processor: "ReprProcessor") -> None: global_repr_processors.append(processor) -sequence_types: "List[type]" = [tuple, list, set, frozenset, bytes] +sequence_types: "List[type]" = [tuple, list, set, frozenset, array] def add_repr_sequence_type(ty: type) -> None: From 30f9d74d2059a84bd2a6fa5393e716dbf24e46e8 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 20 May 2026 12:35:40 +0200 Subject: [PATCH 6/6] . --- tests/test_serializer.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 9e3534b3ad..f1483aba8d 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -1,4 +1,5 @@ import re +from array import array import pytest @@ -204,6 +205,7 @@ def __iter__(self): "list": [1, 2, 3], "set": {1, 2, 3}, "frozenset": frozenset([1, 2, 3]), + "array": array("l", [1, 2, 3]), "custom": Custom([1, 2, 3]), } @@ -211,8 +213,9 @@ def __iter__(self): assert result["str"] == "'123'" assert result["bytes"] == "b'123'" assert result["list"] == ["1", "2", "3"] - assert result["set"] == ["1", "2", "3"] - assert result["frozenset"] == ["1", "2", "3"] + assert sorted(result["set"]) == ["1", "2", "3"] + assert sorted(result["frozenset"]) == ["1", "2", "3"] + assert result["array"] == ["1", "2", "3"] assert result["custom"].startswith( ".Custom object at" )