internal/capi: zero-capacity UDP read fails with "bad buffer" and drops the datagram

Aperta Adatta ai principianti
#163 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
69/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
go
Ambito
networking

Direzione di ricerca

L’issue indica l’API C in tailcat.h e il percorso di lettura UDP verificato da internal/capi. Inizia leggendo la documentazione dell’API di lettura e i test di lettura UDP esistenti; la riproduzione può essere salvata in internal/capi/udp_zero_read_test.go ed eseguita con go test -v ./internal/capi -run TestUDPZeroCapacityRead. Il lavoro è completato quando le letture a capacità zero seguono un comportamento documentato e un test di regressione conferma se il datagramma viene consumato.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

tc_conn_read(conn, token, NULL, 0, &count, &err) on a UDP flow returns TC_FAILURE with read udp [...]: bad buffer, and the pending datagram is discarded even though the call failed.

tailcat.h does not say what a zero-capacity UDP read does, but it reads as allowed:

For UDP, one call consumes one datagram, truncating it if capacity is too small; an empty datagram returns TC_OK with count zero. buffer may be NULL only when capacity is zero.

The TCP case is spelled out ("A zero-capacity TCP read succeeds with count zero"); the UDP case is ambiguous.

Reproduction

Save as internal/capi/udp_zero_read_test.go (it uses the newE2E helpers from e2e_test.go in the same package) and run go test -v ./internal/capi -run TestUDPZeroCapacityRead:

package capi

import "testing"

func TestUDPZeroCapacityRead(t *testing.T) {
	x := newE2E(t)
	_, dialed, accepted := x.connect(UDP) // sends "hello"
	Write(dialed, x.token(), []byte("second"))

	buf0 := make([]byte, 0)
	n0, err0 := Read(accepted, x.token(), buf0)
	t.Logf("zero-capacity read: n=%d err=%v", n0, err0)

	buf := make([]byte, 64)
	n, err := Read(accepted, x.token(), buf)
	t.Logf("next read: n=%d err=%v data=%q", n, err, buf[:n])
}

Output:

zero-capacity read: n=0 err=read udp [fd7a:...]:39350: bad buffer
next read: n=6 err=<nil> data="second"

"hello" is lost / dropped.

Expected

Either of these, with more clarity in the header:

  • Treat it as truncation to zero bytes: TC_OK with count 0, consuming one datagram. This would match a too-small buffer (a 2-byte read of "hello" returns TC_OK with "he").
  • Reject it: TC_INVALID_ARGUMENT without consuming the datagram.
Lingua principale
Go
Stelle
8.8k
Fork
404
Merge medio
3h 48m
PR unite (30g)
1

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di tailscale/tailcat

Tutte le issue di tailscale/tailcat

Issue simili

Altre issue su Go

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.