shadow1ng/fscan · error
mssql: invalid us varchar size
Error message
mssql: invalid us varchar size
What it means
mssqlReadUSVarChar parses a TDS USHORT-length (UCS-2/UTF-16) string from a raw packet payload. After reading the 2-byte character count it computes the byte size as chars*2 and verifies those bytes exist in the payload. If they do not fit within the remaining buffer, it refuses to slice out of bounds and returns this error.
Source
Thrown at plugins/services/mssql_raw.go:404
return pos, fmt.Errorf("mssql: truncated token")
}
size := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))
next := pos + 2 + size
if next > len(payload) {
return pos, fmt.Errorf("mssql: invalid token size")
}
return next, nil
}
func mssqlReadUSVarChar(payload []byte, pos int) (string, int, error) {
if pos+2 > len(payload) {
return "", pos, fmt.Errorf("mssql: truncated us varchar")
}
chars := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))
pos += 2
size := chars * 2
if pos+size > len(payload) {
return "", pos, fmt.Errorf("mssql: invalid us varchar size")
}
return mssqlDecodeUCS2(payload[pos : pos+size]), pos + size, nil
}
func mssqlWritePacket(w io.Writer, packetType byte, payload []byte) error {
if len(payload)+8 > 0xffff {
return fmt.Errorf("mssql: packet too large")
}
header := []byte{packetType, tdsStatusEOM, 0, 0, 0, 0, 1, 0}
binary.BigEndian.PutUint16(header[2:4], uint16(len(payload)+8))
if _, err := w.Write(header); err != nil {
return err
}
_, err := w.Write(payload)
return err
}
func mssqlReadMessage(r io.Reader) (byte, []byte, error) {View on GitHub (pinned to 95cc12e753)
Solutions
- Verify the server is a genuine SQL Server speaking correct TDS; a wrong service on the port yields garbage payloads.
- Treat the stream as untrusted: this error indicates corrupt input — drop the connection and re-connect if transient.
- If parsing custom TDS tokens, confirm the token length field was honored before calling mssqlReadUSVarChar (offset advanced by the declared token size).
- Update the plugin/parser version — earlier token parsers may mis-offset subsequent usvarchar reads.
Example fix
// before
chars := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))
pos += 2
size := chars * 2
if pos+size > len(payload) {
return "", pos, fmt.Errorf("mssql: invalid us varchar size")
}
// after
chars := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))
pos += 2
size := chars * 2
if size < 0 || pos+size > len(payload) {
return "", pos, fmt.Errorf("mssql: invalid us varchar size (need %d bytes, have %d)", size, len(payload)-pos)
} Defensive patterns
Strategy: validation
Validate before calling
func canReadUSVarChar(payload []byte, pos int) bool {
if pos+2 > len(payload) {
return false
}
chars := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))
return pos+2+chars*2 <= len(payload)
} Try / catch
if err != nil {
if strings.Contains(err.Error(), "invalid us varchar size") {
// malformed TDS token: drop connection, mark target untrusted
}
} Prevention
- Never parse TDS payloads from unverified services; confirm the peer speaks TDS first.
- Honor token-level length fields before advancing into embedded strings.
- Cap accumulated parse sizes to catch truncated streams early.
- Reconnect rather than resynchronizing a corrupted stream.
When it happens
Trigger: Parsing a TDS token (e.g. an ERROR token via mssqlParseErrorToken, or mssqlSkipUSVarError) whose embedded usvarchar length field claims more bytes than the packet actually contains — typically a malformed, truncated, or maliciously crafted server response.
Common situations: Talking to a non-MSSQL or middleware service that emits broken TDS streams; a packet truncated by a proxy or NAT; fuzzing/pen-testing a fake SQL Server that returns malformed ERROR tokens.
Related errors
- mssql: packet type changed in message
- mssql: invalid packet size
- mssql: login acknowledgement not received
- mssql: invalid prelogin response packet type %d
- mssql: empty prelogin response
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/d300071de018168c.
Report an issue: GitHub.