Quantcast
Channel: Randy Riness @ SPSCC aggregator
Viewing all articles
Browse latest Browse all 3015

MSDN Blogs: How can I check whether a parameter is a pointer to a stack variable?

$
0
0


A customer traced a bug in their program back to the fact
that somebody passed a stack buffer to a function that operates
asynchronously.
Something like this:



// This function sends the buffer to the destination
// asynchronously. When the send completes, the completion
// handler is invoked.
HRESULT SendDataAsync(void *buffer, size_t bufferSize,
ITransferCompletion* completion);

class ColorSender : public ITransferCompletion
{

};

// Code in italics is wrong
HRESULT ColorSender::SendColor()
{
COLORREF color = GetColorToSend();
return SendDataAsync(&color, sizeof(color), this);
}



This bug led to the destination sometimes receiving corrupted data
because it was a race between the stack variable being
reused for something else
and the data transport code copying the buffer into
the transport channel.
In this particular case, the customer fixed the problem
by making the color local variable
a member of the Color­Sender class,
because
the Color­Sender
object itself must remain valid for the lifetime of the
transfer seeing as it is the completion handler.
(We’re using the principle that

code is mostly correct
.)



The customer wanted to add some debugging code
to the Send­Data­Async function
so that it can assert that the buffer is not on the stack.
The customer understands that this may be overly restrictive,
and would not be appropriate for a function with a broad audience,
but this function is used only within their application,
so being extra-restrictive is probably okay.¹



On Windows 8 and higher,
the customer can use the
Get­Current­Thread­Stack­Limits function
to get the bounds of the current thread’s stack and use that
to verify that the buffer pointer is not in that range.
(Since this is just for debugging purposes, they can skip
the test if running on older versions of Windows,
and hope that their testing on Windows 8 will catch the
problem.)



¹ If it turns out that the check is too restrictive,
they could create two functions.
The first is called
Send­Possibly­Stack­Data­Async that
does no validation,
and the second is
Send­Data­Async
which does the initial validation that the buffer is not on the
stack, and then calls
Send­Possibly­Stack­Data­Async.
Most callers use
Send­Data­Async,
but if you’re in a special case where you are sending stack
data and you know that you won’t return from the function
until the completion occurs,
then you can use
Send­Possibly­Stack­Data­Async.
The team could have a rule that equires all uses of
Send­Possibly­Stack­Data­Async
to undergo a special review.


Viewing all articles
Browse latest Browse all 3015

Trending Articles