Skip to content

java: limit numeric string length before BigDecimal parsing (#26908)#27063

Merged
copybara-service[bot] merged 1 commit into
mainfrom
test_903851133
Apr 24, 2026
Merged

java: limit numeric string length before BigDecimal parsing (#26908)#27063
copybara-service[bot] merged 1 commit into
mainfrom
test_903851133

Conversation

@copybara-service

Copy link
Copy Markdown

java: limit numeric string length before BigDecimal parsing (#26908)

Summary

BigDecimal(String) has O(N²) time complexity for N-digit strings on JDK versions before 18 (JDK-8291514). Five JSON parser methods — parseInt32, parseInt64, parseUint32, parseUint64, and parseDouble — pass user-controlled strings directly to new BigDecimal() without length validation.

A single JSON numeric value with 1,000,000 digits takes ~13 seconds to parse on JDK 17. This can be used to DoS any service that parses protobuf JSON messages with numeric fields from untrusted input.

Benchmark (JDK 17, x86-64 Linux)

Digits BigDecimal construction time
1,000 1.8 ms
10,000 6.3 ms
100,000 133 ms
1,000,000 13.1 seconds

Fix

Added a parseBigDecimal() helper that rejects strings longer than 1000 characters before constructing BigDecimal. This is generous — valid protobuf numeric values never exceed ~350 characters (Double.MAX_VALUE in non-scientific notation is ~309 digits).

Affected JDK versions

  • JDK 8, 11, 17 (all current LTS releases): Vulnerable — no built-in string length limit in BigDecimal
  • JDK 18+: JDK itself limits BigDecimal string input to 1100 characters by default (JDK-8291514), but the protobuf-level check is still worthwhile as defense-in-depth

Test

Added testParserRejectOverlyLongNumericStrings covering all 5 affected field types.

Closes #26908

COPYBARA_INTEGRATE_REVIEW=#26908 from MindflareX:fix/java-bigdecimal-length-check a461d0e
FUTURE_COPYBARA_INTEGRATE_REVIEW=#26908 from MindflareX:fix/java-bigdecimal-length-check a461d0e

## Summary

`BigDecimal(String)` has O(N²) time complexity for N-digit strings on JDK versions before 18 ([JDK-8291514](https://bugs.openjdk.org/browse/JDK-8291514)). Five JSON parser methods — `parseInt32`, `parseInt64`, `parseUint32`, `parseUint64`, and `parseDouble` — pass user-controlled strings directly to `new BigDecimal()` without length validation.

A single JSON numeric value with 1,000,000 digits takes ~13 seconds to parse on JDK 17. This can be used to DoS any service that parses protobuf JSON messages with numeric fields from untrusted input.

### Benchmark (JDK 17, x86-64 Linux)

| Digits | BigDecimal construction time |
|--------|-----|
| 1,000 | 1.8 ms |
| 10,000 | 6.3 ms |
| 100,000 | 133 ms |
| 1,000,000 | **13.1 seconds** |

### Fix

Added a `parseBigDecimal()` helper that rejects strings longer than 1000 characters before constructing `BigDecimal`. This is generous — valid protobuf numeric values never exceed ~350 characters (Double.MAX_VALUE in non-scientific notation is ~309 digits).

### Affected JDK versions

- JDK 8, 11, 17 (all current LTS releases): **Vulnerable** — no built-in string length limit in BigDecimal
- JDK 18+: JDK itself limits BigDecimal string input to 1100 characters by default (JDK-8291514), but the protobuf-level check is still worthwhile as defense-in-depth

### Test

Added `testParserRejectOverlyLongNumericStrings` covering all 5 affected field types.

Closes #26908

COPYBARA_INTEGRATE_REVIEW=#26908 from MindflareX:fix/java-bigdecimal-length-check a461d0e
PiperOrigin-RevId: 904988136
@copybara-service copybara-service Bot merged commit 25e7005 into main Apr 24, 2026
@copybara-service copybara-service Bot deleted the test_903851133 branch April 24, 2026 13:12
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.

1 participant