Skip to content

fix(obfuscation/http): fuzzer fixes [APMSP-2670]#1684

Open
Eldolfin wants to merge 60 commits intomainfrom
oscarld/obfuscation-http-parity
Open

fix(obfuscation/http): fuzzer fixes [APMSP-2670]#1684
Eldolfin wants to merge 60 commits intomainfrom
oscarld/obfuscation-http-parity

Conversation

@Eldolfin
Copy link
Contributor

@Eldolfin Eldolfin commented Mar 6, 2026

What does this PR do?

Ran a fuzzer to find output difference between this obfuscator and the agent's obfuscator, fixed issues one by one, even the nonsensical edge cases.

Motivation

Reach 100% parity between obfuscation libs.

Additional Notes

Anything else we should know when reviewing?

How to test the change?

Here is the list of input that are fixed in this PR (one per line). These are obviously not correct urls but we need to get the exact same outputs as the agent even in these cases.

 ჸ
!
!#ჸ
!?ჸ
!ჸ
#
#!ჸ
##
#%
#'ჸ
#\u0001
#\u0001ჸ
#ჸ
%
%
%30ჸ
%802
.
.#
.#ჸ
../ჸ
/ჸ
0
:
:
:#\u0001
<!
?#
?#ჸ
?#ჸ
?ჸ
?ჸ#ჸ
A:ჸ
C:#
C:\u0001
[ჸ
\"!
\\
\\ჸ
\u0001
\u0001C:
\u0010
\u0010ჸ
ჸ
ჸ#
ჸ#!
ჸ#%
ჸ#%\u0001
ჸ#'ჸ
ჸ#0
ჸ#\u0010
􅙐%񭯐𵲸󴛏񾰻#󹱐ꦿ𔳕�𭄄!!࡫󃩐ۓ򹏤􂆮͡􏃁􏿯(࡫\u0002󃩐ۓ򹏤􂆮ߤꬃ
ჸ?#
ჸ?%
ჸ?ჸ
򑲸򒌯झ񄶰#\u0003\n񛭐򒗙򒗕򒗕򒗕򒗕䕞򚜍𽋿􎽏򇌇\u0006􎼊�򭟥̿筚͡➑\u0002{􍸓��'
򑲸򒌯झ񄶰#\u0003\n񛭐򒗙򒗕򒗕򒗕򒗕䕞򚜍𽋿􎽏򇌇\u0006􎼊�򭟥̿筚͡➑\u0002{􍸓��'
򑲸򒌯झ񄶰#\u0003\n񛭐򒗙򒗕򒗕򒗕򒗕䕞򚜍𽋿􎽏򇌇\u0006􎼊�򭟥̿筚͡➑\u0002{􍸓��'

@Eldolfin Eldolfin requested a review from Copilot March 6, 2026 16:05
@github-actions
Copy link

github-actions bot commented Mar 6, 2026

Clippy Allow Annotation Report

Comparing clippy allow annotations between branches:

  • Base Branch: origin/main
  • PR Branch: origin/oscarld/obfuscation-http-parity

Summary by Rule

Rule Base Branch PR Branch Change
unwrap_used 1 0 ✅ -1 (-100.0%)
Total 1 0 ✅ -1 (-100.0%)

Annotation Counts by File

File Base Branch PR Branch Change
libdd-trace-obfuscation/src/http.rs 1 0 ✅ -1 (-100.0%)

Annotation Stats by Crate

Crate Base Branch PR Branch Change
clippy-annotation-reporter 5 5 No change (0%)
datadog-ffe-ffi 1 1 No change (0%)
datadog-ipc 28 28 No change (0%)
datadog-live-debugger 6 6 No change (0%)
datadog-live-debugger-ffi 10 10 No change (0%)
datadog-profiling-replayer 4 4 No change (0%)
datadog-remote-config 3 3 No change (0%)
datadog-sidecar 59 59 No change (0%)
libdd-common 10 10 No change (0%)
libdd-common-ffi 12 12 No change (0%)
libdd-data-pipeline 5 5 No change (0%)
libdd-ddsketch 2 2 No change (0%)
libdd-dogstatsd-client 1 1 No change (0%)
libdd-profiling 13 13 No change (0%)
libdd-telemetry 19 19 No change (0%)
libdd-tinybytes 4 4 No change (0%)
libdd-trace-normalization 2 2 No change (0%)
libdd-trace-obfuscation 9 8 ✅ -1 (-11.1%)
libdd-trace-utils 15 15 No change (0%)
Total 208 207 ✅ -1 (-0.5%)

About This Report

This report tracks Clippy allow annotations for specific rules, showing how they've changed in this PR. Decreasing the number of these annotations generally improves code quality.

Eldolfin added 12 commits March 6, 2026 17:09
Go's url.Parse rejects bare '%' and other invalid percent-encoding
sequences, returning an error which causes obfuscateURLString to
return "?". The url crate silently re-encodes them as '%25', so
add an explicit pre-check matching Go's behavior.

Fixes fuzzing testcase: http_fuzzing_594901251
Go's url.Parse stores "." and ".." path segments literally, while the
url crate's join() resolves them via RFC 3986 normalization (making them
empty after stripping the base). Return the original input when
go_like_reference returns empty for a non-empty input that already
passed all error checks (control chars, invalid percent-encoding).

Fixes fuzzing testcase: http_fuzzing_3638045804
Go's url.Parse succeeds for relative URLs (like "0") and applies
path-digit removal to them. The Rust code was returning early from
the go_like_reference path without applying digit removal.

Add remove_relative_path_digits() helper and call it for relative URL
results when remove_path_digits=true.

Fixes fuzzing testcase: http_fuzzing_1928485962
…URLs

Go's url.shouldEscape for encodePath does not allow !, ', (, ), * even though
RFC 3986 considers them valid sub-delimiters in path segments. The url crate
follows RFC 3986 and keeps them unencoded. Post-process go_like_reference
output to encode these characters to match Go's behavior.

Fixes fuzzing testcase: http_fuzzing_4273565798
Go's validEncoded() has an explicit allowlist for !, ', (, ), * so these
are only re-encoded when the path has non-ASCII chars (which forces Go to
call escape() instead of using RawPath). For pure-ASCII inputs, Go's
EscapedPath() returns the RawPath unchanged, keeping ! as-is.

Only apply encode_go_path_chars() when the original input contains non-ASCII.

Fixes fuzzing testcase: http_fuzzing_1457007156
Go's url.Parse percent-encodes non-ASCII chars in fragments (e.g., '#ჸ' →
'#%E1%83%B8'). Our early-return fragment handler was returning the raw
fragment without encoding. Delegate non-empty fragments to go_like_reference
which uses the url crate's join() to correctly encode them.

Fixes fuzzing testcase: http_fuzzing_1092426409
…e error)

Go's url.Parse rejects ":" (missing protocol scheme) and "1:b" (first path
segment cannot contain colon per RFC 3986 §4.2). The url crate accepts them
as path characters. Add an explicit check to return "?" for these inputs.

Fixes fuzzing testcase: http_fuzzing_3119724369
Go's url.Parse percent-encodes control chars in fragments (e.g., '#\x01' →
'#%01'). The url crate silently drops them from fragments, returning '#'.
Pre-encode control bytes in the fragment manually before passing to
go_like_reference via base.join().

Fixes fuzzing testcase: http_fuzzing_1323831861
The previous fix iterated bytes and used 'b as char' which converts u8 to
a Unicode scalar, corrupting multi-byte sequences like Georgian ჸ.
Iterate over chars instead to preserve multi-byte Unicode correctly.

