Skip to content

fix: Avoid stack overflow when deserializing large flat JSON objects#5361

Open
denrase wants to merge 4 commits intomainfrom
fix/json-object-deserializer-iterative
Open

fix: Avoid stack overflow when deserializing large flat JSON objects#5361
denrase wants to merge 4 commits intomainfrom
fix/json-object-deserializer-iterative

Conversation

@denrase
Copy link
Copy Markdown
Collaborator

@denrase denrase commented May 4, 2026

📜 Description

Replace JsonObjectDeserializer's recursive token parsing with an iterative loop. The parser already tracks state explicitly, so recursion was only used to advance to the next JSON token and could overflow on large flat maps.

💡 Motivation and Context

Relates to getsentry/sentry-dart#3668

💚 How did you test it?

Added a regression test. It fails with StackOverflow before the test.

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

Replace JsonObjectDeserializer's recursive token parsing with an iterative loop. The parser already tracks state explicitly, so recursion was only used to advance to the next JSON token and could overflow on large flat maps.

Relates to getsentry/sentry-dart#3668
@sentry
Copy link
Copy Markdown

sentry Bot commented May 4, 2026

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.40.0 (1) release

⚙️ sentry-android Build Distribution Settings

denrase added 3 commits May 4, 2026 11:27
vm might not respect stack size, so increase the frame count (with smaller payload) to make test more robust
@denrase denrase marked this pull request as ready for review May 4, 2026 09:29
Comment on lines +180 to +219
fun `deserializes event with large flat modules map on a small stack`() {
val moduleCount = 50000
val json = buildString {
append("{\"event_id\":\"00000000000000000000000000000000\",\"modules\":{")
repeat(moduleCount) {
if (it > 0) {
append(',')
}
append("\"m")
append(it)
append("\":\"v\"")
}
append("}}")
}

val error = AtomicReference<Throwable?>()
val event = AtomicReference<SentryEvent?>()
val thread =
Thread(
null,
Runnable {
try {
event.set(
JsonSerializer(SentryOptions())
.deserialize(StringReader(json), SentryEvent::class.java)
)
} catch (throwable: Throwable) {
error.set(throwable)
}
},
"large-flat-modules-repro",
1024L * 1024L,
)

thread.start()
thread.join()

assertNull(error.get())
assertEquals(moduleCount, event.get()?.modules?.size)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

does this test fail with the previous (recursive) variant?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes.

@denrase denrase requested a review from buenaflor May 4, 2026 09:47
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 479.32 ms 543.96 ms 64.64 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
8687935 294.00 ms 304.02 ms 10.02 ms
6edfca2 305.52 ms 432.78 ms 127.26 ms
b6702b0 395.86 ms 409.98 ms 14.12 ms
a1eadfa 345.67 ms 411.26 ms 65.59 ms
889ecea 367.58 ms 437.52 ms 69.94 ms
e2dce0b 315.85 ms 369.20 ms 53.35 ms
d15471f 322.58 ms 396.08 ms 73.50 ms
62b579c 349.26 ms 426.26 ms 77.00 ms
cf708bd 434.73 ms 502.96 ms 68.22 ms
6edfca2 316.43 ms 398.90 ms 82.46 ms

App size

Revision Plain With Sentry Diff
8687935 1.58 MiB 2.19 MiB 619.17 KiB
6edfca2 1.58 MiB 2.13 MiB 559.07 KiB
b6702b0 1.58 MiB 2.12 MiB 551.79 KiB
a1eadfa 0 B 0 B 0 B
889ecea 1.58 MiB 2.11 MiB 539.75 KiB
e2dce0b 0 B 0 B 0 B
d15471f 1.58 MiB 2.13 MiB 559.54 KiB
62b579c 0 B 0 B 0 B
cf708bd 1.58 MiB 2.11 MiB 539.71 KiB
6edfca2 1.58 MiB 2.13 MiB 559.07 KiB

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants