text: ).
  20 Reader Comments
  Also, how did that code work in the first place? Seriously, that can't possibly have done what it was intended to do.
  I had that question as well, but I now think that it comes down to the specific tools and libraries used to compile and link (build). Some of the Microsoft tools will take several shots at type casting, "best guessing," sorting through all available versions of a function until it finds one that seems to match the given use, and so on. Functions can even be overridden within a project or library to match a given usage, meaning that a developer might once have taken that path. Therefore, it might have actually worked, once upon a time. I've noticed that with each generation of the Visual Studio package(s), Microsoft seems to make major changes to such things, particularly in enforcement of data types and type casting. Suddenly, old code that worked perfectly when built with the older tools, even if the code was flawed, won't even compile with the newer tools. That sort of thing is no doubt why they are putting their foot down and making developers use the latest libraries. I'm surprised that they had such loose standards and policies there.
  Let's you program in your lab coat?
  ++
  even a more strongly typed language (and associated API) like C++ would be useful.. void pointers make me cringe.
  Thanks for the info Emil,this is why I love reading your posts.
  As others have already pointed out, this kind of problem is a classic failure mode that managed code largely avoids. Everyone who has produced sizeable applications in c or equivalent languages spends a large testing effort trying to catch this kind of problem and still winds up shipping code with bugs that don't turn up for years.
  Don't be silly. That only works with VS2010 Lab Coat edition.
  There's a difference between being given direct access to memory and memory locations (manually dereferencing pointers to obtain memory locations, writing willy-nilly to memory, etc.), which can lead to the problem in this article, and controlling objects' lifecycles in memory, which GC does. That is, GC is not what saves you from this kind of flaw. Isolation from direct memory access and GC typically go hand in hand though.
  The nitroglycerine on the other hand, is going to kill you eventually, no matter what. It might take a few years, when you forget it's there...but it WILL kill you.
  Language used here is C++, not C. (as in most Microsoft software, and especially ATL - which as its name "Advanced Template Library" suggests - exists only in C++).
  c sharp is c#...
  sum.zero
  As an example:
  #include <stdio.h>
  int main(int argc, char* argv)
  {
  int x[10];
  printf("%x\n%x\n", x, &x);
  return 0;
  }
  ... since people rarely believe me. This code produces two equivalent printouts, because the value of x and &x are the same. The only thing that changes is the type. This is hard for people to believe because "an array is just a pointer" gets shoved down their throats. What makes this a bug is the TYPE, not the practice. If this code started out with a different type for the pbArray (as in a BYTE pbArray[SIZE]), it would work perfectly because it is correct code. However, the programmer declared a BYTE* and associated it with something else through the ironically named "SafeArrayAccessData" and screwed up the indirection. If the APIs weren't designed around void*, the cast would not be used, the compiler would have caught the problem.
  Now, I'll agree that using the type system in C this way is strange. And it is entirely possible that someone might be sloppy and do something similar anyway to convert "a pointer to a pointer" into "a pointer to data." But people can make similarly stupid mistakes in any language. It just so happens that this one resulted in a remote exploit instead of just a crash. There is nothing magic about C# - it is perfectly capable of being exploited too by bad programming practices. It is just less susceptible to this particular class of exploit.
  &array = pointer of array
  array = array
  The pointer "points" at a specific memory address as the begining location used by an array. So writing to it WILL write to the same location... the problem is that you can write something bigger and it will overflow to the next thing in memory, since pointers are not size limited.
  So it is valid code doing something unwanted.
  This is also not a TYPO, this is a mistake done by a programmer who INTENDED to make a pointer and SHOULDN'T have. if it was another language he would still make a pointer. Or do you think pressing "shift + 7" is right near the letter "p"?
  No. If you take an address of a BYTE*, you get a BYTE** which points somewhere else - in this case on the stack instead of wherever the structure is that they are trying to index into. This is exactly the mistake that was made, and is what is explained in the article. The code ended up pointing back onto the stack so you could end up writing data back onto the stack, allowing arbitrary code execution.
  If you take an address of a BYTE[], you get a BYTE*, and they are functionally equivalent in most cases, but the type is different. This is safe, correct, but not intuitive to people who are used to thinking of an array as a pointer with special decoration instead of a chunk of memory. However, it is conceivable that this is a "typo" in that it was useful before (with a auto declaration of a BYTE[] instead), but missed when they reworked the code. We don't know since we don't know the history, but I would agree that it is likely that someone just screwed up.
  Also, arrays (AND stl vectors...) are not size limited. If you index off the end, you just go off the end, just like with a pointer. There is no code to save you because you are assumed to know what you are doing.
  You must login or create an account to comment.