Fixes fuzzing testcase: http_fuzzing_35626170
@github-actions
Copy link

github-actions bot commented Mar 6, 2026

📚 Documentation Check Results

⚠️ 520 documentation warning(s) found

📦 libdd-trace-obfuscation - 520 warning(s)


Updated: 2026-03-09 17:50:25 UTC | Commit: 41a7f6e | missing-docs job results

Eldolfin added 14 commits March 6, 2026 17:09
Go's shouldEscape always encodes '\', '^', '{', '}', '|', '<', '>', '`',
and ' ' in paths (they're not in validEncoded's allowlist). The url crate
keeps them unencoded. Separate from the '!'-etc. class which are only
encoded when non-ASCII chars trigger the escape() fallback.

Fixes fuzzing testcase: http_fuzzing_618280270
Like '!', '\'', '(', ')', '*', the '[' and ']' characters are in Go's
validEncoded allowlist but get encoded when escape() is called due to
non-ASCII chars in the path.

Fixes fuzzing testcase: http_fuzzing_1505427946
…ath split

The url crate treats '\' as a path separator, consuming it silently.
Go treats '\' as a path character and encodes it as '%5C'.
Pre-encode '\' as '%5C' before calling go_like_reference so base.join()
preserves it rather than using it as a path segment separator.

Fixes fuzzing testcase: http_fuzzing_backslash_unicode
…ring()

Go's url.URL.String() omits a bare '#' with no fragment content.
The url crate keeps it. Strip trailing '#' from go_like_reference results.

Fixes fuzzing testcase: http_fuzzing_2438023093
… ! etc.

When determining whether to encode !, ', (, ), *, [, ] (Cat2 chars),
only check the path portion (before '#') for non-ASCII bytes.
A non-ASCII character in the fragment does not trigger Go's escape()
fallback for the path, so the path chars should stay unencoded.

Fixes fuzzing testcase: http_fuzzing_2729083127
…eference

For input '/ჸ', base.join('/ჸ') resolves to 'https://example.invalid/%E1%83%B8'.
Stripping base_prefix='https://example.invalid/' (with trailing slash) drops
the leading '/'. For inputs starting with '/', use the no-trailing-slash strip
to preserve the leading '/' in the output.

Fixes fuzzing testcase: http_fuzzing_slash_unicode
Go's shouldEscape('#', encodeFragment) returns true, so '#' within a fragment
is encoded as '%23'. The url crate keeps it raw. For input '##', Go returns
'#%23' (second '#' encoded). Pre-encode '#' in fragment content.

Fixes fuzzing testcase: http_fuzzing_3710129001
Go's url.Parse rejects control chars in the PATH (returning '?') but
percent-encodes them in the FRAGMENT. Only check path portion (before '#')
for control char rejection. Pre-encode control chars in the fragment before
calling go_like_reference.

Fixes fuzzing testcase: http_fuzzing_1009954227
encode_go_path_chars was operating on the whole URL string including fragment.
Go's encodeFragment mode allows '!', '(', ')', '*' (shouldEscape returns false).
Stop path-char encoding at '#' so the fragment portion is preserved unchanged.

Fixes fuzzing testcase: http_fuzzing_hash_exclamation
Go's url.Parse rejects invalid percent-encoding sequences even in the
fragment portion. Add the same check to the fragment handler.

Fixes fuzzing testcase: http_fuzzing_578834728
Go's escape() for encodeFragment encodes these chars (they're in validEncoded's
allowlist but not in shouldEscape's 'return false' cases). When non-ASCII
chars trigger the escape() fallback, these also get encoded. Pre-encode them
in the fragment when non-ASCII is detected.

Fixes fuzzing testcase: http_fuzzing_3991369296
…CII fragment

When the URL has non-ASCII chars in the fragment, Go's escape() also encodes
cat2 chars (!, ', (, ), *, [, ]) in the fragment. Apply the same encoding to
the result's fragment portion when the original URL's fragment had non-ASCII.

Fixes fuzzing testcase: http_fuzzing_path_frag_quote
…n-ASCII present

Go's shouldEscape for encodeFragment returns false for \! ( ) * explicitly,
so those are NOT encoded even when escape() is triggered by non-ASCII.
Only ' [ ] (in validEncoded allowlist but not shouldEscape's return-false)
get encoded when non-ASCII chars trigger the escape() fallback.
Eldolfin added 6 commits March 6, 2026 17:09
For URLs starting with '?' that have a fragment (e.g. '?#ჸ'),
Go's url.URL.String() percent-encodes non-ASCII chars in the fragment
via EscapeFragment. Also, Go omits an empty trailing fragment ('?#' → '?').

Handle these cases early before the 'restore original query' pass
which would otherwise undo the encoding.
The restore-original-query pass was splicing &url[q_start..] which
includes any trailing '#' (empty fragment), overriding the empty-fragment
stripping done by go_like_reference. Now only restores up to '#', and
appends the (already-encoded/stripped) fragment from go_like_reference.
Go's url.Parse decodes %XX sequences where the decoded byte is an
unreserved char (A-Z, a-z, 0-9, -, ., _, ~) as part of path normalization.
E.g. %30 → 0, %41 → A. The url crate preserves them as-is.

Add normalize_pct_encoded_unreserved() and apply it in go_like_reference
on the path portion of all returned values.
Go's url.Parse first splits on '#', then parses the pre-fragment
portion. If that portion starts with ':' (empty scheme), getScheme
returns "missing protocol scheme" and ObfuscateURLString returns '?'.

The Rust code had a check for ':' in the first path segment, but it
was placed after the CTL-in-fragment pre-encode block which returned
early, so inputs like ":#<ctrl>" bypassed the check.

Move the colon check to before the CTL-in-fragment block so it fires
regardless of what the fragment contains.

Fixes parity for input ":#\u{1}" (http_fuzzing_4114246193).
@Eldolfin Eldolfin force-pushed the oscarld/obfuscation-http-parity branch from 694c677 to 43100ec Compare March 6, 2026 16:10
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to reach parity with Go’s URL parsing/serialization behavior for obfuscation by adding Go-specific normalization, encoding, and edge-case handling found via fuzzing.

Changes:

  • Added Go-like URL reference parsing fallback and percent-encoding/normalization helpers.
  • Expanded obfuscation logic to mirror Go’s handling of control chars, fragments, opaque URIs, and query preservation.
  • Added many fuzz/regression tests for parity edge cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


// Try absolute first (like "https://...", "mailto:...", etc.)
if let Ok(abs) = Url::parse(input) {
return abs.to_string();
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go_like_reference normalizes percent-encoded unreserved chars for relative references via normalize_pct_encoded_unreserved, but absolute URLs return abs.to_string() without that normalization. This likely breaks the stated parity goal for inputs like https://h/%41 (Go emits .../A). Consider applying normalize_pct_encoded_unreserved (path-only) to the absolute serialization as well (while leaving query/fragment untouched per your helper’s semantics).

Suggested change
return abs.to_string();
// For absolute URLs, apply the same Go-like normalization to the path portion
// as we do for relative references. Keep query and fragment unchanged.
let s = abs.to_string();
if let Some(scheme_sep) = s.find("://") {
let after_scheme = scheme_sep + 3;
if let Some(rel_path_pos) = s[after_scheme..].find('/') {
let path_start = after_scheme + rel_path_pos;
let (prefix, path_and_rest) = s.split_at(path_start);
let normalized = normalize_pct_encoded_unreserved(path_and_rest);
return format!("{prefix}{normalized}");
}
}
// Non-hierarchical URLs or ones without a clear path are returned as-is.
return s;

Copilot uses AI. Check for mistakes.
Comment on lines +75 to +87
// Category 1: always encoded (not in validEncoded's explicit allowlist)
'\\' | '^' | '{' | '}' | '|' | '<' | '>' | '`' | ' ' => {
encoded.push('%');
encoded.push_str(&format!("{:02X}", c as u8));
}
// Category 2: encoded only when escape() fallback (handled by caller check)
// These are in Go's validEncoded allowlist but get encoded when escape() is called
'!' | '\'' | '(' | ')' | '*' | '[' | ']' => {
encoded.push('%');
encoded.push_str(&format!("{:02X}", c as u8));
}
_ => encoded.push(c),
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Later logic treats '"' as a Category 1 character (has_cat1 includes it), but encode_go_path_chars (and the ASCII-only encoding branch) never encode ". This creates an inconsistent state where needs_full_encoding is triggered by ", but the expected encoding transformation won’t happen. Add '"' to the encoding match arms where Category 1 characters are percent-encoded.

