shadow1ng/fscan · error

invalid oracle packet length %d

Error message

invalid oracle packet length %d

What it means

readPacket first reads an 8-byte header, then derives the packet length: 4 bytes big-endian for post-handshake sessions with version >= 315, otherwise 2 bytes. This error is thrown when the derived length is below the minimum viable packet (8) or exceeds the 16MB cap — a framing desync or malicious/garbage stream.

Source

Thrown at plugins/services/oracle_raw.go:245

	typ  uint8
	flag uint8
	raw  []byte
	data []byte
}

func (s *oracleSession) readPacket() (*oraclePacket, error) {
	header := make([]byte, 8)
	if err := s.readFull(header); err != nil {
		return nil, err
	}
	var length uint32
	if s.handshakeComplete && s.version >= 315 {
		length = binary.BigEndian.Uint32(header[0:4])
	} else {
		length = uint32(binary.BigEndian.Uint16(header[0:2]))
	}
	if length < 8 || length > 16*1024*1024 {
		return nil, fmt.Errorf("invalid oracle packet length %d", length)
	}
	raw := make([]byte, length)
	copy(raw, header)
	if err := s.readFull(raw[8:]); err != nil {
		return nil, err
	}
	p := &oraclePacket{typ: raw[4], flag: raw[5], raw: raw}
	if p.typ == oraclePacketData {
		if len(raw) < 10 {
			return nil, errors.New("short oracle data packet")
		}
		p.data = raw[10:]
		s.in = append(s.in, p.data...)
	}
	return p, nil
}

func (s *oracleSession) readFull(buf []byte) error {

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Check whether a prior parse error desynchronized the stream; re-establish the connection rather than continuing to read
  2. Confirm the peer is an Oracle TNS listener
  3. Verify the version-based length field selection matches the negotiated packet version
  4. If legitimate packets exceed 16MB, revisit the cap (unlikely for TNS control packets)

Example fix

// before
if length < 8 || length > 16*1024*1024 {
    return nil, fmt.Errorf("invalid oracle packet length %d", length)
}
// after
if length < 8 || length > 16*1024*1024 {
    return nil, fmt.Errorf("invalid oracle packet length %d (header % x)", length, header)
}
Defensive patterns

Strategy: validation

Validate before calling

func validPacketLength(length uint32) bool {
    return length >= 8 && length <= 16*1024*1024
}

Type guard

func isValidTNSSession(s *Session) bool { return s != nil && s.version >= 0 } // ensure version negotiated before length parsing

Try / catch

pkt, err := s.readPacket()
if err != nil {
    if strings.Contains(err.Error(), "invalid oracle packet length") {
        return reconnectAndRestart() // framing desynced; session is unrecoverable
    }
    return err
}

Prevention

When it happens

Trigger: connect or read calls readPacket on a stream where the header bytes are not a real TNS packet header — e.g. after protocol desync or from a non-Oracle peer.

Common situations: Parsing a stream offset by a few bytes after a misread packet; target service is not Oracle; corrupted TCP stream from a flaky link; attacker-supplied oversized length field.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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