Skip to content

Commit b8ab780

Browse files
Use numbered capture groups for sentry-trace validation (#4652)
* Use numbered capture groups for sentry-trace validation * Fix tab escape in character gropu and add tests * Use previous tab escape * Add changelog entry * Fix typo --------- Co-authored-by: markushi <[email protected]>
1 parent ee747ae commit b8ab780

File tree

3 files changed

+33
-7
lines changed

3 files changed

+33
-7
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## Unreleased
44

5+
### Fixes
6+
7+
- Do not use named capturing groups for regular expressions ([#4652](https://github.com/getsentry/sentry-java/pull/4652))
8+
- This fixes a crash on Android versions below 8.0 (API level 26)
9+
510
### Features
611

712
- 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))

sentry/src/main/java/io/sentry/SentryTraceHeader.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ public final class SentryTraceHeader {
1515
private final @NotNull SpanId spanId;
1616
private final @Nullable Boolean sampled;
1717

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

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

36-
if (!matchesExist || matcher.group("traceId") == null || matcher.group("spanId") == null) {
36+
if (!matchesExist) {
3737
throw new InvalidSentryTraceHeaderException(value);
3838
}
3939

40-
this.traceId = new SentryId(matcher.group("traceId"));
41-
this.spanId = new SpanId(matcher.group("spanId"));
42-
this.sampled =
43-
matcher.group("sampled") == null ? null : "1".equals(matcher.group("sampled").substring(1));
40+
this.traceId = new SentryId(matcher.group(1));
41+
this.spanId = new SpanId(matcher.group(2));
42+
43+
String sampled = matcher.group(3);
44+
this.sampled = sampled == null ? null : "1".equals(sampled.substring(1));
4445
}
4546

4647
public @NotNull String getName() {

sentry/src/test/java/io/sentry/SentryTraceHeaderTest.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,26 @@ class SentryTraceHeaderTest {
132132
assertNull(header.isSampled)
133133
}
134134

135+
@Test
136+
fun `handles header without sampling decision and leading whitespace`() {
137+
val sentryId = SentryId()
138+
val spanId = SpanId()
139+
val header = SentryTraceHeader(" \t $sentryId-$spanId")
140+
assertEquals(sentryId, header.traceId)
141+
assertEquals(spanId, header.spanId)
142+
assertNull(header.isSampled)
143+
}
144+
145+
@Test
146+
fun `handles header without sampling decision and trailing whitespace`() {
147+
val sentryId = SentryId()
148+
val spanId = SpanId()
149+
val header = SentryTraceHeader("$sentryId-$spanId \t ")
150+
assertEquals(sentryId, header.traceId)
151+
assertEquals(spanId, header.spanId)
152+
assertNull(header.isSampled)
153+
}
154+
135155
@Test
136156
fun `when sampling decision is not made, getValue returns header with traceId and spanId`() {
137157
val sentryId = SentryId()

0 commit comments

Comments
 (0)