Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

### Fixes

- Do not use named capturing groups for regular expressions ([#4652](https://github.com/getsentry/sentry-java/pull/4652))
- This fixes a crash on Android verisons below 8.0 (API level 26)

### Features

- Add onDiscard to enable users to track the type and amount of data discarded before reaching Sentry ([#4612](https://github.com/getsentry/sentry-java/pull/4612))
Expand Down
15 changes: 8 additions & 7 deletions sentry/src/main/java/io/sentry/SentryTraceHeader.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public final class SentryTraceHeader {
private final @NotNull SpanId spanId;
private final @Nullable Boolean sampled;

// Use numbered capture groups for Android API level < 26 compatibility
private static final Pattern SENTRY_TRACEPARENT_HEADER_REGEX =
Pattern.compile(
"^[ \\t]*(?<traceId>[0-9a-f]{32})-(?<spanId>[0-9a-f]{16})(?<sampled>-[01])?[ \\t]*$",
Pattern.CASE_INSENSITIVE);
"^[ \\t]*([0-9a-f]{32})-([0-9a-f]{16})(-[01])?[ \\t]*$", Pattern.CASE_INSENSITIVE);

public SentryTraceHeader(
final @NotNull SentryId traceId,
Expand All @@ -33,14 +33,15 @@ public SentryTraceHeader(final @NotNull String value) throws InvalidSentryTraceH
Matcher matcher = SENTRY_TRACEPARENT_HEADER_REGEX.matcher(value);
boolean matchesExist = matcher.matches();

if (!matchesExist || matcher.group("traceId") == null || matcher.group("spanId") == null) {
if (!matchesExist) {
throw new InvalidSentryTraceHeaderException(value);
}

this.traceId = new SentryId(matcher.group("traceId"));
this.spanId = new SpanId(matcher.group("spanId"));
this.sampled =
matcher.group("sampled") == null ? null : "1".equals(matcher.group("sampled").substring(1));
this.traceId = new SentryId(matcher.group(1));
this.spanId = new SpanId(matcher.group(2));

String sampled = matcher.group(3);
this.sampled = sampled == null ? null : "1".equals(sampled.substring(1));
}

public @NotNull String getName() {
Expand Down
20 changes: 20 additions & 0 deletions sentry/src/test/java/io/sentry/SentryTraceHeaderTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,26 @@ class SentryTraceHeaderTest {
assertNull(header.isSampled)
}

@Test
fun `handles header without sampling decision and leading whitespace`() {
val sentryId = SentryId()
val spanId = SpanId()
val header = SentryTraceHeader(" \t $sentryId-$spanId")
assertEquals(sentryId, header.traceId)
assertEquals(spanId, header.spanId)
assertNull(header.isSampled)
}

@Test
fun `handles header without sampling decision and trailing whitespace`() {
val sentryId = SentryId()
val spanId = SpanId()
val header = SentryTraceHeader("$sentryId-$spanId \t ")
assertEquals(sentryId, header.traceId)
assertEquals(spanId, header.spanId)
assertNull(header.isSampled)
}

@Test
fun `when sampling decision is not made, getValue returns header with traceId and spanId`() {
val sentryId = SentryId()
Expand Down
Loading