Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ddtrace/appsec/_iast/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ def enable_iast_propagation():
from ddtrace.appsec._iast._ast.ast_patching import _should_iast_patch
from ddtrace.appsec._iast._loader import _exec_iast_patched_module
from ddtrace.appsec._iast._taint_tracking import initialize_native_state
from ddtrace.appsec._shared._stacktrace import get_info_frame # noqa: F401

global _iast_propagation_enabled
if _iast_propagation_enabled:
Expand Down
1 change: 0 additions & 1 deletion ddtrace/appsec/_iast/_stacktrace.pyi

This file was deleted.

14 changes: 9 additions & 5 deletions ddtrace/appsec/_patch_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@

log = get_logger(__name__)

# Lazy-cached reference to avoid loading _stacktrace (a C extension used only
# by IAST) when _patch_utils is imported by non-IAST code paths.
_get_info_frame = None

# Cached paths for relativizing file paths (computed once at import time).
_CWD = os.path.abspath(os.getcwd())
_PURELIB_PATH = sysconfig.get_path("purelib") or ""
Expand Down Expand Up @@ -52,12 +56,12 @@ def get_caller_frame_info() -> tuple:

Returns (None, None, None, None) when no relevant frame is found.
"""
try:
from ddtrace.appsec._iast._stacktrace import get_info_frame
except ImportError:
return None, None, None, None
global _get_info_frame
if _get_info_frame is None:
from ddtrace.appsec._shared._stacktrace import get_info_frame

frame_info = get_info_frame()
_get_info_frame = get_info_frame
frame_info = _get_info_frame()
if not frame_info or frame_info[0] in ("", -1, None):
return None, None, None, None

Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ static PyMethodDef StacktraceMethods[] = { { "get_info_frame",
{ NULL, NULL, 0, NULL } };

static struct PyModuleDef stacktrace = { PyModuleDef_HEAD_INIT,
"ddtrace.appsec._iast._stacktrace",
"ddtrace.appsec._shared._stacktrace",
"stacktrace module",
-1,
StacktraceMethods };
Expand Down
3 changes: 3 additions & 0 deletions ddtrace/appsec/_shared/_stacktrace.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from typing import Optional

def get_info_frame() -> tuple[Optional[str], Optional[int], Optional[str], Optional[str]]: ...
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -1275,9 +1275,9 @@ def get_exts_for(name):
if platform.system() not in ("Windows", ""):
ext_modules.append(
Extension(
"ddtrace.appsec._iast._stacktrace",
"ddtrace.appsec._shared._stacktrace",
sources=[
"ddtrace/appsec/_iast/_stacktrace.c",
"ddtrace/appsec/_shared/_stacktrace.c",
],
extra_compile_args=extra_compile_args + debug_compile_args + fast_build_args,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
MODULE_IAST_ONLY = [
"ddtrace.appsec._iast",
"ddtrace.appsec._iast._taint_tracking._native",
"ddtrace.appsec._shared._stacktrace",
]


Expand Down
2 changes: 1 addition & 1 deletion tests/appsec/iast/test_stacktrace.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python3

from ddtrace.appsec._iast._stacktrace import get_info_frame
from ddtrace.appsec._shared._stacktrace import get_info_frame


def test_stacktrace():
Expand Down
2 changes: 1 addition & 1 deletion tests/appsec/iast_memcheck/fixtures/stacktrace.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os

from ddtrace.appsec._iast._stacktrace import get_info_frame
from ddtrace.appsec._shared._stacktrace import get_info_frame


CWD = os.path.abspath(os.getcwd())
Expand Down
2 changes: 1 addition & 1 deletion tests/appsec/iast_memcheck/test_iast_mem_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
from ddtrace.appsec._iast._iast_request_context_base import _iast_finish_request
from ddtrace.appsec._iast._iast_request_context_base import _iast_start_request
from ddtrace.appsec._iast._iast_request_context_base import _num_objects_tainted_in_request
from ddtrace.appsec._iast._stacktrace import get_info_frame
from ddtrace.appsec._iast._taint_tracking import OriginType
from ddtrace.appsec._iast._taint_tracking._context import debug_context_array_size
from ddtrace.appsec._iast._taint_tracking._taint_objects import taint_pyobject
from ddtrace.appsec._iast._taint_tracking._taint_objects_base import get_tainted_ranges
from ddtrace.appsec._shared._stacktrace import get_info_frame
from tests.appsec.iast.iast_utils import _iast_patched_module
from tests.appsec.iast_memcheck.fixtures.stacktrace import func_1

Expand Down
32 changes: 6 additions & 26 deletions tests/appsec/integrations/flask_tests/test_iast_flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,6 @@ def sqli_14():
def test_flask_request_body(self):
@self.app.route("/sqli/body/", methods=("POST",))
def sqli_10():
import json
import sqlite3

from flask import request
Expand All @@ -740,10 +739,7 @@ def sqli_10():

con = sqlite3.connect(":memory:")
cur = con.cursor()
if flask_version > (2, 0):
json_data = request.json
else:
json_data = json.loads(request.data)
json_data = request.json
value = json_data.get("json_body")
assert value == "master"

Expand Down Expand Up @@ -807,10 +803,7 @@ def sqli_11():
con = sqlite3.connect(":memory:")
cur = con.cursor()

if flask_version > (2, 0):
json_data = request.json
else:
json_data = json.loads(request.data)
json_data = request.json
value = json_data.get("body").get("body2").get("body3")
assert value == "master"
assert is_pyobject_tainted(value)
Expand Down Expand Up @@ -873,10 +866,7 @@ def sqli_11():
con = sqlite3.connect(":memory:")
cur = con.cursor()

if flask_version > (2, 0):
json_data = request.json
else:
json_data = json.loads(request.data)
json_data = request.json
value = json_data.get("body").get("body2").get("body3")[3]
assert value == "master"
assert is_pyobject_tainted(value)
Expand Down Expand Up @@ -939,10 +929,7 @@ def sqli_11():
con = sqlite3.connect(":memory:")
cur = con.cursor()

if flask_version > (2, 0):
json_data = request.json
else:
json_data = json.loads(request.data)
json_data = request.json
value = json_data.get("body").get("body2").get("body3")[3].get("body4")
assert value == "master"
assert is_pyobject_tainted(value)
Expand Down Expand Up @@ -1018,10 +1005,7 @@ def iterate_json(data, parent_key=""):
else:
assert not is_pyobject_tainted(data), f"{parent_key}.{data} taint error"

if flask_version > (2, 0):
request_json = request.json
else:
request_json = json.loads(request.data)
request_json = request.json

iterate_json(request_json)

Expand Down Expand Up @@ -1139,7 +1123,6 @@ def test_flask_request_body_iast_and_appsec(self):

@self.app.route("/sqli/body/", methods=("POST",))
def sqli_10():
import json
import sqlite3

from flask import request
Expand All @@ -1148,10 +1131,7 @@ def sqli_10():

con = sqlite3.connect(":memory:")
cur = con.cursor()
if flask_version > (2, 0):
json_data = request.json
else:
json_data = json.loads(request.data)
json_data = request.json
value = json_data.get("json_body")
assert value == "master"

Expand Down
2 changes: 1 addition & 1 deletion tests/internal/test_serverless.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def test_not_azure_function():
"ddtrace.appsec._iast._ast.iastpatch",
"ddtrace.appsec._iast._taint_tracking._native",
"ddtrace.appsec._iast._taint_tracking._vendor",
"ddtrace.appsec._iast._stacktrace",
"ddtrace.appsec._shared._stacktrace",
"ddtrace.internal.datadog.profiling.libdd_wrapper",
"ddtrace.internal.datadog.profiling.ddup._ddup",
"ddtrace.internal.datadog.profiling.stack._stack",
Expand Down
Loading