Copilot uses AI. Check for mistakes.
Comment on lines +367 to +395
let raw = if raw.ends_with('#') { raw[..raw.len()-1].to_string() } else { raw };
let result = if raw.is_empty() && !url.is_empty() { url.to_string() } else { raw };
let path_end_for_ascii = url.find(['?', '#']).unwrap_or(url.len());
let has_non_ascii = url[..path_end_for_ascii].bytes().any(|b| b > 127);
let result = if has_non_ascii { encode_go_path_chars(&result) } else {
let qs = result.find('?').unwrap_or(result.len());
let pp = &result[..qs]; let rr = &result[qs..];
let mut enc = String::with_capacity(pp.len()); let mut changed = false;
for c in pp.chars() { match c { '\\' | '^' | '{' | '}' | '|' | '<' | '>' | '`' | ' ' => { enc.push('%'); enc.push_str(&format!("{:02X}", c as u8)); changed = true; } _ => enc.push(c), } }
if changed { if rr.is_empty() { enc } else { format!("{enc}{rr}") } } else { result }
};
// Also encode Cat1 and (when frag has non-ASCII) Cat2 in the result's fragment
let orig_frag_has_non_ascii = url[url.find('#').map(|i|i+1).unwrap_or(url.len())..].bytes().any(|b| b > 127);
let result = if let Some(fs) = result.find('#') {
let (ph, fr) = result.split_at(fs);
let fr_inner = &fr[1..];
let needs = fr_inner.chars().any(|c| matches!(c, '{' | '}' | '|' | '^' | '`' | '\\' | '<' | '>' | ' '))
|| (orig_frag_has_non_ascii && fr_inner.chars().any(|c| matches!(c, '\'' | '[' | ']')));
if needs {
let mut out = ph.to_string(); out.push('#');
for c in fr_inner.chars() {
if matches!(c, '{' | '}' | '|' | '^' | '`' | '\\' | '<' | '>' | ' ')
|| (orig_frag_has_non_ascii && matches!(c, '\'' | '[' | ']'))
{ out.push_str(&format!("%{:02X}", c as u8)); }
else { out.push(c); }
}
out
} else { result }
} else { result };
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block compresses multiple statements and nested control flow onto single lines, which makes the logic hard to audit and increases the risk of subtle parity regressions. Please reformat this into conventional multi-line Rust and strongly consider extracting this repeated “encode category-1 chars in path-part” logic into a small helper (you already have encode_go_path_chars, and the ASCII-only variant could be another helper).

Suggested change
let raw = if raw.ends_with('#') { raw[..raw.len()-1].to_string() } else { raw };
let result = if raw.is_empty() && !url.is_empty() { url.to_string() } else { raw };
let path_end_for_ascii = url.find(['?', '#']).unwrap_or(url.len());
let has_non_ascii = url[..path_end_for_ascii].bytes().any(|b| b > 127);
let result = if has_non_ascii { encode_go_path_chars(&result) } else {
let qs = result.find('?').unwrap_or(result.len());
let pp = &result[..qs]; let rr = &result[qs..];
let mut enc = String::with_capacity(pp.len()); let mut changed = false;
for c in pp.chars() { match c { '\\' | '^' | '{' | '}' | '|' | '<' | '>' | '`' | ' ' => { enc.push('%'); enc.push_str(&format!("{:02X}", c as u8)); changed = true; } _ => enc.push(c), } }
if changed { if rr.is_empty() { enc } else { format!("{enc}{rr}") } } else { result }
};
// Also encode Cat1 and (when frag has non-ASCII) Cat2 in the result's fragment
let orig_frag_has_non_ascii = url[url.find('#').map(|i|i+1).unwrap_or(url.len())..].bytes().any(|b| b > 127);
let result = if let Some(fs) = result.find('#') {
let (ph, fr) = result.split_at(fs);
let fr_inner = &fr[1..];
let needs = fr_inner.chars().any(|c| matches!(c, '{' | '}' | '|' | '^' | '`' | '\\' | '<' | '>' | ' '))
|| (orig_frag_has_non_ascii && fr_inner.chars().any(|c| matches!(c, '\'' | '[' | ']')));
if needs {
let mut out = ph.to_string(); out.push('#');
for c in fr_inner.chars() {
if matches!(c, '{' | '}' | '|' | '^' | '`' | '\\' | '<' | '>' | ' ')
|| (orig_frag_has_non_ascii && matches!(c, '\'' | '[' | ']'))
{ out.push_str(&format!("%{:02X}", c as u8)); }
else { out.push(c); }
}
out
} else { result }
} else { result };
let raw = if raw.ends_with('#') {
raw[..raw.len() - 1].to_string()
} else {
raw
};
let result = if raw.is_empty() && !url.is_empty() {
url.to_string()
} else {
raw
};
let path_end_for_ascii = url.find(['?', '#']).unwrap_or(url.len());
let has_non_ascii = url[..path_end_for_ascii]
.bytes()
.any(|b| b > 127);
fn encode_ascii_cat1_path_part(input: &str) -> Option<String> {
let qs = input.find('?').unwrap_or(input.len());
let pp = &input[..qs];
let rr = &input[qs..];
let mut enc = String::with_capacity(pp.len());
let mut changed = false;
for c in pp.chars() {
match c {
'\\' | '^' | '{' | '}' | '|' | '<' | '>' | '`' | ' ' => {
enc.push('%');
enc.push_str(&format!("{:02X}", c as u8));
changed = true;
}
_ => enc.push(c),
}
}
if !changed {
return None;
}
if rr.is_empty() {
Some(enc)
} else {
Some(format!("{enc}{rr}"))
}
}
let result = if has_non_ascii {
encode_go_path_chars(&result)
} else {
match encode_ascii_cat1_path_part(&result) {
Some(encoded) => encoded,
None => result,
}
};
// Also encode Cat1 and (when frag has non-ASCII) Cat2 in the result's fragment
let orig_frag_has_non_ascii = url[url
.find('#')
.map(|i| i + 1)
.unwrap_or(url.len())..]
.bytes()
.any(|b| b > 127);
let result = if let Some(fs) = result.find('#') {
let (ph, fr) = result.split_at(fs);
let fr_inner = &fr[1..];
let needs = fr_inner
.chars()
.any(|c| matches!(c, '{' | '}' | '|' | '^' | '`' | '\\' | '<' | '>' | ' '))
|| (orig_frag_has_non_ascii
&& fr_inner
.chars()
.any(|c| matches!(c, '\'' | '[' | ']')));
if needs {
let mut out = ph.to_string();
out.push('#');
for c in fr_inner.chars() {
if matches!(c, '{' | '}' | '|' | '^' | '`' | '\\' | '<' | '>' | ' ')
|| (orig_frag_has_non_ascii
&& matches!(c, '\'' | '[' | ']'))
{
out.push_str(&format!("%{:02X}", c as u8));
} else {
out.push(c);
}
}
out
} else {
result
}
} else {
result
};

