shadow1ng/fscan · error

BER length may be 1 or 2

Error message

BER length may be 1 or 2

What it means

ReadLength decodes a BER length field. If the high-bit short/long form indicates a long length, this implementation only supports 1- or 2-byte length encodings; any other long-form size byte is rejected with this error. It guards against encodings the parser cannot handle.

Source

Thrown at libs/grdp/protocol/t125/ber/ber.go:85

func ReadLength(r io.Reader) (int, error) {
	ret := 0
	size, _ := core.ReadUInt8(r)
	if size&0x80 > 0 {
		size = size &^ 0x80
		if size == 1 {
			r, err := core.ReadUInt8(r)
			if err != nil {
				return 0, err
			}
			ret = int(r)
		} else if size == 2 {
			r, err := core.ReadUint16BE(r)
			if err != nil {
				return 0, err
			}
			ret = int(r)
		} else {
			return 0, errors.New("BER length may be 1 or 2")
		}
	} else {
		ret = int(size)
	}
	return ret, nil
}

func WriteLength(size int, w io.Writer) {
	if size > 0x7f {
		core.WriteUInt8(0x82, w)
		core.WriteUInt16BE(uint16(size), w)
	} else {
		core.WriteUInt8(uint8(size), w)
	}
}

func ReadInteger(r io.Reader) (int, error) {
	if !ReadUniversalTag(TAG_INTEGER, false, r) {

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Extend ReadLength to handle 3- and 4-byte long-form lengths (0x83/0x84) if the server sends large payloads
  2. Capture the response bytes and confirm the length encoding; verify against BER DER rules
  3. Check for stream desync in preceding fields that would misalign the length byte
  4. Reduce certificate size or server response bulk if a 3-byte length is genuinely required

Example fix

// before
} else {
    return 0, errors.New("BER length may be 1 or 2")
}

// after
} else if size == 0x83 {
    r16, err := core.ReadUint16BE(r)
    if err != nil {
        return 0, err
    }
    r8, err := core.ReadUInt8(r)
    if err != nil {
        return 0, err
    }
    ret = int(r16)<<8 + int(r8)
} else {
    return 0, fmt.Errorf("BER length may be 1 or 2, got 0x%02X", size)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-scan the length byte yourself if you control framing
sizeByte := buf[pos]
if sizeByte&0x80 != 0 && (sizeByte&0x7F) > 2 {
    return errors.New("server uses unsupported 3+ byte BER length")
}

Try / catch

n, err := ber.ReadLength(r)
if err != nil {
    if strings.Contains(err.Error(), "BER length may be 1 or 2") {
        return fmt.Errorf("server BER encoding too large for this parser; patch ReadLength: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Any BER read (ReadEnumerated, ReadInteger, ReadApplicationTag, ReadDomainParameters, ReadConnectResponse) whose length byte uses the long form with a size selector other than 1 or 2 (e.g. 0x83 = 3-byte length) or corrupted length bytes.

Common situations: Large CONNECT_RESPONSE payloads (big certificate chains) encoded with 3+ byte lengths; desynced streams where a content byte is misread as a length; nonstandard server encoders.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/c0c9fc3ba63c303e. Report an issue: GitHub.