CVE-2026-58865 AI-generated analysis
platform/frameworks/base, telephony/common MMS PDU parser (com.google.android.mms.pdu.PduParser)
Adds a bounds check on the well-known content-type index in PduParser.parseContentType and null checks on the parameter map and the parsed charset string in PduParser.parseContentTypeParams so a malformed MMS PDU no longer throws ArrayIndexOutOfBoundsException or NullPointerException out of PduParser.parse().
Root cause
In telephony/common/com/google/android/mms/pdu/PduParser.java, parseContentType indexed PduContentTypes.contentTypes directly with the value returned by parseShortInteger(pduDataStream). That value is read from the PDU (0-127 according to the added comment), but the table only has indices 0-82 (per the added comment and test). A short-integer content type of 83 or more therefore threw ArrayIndexOutOfBoundsException. In parseContentTypeParams, the short-integer branch of case P_TYPE/P_CT_MR_TYPE called map.put without checking map for null; per the added test, the ELEMENT_DESCRIPTOR path passes a null map. In the extension-charset branch of the charset parameter, charsetStr from parseWapString was passed to new String() and map.put was called without a null check on either. The added test shows an empty charset string value is expected to trigger this NPE, which implies parseWapString can return null, though its body is not shown. The tests reach all three paths from PduParser.parse() on malformed PDU bytes, and each one surfaced as an uncaught runtime exception.
How the fix works
- PduParser.java:parseContentType: replaces the direct `PduContentTypes.contentTypes[parseShortInteger(pduDataStream)]` lookup with `int index = parseShortInteger(...)`. If `index < PduContentTypes.contentTypes.length` it uses the table entry, otherwise it falls back to `PduContentTypes.contentTypes[0]` ("*/*"). The check is an upper bound only; the added comment states parseShortInteger returns 0-127.
- PduParser.java:parseContentTypeParams, case PduPart.P_TYPE / P_CT_MR_TYPE, short-integer (well-known type) branch: wraps `map.put(PduPart.P_TYPE, type)` in `if (map != null)`. The sibling text-string branch already checked `(null != type) && (null != map)`, and this branch already ignored an out-of-range index.
- PduParser.java:parseContentTypeParams, charset parameter, Text-String (extension-charset) branch: wraps the whole try/catch (CharacterSets.getMibEnumValue(new String(charsetStr)) and both map.put calls) in `if (charsetStr != null && map != null)`, so a null charset string or a null map is silently skipped.
- tests/TelephonyCommonTests/src/com/google/android/mms/pdu/PduParserTest.java (new): adds testParse_invalidContentTypeIndex_doesNotThrowAIOOBE (Content-Type short-integer index 83), testParse_elementDescriptorWithParams_doesNotThrowNPE (ELEMENT_DESCRIPTOR 0xB2 with a P_TYPE parameter, null map) and testParse_emptyCharset_doesNotThrowNPE (P_CHARSET with an empty string). It also adds two OOM regression tests (testParse_malformedHugeHeaderLength_doesNotOOM, testPduParserUnderflowOOM) whose conditions this diff does not touch.
Completeness
- Covers: the direct table lookup in parseContentType; the null map in the short-integer P_TYPE branch of parseContentTypeParams; a null charsetStr or null map in the extension-charset branch of parseContentTypeParams.
- The new bounds check in parseContentType only tests `index < length`, not `index >= 0`. It relies on parseShortInteger returning 0-127, as the comment asserts (not shown in the material).
- The diff does not touch the Well-known-charset else branch of the charset parameter or the other parameter cases of parseContentTypeParams (e.g. start, name). The material does not show whether they dereference map without a null check.
- No code change in this commit addresses the two OOM tests added in PduParserTest.java (huge part header length, uintvar underflow). The material does not show whether other commits already present in these branches handle those conditions.
Behavior changes
- A PDU whose Content-Type is encoded as a short integer with index >= PduContentTypes.contentTypes.length (83 or more) is now parsed with content type "*/*" (table entry 0) instead of aborting with an exception.
- A P_TYPE/P_CT_MR_TYPE well-known-type parameter seen while the parameter map is null (ELEMENT_DESCRIPTOR path) is now silently dropped instead of throwing NullPointerException.
- A text-string charset parameter is now silently ignored, instead of throwing NullPointerException, when parseWapString yields null or the map is null. When both are non-null, the existing behavior is unchanged, including mapping an unknown charset to CharacterSets.ANY_CHARSET.
Per major
- Android 14: Same fix: platform/frameworks/base 53f75b4de647 in android-security-14.0.0_r30, a cherry-pick of cbb0d81bf086 (Change-Id I4fab1579...). Identical hunks at the same line numbers (file index 6b3135945e53..775ef505ac2b) plus the new PduParserTest.java; 8/8 patched lines present.
- Android 15: Same fix: platform/frameworks/base 51268a5c0ff9 in android-security-15.0.0_r18. Diff and file indexes identical to Android 14; 8/8 patched lines present.
- Android 16: Same fix: platform/frameworks/base 60f9d9a0bcac in android-security-16.0.0_r9. Diff and file indexes identical to Android 14/15; 8/8 patched lines present.
- Android 17: Same fix: platform/frameworks/base 05fef2f15699 in android-security-17.0.0_r2. Identical hunks at the same line numbers, but the PduParser.java base blob differs (e805089306dc..d2f23026e5d8), so the file has differences outside the hunks; 8/8 patched lines present.
Unknowns
- Which process hosts PduParser.parse() for incoming MMS, and therefore what crashes (the material does not show callers or where the PDU bytes come from).
- Whether parseShortInteger can return a negative value; the new check has no lower bound and relies on the commented 0-127 range.
- Whether parseWapString returns null for an empty string (its body is not shown; only the test implies it).
- Whether the other parameter branches of parseContentTypeParams (Well-known-charset, start, name, etc.) dereference map without a null check.
- Which commit(s), if any, address the OOM conditions exercised by the two additional tests in the new PduParserTest.java.
- How the bulletin arrived at a Critical rating for a DoS type; the material gives only the rating.