Reject unrepresentable POSIX listener descriptors before Unix-domain accept

Abierto Apto para principiantes
#1,082 1 comentario 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@ShahadatTest ya está trabajando en esto.

Desde el 3/11/2026.

  • #1083 de @ShahadatTest — abierto

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
84/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
rust

Línea de trabajo

Lee std/net/unix.wave en unix_accept y compara su validación con std/net/socket_base.wave y las rutas protegidas net_accept_v4/net_accept_v6. Añade pruebas de regresión para descriptores demasiado grandes y negativos al truncarse, y comprueba que un accept válido posterior recibe la conexión en cola y los datos. Ejecuta las regresiones con O0 y O2; informa por separado de los resultados en sistemas que no sean Linux.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug good first issue

Problem

unix_accept calls the native accept provider directly without the existing target-aware net_fd_valid guard. Its public listener field is i64, but POSIX descriptors are narrower. A value such as live_fd + 2^32 or live_fd - 2^32 is rejected by net_fd_valid yet can alias the real listener during the native call, consuming its queued connection.

Starting points: unix_accept and the existing target-aware descriptor validation. The guarded net_accept_v4/net_accept_v6 paths are useful references.

Reproduction

Audited canonical master e1f8effd195b6339c3979b1e091e63c25f1da983 on Linux amd64 with checkout-built Wave 0.0.1-alpha-dev, matching std, Rust 1.89.0, Cargo jobs=2 and LLVM 21.1.8. The master SHA was rechecked before registration.

The audit executed both offsets at O0 and O2 using fresh inherited, nonblocking local Unix listeners and one queued byte. The following compact reproduction combines those cases; no remote service is involved:

from pathlib import Path
import socket
import subprocess
import tempfile

root = Path.cwd()
compiler = root / "target/debug/wavec"
with tempfile.TemporaryDirectory(prefix="wave-unix-accept-") as temporary:
    directory = Path(temporary)
    for optimization in ("-O0", "-O2"):
        for delta in (4294967296, -4294967296):
            with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as listener:
                with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client:
                    address = directory / "listen"
                    if address.exists():
                        address.unlink()
                    listener.bind(str(address))
                    listener.listen(2)
                    listener.setblocking(False)
                    client.connect(str(address))
                    client.sendall(b"Z")
                    source = directory / "probe.wave"
                    binary = directory / "probe"
                    source.write_text(f"""
import("std::net::unix")::{{UnixListener,UnixStream,unix_accept,unix_read,unix_close}};
import("std::net::error")::{{NetResult,NetIoResult}};
import("std::net::socket_base")::{{net_fd_valid}};
fun main() -> i32 {{
    var invalid: i64 = {listener.fileno()} + ({delta});
    var result: NetResult<UnixStream> = unix_accept(UnixListener {{ fd: invalid }});
    println("valid={{}} accepted={{}} error={{}}",
        net_fd_valid(invalid), result.ok, result.error.native_code);
    if (result.ok) {{
        var sample: u8 = 0;
        var read: NetIoResult = unix_read(result.value, &sample, 1);
        println("read={{}} byte={{}}", read.count, sample);
        unix_close(result.value);
    }}
    return 0;
}}
""", encoding="utf-8")
                    subprocess.run([
                        str(compiler), "--std-root", str(root / "std"), "build",
                        str(source), optimization, "-o", str(binary),
                    ], check=True, capture_output=True, timeout=45)
                    result = subprocess.run(
                        [str(binary)], pass_fds=(listener.fileno(),),
                        capture_output=True, text=True, timeout=3,
                    )
                    print(optimization, delta, result.returncode, result.stdout.strip())

Observed for both offsets at O0/O2:

valid=0 accepted=1 error=0
read=1 byte=90

The invalid listener consumed a valid pending connection, and the accepted stream read Z. Reusing a listener after its connection was drained would not be a valid negative control.

Scope

Apply the existing target-aware descriptor guard before accepting a Unix-domain connection. Reject invalid listeners without accepting, closing or otherwise modifying the real descriptor or queued connection. Preserve valid-listener behavior, ordinary provider error contracts and full-width Windows SOCKET handling where applicable.

Related: #988 fixed ordinary portable socket entry points, #1069 timed TCP and #807 readiness. This direct Unix accept path is a separate remaining omission.

This is suitable for a first contribution: one public entry point, an established validation helper and a deterministic local-socket regression. No new API or descriptor-width policy is needed.

Completion criteria

  • Oversized and truncating-negative POSIX descriptors fail before native accept.
  • The pending connection and its queued data remain available to a subsequent valid accept.
  • Valid and ordinary invalid listeners retain expected results.
  • O0/O2 regressions exercise both offsets; non-Linux execution is reported separately rather than inferred from the Linux reproduction.
Lenguaje dominante
Rust
Estrellas
56
Forks
21
Merge medio
20 h 49 min
PR fusionados (30 d)
45

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de wavefnd/Wave

Todos los issues de wavefnd/Wave

Issues similares

Más issues de Rust

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.