Skip to content

Commit ddb009f

Browse files
committed
Merge branch 'feat/data-collection-external-options' into feat/data-collection-android-manifest
2 parents e549730 + 9623300 commit ddb009f

5 files changed

Lines changed: 140 additions & 50 deletions

File tree

sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,14 @@ private static void readDefaultOptionValues(
471471
options.addInAppInclude(packageName);
472472
}
473473
}
474+
475+
if (options.getDistinctId() == null) {
476+
try {
477+
options.setDistinctId(Installation.id(context));
478+
} catch (RuntimeException e) {
479+
options.getLogger().log(SentryLevel.ERROR, "Could not generate distinct Id.", e);
480+
}
481+
}
474482
}
475483

476484
/**

sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,6 @@ public static void init(
149149
"Error in the 'OptionsConfiguration.configure' callback.",
150150
t);
151151
}
152-
if (options.getDistinctId() == null) {
153-
try {
154-
options.setDistinctId(Installation.id(context));
155-
} catch (RuntimeException e) {
156-
options.getLogger().log(SentryLevel.ERROR, "Could not generate distinct Id.", e);
157-
}
158-
}
159152

160153
// if SentryPerformanceProvider was disabled or removed,
161154
// we set the app start / sdk init time here instead

sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,6 @@ class AndroidOptionsInitializerTest {
111111
)
112112

113113
sentryOptions.configureOptions()
114-
if (sentryOptions.distinctId == null) {
115-
sentryOptions.distinctId = Installation.id(if (useRealContext) context else mockContext)
116-
}
117114
AndroidOptionsInitializer.initializeIntegrationsAndProcessors(
118115
sentryOptions,
119116
if (useRealContext) context else mockContext,
@@ -352,44 +349,6 @@ class AndroidOptionsInitializerTest {
352349
installation.deleteOnExit()
353350
}
354351

355-
@Test
356-
fun `init should set generated distinct id when user info is disabled`() {
357-
fixture.initSut(configureOptions = { dataCollection.setUserInfo(false) })
358-
359-
assertNotNull(fixture.sentryOptions.distinctId)
360-
}
361-
362-
@Test
363-
fun `init should set generated distinct id when user info is enabled`() {
364-
fixture.initSut(configureOptions = { dataCollection.setUserInfo(true) })
365-
366-
assertNotNull(fixture.sentryOptions.distinctId)
367-
}
368-
369-
@Test
370-
fun `init should preserve explicit distinct id when user info is disabled`() {
371-
fixture.initSut(
372-
configureOptions = {
373-
dataCollection.setUserInfo(false)
374-
distinctId = "custom-id"
375-
}
376-
)
377-
378-
assertEquals("custom-id", fixture.sentryOptions.distinctId)
379-
}
380-
381-
@Test
382-
fun `init should set generated distinct id when explicit value is null`() {
383-
fixture.initSut(
384-
configureOptions = {
385-
dataCollection.setUserInfo(true)
386-
distinctId = null
387-
}
388-
)
389-
390-
assertNotNull(fixture.sentryOptions.distinctId)
391-
}
392-
393352
@Test
394353
fun `init should set proguard uuid id on start`() {
395354
fixture.initSut(

sentry/src/main/java/io/sentry/util/HttpUtils.java

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,75 @@ public static boolean containsSensitiveHeader(final @NotNull String header) {
208208
}
209209

210210
private static boolean isValidCookiePair(final @NotNull String cookie) {
211-
final int separator = cookie.indexOf('=');
212-
return separator >= 0 && !cookie.substring(0, separator).trim().isEmpty();
211+
final @NotNull String cookiePair = cookie.trim();
212+
final int separator = cookiePair.indexOf('=');
213+
if (separator <= 0 || !isValidCookieName(cookiePair.substring(0, separator))) {
214+
return false;
215+
}
216+
217+
final @NotNull String value = cookiePair.substring(separator + 1);
218+
int start = 0;
219+
int end = value.length();
220+
if (!value.isEmpty() && value.charAt(0) == '"') {
221+
if (value.length() < 2 || value.charAt(value.length() - 1) != '"') {
222+
return false;
223+
}
224+
start++;
225+
end--;
226+
}
227+
228+
for (int i = start; i < end; i++) {
229+
if (!isCookieOctet(value.charAt(i))) {
230+
return false;
231+
}
232+
}
233+
return true;
234+
}
235+
236+
private static boolean isValidCookieName(final @NotNull String name) {
237+
for (int i = 0; i < name.length(); i++) {
238+
if (!isCookieNameCharacter(name.charAt(i))) {
239+
return false;
240+
}
241+
}
242+
return true;
243+
}
244+
245+
private static boolean isCookieNameCharacter(final char value) {
246+
if ((value >= 'a' && value <= 'z')
247+
|| (value >= 'A' && value <= 'Z')
248+
|| (value >= '0' && value <= '9')) {
249+
return true;
250+
}
251+
252+
switch (value) {
253+
case '!':
254+
case '#':
255+
case '$':
256+
case '%':
257+
case '&':
258+
case '\'':
259+
case '*':
260+
case '+':
261+
case '-':
262+
case '.':
263+
case '^':
264+
case '_':
265+
case '`':
266+
case '|':
267+
case '~':
268+
return true;
269+
default:
270+
return false;
271+
}
272+
}
273+
274+
private static boolean isCookieOctet(final char value) {
275+
return value == 0x21
276+
|| (value >= 0x23 && value <= 0x2B)
277+
|| (value >= 0x2D && value <= 0x3A)
278+
|| (value >= 0x3C && value <= 0x5B)
279+
|| (value >= 0x5D && value <= 0x7E);
213280
}
214281

215282
public static @NotNull Map<String, String> filterHeaders(

sentry/src/test/java/io/sentry/util/HttpUtilsTest.kt

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,69 @@ class HttpUtilsTest {
133133
.isEqualTo("theme=dark;[Filtered];[Filtered]; empty=; sessionId=[Filtered]")
134134
}
135135

136+
@Test
137+
fun `cookie filter replaces comma-separated malformed cookies`() {
138+
assertThat(
139+
HttpUtils.filterCookies(
140+
"theme=dark, sessionId=secret",
141+
KeyValueCollectionBehavior.denyList(),
142+
emptyList(),
143+
)
144+
)
145+
.isEqualTo("[Filtered]")
146+
}
147+
148+
@Test
149+
fun `cookie filter replaces space-separated malformed cookies`() {
150+
assertThat(
151+
HttpUtils.filterCookies(
152+
"theme=dark sessionId=secret",
153+
KeyValueCollectionBehavior.denyList(),
154+
emptyList(),
155+
)
156+
)
157+
.isEqualTo("[Filtered]")
158+
}
159+
160+
@Test
161+
fun `cookie filter preserves valid names and values`() {
162+
val cookies =
163+
"plain=abc123; empty=; base64=YWJjZA==; quoted=\"dark\"; quoted-empty=\"\"; encoded=hello%2Fworld; !#\$%&'*+-.^_`|~=!#\$%&'()*+-./:<=>?@[]^_`{|}~"
164+
165+
assertThat(
166+
HttpUtils.filterCookies(
167+
cookies,
168+
KeyValueCollectionBehavior.denyList(),
169+
emptyList(),
170+
)
171+
)
172+
.isEqualTo(cookies)
173+
}
174+
175+
@Test
176+
fun `cookie filter replaces comma-separated malformed cookies in quoted values`() {
177+
assertThat(
178+
HttpUtils.filterCookies(
179+
"theme=\"dark, sessionId=secret\"",
180+
KeyValueCollectionBehavior.denyList(),
181+
emptyList(),
182+
)
183+
)
184+
.isEqualTo("[Filtered]")
185+
}
186+
187+
@Test
188+
fun `cookie filter replaces space-separated malformed cookies in quoted values`() {
189+
assertThat(
190+
HttpUtils.filterCookies(
191+
"theme=\"dark sessionId=secret\"",
192+
KeyValueCollectionBehavior.denyList(),
193+
emptyList(),
194+
)
195+
)
196+
.isEqualTo("[Filtered]")
197+
}
198+
136199
@Test
137200
fun `cookie allow list never exposes malformed pairs`() {
138201
assertThat(

0 commit comments

Comments
 (0)