Copilot uses AI. Check for mistakes.
Comment on lines +481 to +490
let fixme_url_go_parsing_raw =
go_like_reference(url_for_go_like, remove_query_string);
// Go's url.URL.String() omits a trailing empty fragment (bare '#').
// The url crate keeps it. Strip it here for parity.
let fixme_url_go_parsing = if fixme_url_go_parsing_raw.ends_with('#') {
fixme_url_go_parsing_raw[..fixme_url_go_parsing_raw.len() - 1].to_string()
} else {
fixme_url_go_parsing_raw
};
let result = if fixme_url_go_parsing.is_empty() && !url.is_empty() {
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixme_url_go_parsing_raw / fixme_url_go_parsing read like temporary placeholders but are part of the final implementation. Rename them to something that reflects their meaning (e.g., go_ref_raw / go_ref, resolved_ref_raw / resolved_ref) to reduce cognitive load when debugging parity cases.

Suggested change
let fixme_url_go_parsing_raw =
go_like_reference(url_for_go_like, remove_query_string);
// Go's url.URL.String() omits a trailing empty fragment (bare '#').
// The url crate keeps it. Strip it here for parity.
let fixme_url_go_parsing = if fixme_url_go_parsing_raw.ends_with('#') {
fixme_url_go_parsing_raw[..fixme_url_go_parsing_raw.len() - 1].to_string()
} else {
fixme_url_go_parsing_raw
};
let result = if fixme_url_go_parsing.is_empty() && !url.is_empty() {
let go_ref_raw = go_like_reference(url_for_go_like, remove_query_string);
// Go's url.URL.String() omits a trailing empty fragment (bare '#').
// The url crate keeps it. Strip it here for parity.
let go_ref = if go_ref_raw.ends_with('#') {
go_ref_raw[..go_ref_raw.len() - 1].to_string()
} else {
go_ref_raw
};
let result = if go_ref.is_empty() && !url.is_empty() {

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +68
/// Encode path characters that Go's url.EscapedPath() encodes but the url crate doesn't.
/// Only applied to the path portion (before the first '?').
///
/// Two categories:
/// 1. Always encoded: chars not in Go's validEncoded allowlist (e.g. '\', '^', '{', '}', '|')
/// 2. Encoded only when escape() fallback occurs (non-ASCII present): '!', '\'', '(', ')', '*'
/// These are in validEncoded's allowlist so RawPath is used for pure-ASCII paths.
fn encode_go_path_chars(url_str: &str) -> String {
// Only encode up to the first '?' or '#' — the fragment has different encoding rules
// (e.g., '!' is allowed in fragments per Go's shouldEscape for encodeFragment).
let path_end = url_str
.find(['?', '#'])
.unwrap_or(url_str.len());
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc comment says “before the first ‘?’”, but the implementation explicitly stops at either ‘?’ or ‘#’. Update the doc to match the actual behavior (or adjust the implementation if the doc is the intended contract).

Copilot uses AI. Check for mistakes.

// Try absolute first (like "https://...", "mailto:...", etc.)
if let Ok(abs) = Url::parse(input) {
return abs.to_string();
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the new normalize_pct_encoded_unreserved helper and parity goal, it would be valuable to add a regression test that covers absolute URLs with percent-encoded unreserved characters in the path (e.g. https://foo/%41 should round-trip to include A rather than %41 if matching Go). This directly exercises the absolute-return branch here, which currently bypasses path normalization.

Suggested change
return abs.to_string();
// Normalize percent-encoded unreserved characters in the path, to match Go.
return normalize_pct_encoded_unreserved(abs.as_str());

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

github-actions bot commented Mar 6, 2026

🔒 Cargo Deny Results

No issues found!

📦 libdd-trace-obfuscation - ✅ No issues


Updated: 2026-03-09 17:53:12 UTC | Commit: 41a7f6e | dependency-check job results

@pr-commenter
Copy link

pr-commenter bot commented Mar 6, 2026

Benchmarks

Comparison

Benchmark execution time: 2026-03-09 18:05:45

Comparing candidate commit 4366490 in PR branch oscarld/obfuscation-http-parity with baseline commit 79f879e in branch main.

Found 14 performance improvements and 4 performance regressions! Performance is the same for 40 metrics, 2 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:credit_card/is_card_number/ 3782-8224-6310-005

  • 🟩 execution_time [-3.560µs; -3.309µs] or [-4.467%; -4.151%]
  • 🟩 throughput [+544885.261op/s; +587212.445op/s] or [+4.343%; +4.680%]

scenario:credit_card/is_card_number/ 378282246310005

  • 🟩 execution_time [-4.389µs; -4.294µs] or [-6.022%; -5.891%]
  • 🟩 throughput [+859762.907op/s; +877863.259op/s] or [+6.266%; +6.398%]

scenario:credit_card/is_card_number/378282246310005

  • 🟩 execution_time [-4.911µs; -4.814µs] or [-7.044%; -6.906%]
  • 🟩 throughput [+1065246.563op/s; +1085574.938op/s] or [+7.426%; +7.567%]

scenario:credit_card/is_card_number/37828224631000521389798

  • 🟩 execution_time [-6.545µs; -6.500µs] or [-12.535%; -12.449%]
  • 🟩 throughput [+2723889.901op/s; +2745259.583op/s] or [+14.221%; +14.333%]

scenario:credit_card/is_card_number/x371413321323331

  • 🟥 execution_time [+394.514ns; +398.580ns] or [+6.533%; +6.600%]
  • 🟥 throughput [-10258514.410op/s; -10148808.391op/s] or [-6.195%; -6.129%]

scenario:credit_card/is_card_number_no_luhn/ 378282246310005

  • 🟩 execution_time [-4.243µs; -4.195µs] or [-7.262%; -7.180%]
  • 🟩 throughput [+1324956.149op/s; +1339390.918op/s] or [+7.741%; +7.825%]

scenario:credit_card/is_card_number_no_luhn/378282246310005

  • 🟩 execution_time [-4.434µs; -4.338µs] or [-8.069%; -7.895%]
  • 🟩 throughput [+1562027.119op/s; +1595135.478op/s] or [+8.582%; +8.764%]

scenario:credit_card/is_card_number_no_luhn/37828224631000521389798

  • 🟩 execution_time [-6.581µs; -6.538µs] or [-12.603%; -12.520%]
  • 🟩 throughput [+2741227.058op/s; +2761309.923op/s] or [+14.315%; +14.419%]

scenario:credit_card/is_card_number_no_luhn/x371413321323331

  • 🟥 execution_time [+401.169ns; +403.091ns] or [+6.647%; +6.679%]
  • 🟥 throughput [-10376301.429op/s; -10325786.657op/s] or [-6.262%; -6.232%]

Candidate

Candidate benchmark details

Group 1

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
benching serializing traces from their internal representation to msgpack execution_time 14.008ms 14.060ms ± 0.030ms 14.056ms ± 0.015ms 14.072ms 14.113ms 14.167ms 14.207ms 1.08% 1.847 5.360 0.21% 0.002ms 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
benching serializing traces from their internal representation to msgpack execution_time [14.056ms; 14.064ms] or [-0.029%; +0.029%] None None None

Group 2

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
concentrator/add_spans_to_concentrator execution_time 10.707ms 10.737ms ± 0.015ms 10.735ms ± 0.010ms 10.746ms 10.762ms 10.787ms 10.795ms 0.55% 0.863 1.575 0.14% 0.001ms 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
concentrator/add_spans_to_concentrator execution_time [10.735ms; 10.739ms] or [-0.019%; +0.019%] None None None

Group 3

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
write only interface execution_time 1.279µs 3.228µs ± 1.464µs 2.993µs ± 0.035µs 3.026µs 3.682µs 14.228µs 15.479µs 417.15% 7.315 55.012 45.25% 0.104µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
write only interface execution_time [3.025µs; 3.431µs] or [-6.287%; +6.287%] None None None

Group 4

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
normalization/normalize_trace/test_trace execution_time 239.305ns 250.772ns ± 14.949ns 243.432ns ± 2.589ns 253.283ns 283.169ns 298.786ns 303.320ns 24.60% 1.791 2.370 5.95% 1.057ns 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
normalization/normalize_trace/test_trace execution_time [248.700ns; 252.844ns] or [-0.826%; +0.826%] None None None

Group 5

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
sql/obfuscate_sql_string execution_time 88.447µs 88.684µs ± 0.153µs 88.669µs ± 0.041µs 88.709µs 88.810µs 88.937µs 90.520µs 2.09% 9.038 104.204 0.17% 0.011µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
sql/obfuscate_sql_string execution_time [88.662µs; 88.705µs] or [-0.024%; +0.024%] None None None

Group 6

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
benching deserializing traces from msgpack to their internal representation execution_time 49.069ms 49.413ms ± 1.372ms 49.229ms ± 0.086ms 49.299ms 49.567ms 57.497ms 62.816ms 27.60% 8.288 69.644 2.77% 0.097ms 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
benching deserializing traces from msgpack to their internal representation execution_time [49.223ms; 49.604ms] or [-0.385%; +0.385%] None None None

Group 7

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
sdk_test_data/rules-based execution_time 144.881µs 146.667µs ± 1.661µs 146.338µs ± 0.574µs 146.995µs 149.013µs 153.977µs 161.793µs 10.56% 5.063 37.344 1.13% 0.117µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
sdk_test_data/rules-based execution_time [146.436µs; 146.897µs] or [-0.157%; +0.157%] None None None

Group 8

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
two way interface execution_time 17.748µs 25.393µs ± 9.167µs 18.060µs ± 0.222µs 33.689µs 42.738µs 51.514µs 58.022µs 221.28% 0.818 -0.252 36.01% 0.648µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
two way interface execution_time [24.123µs; 26.664µs] or [-5.003%; +5.003%] None None None

Group 9

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
normalization/normalize_name/normalize_name/Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Lo... execution_time 185.375µs 186.170µs ± 0.630µs 186.047µs ± 0.339µs 186.426µs 187.165µs 188.287µs 189.848µs 2.04% 2.156 7.478 0.34% 0.045µs 1 200
normalization/normalize_name/normalize_name/Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Lo... throughput 5267360.694op/s 5371492.870op/s ± 18056.675op/s 5374997.092op/s ± 9802.560op/s 5384283.553op/s 5390517.129op/s 5394139.017op/s 5394482.308op/s 0.36% -2.108 7.154 0.34% 1276.800op/s 1 200
normalization/normalize_name/normalize_name/bad-name execution_time 17.920µs 18.010µs ± 0.038µs 18.007µs ± 0.022µs 18.032µs 18.067µs 18.100µs 18.235µs 1.27% 1.115 5.189 0.21% 0.003µs 1 200
normalization/normalize_name/normalize_name/bad-name throughput 54840807.275op/s 55525182.175op/s ± 117878.767op/s 55534982.723op/s ± 67897.427op/s 55595526.196op/s 55698263.550op/s 55750419.151op/s 55803152.737op/s 0.48% -1.078 4.970 0.21% 8335.288op/s 1 200
normalization/normalize_name/normalize_name/good execution_time 10.290µs 10.356µs ± 0.032µs 10.354µs ± 0.018µs 10.370µs 10.409µs 10.457µs 10.465µs 1.08% 0.866 1.031 0.30% 0.002µs 1 200
normalization/normalize_name/normalize_name/good throughput 95553712.045op/s 96562654.734op/s ± 293626.652op/s 96581278.845op/s ± 168372.638op/s 96760023.597op/s 96965718.762op/s 97073001.912op/s 97179726.542op/s 0.62% -0.846 0.980 0.30% 20762.540op/s 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
normalization/normalize_name/normalize_name/Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Lo... execution_time [186.083µs; 186.257µs] or [-0.047%; +0.047%] None None None
normalization/normalize_name/normalize_name/Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Long-.Too-Lo... throughput [5368990.389op/s; 5373995.351op/s] or [-0.047%; +0.047%] None None None
normalization/normalize_name/normalize_name/bad-name execution_time [18.005µs; 18.015µs] or [-0.029%; +0.029%] None None None
normalization/normalize_name/normalize_name/bad-name throughput [55508845.312op/s; 55541519.039op/s] or [-0.029%; +0.029%] None None None
normalization/normalize_name/normalize_name/good execution_time [10.352µs; 10.360µs] or [-0.042%; +0.042%] None None None
normalization/normalize_name/normalize_name/good throughput [96521960.904op/s; 96603348.564op/s] or [-0.042%; +0.042%] None None None

Group 10

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
single_flag_killswitch/rules-based execution_time 188.297ns 190.672ns ± 1.978ns 190.370ns ± 1.527ns 191.953ns 194.199ns 196.161ns 197.470ns 3.73% 0.833 0.208 1.03% 0.140ns 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
single_flag_killswitch/rules-based execution_time [190.398ns; 190.946ns] or [-0.144%; +0.144%] None None None

Group 11

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
normalization/normalize_service/normalize_service/A0000000000000000000000000000000000000000000000000... execution_time 534.131µs 535.548µs ± 1.127µs 535.186µs ± 0.299µs 535.579µs 537.573µs 540.812µs 542.684µs 1.40% 2.861 11.594 0.21% 0.080µs 1 200
normalization/normalize_service/normalize_service/A0000000000000000000000000000000000000000000000000... throughput 1842693.385op/s 1867252.873op/s ± 3904.968op/s 1868507.623op/s ± 1043.152op/s 1869331.270op/s 1870641.992op/s 1871177.131op/s 1872200.510op/s 0.20% -2.828 11.311 0.21% 276.123op/s 1 200
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて execution_time 380.517µs 381.233µs ± 0.337µs 381.190µs ± 0.234µs 381.454µs 381.833µs 382.225µs 382.244µs 0.28% 0.503 0.156 0.09% 0.024µs 1 200
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて throughput 2616126.738op/s 2623070.398op/s ± 2318.894op/s 2623366.221op/s ± 1610.739op/s 2624853.436op/s 2626246.540op/s 2627896.675op/s 2628002.278op/s 0.18% -0.498 0.148 0.09% 163.971op/s 1 200
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters execution_time 189.751µs 190.235µs ± 0.202µs 190.233µs ± 0.129µs 190.359µs 190.584µs 190.748µs 190.941µs 0.37% 0.316 0.436 0.11% 0.014µs 1 200
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters throughput 5237230.424op/s 5256672.571op/s ± 5585.836op/s 5256724.261op/s ± 3576.372op/s 5260320.978op/s 5265315.786op/s 5268761.304op/s 5270061.604op/s 0.25% -0.309 0.426 0.11% 394.978op/s 1 200
normalization/normalize_service/normalize_service/[empty string] execution_time 37.450µs 37.599µs ± 0.063µs 37.592µs ± 0.046µs 37.640µs 37.707µs 37.745µs 37.763µs 0.45% 0.280 -0.467 0.17% 0.004µs 1 200
normalization/normalize_service/normalize_service/[empty string] throughput 26480859.304op/s 26596530.851op/s ± 44413.259op/s 26601179.216op/s ± 32719.047op/s 26632331.043op/s 26660401.050op/s 26686988.767op/s 26702511.610op/s 0.38% -0.272 -0.471 0.17% 3140.492op/s 1 200
normalization/normalize_service/normalize_service/test_ASCII execution_time 45.799µs 45.895µs ± 0.112µs 45.880µs ± 0.036µs 45.919µs 45.988µs 46.053µs 47.300µs 3.10% 9.962 121.987 0.24% 0.008µs 1 200
normalization/normalize_service/normalize_service/test_ASCII throughput 21141460.330op/s 21789201.205op/s ± 51980.121op/s 21796021.209op/s ± 17165.405op/s 21809456.717op/s 21825538.482op/s 21831490.984op/s 21834325.986op/s 0.18% -9.781 118.936 0.24% 3675.550op/s 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
normalization/normalize_service/normalize_service/A0000000000000000000000000000000000000000000000000... execution_time [535.392µs; 535.705µs] or [-0.029%; +0.029%] None None None
normalization/normalize_service/normalize_service/A0000000000000000000000000000000000000000000000000... throughput [1866711.682op/s; 1867794.064op/s] or [-0.029%; +0.029%] None None None
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて execution_time [381.186µs; 381.280µs] or [-0.012%; +0.012%] None None None
normalization/normalize_service/normalize_service/Data🐨dog🐶 繋がっ⛰てて throughput [2622749.021op/s; 2623391.774op/s] or [-0.012%; +0.012%] None None None
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters execution_time [190.207µs; 190.263µs] or [-0.015%; +0.015%] None None None
normalization/normalize_service/normalize_service/Test Conversion 0f Weird !@#$%^&**() Characters throughput [5255898.428op/s; 5257446.714op/s] or [-0.015%; +0.015%] None None None
normalization/normalize_service/normalize_service/[empty string] execution_time [37.590µs; 37.608µs] or [-0.023%; +0.023%] None None None
normalization/normalize_service/normalize_service/[empty string] throughput [26590375.600op/s; 26602686.101op/s] or [-0.023%; +0.023%] None None None
normalization/normalize_service/normalize_service/test_ASCII execution_time [45.879µs; 45.910µs] or [-0.034%; +0.034%] None None None
normalization/normalize_service/normalize_service/test_ASCII throughput [21781997.260op/s; 21796405.150op/s] or [-0.033%; +0.033%] None None None

Group 12

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
profile_add_sample_frames_x1000 execution_time 4.204ms 4.209ms ± 0.008ms 4.208ms ± 0.002ms 4.210ms 4.213ms 4.221ms 4.318ms 2.60% 11.865 154.124 0.19% 0.001ms 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
profile_add_sample_frames_x1000 execution_time [4.208ms; 4.210ms] or [-0.027%; +0.027%] None None None

Group 13

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
ip_address/quantize_peer_ip_address_benchmark execution_time 4.972µs 5.034µs ± 0.054µs 5.006µs ± 0.020µs 5.058µs 5.148µs 5.150µs 5.151µs 2.90% 0.996 -0.325 1.07% 0.004µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
ip_address/quantize_peer_ip_address_benchmark execution_time [5.026µs; 5.041µs] or [-0.149%; +0.149%] None None None

Group 14

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
benching string interning on wordpress profile execution_time 160.551µs 161.330µs ± 1.367µs 161.209µs ± 0.121µs 161.341µs 161.614µs 162.451µs 180.171µs 11.76% 13.206 179.490 0.84% 0.097µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
benching string interning on wordpress profile execution_time [161.140µs; 161.519µs] or [-0.117%; +0.117%] None None None

Group 15

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
receiver_entry_point/report/2598 execution_time 3.420ms 3.444ms ± 0.014ms 3.440ms ± 0.007ms 3.450ms 3.473ms 3.489ms 3.507ms 1.94% 1.447 2.856 0.41% 0.001ms 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
receiver_entry_point/report/2598 execution_time [3.442ms; 3.446ms] or [-0.057%; +0.057%] None None None

Group 16

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
profile_add_sample2_frames_x1000 execution_time 735.479µs 737.098µs ± 0.832µs 737.055µs ± 0.404µs 737.446µs 738.176µs 738.782µs 744.210µs 0.97% 3.183 25.181 0.11% 0.059µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
profile_add_sample2_frames_x1000 execution_time [736.983µs; 737.213µs] or [-0.016%; +0.016%] None None None

Group 17

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
credit_card/is_card_number/ execution_time 3.896µs 3.912µs ± 0.003µs 3.912µs ± 0.001µs 3.913µs 3.917µs 3.920µs 3.921µs 0.22% -0.465 9.300 0.07% 0.000µs 1 200
credit_card/is_card_number/ throughput 255043370.350op/s 255596113.654op/s ± 168324.093op/s 255615308.077op/s ± 80453.122op/s 255691218.679op/s 255787679.287op/s 255826308.273op/s 256698086.981op/s 0.42% 0.487 9.422 0.07% 11902.311op/s 1 200
credit_card/is_card_number/ 3782-8224-6310-005 execution_time 74.392µs 76.269µs ± 0.804µs 76.257µs ± 0.593µs 76.744µs 77.659µs 78.215µs 78.429µs 2.85% 0.333 -0.250 1.05% 0.057µs 1 200
credit_card/is_card_number/ 3782-8224-6310-005 throughput 12750427.574op/s 13112963.841op/s ± 137727.280op/s 13113501.376op/s ± 102717.601op/s 13227374.713op/s 13328206.887op/s 13349763.936op/s 13442368.594op/s 2.51% -0.282 -0.298 1.05% 9738.789op/s 1 200
credit_card/is_card_number/ 378282246310005 execution_time 68.384µs 68.543µs ± 0.086µs 68.538µs ± 0.053µs 68.592µs 68.665µs 68.688µs 69.237µs 1.02% 2.537 19.317 0.13% 0.006µs 1 200
credit_card/is_card_number/ 378282246310005 throughput 14443140.275op/s 14589390.900op/s ± 18287.625op/s 14590513.257op/s ± 11280.576op/s 14601203.877op/s 14616493.983op/s 14621370.918op/s 14623354.960op/s 0.23% -2.482 18.764 0.13% 1293.130op/s 1 200
credit_card/is_card_number/37828224631 execution_time 3.895µs 3.913µs ± 0.003µs 3.913µs ± 0.001µs 3.914µs 3.918µs 3.920µs 3.924µs 0.28% -0.857 10.615 0.07% 0.000µs 1 200
credit_card/is_card_number/37828224631 throughput 254856583.346op/s 255543020.035op/s ± 179817.940op/s 255565000.384op/s ± 91926.839op/s 255638192.347op/s 255754628.010op/s 255816397.742op/s 256771674.829op/s 0.47% 0.882 10.770 0.07% 12715.049op/s 1 200
credit_card/is_card_number/378282246310005 execution_time 64.602µs 64.848µs ± 0.147µs 64.807µs ± 0.078µs 64.917µs 65.149µs 65.345µs 65.486µs 1.05% 1.402 2.721 0.23% 0.010µs 1 200
credit_card/is_card_number/378282246310005 throughput 15270555.325op/s 15420638.995op/s ± 34896.065op/s 15430438.810op/s ± 18481.064op/s 15443872.722op/s 15462794.123op/s 15471341.090op/s 15479420.111op/s 0.32% -1.384 2.644 0.23% 2467.524op/s 1 200
credit_card/is_card_number/37828224631000521389798 execution_time 45.361µs 45.687µs ± 0.159µs 45.691µs ± 0.118µs 45.811µs 45.934µs 45.963µs 45.988µs 0.65% -0.112 -0.918 0.35% 0.011µs 1 200
credit_card/is_card_number/37828224631000521389798 throughput 21745029.697op/s 21888447.148op/s ± 76007.945op/s 21886184.406op/s ± 56908.245op/s 21942720.284op/s 22016410.897op/s 22038568.891op/s 22045529.152op/s 0.73% 0.123 -0.915 0.35% 5374.573op/s 1 200
credit_card/is_card_number/x371413321323331 execution_time 6.428µs 6.436µs ± 0.003µs 6.435µs ± 0.002µs 6.438µs 6.441µs 6.445µs 6.449µs 0.22% 0.613 0.796 0.05% 0.000µs 1 200
credit_card/is_card_number/x371413321323331 throughput 155051846.584op/s 155382578.236op/s ± 80589.025op/s 155390451.259op/s ± 53427.548op/s 155439889.764op/s 155503075.216op/s 155523003.612op/s 155567219.204op/s 0.11% -0.610 0.786 0.05% 5698.505op/s 1 200
credit_card/is_card_number_no_luhn/ execution_time 3.896µs 3.912µs ± 0.002µs 3.912µs ± 0.001µs 3.913µs 3.915µs 3.916µs 3.917µs 0.13% -1.938 13.727 0.06% 0.000µs 1 200
credit_card/is_card_number_no_luhn/ throughput 255271552.227op/s 255614197.448op/s ± 146461.750op/s 255611405.087op/s ± 80426.052op/s 255694259.665op/s 255829067.047op/s 255876152.052op/s 256703634.199op/s 0.43% 1.958 13.908 0.06% 10356.410op/s 1 200
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 execution_time 59.951µs 62.005µs ± 0.899µs 62.013µs ± 0.668µs 62.692µs 63.260µs 64.307µs 64.784µs 4.47% 0.125 -0.241 1.45% 0.064µs 1 200
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 throughput 15435863.036op/s 16131055.906op/s ± 233668.340op/s 16125666.327op/s ± 173597.255op/s 16297746.562op/s 16514166.803op/s 16604639.422op/s 16680376.495op/s 3.44% -0.051 -0.318 1.44% 16522.847op/s 1 200
credit_card/is_card_number_no_luhn/ 378282246310005 execution_time 54.017µs 54.203µs ± 0.080µs 54.194µs ± 0.056µs 54.257µs 54.357µs 54.400µs 54.412µs 0.40% 0.484 -0.226 0.15% 0.006µs 1 200
credit_card/is_card_number_no_luhn/ 378282246310005 throughput 18378393.844op/s 18449165.508op/s ± 27097.016op/s 18452185.776op/s ± 19001.624op/s 18469822.161op/s 18486572.648op/s 18498455.645op/s 18512755.288op/s 0.33% -0.477 -0.233 0.15% 1916.048op/s 1 200
credit_card/is_card_number_no_luhn/37828224631 execution_time 3.895µs 3.913µs ± 0.003µs 3.913µs ± 0.002µs 3.915µs 3.918µs 3.919µs 3.920µs 0.17% -1.080 7.348 0.07% 0.000µs 1 200
credit_card/is_card_number_no_luhn/37828224631 throughput 255110719.748op/s 255539422.775op/s ± 187249.866op/s 255547642.518op/s ± 113638.717op/s 255653956.736op/s 255796416.065op/s 255844140.130op/s 256750288.405op/s 0.47% 1.098 7.474 0.07% 13240.565op/s 1 200
credit_card/is_card_number_no_luhn/378282246310005 execution_time 50.299µs 50.557µs ± 0.178µs 50.531µs ± 0.077µs 50.597µs 50.989µs 51.202µs 51.235µs 1.39% 1.749 3.466 0.35% 0.013µs 1 200
credit_card/is_card_number_no_luhn/378282246310005 throughput 19518069.296op/s 19779813.251op/s ± 69044.050op/s 19789839.903op/s ± 30317.197op/s 19821597.615op/s 19862912.605op/s 19876012.932op/s 19881098.979op/s 0.46% -1.723 3.375 0.35% 4882.152op/s 1 200
credit_card/is_card_number_no_luhn/37828224631000521389798 execution_time 45.357µs 45.660µs ± 0.145µs 45.655µs ± 0.101µs 45.761µs 45.892µs 45.931µs 45.968µs 0.69% -0.017 -0.738 0.32% 0.010µs 1 200
credit_card/is_card_number_no_luhn/37828224631000521389798 throughput 21754060.708op/s 21901166.188op/s ± 69377.435op/s 21903484.845op/s ± 48276.546op/s 21947624.700op/s 22020203.469op/s 22038586.855op/s 22047204.777op/s 0.66% 0.029 -0.736 0.32% 4905.725op/s 1 200
credit_card/is_card_number_no_luhn/x371413321323331 execution_time 6.429µs 6.437µs ± 0.004µs 6.437µs ± 0.002µs 6.439µs 6.445µs 6.450µs 6.451µs 0.22% 0.795 1.134 0.06% 0.000µs 1 200
credit_card/is_card_number_no_luhn/x371413321323331 throughput 155026123.498op/s 155346010.267op/s ± 98574.186op/s 155360251.080op/s ± 55391.505op/s 155409169.141op/s 155486802.062op/s 155531254.225op/s 155547692.534op/s 0.12% -0.790 1.124 0.06% 6970.248op/s 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
credit_card/is_card_number/ execution_time [3.912µs; 3.913µs] or [-0.009%; +0.009%] None None None
credit_card/is_card_number/ throughput [255572785.554op/s; 255619441.755op/s] or [-0.009%; +0.009%] None None None
credit_card/is_card_number/ 3782-8224-6310-005 execution_time [76.157µs; 76.380µs] or [-0.146%; +0.146%] None None None
credit_card/is_card_number/ 3782-8224-6310-005 throughput [13093876.164op/s; 13132051.517op/s] or [-0.146%; +0.146%] None None None
credit_card/is_card_number/ 378282246310005 execution_time [68.531µs; 68.555µs] or [-0.017%; +0.017%] None None None
credit_card/is_card_number/ 378282246310005 throughput [14586856.411op/s; 14591925.389op/s] or [-0.017%; +0.017%] None None None
credit_card/is_card_number/37828224631 execution_time [3.913µs; 3.914µs] or [-0.010%; +0.010%] None None None
credit_card/is_card_number/37828224631 throughput [255518098.998op/s; 255567941.073op/s] or [-0.010%; +0.010%] None None None
credit_card/is_card_number/378282246310005 execution_time [64.828µs; 64.869µs] or [-0.031%; +0.031%] None None None
credit_card/is_card_number/378282246310005 throughput [15415802.736op/s; 15425475.254op/s] or [-0.031%; +0.031%] None None None
credit_card/is_card_number/37828224631000521389798 execution_time [45.665µs; 45.709µs] or [-0.048%; +0.048%] None None None
credit_card/is_card_number/37828224631000521389798 throughput [21877913.178op/s; 21898981.118op/s] or [-0.048%; +0.048%] None None None
credit_card/is_card_number/x371413321323331 execution_time [6.435µs; 6.436µs] or [-0.007%; +0.007%] None None None
credit_card/is_card_number/x371413321323331 throughput [155371409.372op/s; 155393747.100op/s] or [-0.007%; +0.007%] None None None
credit_card/is_card_number_no_luhn/ execution_time [3.912µs; 3.912µs] or [-0.008%; +0.008%] None None None
credit_card/is_card_number_no_luhn/ throughput [255593899.258op/s; 255634495.638op/s] or [-0.008%; +0.008%] None None None
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 execution_time [61.881µs; 62.130µs] or [-0.201%; +0.201%] None None None
credit_card/is_card_number_no_luhn/ 3782-8224-6310-005 throughput [16098671.722op/s; 16163440.091op/s] or [-0.201%; +0.201%] None None None
credit_card/is_card_number_no_luhn/ 378282246310005 execution_time [54.192µs; 54.214µs] or [-0.020%; +0.020%] None None None
credit_card/is_card_number_no_luhn/ 378282246310005 throughput [18445410.122op/s; 18452920.894op/s] or [-0.020%; +0.020%] None None None
credit_card/is_card_number_no_luhn/37828224631 execution_time [3.913µs; 3.914µs] or [-0.010%; +0.010%] None None None
credit_card/is_card_number_no_luhn/37828224631 throughput [255513471.744op/s; 255565373.805op/s] or [-0.010%; +0.010%] None None None
credit_card/is_card_number_no_luhn/378282246310005 execution_time [50.533µs; 50.582µs] or [-0.049%; +0.049%] None None None
credit_card/is_card_number_no_luhn/378282246310005 throughput [19770244.410op/s; 19789382.093op/s] or [-0.048%; +0.048%] None None None
credit_card/is_card_number_no_luhn/37828224631000521389798 execution_time [45.640µs; 45.680µs] or [-0.044%; +0.044%] None None None
credit_card/is_card_number_no_luhn/37828224631000521389798 throughput [21891551.142op/s; 21910781.233op/s] or [-0.044%; +0.044%] None None None
credit_card/is_card_number_no_luhn/x371413321323331 execution_time [6.437µs; 6.438µs] or [-0.009%; +0.009%] None None None
credit_card/is_card_number_no_luhn/x371413321323331 throughput [155332348.833op/s; 155359671.701op/s] or [-0.009%; +0.009%] None None None

Group 18

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
redis/obfuscate_redis_string execution_time 33.218µs 33.578µs ± 0.621µs 33.310µs ± 0.054µs 33.414µs 34.678µs 34.776µs 38.402µs 15.29% 3.255 17.191 1.84% 0.044µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
redis/obfuscate_redis_string execution_time [33.492µs; 33.664µs] or [-0.256%; +0.256%] None None None

Group 19

cpu_model git_commit_sha git_commit_date git_branch
Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz 4366490 1773078521 oscarld/obfuscation-http-parity
scenario metric min mean ± sd median ± mad p75 p95 p99 max peak_to_median_ratio skewness kurtosis cv sem runs sample_size
tags/replace_trace_tags execution_time 2.399µs 2.420µs ± 0.012µs 2.419µs ± 0.009µs 2.429µs 2.443µs 2.451µs 2.460µs 1.71% 0.666 -0.130 0.51% 0.001µs 1 200
scenario metric 95% CI mean Shapiro-Wilk pvalue Ljung-Box pvalue (lag=1) Dip test pvalue
tags/replace_trace_tags execution_time [2.419µs; 2.422µs] or [-0.070%; +0.070%] None None None

Baseline

Omitted due to size.

@dd-octo-sts
Copy link
Contributor

dd-octo-sts bot commented Mar 6, 2026

Artifact Size Benchmark Report

aarch64-alpine-linux-musl
Artifact Baseline Commit Change
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 8.63 MB 8.63 MB 0% (0 B) 👌
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.a 100.28 MB 100.28 MB 0% (0 B) 👌
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 11.21 MB 11.21 MB 0% (0 B) 👌
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 116.94 MB 116.94 MB 0% (0 B) 👌
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 27.16 MB 27.16 MB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 76.26 KB 76.26 KB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 186.05 MB 186.03 MB -0% (-16.00 KB) 👌
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 917.14 MB 917.14 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 9.93 MB 9.93 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 76.26 KB 76.26 KB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 24.77 MB 24.77 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 51.43 MB 51.43 MB 0% (0 B) 👌
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 22.97 MB 22.97 MB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 77.44 KB 77.44 KB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 190.26 MB 190.21 MB --.02% (-56.00 KB) 💪
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 900.80 MB 900.80 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 7.53 MB 7.53 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 77.44 KB 77.44 KB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 26.51 MB 26.51 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 47.05 MB 47.05 MB 0% (0 B) 👌
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 87.50 MB 87.50 MB 0% (0 B) 👌
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 10.21 MB 10.21 MB 0% (0 B) 👌
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 109.81 MB 109.81 MB 0% (0 B) 👌
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 11.95 MB 11.95 MB 0% (0 B) 👌

@codecov-commenter
Copy link

codecov-commenter commented Mar 6, 2026

Codecov Report

❌ Patch coverage is 97.90210% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.09%. Comparing base (79f879e) to head (4366490).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1684      +/-   ##
==========================================
+ Coverage   71.05%   71.09%   +0.03%     
==========================================
  Files         427      427              
  Lines       62963    63087     +124     
==========================================
+ Hits        44738    44851     +113     
- Misses      18225    18236      +11     
Components Coverage Δ
libdd-crashtracker 62.44% <ø> (ø)
libdd-crashtracker-ffi 17.49% <ø> (ø)
libdd-alloc 98.77% <ø> (ø)
libdd-data-pipeline 88.02% <ø> (ø)
libdd-data-pipeline-ffi 75.72% <ø> (ø)
libdd-common 79.73% <ø> (ø)
libdd-common-ffi 73.40% <ø> (ø)
libdd-telemetry 62.48% <ø> (ø)
libdd-telemetry-ffi 16.75% <ø> (ø)
libdd-dogstatsd-client 82.64% <ø> (ø)
datadog-ipc 80.35% <ø> (ø)
libdd-profiling 81.60% <ø> (ø)
libdd-profiling-ffi 63.65% <ø> (ø)
datadog-sidecar 32.47% <ø> (ø)
datdog-sidecar-ffi 7.73% <ø> (ø)
spawn-worker 54.69% <ø> (ø)
libdd-tinybytes 93.16% <ø> (ø)
libdd-trace-normalization 81.71% <ø> (ø)
libdd-trace-obfuscation 95.03% <97.90%> (+0.33%) ⬆️
libdd-trace-protobuf 68.25% <ø> (ø)
libdd-trace-utils 89.08% <ø> (ø)
datadog-tracer-flare 88.95% <ø> (ø)
libdd-log 74.69% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Eldolfin Eldolfin changed the title Oscarld/obfuscation http parity fix: obfuscation http parity Mar 9, 2026
@Eldolfin Eldolfin changed the title fix: obfuscation http parity fix: obfuscation http parity [APMSP-2670] Mar 9, 2026
@Eldolfin
Copy link
Contributor Author

Eldolfin commented Mar 9, 2026

For the kind of tests this fixes, it's not worth it given how much complexity it adds to a very simple function

@Eldolfin Eldolfin closed this Mar 9, 2026
@Eldolfin Eldolfin reopened this Mar 9, 2026
@Eldolfin Eldolfin marked this pull request as ready for review March 9, 2026 17:20
@Eldolfin Eldolfin requested review from a team as code owners March 9, 2026 17:20
@Eldolfin Eldolfin changed the title fix: obfuscation http parity [APMSP-2670] fix(obfuscation/http): fuzzer fixes [APMSP-2670] Mar 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants