CVE-2026-0076 AI-generated analysis
platform/frameworks/base, libs/androidfw (ResourceTypes.cpp, binary XML parser ResXMLTree)
Adds a minimum-size check on ResXMLTree_attrExt::attributeSize in ResXMLTree::validateNode so binary XML nodes declaring an attribute size smaller than sizeof(ResXMLTree_attribute) are rejected with BAD_TYPE instead of being parsed.
Root cause
ResXMLTree::validateNode (libs/androidfw/ResourceTypes.cpp) validated a START_ELEMENT node's attribute block only by checking that attributeStart + (attributeSize * attributeCount) fits within the node (size - headerSize). It never checked that attributeSize itself was at least sizeof(ResXMLTree_attribute). Per the commit message, the code that later reads attributes uses the minimum sizes rather than the specified size, so a node declaring attributeSize smaller than that structure passes the product check while the actual accesses extend past the validated range, reading beyond the end of memory.
How the fix works
- libs/androidfw/ResourceTypes.cpp : ResXMLTree::validateNode: inside the existing branch that confirms the node is large enough to hold a ResXMLTree_attrExt, a new check is inserted before the attrSize product computation: if dtohs(attrExt->attributeSize) < sizeof(ResXMLTree_attribute), log 'Bad XML block: attribute size %d is smaller than min expected %d' via ALOGW and return BAD_TYPE.
- The pre-existing checks are kept unchanged: the node must be >= headerSize + sizeof(ResXMLTree_attrExt), attrExt must lie after node, and attributeStart + attributeSize*attributeCount must be <= size - headerSize. The new check makes the product check meaningful because each element is now guaranteed to be at least the minimum structure size.
- libs/androidfw/tests/ResourceTypes_test.cpp: new test ResXMLTree_ValidateNode_SmallAttributeSize builds a mock RES_XML_TYPE chunk with an empty string pool and one START_ELEMENT node whose attributeSize is sizeof(ResXMLTree_attribute) - 1 and attributeCount 1, with a node size padded so the old product check would pass, and asserts ResXMLTree::setTo returns BAD_TYPE.
Completeness
- Covers the specific gap: attributeSize below sizeof(ResXMLTree_attribute) is now rejected for every RES_XML_START_ELEMENT_TYPE node that passes through validateNode.
- The product attributeSize * attributeCount is computed in size_t from two 16-bit values, so it cannot overflow; combined with the new lower bound, the declared attribute range now fits inside the node's declared size.
- attributeStart has no lower bound check (it is only bounded above through attributeStart + attrSize <= size - headerSize); a small attributeStart would place attributes overlapping the attrExt header but still within the node, so this is not an out-of-bounds condition from the shown code.
- Only validateNode is changed; the material does not show the attribute accessor code, so whether any path reads attributes without first going through validateNode cannot be judged from the material.
Behavior changes
- ResXMLTree::setTo / node validation now returns BAD_TYPE for binary XML whose START_ELEMENT attrExt declares attributeSize < sizeof(ResXMLTree_attribute); such documents fail to parse instead of being accepted.
- A new ALOGW message 'Bad XML block: attribute size %d is smaller than min expected %d' is emitted when the check fails.
Per major
- Android 14: same fix: platform/frameworks/base 40ed3bb3016e in android-security-14.0.0_r28, identical 5-line check plus test; 8/8 patched lines present at android-security-14.0.0_r29.
- Android 15: same fix: platform/frameworks/base b4f448b356b1 in android-security-15.0.0_r16, identical diff content (hunk at line 1986 instead of 1915); 8/8 lines present at android-security-15.0.0_r17.
- Android 16: same fix: platform/frameworks/base a91d16a02b51 in android-security-16.0.0_r7, identical diff content (hunk at line 1989); 8/8 lines present at android-security-16.0.0_r8.
- Android 17: same fix: platform/frameworks/base 881e565347a5 landed in android-17.0.0_r1 (base release), identical diff; 8/8 lines present at android-security-17.0.0_r1.
Unknowns
- The attribute accessor code that reads using the minimum ResXMLTree_attribute size (referenced by the commit message) is not shown, so the exact out-of-bounds read site is not confirmed from the material.
- Which process or entry point parses attacker-supplied binary XML to make this an EoP, and the privilege boundary crossed, are not stated in the material.
- Whether any code path reads attributes of a node without a prior validateNode call is not shown.
- Whether any legitimately produced binary XML uses attributeSize below sizeof(ResXMLTree_attribute) is not shown.