From 988a3f89049fd4626bc6bccf8a1d2a05def01ba4 Mon Sep 17 00:00:00 2001 From: Levi Morrison Date: Mon, 11 May 2026 15:04:29 -0600 Subject: [PATCH 1/6] Add SpanLink long origin regression test --- ...ce_span_link_from_headers_long_origin.phpt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt diff --git a/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt b/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt new file mode 100644 index 0000000000..077ba2b851 --- /dev/null +++ b/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt @@ -0,0 +1,29 @@ +--TEST-- +SpanLink::fromHeaders handles long tracestate origins +--DESCRIPTION-- +Formatting a propagated tracestate origin sanitizes the origin after appending +it to a smart_str. The sanitizer must not keep a pointer into the smart_str +across the append, because a long origin can reallocate the buffer before +sanitization. +--FILE-- + "00-0000000000000000000000000000002a-0000000000000001-01", + "tracestate" => "dd=o:" . $origin, +]); + +$traceState = $link->traceState; + +var_dump(strlen($traceState)); +var_dump(substr_count($traceState, "=")); +var_dump(substr_count($traceState, "~")); +var_dump($traceState === "dd=o:" . $origin); + +?> +--EXPECT-- +int(1005) +int(1) +int(1000) +bool(true) From 96140676818a5dbf1fb1519b1c1014776ae95c94 Mon Sep 17 00:00:00 2001 From: Levi Morrison Date: Mon, 11 May 2026 15:13:07 -0600 Subject: [PATCH 2/6] Fix SpanLink long origin tracestate formatting --- ext/handlers_http.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/handlers_http.h b/ext/handlers_http.h index 16c403c98c..61bdeec4d4 100644 --- a/ext/handlers_http.h +++ b/ext/handlers_http.h @@ -22,9 +22,10 @@ static inline zend_string *ddtrace_format_tracestate(zend_string *tracestate, ui smart_str_appendc(&str, ';'); } smart_str_appends(&str, "o:"); - signed char *cur = (signed char *)ZSTR_VAL(str.s) + ZSTR_LEN(str.s); + size_t origin_offset = ZSTR_LEN(str.s); smart_str_append(&str, origin); - for (signed char *end = (signed char *)ZSTR_VAL(str.s) + ZSTR_LEN(str.s); cur < end; ++cur) { + for (signed char *cur = (signed char *)ZSTR_VAL(str.s) + origin_offset, + *end = (signed char *)ZSTR_VAL(str.s) + ZSTR_LEN(str.s); cur < end; ++cur) { if (*cur == '=') { *cur = '~'; } else if (*cur < 0x20 || *cur == ',' || *cur == ';' || *cur == '~') { From 15316741386e7b00b593f75d0b6623a7109f521e Mon Sep 17 00:00:00 2001 From: Levi Morrison Date: Mon, 11 May 2026 15:54:14 -0600 Subject: [PATCH 3/6] Fix SpanLink long origin regression test --- ...ce_span_link_from_headers_long_origin.phpt | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt b/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt index 077ba2b851..ebeb254bbc 100644 --- a/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt +++ b/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt @@ -1,17 +1,20 @@ --TEST-- -SpanLink::fromHeaders handles long tracestate origins +SpanLink::fromHeaders handles long propagated origins --DESCRIPTION-- -Formatting a propagated tracestate origin sanitizes the origin after appending -it to a smart_str. The sanitizer must not keep a pointer into the smart_str -across the append, because a long origin can reallocate the buffer before -sanitization. +Formatting a propagated origin into tracestate sanitizes the origin after +appending it to a smart_str. The sanitizer must not keep a pointer into the +smart_str across the append, because a long origin can reallocate the buffer +before sanitization. +--ENV-- +DD_TRACE_PROPAGATION_STYLE_EXTRACT=datadog --FILE-- "00-0000000000000000000000000000002a-0000000000000001-01", - "tracestate" => "dd=o:" . $origin, + "x-datadog-trace-id" => "42", + "x-datadog-parent-id" => "1", + "x-datadog-origin" => $origin, ]); $traceState = $link->traceState; @@ -19,7 +22,7 @@ $traceState = $link->traceState; var_dump(strlen($traceState)); var_dump(substr_count($traceState, "=")); var_dump(substr_count($traceState, "~")); -var_dump($traceState === "dd=o:" . $origin); +var_dump($traceState === "dd=o:" . str_repeat("~", strlen($origin))); ?> --EXPECT-- From 1758562f5cd29064ed8c06439fb4df219a34b0d1 Mon Sep 17 00:00:00 2001 From: Levi Morrison Date: Mon, 11 May 2026 15:55:59 -0600 Subject: [PATCH 4/6] Make SpanLink long origin test config explicit --- ...istributed_trace_span_link_from_headers_long_origin.phpt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt b/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt index ebeb254bbc..a4601cabe0 100644 --- a/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt +++ b/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt @@ -5,8 +5,10 @@ Formatting a propagated origin into tracestate sanitizes the origin after appending it to a smart_str. The sanitizer must not keep a pointer into the smart_str across the append, because a long origin can reallocate the buffer before sanitization. ---ENV-- -DD_TRACE_PROPAGATION_STYLE_EXTRACT=datadog +--INI-- +datadog.trace.enabled=1 +datadog.trace.generate_root_span=0 +datadog.trace.propagation_style_extract=datadog --FILE-- Date: Mon, 11 May 2026 16:29:21 -0600 Subject: [PATCH 5/6] Relax SpanLink long origin length assertion --- ...ted_trace_span_link_from_headers_long_origin.phpt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt b/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt index a4601cabe0..3375f9b35a 100644 --- a/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt +++ b/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt @@ -20,15 +20,17 @@ $link = DDTrace\SpanLink::fromHeaders([ ]); $traceState = $link->traceState; +$traceStatePrefix = "dd=o:"; +$formattedOrigin = substr($traceState, strlen($traceStatePrefix)); -var_dump(strlen($traceState)); +var_dump(substr($traceState, 0, strlen($traceStatePrefix))); var_dump(substr_count($traceState, "=")); -var_dump(substr_count($traceState, "~")); -var_dump($traceState === "dd=o:" . str_repeat("~", strlen($origin))); +var_dump($formattedOrigin === str_repeat("~", strlen($formattedOrigin))); +var_dump(strlen($formattedOrigin) > 256); ?> --EXPECT-- -int(1005) +string(5) "dd=o:" int(1) -int(1000) +bool(true) bool(true) From 4a8928f75aa426336add4a0a2e86f6f796beed53 Mon Sep 17 00:00:00 2001 From: Levi Morrison Date: Mon, 11 May 2026 17:57:31 -0600 Subject: [PATCH 6/6] Clarify SpanLink origin sanitization pointer scope --- ext/handlers_http.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ext/handlers_http.h b/ext/handlers_http.h index 61bdeec4d4..b2ad4ff15e 100644 --- a/ext/handlers_http.h +++ b/ext/handlers_http.h @@ -24,12 +24,15 @@ static inline zend_string *ddtrace_format_tracestate(zend_string *tracestate, ui smart_str_appends(&str, "o:"); size_t origin_offset = ZSTR_LEN(str.s); smart_str_append(&str, origin); - for (signed char *cur = (signed char *)ZSTR_VAL(str.s) + origin_offset, - *end = (signed char *)ZSTR_VAL(str.s) + ZSTR_LEN(str.s); cur < end; ++cur) { - if (*cur == '=') { - *cur = '~'; - } else if (*cur < 0x20 || *cur == ',' || *cur == ';' || *cur == '~') { - *cur = '_'; + { + signed char *cur = (signed char *)ZSTR_VAL(str.s) + origin_offset; + signed char *end = (signed char *)ZSTR_VAL(str.s) + ZSTR_LEN(str.s); + for (; cur < end; ++cur) { + if (*cur == '=') { + *cur = '~'; + } else if (*cur < 0x20 || *cur == ',' || *cur == ';' || *cur == '~') { + *cur = '_'; + } } } }