-2

I have a code that is accessing specific memory and writing to it :

*addr = _data;

but there are cases, in which addr variable can point to inaccessible memory, that cannot be read or written to (for instance, nullptr). In such case the code above should not be executed. The question is, how do i check if a memory address in addr is valid? I have learned that i cannot catch Access violation exceptions, neither i can use IsBadReadPtr WinAPI function, because it is basically useless. How should i check for such cases?

Mohammad Kanan
  • 4,452
  • 10
  • 23
  • 47
Eugen1344
  • 165
  • 3
  • 17
  • 5
    ***how do i check if a memory address in "addr" is valid?*** You can check against nullptr however you can't really check if it is valid. The best advice I will give is to avoid code like this. Modern `c++` is about using the standard library containers and smartpointers. I have not written code like your example in over a decade. – drescherjm Feb 09 '18 at 14:54
  • Perhaps `if (addr == nullptr)` or `if (!ptr)`? What do you mean by _is valid_? – Ron Feb 09 '18 at 14:55
  • 2
    All you can do is see if it is null. You can't tell if a non null address is valid. – NathanOliver Feb 09 '18 at 14:55
  • I am absolutely aware that i should never write code like this. I am writing this solely to test low level stuff, so i have to write to a random point in memory – Eugen1344 Feb 09 '18 at 15:05
  • @Ron by "valid" i mean writable and readable so my code will not throw access violation – Eugen1344 Feb 09 '18 at 15:06
  • 2
    You can't. You might be able to write to memory, but doing so corrupts your program. – David Heffernan Feb 09 '18 at 15:06
  • 2
    ***but doing so corrupts your program*** Exactly! What you are doing here is Undefined Behavior even if the memory is writable in your program's address space. One could use VirtualQuery to check every address before hand but its still UB. – drescherjm Feb 09 '18 at 15:12
  • @DavidHeffernan that is what i need. I need to corrupt my program without system exceptions – Eugen1344 Feb 09 '18 at 15:12
  • 1
    Just to be sure, you want to write defensive library functions which take an address to write into from the caller, and you have no control over the caller? – YSC Feb 09 '18 at 15:13
  • ***without system exceptions*** I don't think you can totally avoid that even if you are careful to check every address first. – drescherjm Feb 09 '18 at 15:14
  • **i have to write to a random point in memory** No; it's not random. Computers famously have needed a lot of effort to do random at all. Programs that do `int tmp = *(int*)rand())` or visa versa get every segfault they deserve – UKMonkey Feb 09 '18 at 15:26
  • 3
    Walk through the address space, and when you find a writeable page, write to it. Seems rather pointless to me. – David Heffernan Feb 09 '18 at 15:26
  • Just because you can read/write the memory address in question does not mean that you __should__ read/write at the memory address. It might not be owned by your program but by the runtime-support, bits of the OS etc – Richard Critten Feb 09 '18 at 15:42
  • @David Heffernan, to understand your comment, I am focusing on `stack` .. how could memory be invalid in `stack` though! provided that a pointer check comes before reading -> `if (addr) { *addr = _data;}` – Mohammad Kanan Feb 09 '18 at 15:49
  • @RichardCritten or it could be owned by the program ... like the middle of the stack ... good luck debugging that problem – UKMonkey Feb 09 '18 at 15:49
  • 2
    [This sounds quite a bit XY](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) (Maybe even XYZ), With a bit more information about the goal someone may be able to guide you out of this mess. – user4581301 Feb 09 '18 at 15:49
  • 2
    @UKMonkey yup it's the programmers version of Russian Roulette. – Richard Critten Feb 09 '18 at 15:51
  • Without a valid use case, the question seems broad .. – Mohammad Kanan Feb 09 '18 at 16:16
  • @Mohammad I've no idea what you mean – David Heffernan Feb 09 '18 at 16:16
  • @DavidHeffernan, I am considering the normal case of declaring a pointer and consuming its address ... this is because OP is derefrencing a pointer – Mohammad Kanan Feb 09 '18 at 16:18
  • @Mohammad Pointers are not restricted to point to the stack. Otherwise how would dynamic memory ever be useful? – David Heffernan Feb 09 '18 at 16:28
  • @DavidHeffernan, I know that, thats why I said, I am considering stack (vs. are not putting it in heap with `new`) – Mohammad Kanan Feb 09 '18 at 16:31
  • @Mohammad We don't really care what you are doing, these comments should relate to the question that was asked – David Heffernan Feb 09 '18 at 16:37
  • @DavidHeffernan, thank you! – Mohammad Kanan Feb 09 '18 at 16:41
  • Possible duplicate of [C++ - Check if pointer is pointing to valid memory (Can't use NULL checks here)](https://stackoverflow.com/questions/11787650/c-check-if-pointer-is-pointing-to-valid-memory-cant-use-null-checks-here) – xskxzr Feb 09 '18 at 16:45
  • @UKMonkey i can't even imaging a person stupid enough to do this. I, personally am deliberately trying to crash to program – Eugen1344 Feb 09 '18 at 16:54
  • 3
    Your question is asking how **not** to crash a program. Can't you just make up your mind? – IInspectable Feb 09 '18 at 17:04

2 Answers2

4

If you want to know, whether an address is writable, write to it. Wrap the code in an SEH handler, and take it from there.

You cannot reliably query writeability (using VirtualQuery, for example), since your process' address space is in constant flux. Doing so introduces a TOCTOU race.

IInspectable
  • 46,945
  • 8
  • 85
  • 181
  • And if the write succeeds (no exception) and the C++ program did not (logically) own the memory but was part of the runtime-support etc what state is the program in? – Richard Critten Feb 09 '18 at 15:45
  • @RichardCritten: The question was asking about writing to random memory, and I answered that question. I don't know what difference it makes, whether that memory is owned by the C++ runtime support, the Universal CRT, or the application. The OP wants UB without immediately terminating the process and I told them how to get UB without immediately terminating the process. I don't know, why this would be helpful, and cannot imagine what problem this would be the solution to. But that's not on me to judge either. – IInspectable Feb 09 '18 at 15:55
  • @IInspectable, But I don't get that! when your _program_ declare a pointer, its OS responsibility to track that address and make sure it does not corrupt .. I feel I am missing something! – Mohammad Kanan Feb 09 '18 at 16:13
  • 2
    @MohammadKanan: The OS doesn't know, what a pointer is. That's a programming language concept. The OS knows what addresses are, and it will protect against unauthorized memory access. It will not (and can not) protect against authorized (but invalid) memory access. C++ is not Java. The OS (or runtime, rather) doesn't track diddly. – IInspectable Feb 09 '18 at 16:22
  • @IInspectable, I know, I said _OS track that **address**_, but what I really stuck with is _invalid mem access_! .. the only case I know is when you `delete` your pointer and later accedently try to access it – Mohammad Kanan Feb 09 '18 at 16:39
  • @mohammad You can just stuff an arbitrary address into a pointer variable. Exactly as the asker is apparently doing in an act of self harm. – David Heffernan Feb 09 '18 at 16:43
  • 1
    @MohammadKanan: `*(int*)0 = 42;`? `*(float*)0xBAADF00D = 7.0f;`? `*(bool*)0xBABE2BED = true;`? \*me shrugs\*. – IInspectable Feb 09 '18 at 16:46
  • @IInspectable i am doing this exactly to crash my application, not to make a good design. So how do i wrap in it SEH handler? As far as i am concerned, this is not possible with Windows exceptions – Eugen1344 Feb 09 '18 at 16:47
  • 1
    @Eugen1344: If you attempt to crash your application, then you do not need to do any error recovery. `*(int*)0 = 42;` is sufficient. That is not clear from your question, though. – IInspectable Feb 09 '18 at 16:48
  • @IInspectable no, it's not. I don't want to have access violation exception as i clearly said in my topic – Eugen1344 Feb 09 '18 at 16:49
  • @Eugen1344: So then, what is your interpretation of *"crash"*. A process being shut down due to an access violation is a common interpretation of *"crash"*. – IInspectable Feb 09 '18 at 16:51
  • @IInspectable, ah really clear, appreciate your patience! – Mohammad Kanan Feb 09 '18 at 16:53
  • @IInspectable My definition is a process, being shut down due to a random error, not because of a raised system exception – Eugen1344 Feb 09 '18 at 17:04
  • 1
    @Eugen1344: What isn't random about a system exception? – IInspectable Feb 09 '18 at 17:05
  • What is motivating this question? – David Heffernan Feb 09 '18 at 17:10
1

Use VirtualQuery to obtain a page's protection and see if the region the pointer points to is writeable.

But note that this should not be used to conceal bad design. Make sure all pointers and references are valid when used.

IInspectable
  • 46,945
  • 8
  • 85
  • 181
The Techel
  • 918
  • 8
  • 13