Begin and End asynchronous calls in legacy .NET¶
Legacy .NET asynchronous APIs often pair a Begin method with an End method. Examples include stream BeginRead/EndRead and delegate BeginInvoke/EndInvoke on .NET Framework. The completion step retrieves results and observes asynchronous failures. Missing it is primarily a correctness and resource-lifecycle concern; a security impact needs evidence such as bypassed error handling or attacker-triggered resource exhaustion.
Observe completion before using results¶
Assume stream is an open System.IO.Stream, buffer is a nonempty byte array, and Consume processes only the indicated number of bytes.
Unsafe: assume the read has finished and filled the buffer.
IAsyncResult pending = stream.BeginRead(
buffer, 0, buffer.Length, null, null);
Consume(buffer, buffer.Length);
Safer within the APM contract: complete the matching operation.
IAsyncResult pending = stream.BeginRead(
buffer, 0, buffer.Length, null, null);
int bytesRead = stream.EndRead(pending);
Consume(buffer, bytesRead);
The End method receives the result from its matching Begin call. It may block until completion and can throw the operation's exception. Do not call it twice or pass a different operation's result. Microsoft's APM documentation describes this contract.
Handle errors at the owning operation boundary and keep the stream and buffer alive until completion. The synchronous wait above makes the pairing visible; it is not a recommendation to block an interactive UI thread. New code should normally use a supported task-based API, such as ReadAsync, and await its result. Legacy delegate asynchronous invocation is not a portability assumption for modern .NET.
Check the behavior¶
Use a local memory stream containing three bytes and a larger destination buffer. Assert that the safer implementation consumes exactly three bytes. Test an empty stream and a controlled failing stream; the caller must not report success after an exception. For an event-driven implementation, also test cancellation and disposal timing.
Review empty catch blocks, resource exhaustion and the C# guide. A suspicious Begin/End pattern requires API-specific review. Do not report every occurrence of asynchronous invocation as a vulnerability.