Thread: How to detect if a pointer points to invalid memory? (Win32)

  1. #1
    Registered User
    Join Date
    May 2007
    Posts
    41

    How to detect if a pointer points to invalid memory? (Win32)

    Hello...I call a function inside a DLL that allocates memory and returns a pointer to that memory area. Now how can I be sure that the memory it allocated can be read?

    I know there are API like isBadReadPtr() ecc. but I read everywhere that they crashes the programs using them...so how can I do this in C?

    Thanks

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Uhh, IsBadReadPtr does not crash your program if the memory can't be read. It will return true if it's bad or false if not.
    There's no "easy" way to know if memory can be read or not. The best way is simply to return a NULL pointer if something failed.
    In C, I don't know of any way other than IsBadReadPtr to figure out if it's bad or not.
    In C++, you could always use try/catch, but it's not a gaurantee.

  3. #3
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    You could call IsBadReadPtr() using Structured Exception Handling (SEH) - if your compiler supports it.

    gg

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > Now how can I be sure that the memory it allocated can be read?
    In what circumstances would you expect this to be ever false?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Unless you have access to kernel memory data structures, the only way to actually know if a memory address is valid is to attempt to access the memory and see if it fails. This, of course, should be done in a block protected by relevant exception handling, or you haven't got a chance to survive. [actually, you only need to check each first byte of every even 4KB region, since that's the granularity of the memory allocations].

    The way that the kernel COULD validate memory is by walking over the page-table entries relevant to that address - however, if the successrate of "just attempting access the memory" is relatively high (it's likely that you've been given a valid memory location) then "try and see" is an option.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    May 2007
    Posts
    41
    Quote Originally Posted by Elysia View Post
    Uhh, IsBadReadPtr does not crash your program if the memory can't be read. It will return true if it's bad or false if not.
    I was thinking that too...then I've read this: http://geekswithblogs.net/ssimakov/a...5/19/5066.aspx

    What do you think about that article?

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    From reading it, I see two things:
    A virtual memory address can be unmapped at any point when inside the function:
    Well, guard your memory access. Always a good rule. And second, this can happen whether or not you use the function. You can just validate the memory in some other way and then it becomes invalid - same thing. Different threads should never access the same memory without some sort of lock/synchronization.

    About the second... about the stack page guard.
    I don't know much about it, but since when do you pass a stack address to the function? That's stupid. A pointer to an object on the stack is always gauranteed to be valid since the stack doesn't delete objects.
    So then again... you pass a stack object by pointer to a function. Then what? Since a stack object cannot be destroyed (data only re-written; correct me someone if I'm wrong), then there's no point in checking. Sure, so they can pass an invalid address, but does that point to the stack?
    Also, other threads can't modify stack objects since each thread gets their own stack, so I find those points kind of moot.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    The article is correct - if you arbitrarily check ALL kinds of pointers with IsBadXXXPtr then you could cause more problems than you will fix. You should not check stack-addresses with IsBadXXXPtr [1].

    Which goes back to Salem's question: What are you actually trying to "fix"? If your app is using some DLL that has a function that returns a pointer to some memory, it is a broken implementation if you can't read that memory. The next question is of course if you and the DLL agree on the size and usage of that memory - but the DLL is fundamentally broken if it doesn't return a valid memory address when that is what's expected of it.

    [1] Since the stack is ALWAYS readable and writable by your application, that should cause no problem. The next problem is of course to determine if an address is within the stack. The following code shows how you can do that:

    Code:
    char *baseStackPtr;
    void initStackCheck(void *p)
    {
       baseStackPtr = p;
    }
    
    int isStackPtr(void *p)
    {
        char dummy;
        char *topOfStack = &dummy;
        char *cp = p;
        
        if (cp > baseStackPtr && cp < topOfStack) 
          return 1;
        return 0;
    }
    
    int main()
    {
        int x;  // Any local variabe in main will do. 
        initStackCheck(&x);
        ....
         // your code goes here.
        
        return 0;
    }
    Also, you will only hit a stack guardpage if you are using a negative offset off the current stack position, since the stack grows towards zero - so the code is most likely broken in some bad way in the first place, if you hit that problem - because it means you are using some piece of memory that you don't currently own!

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > A virtual memory address can be unmapped at any point when inside the function:
    But if it is unmapped, the process will be asleep at that point and the page will be in the swap file. When the process next runs, the illegal memory reference will be trapped by the OS to restore the page and then allow the process to continue.

    If it started out valid when you allocated it, it will remain so until you free it.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Elysia View Post
    About the second... about the stack page guard.
    I don't know much about it, but since when do you pass a stack address to the function? That's stupid. A pointer to an object on the stack is always gauranteed to be valid since the stack doesn't delete objects.
    So then again... you pass a stack object by pointer to a function. Then what? Since a stack object cannot be destroyed (data only re-written; correct me someone if I'm wrong), then there's no point in checking. Sure, so they can pass an invalid address, but does that point to the stack?
    Also, other threads can't modify stack objects since each thread gets their own stack, so I find those points kind of moot.
    It is quite common to pass a stack based address to a funciton - every time you use the address of a local variable, in fact, which is a fairly common thing - at least I do that quite often. [However, if we are talking of something returned from another function, it'd better NOT be a stack address UNLESS it's also been passed in by the calling code, and it's BELOW [a higher address than] the current stack pointer].

    Stack objects can not be destroyed BELOW your point on the stack, that is correct.

    Other threads can [but shouldn't] modify stuff on your stack, since all threads share the same memory mappings, and all stacks are shared within the task/process.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Salem View Post
    > A virtual memory address can be unmapped at any point when inside the function:
    But if it is unmapped, the process will be asleep at that point and the page will be in the swap file. When the process next runs, the illegal memory reference will be trapped by the OS to restore the page and then allow the process to continue.

    If it started out valid when you allocated it, it will remain so until you free it.
    I think this refers to a case where something is UNMAPPED, not "swapped out", so the memory is no longer valid. And this is only done [intentionally] by malicious code, and much more a problem when using kernel code than when using user-mode code.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #12
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Quote Originally Posted by --article--
    The only thing that IsBadReadPtr/IsBadWritePtr verifies is that at the instant that the API is called, there was valid memory at that location. There’s nothing to prevent another thread in the application from unmapping the virtual address passed into IsBadReadPtr immediately after the call is made.
    In simple language: a machine checking if food is poisoned is totally useless, because it doesn't stop anyone from injecting poison into the food after it is checked by the machine... lol.
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by maxorator View Post
    In simple language: a machine checking if food is poisoned is totally useless, because it doesn't stop anyone from injecting poison into the food after it is checked by the machine... lol.
    Good analogy!

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by matsp View Post
    I think this refers to a case where something is UNMAPPED, not "swapped out", so the memory is no longer valid. And this is only done [intentionally] by malicious code, and much more a problem when using kernel code than when using user-mode code.

    --
    Mats
    But then again, if malicous code is injected, what program wouldn't crash or behave odd? If it's in user mode, it's better that it crashes rather than execute malicious code. In kernel mode too, though it would be better with a graceful exist instead of crashing the entire OS.

    maxorator: Great quote
    I agree with that statement --> use memory guards when writing/reading from the same address from 2 or more threads.

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Yes, crashing when malicious code is run is definitely not a bad thing.

    Note also that "unmapped" in this context means not just free'd/delete'd, but that the memory has been "removed from the virtual space of that application". It can be done, for example if you delete the heap, or you map and unmap using VirtualAlloc and friends, but it's not your typical code.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Suggestions on this C style code
    By Joelito in forum C Programming
    Replies: 11
    Last Post: 06-07-2007, 03:22 AM
  2. Replies: 8
    Last Post: 01-04-2006, 07:42 PM
  3. Locating A Segmentation Fault
    By Stack Overflow in forum C Programming
    Replies: 12
    Last Post: 12-14-2004, 01:33 PM
  4. Manipulating the Windows Clipboard
    By Johno in forum Windows Programming
    Replies: 2
    Last Post: 10-01-2002, 09:37 AM
  5. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM