Skip to content

Commit 4b0070a

Browse files
committed
Remove use of "pickle.loads()" to comply with security tools (#563)
1 parent f2d5133 commit 4b0070a

2 files changed

Lines changed: 32 additions & 14 deletions

File tree

loguru/_recattrs.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,14 @@ def __repr__(self):
6464
return "(type=%r, value=%r, traceback=%r)" % (self.type, self.value, self.traceback)
6565

6666
def __reduce__(self):
67+
# The traceback is not picklable so we need to remove it. Also, some custom exception
68+
# values aren't picklable either. For user convenience, we try first to serialize it and
69+
# we remove the value in case or error. As an optimization, we could have re-used the
70+
# dumped value during unpickling, but this requires using "pickle.loads()" which is
71+
# flagged as insecure by some security tools.
6772
try:
68-
pickled_value = pickle.dumps(self.value)
73+
pickle.dumps(self.value)
6974
except pickle.PickleError:
7075
return (RecordException, (self.type, None, None))
7176
else:
72-
return (RecordException._from_pickled_value, (self.type, pickled_value, None))
73-
74-
@classmethod
75-
def _from_pickled_value(cls, type_, pickled_value, traceback_):
76-
try:
77-
value = pickle.loads(pickled_value)
78-
except pickle.PickleError:
79-
return cls(type_, None, traceback_)
80-
else:
81-
return cls(type_, value, traceback_)
77+
return (RecordException, (self.type, self.value, None))

tests/test_add_option_enqueue.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,7 @@ def slow_sink(message):
191191
assert err == "".join("%d\n" % i for i in range(10))
192192

193193

194-
@pytest.mark.parametrize("arg", [NotPicklable(), NotUnpicklable()])
195-
def test_logging_not_picklable_exception(arg):
194+
def test_logging_not_picklable_exception():
196195
exception = None
197196

198197
def sink(message):
@@ -202,7 +201,30 @@ def sink(message):
202201
logger.add(sink, enqueue=True, catch=False)
203202

204203
try:
205-
raise ValueError(arg)
204+
raise ValueError(NotPicklable())
205+
except Exception:
206+
logger.exception("Oups")
207+
208+
logger.remove()
209+
210+
type_, value, traceback_ = exception
211+
assert type_ is ValueError
212+
assert value is None
213+
assert traceback_ is None
214+
215+
216+
@pytest.mark.xfail(reason="No way to safely deserialize exception yet")
217+
def test_logging_not_unpicklable_exception():
218+
exception = None
219+
220+
def sink(message):
221+
nonlocal exception
222+
exception = message.record["exception"]
223+
224+
logger.add(sink, enqueue=True, catch=False)
225+
226+
try:
227+
raise ValueError(NotUnpicklable())
206228
except Exception:
207229
logger.exception("Oups")
208230

0 commit comments

Comments
 (0)