views:

1332

answers:

6

I have some Visual C++ code that receives a pointer to a buffer with data that needs to be processed by my code and the length of that buffer. Due to a bug outside my control, sometimes this pointer comes into my code uninitialized or otherwise unsuitable for reading (i.e. it causes a crash when I try to access the data in the buffer.)

So, I need to verify this pointer before I use it. I don't want to use IsBadReadPtr or IsBadWritePtr because everyone agrees that they're buggy. (Google them for examples.) They're also not thread-safe -- that's probably not a concern in this case, though a thread-safe solution would be nice.

I've seen suggestions on the net of accomplishing this by using VirtualQuery, or by just doing a memcpy inside an exception handler. However, the code where this check needs to be done is time sensitive so I need the most efficient check possible that is also 100% effective. Any ideas would be appreciated.

Just to be clear: I know that the best practice would be to just read the bad pointer, let it cause an exception, then trace that back to the source and fix the actual problem. However, in this case the bad pointers are coming from Microsoft code that I don't have control over so I have to verify them.

Note also that I don't care if the data pointed at is valid. My code is looking for specific data patterns and will ignore the data if it doesn't find them. I'm just trying to prevent the crash that occurs when running memcpy on this data, and handling the exception at the point memcpy is attempted would require changing a dozen places in my code (but if I had something like IsBadReadPtr to call I would only have to change code in one place).

A: 

I am afraid you are out of luck - there is no way to reliably check the validity of a pointer. What Microsoft code is giving you bad pointers?

Nemanja Trifunovic
It's the Winsock 2 layered service provider (LSP) sample code.
jeffm
If you're working on an LSP, get ready for many days of hair pulling. And get a good Dev Support contract from Microsoft.
Michael Burr
+5  A: 

a thread-safe solution would be nice

I'm guessing it's only IsBadWritePtr that isn't thread-safe.

just doing a memcpy inside an exception handler

This is effectively what IsBadReadPtr is doing ... and if you did it in your code, then your code would have the same bug as the IsBadReadPtr implementation: http://blogs.msdn.com/oldnewthing/archive/2006/09/27/773741.aspx

--Edit:--

The only problem with IsBadReadPtr that I've read about is that the bad pointer might be pointing to (and so you might accidentally touch) a stack's guard page. Perhaps you could avoid this problem (and therefore use IsBadReadPtr safely), by:

  • Know what threads are running in your process
  • Know where the threads' stacks are, and how big they are
  • Walk down each stack, delberately touching each page of the stack at least once, before you begin to call isBadReadPtr

Also, the some of the comments associated with the URL above also suggest using VirtualQuery.

ChrisW
Thanks. I think the VirtualQuery idea is the most promising, but I don't really understand it. Do you have any idea why the code above doesn't work reliably?
jeffm
This wouldn't work in general. When you touch the stack guard page it will grow the stack only if you touched it from the thread that owns it!
Hrvoje Prgeša
+3  A: 

The reason these functions are bad to use is that the problem can't be solved reliably.

What if the function you're calling returns a pointer to memory that is allocated, so it looks valid, but it's pointing to other, unrelated data, and will corrupt your application if you use it.

Most likely, the function you're calling actually behaves correctly, and you are misusing it. (Not guaranteed, but that is often the case.)

Which function is it?

jalf
It's actually probably not a problem if the data can be read from but is bogus, because my code is looking for some specific data patterns and if they aren't there it will just ignore the data. It's the random crashes I'm trying to fix. :-)
jeffm
But it still means that the function you called has ventured into undefined territory. You can't really rely on it to not corrupt your program state any more.But of course the if you're willing to put up with that, simply catch the acccess violation and pretend nothing happened.
jalf
There's also the risk that these bit patterns are found in the random data it pointed to, which means you'll be the one corrupting your program state ;)
jalf
A: 

Why can't you call the api

AfxIsValidAddress((p), sizeof(type), FALSE));

Vinay
He can, but it won't help him: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/098e8b68-125d-4924-894c-acfcdbfe9035/
Nemanja Trifunovic
A: 

if you are using VC++ then I suggest to use microsoft specific keywords __try __except to and catch HW exceptions

Ahmed Said
A: 

Any implementation of checking the validity of memory is subject to the same constriants that make IsBadReadPtr fail. Can you post an example callstack of where you want to check the validity of memory of a pointer passed to you from Windows? That might help other people (including me) diagnose why you need to do this in the first place.

MSN