Skip to content

Commit f8022c8

Browse files
committed
chore(iast): avoid exception when no relevant frame is found (#13346)
Follow up to #13272: - Avoid an exception when no relevant frame is found, return a tuple of `None` objects instead. This was a regression in #13272. (cherry picked from commit 2e2cb67)
1 parent d44f714 commit f8022c8

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

ddtrace/appsec/_iast/_stacktrace.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ get_file_and_line(PyObject* Py_UNUSED(module), PyObject* Py_UNUSED(args))
227227

228228
exit:
229229
FRAME_XDECREF(frame);
230+
if (!result) {
231+
result = PyTuple_Pack(4, Py_None, Py_None, Py_None, Py_None);
232+
}
233+
in_stacktrace = 0;
230234
return result;
231235
}
232236

ddtrace/appsec/_iast/taint_sinks/_base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ def report(cls, evidence_value: Text = "", dialect: Optional[Text] = None) -> No
129129
return None
130130

131131
file_name, line_number = frame_info
132+
if not file_name:
133+
return
132134

133135
file_name = cls._rel_path(file_name)
134136
if not file_name:
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env python3
2+
3+
import sys
4+
5+
import pytest
6+
7+
from ddtrace.appsec._iast._stacktrace import get_info_frame
8+
9+
10+
def test_stacktrace():
11+
file, line, function, class_ = get_info_frame()
12+
import traceback
13+
14+
traceback.print_stack()
15+
assert file is not None
16+
assert file.endswith("test_stacktrace.py")
17+
assert line is not None
18+
assert function == "test_stacktrace"
19+
assert class_ is not None
20+
21+
22+
async def test_stacktrace_async():
23+
async def _inner():
24+
return get_info_frame()
25+
26+
file, line, function, class_ = await _inner()
27+
assert file is not None
28+
assert file.endswith("test_stacktrace.py")
29+
assert line is not None
30+
assert function == "_inner"
31+
assert class_ is not None
32+
33+
34+
@pytest.mark.skipif(sys.version_info < (3, 9, 0), reason="Test compatible with Python 3.9+")
35+
async def test_stacktrace_async_no_relevant_frame():
36+
"""
37+
In the absence of any non-ddtrace and non-stdlib frame in the stacktrace, no frame is returned.
38+
(And no exception is raised).
39+
"""
40+
import asyncio
41+
42+
file, line, function, class_ = await asyncio.to_thread(get_info_frame)
43+
assert file is None
44+
assert line is None
45+
assert function is None
46+
assert class_ is None

0 commit comments

Comments
 (0)