Skip to content

Commit a78496a

Browse files
authored
Remove null keys/values before creating concurrent hashmap (#2708)
* remove null keys/values before creating concurrent hashmap * move null save logic to CollectionUtils * add changelog entry * add test * add test cases for ignoring null values when creating concurrent hash map
1 parent 5a573d4 commit a78496a

File tree

5 files changed

+284
-3
lines changed

5 files changed

+284
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
- Android Profiler on calling thread ([#2691](https://github.com/getsentry/sentry-java/pull/2691))
2222
- Use `configureScope` instead of `withScope` in `Hub.close()`. This ensures that the main scope releases the in-memory data when closing a hub instance. ([#2688](https://github.com/getsentry/sentry-java/pull/2688))
23+
- Remove null keys/values before creating concurrent hashmap in order to avoid NPE ([#2708](https://github.com/getsentry/sentry-java/pull/2708))
2324

2425
### Dependencies
2526

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ public static int size(final @NotNull Iterable<?> data) {
3434
}
3535

3636
/**
37-
* Creates a new {@link ConcurrentHashMap} as a shallow copy of map given by parameter.
37+
* Creates a new {@link ConcurrentHashMap} as a shallow copy of map given by parameter. Also makes
38+
* sure no null keys or values are put into the resulting {@link ConcurrentHashMap}.
3839
*
3940
* @param map the map to copy
4041
* @param <K> the type of map keys
@@ -44,7 +45,14 @@ public static int size(final @NotNull Iterable<?> data) {
4445
public static <K, V> @Nullable Map<K, @NotNull V> newConcurrentHashMap(
4546
@Nullable Map<K, @NotNull V> map) {
4647
if (map != null) {
47-
return new ConcurrentHashMap<>(map);
48+
Map<K, @NotNull V> concurrentMap = new ConcurrentHashMap<>();
49+
50+
for (Map.Entry<K, V> entry : map.entrySet()) {
51+
if (entry.getKey() != null && entry.getValue() != null) {
52+
concurrentMap.put(entry.getKey(), entry.getValue());
53+
}
54+
}
55+
return concurrentMap;
4856
} else {
4957
return null;
5058
}

sentry/src/test/java/io/sentry/protocol/SentryBaseEventSerializationTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,10 @@ class SentryBaseEventSerializationTest {
8787

8888
@Test
8989
fun deserialize() {
90+
val inputJson = SerializationUtils.sanitizedFile("json/sentry_base_event_with_null_extra.json")
9091
val expectedJson = SerializationUtils.sanitizedFile("json/sentry_base_event.json")
9192
val actual = SerializationUtils.deserializeJson(
92-
expectedJson,
93+
inputJson,
9394
Sut.Deserializer(),
9495
fixture.logger
9596
)

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.sentry.util
22

3+
import io.sentry.JsonObjectReader
4+
import java.io.StringReader
35
import kotlin.test.Test
46
import kotlin.test.assertEquals
57

@@ -25,4 +27,39 @@ class CollectionUtilsTest {
2527
assertEquals("key3", result[1])
2628
assertEquals(2, result.size)
2729
}
30+
31+
@Test
32+
fun `concurrent hashmap creation with null returns null`() {
33+
val result: Map<String, String>? = CollectionUtils.newConcurrentHashMap(null)
34+
assertEquals(null, result)
35+
}
36+
37+
@Test
38+
fun `concurrent hashmap creation ignores null keys`() {
39+
val map = mutableMapOf("key1" to "value1", null to "value2", "key3" to "value3")
40+
val result = CollectionUtils.newConcurrentHashMap(map)
41+
42+
assertEquals(2, result?.size)
43+
assertEquals("value1", result?.get("key1"))
44+
assertEquals("value3", result?.get("key3"))
45+
}
46+
47+
@Test
48+
fun `concurrent hashmap creation ignores null values`() {
49+
val json = """
50+
{
51+
"key1": "value1",
52+
"key2": null,
53+
"key3": "value3"
54+
}
55+
""".trimIndent()
56+
val reader = JsonObjectReader(StringReader(json))
57+
val deserializedMap = reader.nextObjectOrNull() as Map<String, String>
58+
59+
val result: Map<String, String>? = CollectionUtils.newConcurrentHashMap(deserializedMap)
60+
61+
assertEquals(2, result?.size)
62+
assertEquals("value1", result?.get("key1"))
63+
assertEquals("value3", result?.get("key3"))
64+
}
2865
}
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
{
2+
"event_id": "afcb46b1140ade5187c4bbb5daa804df",
3+
"contexts":
4+
{
5+
"app":
6+
{
7+
"app_identifier": "3b7a3313-53b4-43f4-a6a1-7a7c36a9b0db",
8+
"app_start_time": "1918-11-17T07:46:04.000Z",
9+
"device_app_hash": "3d1fcf36-2c25-4378-bdf8-1e65239f1df4",
10+
"build_type": "d78c56cd-eb0f-4213-8899-cd10ddf20763",
11+
"app_name": "873656fd-f620-4edf-bb7a-a0d13325dba0",
12+
"app_version": "801aab22-ad4b-44fb-995c-bacb5387e20c",
13+
"app_build": "660f0cde-eedb-49dc-a973-8aa1c04f4a28",
14+
"permissions":
15+
{
16+
"WRITE_EXTERNAL_STORAGE": "not_granted",
17+
"CAMERA": "granted"
18+
},
19+
"in_foreground": true
20+
},
21+
"browser":
22+
{
23+
"name": "e1c723db-7408-4043-baa7-f4e96234e5dc",
24+
"version": "724a48e9-2d35-416b-9f79-132beba2473a"
25+
},
26+
"device":
27+
{
28+
"name": "83f1de77-fdb0-470e-8249-8f5c5d894ec4",
29+
"manufacturer": "e21b2405-e378-4a0b-ad2c-4822d97cd38c",
30+
"brand": "1abbd13e-d1ca-4d81-bd1b-24aa2c339cf9",
31+
"family": "67a4b8ea-6c38-4c33-8579-7697f538685c",
32+
"model": "d6ca2f35-bcc5-4dd3-ad64-7c3b585e02fd",
33+
"model_id": "d3f133bd-b0a2-4aa4-9eed-875eba93652e",
34+
"archs":
35+
[
36+
"856e5da3-774c-4663-a830-d19f0b7dbb5b",
37+
"b345bd5a-90a5-4301-a5a2-6c102d7589b6",
38+
"fd7ed64e-a591-49e0-8dc1-578234356d23",
39+
"8cec4101-0305-480b-91ee-f3c007f668c3",
40+
"22583b9b-195e-49bf-bfe8-825ae3a346f2",
41+
"8675b7aa-5b94-42d0-bc14-72ea1bb7112e"
42+
],
43+
"battery_level": 0.45770407,
44+
"charging": false,
45+
"online": true,
46+
"orientation": "portrait",
47+
"simulator": true,
48+
"memory_size": -6712323365568152393,
49+
"free_memory": -953384122080236886,
50+
"usable_memory": -8999512249221323968,
51+
"low_memory": false,
52+
"storage_size": -3227905175393990709,
53+
"free_storage": -3749039933924297357,
54+
"external_storage_size": -7739608324159255302,
55+
"external_free_storage": -1562576688560812557,
56+
"screen_width_pixels": 1101873181,
57+
"screen_height_pixels": 1902392170,
58+
"screen_density": 0.9829039,
59+
"screen_dpi": -2092079070,
60+
"boot_time": "2004-11-04T08:38:00.000Z",
61+
"timezone": "Europe/Vienna",
62+
"id": "e0fa5c8d-83f5-4e70-bc60-1e82ad30e196",
63+
"language": "6dd45f60-111d-42d8-9204-0452cc836ad8",
64+
"connection_type": "9ceb3a6c-5292-4ed9-8665-5732495e8ed4",
65+
"battery_temperature": 0.14775127,
66+
"processor_count": 4,
67+
"processor_frequency": 800.0,
68+
"cpu_description": "cpu0"
69+
},
70+
"gpu":
71+
{
72+
"name": "d623a6b5-e1ab-4402-931b-c06f5a43a5ae",
73+
"id": -596576280,
74+
"vendor_id": "1874778041",
75+
"vendor_name": "d732cf76-07dc-48e2-8920-96d6bfc2439d",
76+
"memory_size": -1484004451,
77+
"api_type": "95dfc8bc-88ae-4d66-b85f-6c88ad45b80f",
78+
"multi_threaded_rendering": true,
79+
"version": "3f3f73c3-83a2-423a-8a6f-bb3de0d4a6ae",
80+
"npot_support": "e06b074a-463c-45de-a959-cbabd461d99d"
81+
},
82+
"os":
83+
{
84+
"name": "686a11a8-eae7-4393-aa10-a1368d523cb2",
85+
"version": "3033f32d-6a27-4715-80c8-b232ce84ca61",
86+
"raw_description": "eb2d0c5e-f5d4-49c7-b876-d8a654ee87cf",
87+
"build": "bd197b97-eb68-49c3-9d07-ef789caf3069",
88+
"kernel_version": "1df24aec-3a6f-49a9-8b50-69ae5f9dde08",
89+
"rooted": true
90+
},
91+
"response":
92+
{
93+
"cookies": "PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43; _gat=1;",
94+
"headers": {
95+
"content-type": "text/html"
96+
},
97+
"status_code": 500,
98+
"body_size": 1000,
99+
"arbitrary_field": "arbitrary"
100+
},
101+
"runtime":
102+
{
103+
"name": "4ed019c4-9af9-43e0-830e-bfde9fe4461c",
104+
"version": "16534f6b-1670-4bb8-aec2-647a1b97669b",
105+
"raw_description": "773b5b05-a0f9-4ee6-9f3b-13155c37ad6e"
106+
},
107+
"trace":
108+
{
109+
"trace_id": "afcb46b1140ade5187c4bbb5daa804df",
110+
"span_id": "bf6b582d-8ce3-412b-a334-f4c5539b9602",
111+
"parent_span_id": "c7500f2a-d4e6-4f5f-a0f4-6bb67e98d5a2",
112+
"op": "e481581d-35a4-4e97-8a1c-b554bf49f23e",
113+
"description": "c204b6c7-9753-4d45-927d-b19789bfc9a5",
114+
"status": "resource_exhausted",
115+
"tags":
116+
{
117+
"2a5fa3f5-7b87-487f-aaa5-84567aa73642": "4781d51a-c5af-47f2-a4ed-f030c9b3e194",
118+
"29106d7d-7fa4-444f-9d34-b9d7510c69ab": "218c23ea-694a-497e-bf6d-e5f26f1ad7bd",
119+
"ba9ce913-269f-4c03-882d-8ca5e6991b14": "35a74e90-8db8-4610-a411-872cbc1030ac"
120+
}
121+
}
122+
},
123+
"sdk":
124+
{
125+
"name": "3e934135-3f2b-49bc-8756-9f025b55143e",
126+
"version": "3e31738e-4106-42d0-8be2-4a3a1bc648d3",
127+
"packages":
128+
[
129+
{
130+
"name": "b59a1949-9950-4203-b394-ddd8d02c9633",
131+
"version": "3d7790f3-7f32-43f7-b82f-9f5bc85205a8"
132+
}
133+
],
134+
"integrations":
135+
[
136+
"daec50ae-8729-49b5-82f7-991446745cd5",
137+
"8fc94968-3499-4a2c-b4d7-ecc058d9c1b0"
138+
]
139+
},
140+
"request":
141+
{
142+
"url": "67369bc9-64d3-4d31-bfba-37393b145682",
143+
"method": "8185abc3-5411-4041-a0d9-374180081044",
144+
"query_string": "e3dc7659-f42e-413c-a07c-52b24bf9d60d",
145+
"data":
146+
{
147+
"d9d709db-b666-40cc-bcbb-093bb12aad26": "1631d0e6-96b7-4632-85f8-ef69e8bcfb16"
148+
},
149+
"cookies": "d84f4cfc-5310-4818-ad4f-3f8d22ceaca8",
150+
"headers":
151+
{
152+
"c4991f66-9af9-4914-ac5e-e4854a5a4822": "37714d22-25a7-469b-b762-289b456fbec3"
153+
},
154+
"env":
155+
{
156+
"6d569c89-5d5e-40e0-a4fc-109b20a53778": "ccadf763-44e4-475c-830c-de6ba0dbd202"
157+
},
158+
"other":
159+
{
160+
"669ff1c1-517b-46dc-a889-131555364a56": "89043294-f6e1-4e2e-b152-1fdf9b1102fc"
161+
},
162+
"fragment": "fragment",
163+
"body_size": 1000
164+
},
165+
"tags":
166+
{
167+
"79ba41db-8dc6-4156-b53e-6cf6d742eb88": "690ce82f-4d5d-4d81-b467-461a41dd9419"
168+
},
169+
"release": "be9b8133-72f5-497b-adeb-b0a245eebad6",
170+
"environment": "89204175-e462-4628-8acb-3a7fa8d8da7d",
171+
"platform": "38decc78-2711-4a6a-a0be-abb61bfa5a6e",
172+
"user":
173+
{
174+
"email": "c4d61c1b-c144-431e-868f-37a46be5e5f2",
175+
"id": "efb2084b-1871-4b59-8897-b4bd9f196a01",
176+
"username": "60c05dff-7140-4d94-9a61-c9cdd9ca9b96",
177+
"ip_address": "51d22b77-f663-4dbe-8103-8b749d1d9a48",
178+
"name": "c8c60762-b1cf-11ed-afa1-0242ac120002",
179+
"geo": {
180+
"city": "0e6ed0b0-b1c5-11ed-afa1-0242ac120002",
181+
"country_code": "JP",
182+
"region": "273a3d0a-b1c5-11ed-afa1-0242ac120002"
183+
},
184+
"data":
185+
{
186+
"dc2813d0-0f66-4a3f-a995-71268f61a8fa": "991659ad-7c59-4dd3-bb89-0bd5c74014bd"
187+
}
188+
},
189+
"server_name": "e6f0ae04-0f40-421b-aad1-f68c15117937",
190+
"dist": "27022a08-aace-40c6-8d0a-358a27fcaa7a",
191+
"breadcrumbs":
192+
[
193+
{
194+
"timestamp": "2009-11-16T01:08:47.000Z",
195+
"message": "46f233c0-7c2d-488a-b05a-7be559173e16",
196+
"type": "ace57e2e-305e-4048-abf0-6c8538ea7bf4",
197+
"data":
198+
{
199+
"6607d106-d426-462b-af74-f29fce978e48": "149bb94a-1387-4484-90be-2df15d1322ab"
200+
},
201+
"category": "b6eea851-5ae5-40ed-8fdd-5e1a655a879c",
202+
"level": "debug"
203+
}
204+
],
205+
"debug_meta":
206+
{
207+
"sdk_info":
208+
{
209+
"sdk_name": "182c4407-c1e1-4427-9b5a-ad2e22b1046a",
210+
"version_major": 2045114005,
211+
"version_minor": 1436566288,
212+
"version_patchlevel": 1637914973
213+
},
214+
"images":
215+
[
216+
{
217+
"uuid": "8994027e-1cd9-4be8-b611-88ce08cf16e6",
218+
"type": "fd6e053b-a7fe-4754-916e-bfb3ab77177d",
219+
"debug_id": "8c653f5a-3418-4823-ba91-29a84c9c1235",
220+
"debug_file": "55cc15dd-51f3-4cad-803c-6fd90eac21f6",
221+
"code_id": "01230ece-f729-4af4-8b48-df74700aa4bf",
222+
"code_file": "415c8995-1cb4-4bed-ba5c-5b3d6ba1ad47",
223+
"image_addr": "8a258c81-641d-4e54-b06e-a0f56b1ee2ef",
224+
"image_size": -7905338721846826571,
225+
"arch": "d00d5bea-fb5c-43c9-85f0-dc1350d957a4"
226+
}
227+
]
228+
},
229+
"extra":
230+
{
231+
"34a7d067-fad2-49d9-97b9-71eff243127b": "fe3dc1cf-4a99-4213-85bb-e0957b8349b8",
232+
"keyWithNullValue": null
233+
}
234+
}

0 commit comments

Comments
 (0)