Write timeout discards pooled buffer and latches write deadline to closed
medium swesweep-fasthttp · fasthttputil/pipeconns.go · Write · run #4
Description
When c.wCh is full and c.writeDeadlineCh fires, Write returns ErrTimeout without returning b to byteBufferPool. The buffer becomes garbage instead of being reused, so attacker-induced repeated write timeouts cause repeated allocation of potentially large byte slices and GC/memory pressure. c.writeDeadlineCh is also set to closedDeadlineCh permanently, making later full-channel writes discard buffers immediately.
Triage
- Verdict
- INVALID confidence 0.0
- Model
- qwen/qwen3.8-27b
- Rounds
- 5
- Cost
- $0.0205 · 102.6 s
1. **Bug Reality**: The code in `pipeConn.Write` confirms the reported pattern. If `c.wCh` is full and `c.writeDeadlineCh` fires, the branch `case <-c.writeDeadlineCh:` is taken. It sets `c.writeDeadlineCh = closedDeadlineCh` and returns `ErrTimeout` without calling `releaseByteBuffer(b)`. The buffer `b` is allocated via `acquireByteBuffer()` at the start of `Write`. This constitutes a leak of the buffer to the garbage collector. Additionally, because `closedDeadlineCh` is a closed channel, subsequent `Write` calls will immediately match this case, causing permanent timeout behavior and further buffer leaks. The bug is real. 2. **Threat Model & Reachability**: The threat model defines the attacker as code calling the public API and, specifically, 'parsers, decoders, deserializers and protocol handlers' that receive adversarial payloads. `PipeConns` is an in-memory, in-process bidirectional transport utility. It does not parse, decode, or deserialize untrusted external data (like network packets, files, or API requests). It simply shuttles bytes between two goroutines within the same trusted address space. The grep results show `NewPipeConns` is used in tests (`server_test.go`, `pipeconns_test.go`), an in-memory listener utility (`inmemory_listener.go`), and `stream.go` (internal fasthttp streaming logic). In these contexts, `PipeConns` is a trusted internal component. An external attacker cannot directly invoke `PipeConns.Write` with controlled timing to trigger the timeout race; they can only influence the host application's logic which, if written correctly, manages the pipe. Even if the host application passes data to `Write`, the 'timeout' condition depends on internal channel backpressure and timer state, not on the content of the data. Thus, the bug is not reachable via untrusted external input in a way that allows an attacker to trigger it at will. 3. **Security Relevance**: The impact is a resource leak (GC pressure) and functional degradation (connection becomes unusable). This is a resource management and code quality issue, not a memory safety vulnerability (corruption, OOB, UAF) or an authentication bypass. Under the provided threat model, issues that are not reachable through untrusted input or are mere code quality/resource hygiene issues in internal utilities are classified as INVALID. The 'attacker' would have to be a compromised internal component or a developer misusing the API, which is outside the scope of the 'external untrusted input' threat model for a library component like this. CRUX: PipeConns is an in-process, trusted transport utility that does not parse untrusted external input; the buffer leak is a resource hygiene issue not exploitable by an external attacker via the defined entry points. GREP: NewPipeConns
All rounds
[
{
"finding_title": "Write timeout discards pooled buffer and latches write deadline to closed",
"verdict": "INVALID",
"reasoning": "The reported vulnerability claims that when a write timeout occurs (`ErrTimeout`), the allocated `byteBuffer` is not released to the pool, causing a memory leak, and that the channel latches to a closed deadline, causing subsequent writes to discard buffers. \n\n1. **Bug Reality**: The code in `Write` indeed does not call `releaseByteBuffer(b)` when the `case <-c.writeDeadlineCh:` branch is hit. The buffer `b` (containing the payload `p`) is simply abandoned. Furthermore, `c.writeDeadlineCh` is set to `closedDeadlineCh`, which ensures that any subsequent `Write` call will immediately take the timeout branch (since selecting on a closed channel is always ready) and return `ErrTimeout` without releasing the new buffer. Thus, the mechanism for buffer discarding is real.\n\n2. **Threat Model & Reachability**: The threat model for a library like `fasthttp` (specifically `fasthttputil`) defines the attacker as code calling the public API or data passing through it. `PipeConns` is an in-memory transport. It is not a network-facing parser like `fasthttp`'s HTTP request handler. It is used by applications to connect in-process components. The \"attacker\" would need to be a trusted component within the same process that has access to the `PipeConns` endpoints. Even if an external network attacker sends data to a `fasthttp` server, the server's HTTP layer parses it, but `PipeConns` is not the entry point for untrusted network data. It is an internal utility. \n\n3. **Security Relevance**: \n - **Memory Leak/DoS**: While abandoning buffers to the GC is poor hygiene, it does not cause immediate memory corruption or crash. The GC will eventually reclaim these objects. \"Memory pressure\" leading to a crash requires extreme conditions (huge allocations, very high rate of timeouts) that are not a standard security vulnerability in an in-process pipe utility. \n - **Latched Deadline**: The fact that the connection becomes unusable after a timeout is consistent with `net.Conn` semantics where deadlines can expire. If an application sets a write deadline and it fires, the connection is typically considered \"stale\" or closed. The latching behavior might be a bug in the *utility* (it makes the conn permanently broken), but it is not a security vulnerability (like auth bypass or RCE) in the context of the threat model. \n - **Trust Boundary**: The threat model states: \"Not a vulnerability under this model: ... misuse that violates a documented precondition...\" and generally focuses on untrusted external input. `PipeConns` does not process untrusted external input directly; it shuttles memory between trusted in-process components. Therefore, an \"attacker\" cannot trigger this via untrusted network traffic. \n\n4. **Conclusion**: This is a code quality issue (resource leak and incorrect state management) in an in-process utility, not a security vulnerability exploitable by an external attacker. It does not lead to code execution, memory corruption, or significant DoS via untrusted input.\n\nCRUX: PipeConns is an in-process memory transport, not a network-facing parser; untrusted external input does not directly reach this code in a way that makes the buffer leak a security vulnerability.\nGREP: NewPipeConns",
"elapsed": 24.0,
"tokens": 4863,
"tokens_in": 4142,
"tokens_out": 721,
"cost_usd": 0.0039026399999999998,
"file": "fasthttputil/pipeconns.go",
"round": 1,
"grep_used": true,
"grep_results": "GREP `NewPipeConns`:\n```\nfasthttputil/inmemory_listener.go:111:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:15:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:85:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:157:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:229:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:232:\tpc = NewPipeConns()\nfasthttputil/pipeconns_test.go:290:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:293:\tpc = NewPipeConns()\nfasthttputil/pipeconns_test.go:364:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:379:\tpc := NewPipeConns()\nfasthttputil/pipeconns.go:11:// NewPipeConns returns new bi-directional connection pipe.\nfasthttputil/pipeconns.go:14:func NewPipeConns() *PipeConns {\nfasthttputil/pipeconns.go:33:// PipeConns must be created by calling NewPipeConns.\nserver_test.go:1238:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4439:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4494:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4541:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4594:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4652:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4838:\tpcs := fasthttputil.NewPipeConns()\nstream.go:30:\tpc := fasthttputil.NewPipeConns()\n```"
},
{
"finding_title": "Write timeout discards pooled buffer and latches write deadline to closed",
"verdict": "INVALID",
"reasoning": "The reported bug pattern is real: in `pipeConn.Write`, if the channel `c.wCh` is full and the `writeDeadlineCh` fires, the code returns `ErrTimeout` without calling `releaseByteBuffer(b)`. This leaks the allocated buffer to the garbage collector. Additionally, `c.writeDeadlineCh` is latched to `closedDeadlineCh`, causing subsequent writes to also timeout and leak. However, this is not a security vulnerability under the provided threat model. `PipeConns` is an in-process memory transport utility (`fasthttputil`). It does not parse or decode untrusted external data (like network packets). The 'attacker' for a library like this is typically an application developer misusing the API or passing malicious data into components that *use* this pipe, but the pipe itself just moves bytes. A memory leak in an internal transport mechanism, caused by a timing race between a full channel and a deadline, is a code quality/resource management bug, not a memory safety issue (corruption) or a direct DoS vector exploitable by an external entity via untrusted input. The threat model explicitly excludes issues that are not reachable through untrusted input or are code quality issues. Since `PipeConns` is an internal utility for connecting in-process components (often used for testing or internal IPC), an external attacker cannot directly control the `Write` calls or the channel state in a way that triggers this specific race to cause meaningful harm (crash/compromise) distinct from standard resource exhaustion which is mitigated by the GC.\n\nCRUX: PipeConns is an internal in-process utility and not a network-facing parser; the buffer leak is a resource hygiene issue, not an exploitable memory corruption or DoS via untrusted input.\nGREP: NewPipeConns",
"elapsed": 11.4,
"tokens": 5858,
"tokens_in": 5475,
"tokens_out": 383,
"cost_usd": 0.0034485,
"file": "fasthttputil/pipeconns.go",
"round": 2,
"grep_used": true,
"grep_results": "GREP `NewPipeConns`:\n```\nserver_test.go:1238:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4439:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4494:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4541:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4594:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4652:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4838:\tpcs := fasthttputil.NewPipeConns()\nstream.go:30:\tpc := fasthttputil.NewPipeConns()\nfasthttputil/inmemory_listener.go:111:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:15:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:85:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:157:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:229:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:232:\tpc = NewPipeConns()\nfasthttputil/pipeconns_test.go:290:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:293:\tpc = NewPipeConns()\nfasthttputil/pipeconns_test.go:364:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:379:\tpc := NewPipeConns()\nfasthttputil/pipeconns.go:11:// NewPipeConns returns new bi-directional connection pipe.\nfasthttputil/pipeconns.go:14:func NewPipeConns() *PipeConns {\nfasthttputil/pipeconns.go:33:// PipeConns must be created by calling NewPipeConns.\n```"
},
{
"finding_title": "Write timeout discards pooled buffer and latches write deadline to closed",
"verdict": "INVALID",
"reasoning": "The reported vulnerability claims that a write timeout in `PipeConns` causes a buffer leak (memory DoS) and latches the deadline, preventing future writes. \n\n1. **Bug Reality**: The code inspection confirms the mechanism. In `pipeConn.Write`, if the channel `c.wCh` is full and the `writeDeadlineCh` fires, the code executes `c.writeDeadlineCh = closedDeadlineCh` and returns `ErrTimeout` without calling `releaseByteBuffer(b)`. The buffer `b` is indeed leaked to the GC. Furthermore, since `closedDeadlineCh` is a closed channel, any subsequent `Write` call will immediately satisfy the `case <-c.writeDeadlineCh:` branch (as receiving from a closed channel is always ready), causing the same leak and preventing any data from being sent on that connection permanently.\n\n2. **Threat Model & Reachability**: The threat model defines the attacker as code calling the public API and data passed through it. However, it explicitly states: \"Not a vulnerability under this model: ... misuse that violates a documented precondition...\" and focuses on \"untrusted external input\" or \"adversarial payloads\". \n - `PipeConns` is an in-memory, in-process transport utility. It does not parse untrusted network data; it simply moves bytes between two goroutines in the same address space.\n - To trigger the leak, an attacker would need to control the timing of `Write` calls to the point where the channel (capacity 4) is full and the write deadline expires. This requires precise control over the internal state of the host application's in-process pipe.\n - Even if an external attacker sends data to a host application using `PipeConns` internally, the `Write` operations are performed by the trusted host application logic, not directly by the attacker. The attacker cannot directly invoke `PipeConns.Write`.\n - The \"leak\" is a resource hygiene issue (GC pressure), not memory corruption or immediate crash. While a tight loop of timeouts could theoretically cause high GC load, this is a Denial of Service via resource exhaustion that depends on the host application's specific usage pattern and the ability to induce frequent timeouts in an internal pipe. \n\n3. **Security Relevance**: The rules state: \"A data race on diagnostic state, a missing NULL check on an internal API that only trusted callers use, or undefined behavior only in debug builds are code quality issues, NOT security vulnerabilities\". Similarly, a resource leak in an in-process utility component that is not directly reachable by untrusted external input is a code quality issue. The primary use of `PipeConns` is for testing or internal IPC within a trusted domain. It does not handle untrusted external input directly. The impact (GC pressure) is negligible compared to the attack complexity (controlling internal pipe timing). Therefore, this is not a security vulnerability under the defined threat model.\n\nThe bug is real but is a code quality/resource management issue in an in-process utility, not an exploitable security vulnerability reachable by an external attacker via untrusted input.\n\nCRUX: PipeConns is an in-process in-memory transport utility; the buffer leak is a resource hygiene issue not reachable by external untrusted input in a way that causes meaningful security harm under the library threat model.\nGREP: NewPipeConns",
"elapsed": 13.2,
"tokens": 6647,
"tokens_in": 5935,
"tokens_out": 712,
"cost_usd": 0.0046286999999999995,
"file": "fasthttputil/pipeconns.go",
"round": 3,
"grep_used": true,
"grep_results": "GREP `NewPipeConns`:\n```\nserver_test.go:1238:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4439:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4494:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4541:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4594:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4652:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4838:\tpcs := fasthttputil.NewPipeConns()\nfasthttputil/inmemory_listener.go:111:\tpc := NewPipeConns()\nstream.go:30:\tpc := fasthttputil.NewPipeConns()\nfasthttputil/pipeconns_test.go:15:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:85:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:157:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:229:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:232:\tpc = NewPipeConns()\nfasthttputil/pipeconns_test.go:290:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:293:\tpc = NewPipeConns()\nfasthttputil/pipeconns_test.go:364:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:379:\tpc := NewPipeConns()\nfasthttputil/pipeconns.go:11:// NewPipeConns returns new bi-directional connection pipe.\nfasthttputil/pipeconns.go:14:func NewPipeConns() *PipeConns {\nfasthttputil/pipeconns.go:33:// PipeConns must be created by calling NewPipeConns.\n```"
},
{
"finding_title": "Write timeout discards pooled buffer and latches write deadline to closed",
"verdict": "INVALID",
"reasoning": "The reported vulnerability describes a buffer leak in `PipeConns.Write` where, upon a write timeout, the allocated `byteBuffer` is not returned to the pool, and the write deadline channel is latched to a closed state, causing subsequent writes to also leak buffers. While the code inspection confirms this resource management flaw (a leak, not a crash or corruption), the threat model for this library (fasthttp) defines the attacker as external code passing adversarial payloads through public API entry points that parse/decode untrusted data. `PipeConns` is an in-process, memory-based transport utility used to connect components within the same trusted address space (e.g., for testing or internal IPC). It does not directly parse or handle untrusted network input. The buffer leak results in minor GC pressure but does not lead to memory corruption, out-of-bounds access, or a meaningful Denial of Service that an external attacker can trigger via untrusted input. The 'attacker' would need to be a trusted component within the host application manipulating the internal pipe state, which is outside the scope of the external threat model. Therefore, this is a code quality/resource hygiene issue, not a security vulnerability.\n\nCRUX: PipeConns is an in-process transport utility that does not directly handle untrusted external input, making the buffer leak a resource hygiene issue rather than an exploitable security vulnerability.\nGREP: NewPipeConns",
"elapsed": 17.1,
"tokens": 7018,
"tokens_in": 6714,
"tokens_out": 304,
"cost_usd": 0.0037318800000000004,
"file": "fasthttputil/pipeconns.go",
"round": 4,
"grep_used": true,
"grep_results": "GREP `NewPipeConns`:\n```\nfasthttputil/inmemory_listener.go:111:\tpc := NewPipeConns()\nserver_test.go:1238:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4439:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4494:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4541:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4594:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4652:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4838:\tpcs := fasthttputil.NewPipeConns()\nfasthttputil/pipeconns_test.go:15:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:85:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:157:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:229:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:232:\tpc = NewPipeConns()\nfasthttputil/pipeconns_test.go:290:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:293:\tpc = NewPipeConns()\nfasthttputil/pipeconns_test.go:364:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:379:\tpc := NewPipeConns()\nstream.go:30:\tpc := fasthttputil.NewPipeConns()\nfasthttputil/pipeconns.go:11:// NewPipeConns returns new bi-directional connection pipe.\nfasthttputil/pipeconns.go:14:func NewPipeConns() *PipeConns {\nfasthttputil/pipeconns.go:33:// PipeConns must be created by calling NewPipeConns.\n```"
},
{
"finding_title": "Write timeout discards pooled buffer and latches write deadline to closed",
"verdict": "INVALID",
"reasoning": "1. **Bug Reality**: The code in `pipeConn.Write` confirms the reported pattern. If `c.wCh` is full and `c.writeDeadlineCh` fires, the branch `case <-c.writeDeadlineCh:` is taken. It sets `c.writeDeadlineCh = closedDeadlineCh` and returns `ErrTimeout` without calling `releaseByteBuffer(b)`. The buffer `b` is allocated via `acquireByteBuffer()` at the start of `Write`. This constitutes a leak of the buffer to the garbage collector. Additionally, because `closedDeadlineCh` is a closed channel, subsequent `Write` calls will immediately match this case, causing permanent timeout behavior and further buffer leaks. The bug is real.\n\n2. **Threat Model & Reachability**: The threat model defines the attacker as code calling the public API and, specifically, 'parsers, decoders, deserializers and protocol handlers' that receive adversarial payloads. `PipeConns` is an in-memory, in-process bidirectional transport utility. It does not parse, decode, or deserialize untrusted external data (like network packets, files, or API requests). It simply shuttles bytes between two goroutines within the same trusted address space. The grep results show `NewPipeConns` is used in tests (`server_test.go`, `pipeconns_test.go`), an in-memory listener utility (`inmemory_listener.go`), and `stream.go` (internal fasthttp streaming logic). In these contexts, `PipeConns` is a trusted internal component. An external attacker cannot directly invoke `PipeConns.Write` with controlled timing to trigger the timeout race; they can only influence the host application's logic which, if written correctly, manages the pipe. Even if the host application passes data to `Write`, the 'timeout' condition depends on internal channel backpressure and timer state, not on the content of the data. Thus, the bug is not reachable via untrusted external input in a way that allows an attacker to trigger it at will.\n\n3. **Security Relevance**: The impact is a resource leak (GC pressure) and functional degradation (connection becomes unusable). This is a resource management and code quality issue, not a memory safety vulnerability (corruption, OOB, UAF) or an authentication bypass. Under the provided threat model, issues that are not reachable through untrusted input or are mere code quality/resource hygiene issues in internal utilities are classified as INVALID. The 'attacker' would have to be a compromised internal component or a developer misusing the API, which is outside the scope of the 'external untrusted input' threat model for a library component like this.\n\nCRUX: PipeConns is an in-process, trusted transport utility that does not parse untrusted external input; the buffer leak is a resource hygiene issue not exploitable by an external attacker via the defined entry points.\nGREP: NewPipeConns",
"elapsed": 36.9,
"tokens": 7711,
"tokens_in": 7096,
"tokens_out": 615,
"cost_usd": 0.00482532,
"file": "fasthttputil/pipeconns.go",
"round": 5,
"grep_used": true,
"grep_results": "GREP `NewPipeConns`:\n```\nserver_test.go:1238:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4439:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4494:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4541:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4594:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4652:\tpipe := fasthttputil.NewPipeConns()\nserver_test.go:4838:\tpcs := fasthttputil.NewPipeConns()\nfasthttputil/inmemory_listener.go:111:\tpc := NewPipeConns()\nstream.go:30:\tpc := fasthttputil.NewPipeConns()\nfasthttputil/pipeconns_test.go:15:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:85:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:157:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:229:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:232:\tpc = NewPipeConns()\nfasthttputil/pipeconns_test.go:290:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:293:\tpc = NewPipeConns()\nfasthttputil/pipeconns_test.go:364:\tpc := NewPipeConns()\nfasthttputil/pipeconns_test.go:379:\tpc := NewPipeConns()\nfasthttputil/pipeconns.go:11:// NewPipeConns returns new bi-directional connection pipe.\nfasthttputil/pipeconns.go:14:func NewPipeConns() *PipeConns {\nfasthttputil/pipeconns.go:33:// PipeConns must be created by calling NewPipeConns.\n```"
}
]Raw scan report for this file
The public surface is `NewPipeConns`, the returned `net.Conn` ends, `SetAddresses`, and `Close`. Attacker-relevant input is primarily byte data passed through `Write`/`Read` and the behavior of the peer end (for example, whether it keeps reading). Classic out-of-bounds memory corruption is unlikely because `append` and `copy` are bounds-checked. The main risk areas are channel backpressure, deadline state handling, buffer pooling, and goroutine/resource exhaustion.
Key observations:
- `Write` copies data into a pooled buffer and sends it over a capacity-4 channel.
- If the channel is full and no write deadline is set, `Write` can block indefinitely.
- On write timeout, the buffer is not returned to the pool and the write deadline channel is latched to a closed channel.
- Read deadline handling can deliver attacker-queued data after the deadline has expired.
- Zero-length writes inject empty buffers, which can cause `Read` to return `0, nil`.
- `c.writeDeadlineCh` is written by `SetWriteDeadline` and read by `Write` without synchronization.
```json
[
{
"severity": "medium",
"title": "Unbounded writer blocking when the receiving end fills the channel and stops reading",
"function": "Write",
"description": "The write channel has capacity 4. If an attacker controls the reading end, it can stop calling Read after four buffers have been queued. Write then blocks in the inner select on c.wCh <- b. Without a write deadline, only Close can wake it, so many stalled connections can exhaust goroutines, stacks, and heap in the host process."
},
{
"severity": "medium",
"title": "Write timeout discards pooled buffer and latches write deadline to closed",
"function": "Write",
"description": "When c.wCh is full and c.writeDeadlineCh fires, Write returns ErrTimeout without returning b to byteBufferPool. The buffer becomes garbage instead of being reused, so attacker-induced repeated write timeouts cause repeated allocation of potentially large byte slices and GC/memory pressure. c.writeDeadlineCh is also set to closedDeadlineCh permanently, making later full-channel writes discard buffers immediately."
},
{
"severity": "low",
"title": "Queued attacker data can be read after a read deadline has expired",
"function": "readNextByteBuffer",
"description": "On read deadline expiry, readNextByteBuffer sets readDeadlineCh to closedDeadlineCh and then non-blockingly drains one rCh buffer. If an attacker has queued data at that moment, Read returns the data instead of ErrTimeout. Repeated one-buffer dribbles can keep a timed-out connection delivering data, weakening deadline-based protection against slow clients."
},
{
"severity": "low",
"title": "Empty writes can produce Read returns of 0, nil",
"function": "Write, Read",
"description": "Write accepts len(p)==0 and sends an empty byteBuffer. The peer consumes the empty buffer; read() then returns 0, nil and the top-level Read may convert the following errWouldBlock to nil, returning 0, nil. Protocol handlers that expect either bytes or an error may misbehave, and an attacker can trigger this with zero-length writes."
},
{
"severity": "low",
"title": "Data race on writeDeadlineCh between Write and SetWriteDeadline",
"function": "Write, SetWriteDeadline",
"description": "Write reads c.writeDeadlineCh in a select without synchronization, while SetWriteDeadline writes it without synchronization. A slow attacker can keep Write blocked, widening the window for host code to update the deadline concurrently. The race can cause missed deadlines, use of a stale channel, or undefined behavior under the Go memory model."
}
]
```