Hey I have a general question about accessing memory and crashes that may occur. How can you test if a certain address is readable/writeable?
If I for example have: mov eax,dword ptr [esi+100]
then if the address "esi+100" is not readable the application will crash. How can such a thing be avoided, I mean if it can't read from that address, then just dont and return from the function. Is there anyway to handle with this?
Thanks in advance
kemicza
Yes, there are multiple ways in Windows:
- establish an structured exception handler (SEH) and inside it handle the situation
- VirtualQuerry
- IsBadReadPtr
Most important and faster: control your pointers and/or do the pointer limits checks yourself and never try to access memory based on input from files or user without a prior check of your buffer llimits.
From the MSDN Page for IsBadReadPtr():
"This function is obsolete and should not be used. Despite its name, it does not guarantee that the pointer is valid or that the memory pointed to is safe to use."
Actually IsBadReadPtr was the first thing I tried that BogdanOntanu suggested, and it's exactly what I needed, and works exactly as it should :)
thanks!
That's a really, really, really bad idea. You can't fix bad pointers. All that function is going to do is make the existing bugs harder to find, and introduce numerous new ones. You've been warned!
Redskull is correct. :eek
Raymond Chen explains everything in great detail: IsBadXXXPtr should really be called CrashProgramRandomly (http://blogs.msdn.com/b/oldnewthing/archive/2006/09/27/773741.aspx)
...also, this blog post from Larry Osterman: Should I check the parameters to my function? (http://blogs.msdn.com/b/larryosterman/archive/2004/05/18/134471.aspx)
I've seen actual production code, a complex interaction between a number of custom COM components, that used IsBadReadPtr and IsBadWritePtr all over the place (presumably to prevent the app from crashing),...and it's frightening. Trying to debug these applications is nearly impossible. However, if you are using it in a simple app, under restricted conditions, it will probably work. But, you should be aware of it's limitations.
I have much the same comment as the rest, if you have to test if an address is valid or not, you have written the allocation code incorrectly. You should ALWAYS know the start address and boundaries of allocated memory and you should ALWAYS work within that range, do it otherwise and it goes BANG on you in embarrassing places.
Quote from: baltoro on January 29, 2011, 07:28:39 PM
Redskull is correct. :eek
Raymond Chen explains everything in great detail: IsBadXXXPtr should really be called CrashProgramRandomly (http://blogs.msdn.com/b/oldnewthing/archive/2006/09/27/773741.aspx)
...also, this blog post from Larry Osterman: Should I check the parameters to my function? (http://blogs.msdn.com/b/larryosterman/archive/2004/05/18/134471.aspx)
I've seen actual production code, a complex interaction between a number of custom COM components, that used IsBadReadPtr and IsBadWritePtr all over the place (presumably to prevent the app from crashing),...and it's frightening. Trying to debug these applications is nearly impossible. However, if you are using it in a simple app, under restricted conditions, it will probably work. But, you should be aware of it's limitations.
Raymond Chen is really overstating the case. The problem with the IsBadXXXPtr functions is mainly that they use exceptions as opposed to bounds checks to determine if the memory is available or not. Since I have yet to ever see a program posted here that uses guard pages (I have only ever written 1 that needed them) and not more than 3 or 4 in other languages, the use of exceptions is for the most part moot. However, as Hutch says, you can perform a bounds check much faster than generating an exception and even in the case of user input you should always verify any data entered to make sure its valid so it should not be an issue.
Edgar
I agree that the guard page issue (while valid) is not necessarily a big deal, but the problem is that the function merely tells you that the number you pass cooresponds to memory that is allocated; nothing about that means that it points to the RIGHT data, or that it's even a pointer at all; if you are unlucky, a loop counter could be construed as a "good pointer", yet it's just randomly pointing to garbage. And, even if it is a pointer in its own right, there's no function in the world that can tell you it's pointing to the data you think it is.
IMHO, the minute you become unsure of what a pointer is pointing to, your program is already too far gone.
-r
the logic of memory allocation in a protected mode operating system is very straight forward, from whatever scope you allocate memory you must have a working de-allocation within that same scope and with the allocated memory you have BOTH the start address and the amount allocated. That gives you the lowest and highest address that you can read and write and you should not need more than that. If you are calling a function that allocates memory and passes back the pointer you also need the length of that memory so that you know the upper address you can write to.
There are no short cuts or successful bypasses for doing this, storing BOTH the start address and the length are necessities for dealing with allocated memory. About the only exception is memory allocated on the stack as LOCAL as the procedure removes it on exit with the stack address correction.
LOCAL memPointer :DWORD
LOCAL mLength :DWORD
LOCAL upperMem :DWORD
mov mLength, 1024*1024 ; the LENGTH
invoke YourMemAlloc,mLength
mov memPointer, eax ; the POINTER
add eax, mLength
mov upperMem, eax ; the UPPER usable address