diff --git a/ext/handlers_http.h b/ext/handlers_http.h index 16c403c98c..b2ad4ff15e 100644 --- a/ext/handlers_http.h +++ b/ext/handlers_http.h @@ -22,13 +22,17 @@ 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) { - 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 = '_'; + } } } } 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..3375f9b35a --- /dev/null +++ b/tests/ext/distributed_tracing/distributed_trace_span_link_from_headers_long_origin.phpt @@ -0,0 +1,36 @@ +--TEST-- +SpanLink::fromHeaders handles long propagated origins +--DESCRIPTION-- +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. +--INI-- +datadog.trace.enabled=1 +datadog.trace.generate_root_span=0 +datadog.trace.propagation_style_extract=datadog +--FILE-- + "42", + "x-datadog-parent-id" => "1", + "x-datadog-origin" => $origin, +]); + +$traceState = $link->traceState; +$traceStatePrefix = "dd=o:"; +$formattedOrigin = substr($traceState, strlen($traceStatePrefix)); + +var_dump(substr($traceState, 0, strlen($traceStatePrefix))); +var_dump(substr_count($traceState, "=")); +var_dump($formattedOrigin === str_repeat("~", strlen($formattedOrigin))); +var_dump(strlen($formattedOrigin) > 256); + +?> +--EXPECT-- +string(5) "dd=o:" +int(1) +bool(true) +bool(true)