microg/GmsCore · error · RuntimeException
Overread allowed size end=%d
Error message
Overread allowed size end=%d
What it means
The generated creator reads the parcel inside an explicitly sized block (end = payload start + object size). After deserialization it checks parcel.dataPosition() > end; if the reader consumed more bytes than the object declared, it throws RuntimeException("Overread allowed size end=%d"). This guards against corrupt or hostile parcel data where field headers claim more bytes than the enclosing object contains.
Source
Thrown at safe-parcel-processor/src/main/kotlin/org/microg/safeparcel/SafeParcelProcessor.kt:171
$variableDeclarations
$setVariablesDefault
while (parcel.dataPosition() < end) {
int header = $SafeParcelReader.readHeader(parcel);
int fieldId = $SafeParcelReader.getFieldId(header);
switch (fieldId) {
$readVariablesFromParcel
default:
$Log.d("SafeParcel", String.format("Unknown field id %d in %s, skipping.", fieldId, "$fullName"));
$SafeParcelReader.skip(parcel, header);
}
}
$invokeConstructor
$setFieldsFromVariables
} catch (Exception e) {
throw new RuntimeException(String.format("Error reading %s", "$fullName"), e);
}
if (parcel.dataPosition() > end) {
throw new RuntimeException(String.format("Overread allowed size end=%d", end));
}
return object;
}
@Override
public void writeToParcel($fullName object, $Parcel parcel, int flags) {
int start = $SafeParcelWriter.writeObjectHeader(parcel);
try {
$variableDeclarations
$setVariablesFromFields
$writeVariableToParcel
} catch (Exception e) {
throw new RuntimeException(String.format("Error writing %s", "$fullName"), e);
}
$SafeParcelWriter.finishObjectHeader(parcel, start);
}
@OverrideView on GitHub (pinned to 157c9d86ac)
Solutions
- Treat the incoming parcel as untrusted: validate size headers before passing to the creator, or reject the payload
- Align library versions between writer and reader so field layouts match
- Re-source the data (re-fetch / re-persist) instead of decoding the corrupt blob
- If the class schema legitimately changed, update both sides and bump the parcel format consistently
Example fix
// before: blindly unparceling untrusted data
val obj = CREATOR.createFromParcel(parcel)
// after: validate declared size against remaining bytes
val end = parcel.dataPosition() + parcel.readInt()
require(end <= parcel.dataSize()) { "Truncated parcel" }
val obj = CREATOR.createFromParcel(parcel) Defensive patterns
Strategy: validation
Validate before calling
// sanity-check declared size against remaining parcel bytes before reading
val header = parcel.dataPosition()
val size = parcel.readInt()
if (size <= 0 || header + size > parcel.dataSize()) throw SecurityException("Bad parcel size") Type guard
fun Parcel.hasValidObjectHeader(): Boolean {
val pos = dataPosition()
val size = readInt()
setDataPosition(pos)
return size > 0 && pos + 4 + size <= dataSize()
} Try / catch
try {
val obj = CREATOR.createFromParcel(parcel)
} catch (e: RuntimeException) {
if (e.message?.startsWith("Overread allowed size") == true) {
Log.w(TAG, "Parcel overread — corrupt/untrusted payload")
obj = null
} else throw e
} Prevention
- Treat parcels from other apps as untrusted input; validate sizes before deserializing
- Ensure writer and reader use the same library version and class schema
- Discard and re-source data when overread is detected instead of retrying the same blob
When it happens
Trigger: Deserializing a @SafeParcelable whose in-parcel length header is smaller than the fields actually encoded — e.g. truncated parcel, hand-crafted/malicious parcel, or a writer from a different library version that serialized extra fields while the reader assumes the old size.
Common situations: IPC payloads from a third-party app spoofing Play Services data; data written by a newer library version read by an older one; corrupted persisted state (Intent extras saved to disk, restored accounts) whose size prefix no longer matches contents.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- Access denied, missing google package permission for
- suggested UID [
- suggested PID [
- UID [
- null reference
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/c708a42c68b9e255.
Report an issue: GitHub.