peass-ng/PEASS-ng · error · IOException

corrupted stream - negative length found

Error message

corrupted stream - negative length found

What it means

Thrown by ReadLength when decoding a DER long-form length: the first length byte indicates how many subsequent bytes encode the length, and that count exceeds 4 bytes, so the encoding is malformed or the stream is not valid DER at that position.

Source

Thrown at winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/asn1/Asn1InputStream.cs:302

                int size = length & 0x7f;

                // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
                if (size > 4)
                    throw new IOException("DER length more than 4 bytes: " + size);

                length = 0;
                for (int i = 0; i < size; i++)
                {
                    int next = s.ReadByte();

                    if (next < 0)
                        throw new EndOfStreamException("EOF found reading length");

                    length = (length << 8) + next;
                }

                if (length < 0)
                    throw new IOException("corrupted stream - negative length found");

                if (length >= limit && !isParsing)   // after all we must have read at least 1 byte
                    throw new IOException("corrupted stream - out of bounds length found: " + length + " >= " + limit);
            }

            return length;
        }

        private static byte[] GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
        {
            int len = defIn.Remaining;
            if (len >= tmpBuffers.Length)
            {
                return defIn.ToArray();
            }

            byte[] buf = tmpBuffers[len];
            if (buf == null)

View on GitHub (pinned to 53fb989abc)

Solutions

  1. Treat the input as corrupt; validate/verify its origin and integrity (hash, signature) before parsing
  2. Pre-scan the first bytes: tag + length must follow X.690 encoding rules before invoking the parser
  3. Use a parsing entry point with a bounded limit (Asn1InputStream with explicit limit) on untrusted data
  4. Catch IOException around ReadObject/FromByteArray and reject the object

Example fix

// before
Asn1Object o = Asn1Object.FromByteArray(untrustedBlob);
// after
if (untrustedBlob.Length < 2) throw new ArgumentException("too short");
try { Asn1Object o = Asn1Object.FromByteArray(untrustedBlob); }
catch (IOException) { /* reject corrupt input */ }
Defensive patterns

Strategy: validation

Validate before calling

static bool PlausibleAsn1Header(byte[] data)
{
    if (data == null || data.Length < 2) return false;
    byte tag = data[0];
    if ((tag & 0x1f) == 0x1f) return false; // high tag numbers unsupported here
    byte lb = data[1];
    if (lb <= 0x7f) return data.Length >= 2 + lb;
    int size = lb & 0x7f;
    if (size == 0 || size > 4 || data.Length < 2 + size) return false;
    // reject lengths that overflow to negative int
    return (data[2] & 0x80) == 0 || size < 4;
}

Try / catch

try { Asn1Object o = Asn1Object.FromByteArray(data); }
catch (IOException ex) when (ex.Message.Contains("negative length") || ex.Message.Contains("out of bounds"))
{
    // corrupt/hostile input: reject
}

Prevention

When it happens

Trigger: A length field of 4 bytes whose high bit is set (e.g. 0x80 0x00 0x00 0x00 style values >= 2^31), producing an int overflow to a negative number during parsing of crafted or corrupt data.

Common situations: Malformed or maliciously crafted ASN.1 input (fuzzing/attacker-controlled blobs); byte-order or offset mistakes corrupting the length bytes; parsing non-DER binary that happens to start with a tag-like byte.

Related errors


AI-assisted analysis of peass-ng/PEASS-ng@53fb989abc (2026-09-02). Data as JSON: /api/errors/1a0752bed87c6d3f. Report an issue: GitHub.