XTLS/Xray-core · error
buffer overrun
Error message
buffer overrun
What it means
Thrown by ReadUntilNull (proxy/socks/protocol.go:302) when reading a null-terminated string (SOCKS4 userid or 4a domain) exhausts the buffer without ever seeing 0x00. The function reads byte-by-byte into a fixed-size buf; a string longer than the buffer, or a client that never terminates, hits the IsFull() check and errors.
Source
Thrown at proxy/socks/protocol.go:302
return username, password, nil
}
// ReadUntilNull reads content from given reader, until a null (0x00) byte.
func ReadUntilNull(reader io.Reader) (string, error) {
b := buf.StackNew()
defer b.Release()
for {
_, err := b.ReadFullFrom(reader, 1)
if err != nil {
return "", err
}
if b.Byte(b.Len()-1) == 0x00 {
b.Resize(0, b.Len()-1)
return b.String(), nil
}
if b.IsFull() {
return "", errors.New("buffer overrun")
}
}
}
func hasAuthMethod(expectedAuth byte, authCandidates []byte) bool {
for _, a := range authCandidates {
if a == expectedAuth {
return true
}
}
return false
}
func writeSocks5AuthenticationResponse(writer io.Writer, version byte, auth byte) error {
return buf.WriteAllBytes(writer, []byte{version, auth}, nil)
}
func writeSocks5Response(writer io.Writer, errCode byte, address net.Address, port net.Port) error {View on GitHub (pinned to 7d214f8b09)
Solutions
- Fix the client to null-terminate userid and domain and keep them short (a domain is max 253 chars anyway).
- Treat occurrences from unknown sources as hostile probing: restrict inbound exposure and keep Xray updated.
- No server config change affects this; it is purely input-shape validation.
Example fix
// before: userid without terminator, never null
conn.Write([]byte{0x04, 0x01, 0x00, 0x50, 93, 184, 216, 34, 'r','o','o','t'})
// after: null-terminated userid
conn.Write([]byte{0x04, 0x01, 0x00, 0x50, 93, 184, 216, 34, 'r','o','o','t', 0x00}) Defensive patterns
Strategy: validation
Validate before calling
// Client-side: validate strings are short and null-free before encoding
func nullTerm(s string, max int) ([]byte, error) {
if len(s) >= max || strings.IndexByte(s, 0) >= 0 {
return nil, fmt.Errorf("string too long or contains NUL")
}
return append([]byte(s), 0x00), nil
} Try / catch
if err != nil && strings.Contains(err.Error(), "buffer overrun") {
conn.Close() // hostile or broken input; drop the session
return nil
} Prevention
- Always null-terminate SOCKS4 userid and 4a domain strings.
- Keep domains within DNS limits (253 chars).
- Rate-limit and restrict exposure of public SOCKS ports to reduce fuzzing noise.
When it happens
Trigger: A SOCKS4 userid or SOCKS4a domain name longer than the buffer size (2KB buf); a client that sends the string without the trailing 0x00; hostile fuzzing input designed to overrun fixed-size parsing buffers.
Common situations: Malicious or fuzzed input probing the SOCKS port; broken 4a implementations that omit the terminator; unusually long machine names/userids.
Related errors
- socks 4 is not allowed when auth is required.
- insufficient header
- failed to read domain for socks 4a
- unsupported command: %v
- failed to read auth methods
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/0efcc81151dea668.
Report an issue: GitHub.