+1 exactly this, friend
That's a bit unfair. The Win32 apis were built with needing to propagate errors across different language barriers (i.e. so you could create MyAwesomeProgram in VB or Pascal or Fortran rather than being forced to use C/C++ in order to interoperate with the Microsoft libraries written in C/C++).
You can't unwind an exception over someone else's code (because you don't know how they are compiled), so you can't use exceptions, heap-pointer based exceptions (like C++) are also bad because it restricts what you can throw (i.e. you can't throw an out-of-memory exception if you'd need to allocate an OOM exception to throw one)
You also can't intern stuff like Java and C# because you don't have a common runtime (because some of the code in the process is Win32 C/C++, some is MyAwesomeProgram.vb and a third party component it is using is in delphi pascal, all interacting with a lovely frontend written in flash).
So sadly Microsoft only has one thing left: A global enum of all possible errors, i.e. HRESULTs.
Basically what I'm saying is that HRESULTs are dirty, but that's because they're intended for crossing language or API boundaries. Microsoft never intended or expected you to use them internally. They expected you to write code like this:
MyAwesomeVoid MyAwesomeFunc(AwesomeParam1 awesomeParams...)
And your runtime would do something like:
void CallOut( std::vector<AwesomeStuff> awesomes )
IEnumerable<void*> nativePtrs = map(awesomes => native);
HRESULT hr = Win32Api(nativePtrs);
if(hr != S_OK)
In fact, that is pretty much exactly what C#/VB.Net is doing under the hood.
It's not the fault of HRESULTs that they are crappy. It's the fault of developers for daring to attempt writing code in anything other than the glorious language of C/C++. If all developers could agree to only ever use C++, I'm sure Microsoft would be happy to dump HRESULTs and move to std::exceptions
@exoteric: you can't blame programming constructs for malicious behavior - you blame malicious programmers (attackers) and programmers who don't design security into their programming logic/patterns/design/architecture. That said, obviously, direct access to memory and unbounded data structures has led to many, many bad things, but then again, bad people do bad things - the developers who coded the holes aren't malicious or bad programmers (generally...), they just didn't/don't place enough emphasis on security, as they do, say, for performance and reliability...
I'd say it's really more about bad programming behavior (writing exploitable code on the one hand, then doing evil things with the holes on the other) than it is about bad programming language features used to write unsafe code that is then exploited by malicious developers for nefarious reasons...
That's why malicious is in quotes in the title and this thread is about what causes problems in practice, when being used by human beings, and not about what works in theory, if programmers were as reliable as computers.
The entire first post should be read to understand that.
No one tool serves all purposes but if a tool is involved in many incidents, when used by its intended users, perhaps that observation is worthy of reflection.
The post is meant to inspire a discussion about language design and on what features cause problems in the wild - an entirely pragmatic view. API design might be relevant insofar as it shows significant pitfalls of the language, as commonly used, in this sense.
The "with" keyword in Delphi.
It allows evil code like this:
SomeObject.SomeProperty := 'Value1';
SomeOtherObject.SomeProperty := 'Value2';
with SomeObject, SomeOtherObject do
SomeProperty := 'Who Knows which one is being set!';
// 50+ lines of code using the Objects without needing the actual object.
@Blue Ink: That's interesting. Macros form a pure functional programming language, right? A pure substitution system.
@Vaccano: That's a great example. I work in a language that has the WITH statement and while it looks nice on the surface because it can remove a little repetition it puts a burden of semantic analysis on the programmer - in particular with nested WITH statements. The cons outweigh the pros in my opinion.
Some people even prefix their variables in a certain way to clarify their scope; a practice that should be left to the compiler services behind the editor doing semantic analysis of the code. Hungarian notation should not be a naming practice but a service-assisted view of the code.