Error messages considered harmful

My office nameplate was entirely apropos; LoadPicture continued to plague me throughout my career. During the Windows Security Push last year we finally turned it off. When VBScript is running in IE, the LoadPicture method causes an illegal function call exception.

Why’s that? There’s a big security hole in LoadPicture. Not because its buggy, but because it works too well!

When I added LoadPicture to VBScript I considered the security implications, but did I mention this was in my second week at Microsoft? I knew very little about security then. I reasoned that sure, this is a method that can access your hard disk, but what’s the worst it can do? It can open a locally stored picture file. Big deal! It can’t write any information back to the disk, so the risk seems very low.

Now of course we use the formal threat modeling process that my colleagues Mike Howard and David Leblanc describe in their book Writing Secure Code. We brainstorm possible threats and vulnerabilities, document them, and ensure that the code is built to resist those threats and mitigate those vulnerabilities. But in the bad old days the kind of off-the-cuff informal analysis I’ve just described was pretty typical.

The vulnerability in LoadPicture is that an attacker can write a web page which, when you visit the page, reports back to the web server your user name, what programs you have installed and potentially the names of your files. This is an information leaking vulnerability.

It can’t actually harm you directly, but attackers want to know everything about your machine. Knowing what all the user names are is a good first step in guessing their passwords. Knowing what programs you have installed tells them whether you’ve installed the latest patches, and hence whether you’re a potential target. And of course there is also the privacy angle. It isn’t anybody else’s business whether you have Office installed or not!

The vulnerability exists because, ironically, we did too good a job of reporting error messages. LoadPicture succeeds if you give it a valid path to an image file. But if you give it an invalid path, it gives you different error messages for “that’s not a legal path“, “that’s a legal path to a file which is not an image“, and “that’s a legal path, but it’s a directory, not a file“.

An attacker can make guesses about where various files and directories are on your system. The “Documents and Settings” folder contains a directory for every user on the machine. Thus the user names could be discovered via a dictionary attack (or brute-force attack; user names are usually short).

Of course, it could be worse. There was a bug in early versions of the CLR (which I believe was fixed before the first beta shipped, fortunately) where you could get an error message something like

Path discovery security exception: You are not allowed to determine the name of directory ‘c\:foobar’

Super! Thanks for letting me know!

The moral of the story is that as developers we tend to design code that produces the error messages that we need to be able to understand the problem and fix it. Unfortunately, those are the same data that attackers need to understand the system to break it. We’ve got to be careful not to leak information in error messages to insecure callers.

 

They call me “LoadPicture Lippert”

As promised, my least customer impactful bug ever.

VBScript version 1.0 was written by one of the VB compiler devs, one of those uber-productive developers who implements compilers on the weekend for fun. It was implemented and tested extremely rapidly, and as a result, a few of the less important methods in the VB runtime were not ported to the VBScript runtime. My first task as a full timer at Microsoft was to add the missing functions to VBScript 2.0.

On August 5th, 1996, I implemented LoadPicture, which, as you might imagine, extracts a picture from a storage. Here’s a scrap of the code I wrote:

IDispatch * pdisp;
// [... open storage and stream ...]
hresult = OleLoadPicture( 
  pstream, 0, TRUE, IID_IPicture, (void **)&pdisp );

Did I mention that I’d been writing COM code for all of two weeks at the time?

There’s a boneheaded bug there. I’m asking for an IPicture* and assigning the result to an IDispatch* This is going to crash and burn the moment anyone tries to call any method on that picture object because the vtable is going to be completely horked. I’ve violated one of the Fundamental Rules of COM. The fact that this bad code shipped to customers indicates that:

  • Most seriously, I did not adequately test it before I checked it in
  • my mentors did not adequately review the code
  • the test team did not adequately test it before it shipped to customers

Those are all bad, and I am happy to say that today we are much, much more hard-core about peer-reviewing, self-testing, buddy-testing, and tester-testing code before it goes to customers than we were seven years ago.

But there is a silver lining of a sort — obviously no one at Microsoft bothered to run this code after I wrote it. But neither did any users. We didn’t get a bug report on this thing until February of 1998. This thing was in the wild for almost a year and a half before someone noticed that it was completely, utterly broken! No one really cared.

The next day the name plate on my office door said LoadPicture Lippert. Ha ha ha, very funny guys.


A few germane questions from the comments:

Is there any use for that thing?

You can’t use it in a web page that loads from the internet for security reasons. HTML-based applications that run locally have better mechanisms for loading pictures. There’s no reason to use it from Windows Script Host or Active Server Pages. The only real use is when you have a trusted script and it is scripting an ActiveX control that can have pictures added to it dynamically.

It’s ironic that this problem would have been avoided had you used your hated smart pointers. Do you know that there are no other places in the script engines where a CoCreateInstance creates an interface and the target pointer does not match?

There is exactly one place in the original script engine code calls CoCreateInstance and it gets it correct; the script engine would crash immediately if that weren’t the case.

Sure, smart pointers would have saved me in this case, but a technique that detects a problem at compile time that would have been caught immediately the first time I ran the code is not really that interesting! The problem here is that I was so unprofessional as to not even run the code I’d just written, and to not show it to anyone who would have immediately realized that it looked wrong.

My distaste for smart pointers is because the bugs that smart pointers cause are deep, insidious, hard to debug, and require detailed knowledge of both the underlying COM concepts that they are abstracting AND detailed knowledge of the smart pointer implementation.

Like I said, I’m not smart enough to use smart pointers. IUnknown::Release I understand, and when I screw up some refcounting, I know how to fix it quickly. Smart pointers work great most of the time, and when they fail, it takes me all day to track down the problem.

Hi, I’m Eric and I’ll be your software developer this evening

The other day I mentioned my worst customer-impacting mistake ever — marking a heavily used object with the wrong threading model. A number of people commented to me that it was unusual to see a developer own up to such a mistake in a public forum. (Surprisingly, no one pointed out that it was also odd to do so while talking like a pirate.)

Well, it’s because of restaurants, believe it or not.

My father has been in the restaurant business for many years. Something he taught me at an early age is that one measure of the quality of a restaurant is how few mistakes they make, but a more important measure is how they treat the customer once a mistake has been made. Do they apologize, take responsibility, and immediately act to correct the mistake, or do they engage in cover-ups, blame-shifting and foot-dragging? I don’t go back to the second kind of restaurant, no matter how good the food is.

The software industry is no different. Here are four aspects to consider:

  • Customer focus: Most importantly, when a customer-impacting mistake is made it is necessary to inform customers of the problem, take responsibility and if possible fix the problem, period. If that means they think I’m a bozo, I’m cool with that. Preventing customer pain is a whole lot more important than anyone’s opinion of me.
  • Public image: Just because I don’t walk up to you and say “Hi, I’m Eric and I’ll be developing your application infrastructure and development tools this evening” doesn’t mean that said tools aren’t developed by humans with names and faces! Too often companies such as Microsoft are perceived as faceless monoliths, a few dozen six-story sea-foam-green glass boxes that mysteriously transform money into code. This misperception belies the reality; I work with dedicated and talented people who care deeply about making their customers more productive. All those people — all the testers, developers, managers, writers, etc, — deserve credit for shipping great software. And when someone really screws up, well, adult humans should be capable of the occasional mea culpa.
  • Evolution of the industry: The engineers who sign off on a bridge are quite literally putting their names on the line. If software engineering is ever going to evolve from a craft to a fully-fledged engineering discipline, we need to start acting like engineers. (And as a Waterloo math major, that’s hard for me to say with a straight face, believe me!) If I’m not comfortable with signing on the line and saying that this code is ready for prime time, then I shouldn’t be shipping it.
  • Diffusion of knowledge: Finally, the best mistakes to learn from are other people’s mistakes. Learning from your own mistakes sucks, not to put too fine a point on it. If I can help other people learn from my mistakes, so much the better for the world as a whole.

Coming soon: Eric’s least customer-impacting mistake ever. But that will have to wait until this evening, because my band has a gig at our Product Unit meeting this afternoon. Yes, the Trinity Team has their own rock band! We are “Red Pills Reloaded“, aka “Rage Against The Blue Pills“.


There was some discussion in the comments about the $DATA stream vulnerability that had been recently discovered, but I don’t think I’ll summarize it here, aside to say that it was fundamentally a “fail to the insecure mode” error.

The Visual Studio Tools for Office team used code names that were all from the “Matrix” series of movies, and it was a fun theme. We put together a cover band — I played keyboards — and did a lot of Steely Dan and other 1970s era rock, which was a lot of fun. Choosing a name inspired by The Matrix was an obvious choice, and now I am intensely disappointed that “red pill” has since been co-opted by misogynist jerks; I can’t in good conscience wear my The Red Pills t-shirt in public.

JScript eval redux, and some spec diving

I was discussing the difference between executing in local and global scopes the other day.  A reader points out something that I forgot to mention – there are two sneaky ways to manipulate the global namespace from an eval in JavaScript.

First, the Function constructor constructs a named function in the global scope. This had slipped my mind when I was writing the entry.

The second trick was very much on my mind but I did not mention as it would be yet another digression.  That is the fact that assigning a value to an undeclared variable creates a new variable in global scope.

This was on my mind because a couple weeks ago my friend CJ was debugging an irksome incompatibility between Gecko and IE. It turned out to hinge on the fact that in IE, fetching the value of an undefined variable is illegal, but setting it is legal.  According to CJ, in Gecko both are legal.

I wouldn’t know, never having actually used any browser other than IE since IE3 was
in development. (UPDATE: There is some dispute over this claim; like I said, I don’t know. Never tried it.)

If you look at the ECMAScript Revision 3 specification (E3) in some depth it becomes
clear that IE and Gecko are both in compliance with the spec, and yet incompatible
with each other.

“How’s that?” I hear you ask. The logic is a little tortuous!

Creating a new global variable when setting an undeclared variable must be legal according to E3 section 10.1.4, line 5, which states that an identifier undeclared in all scopes on the scope chain results in a “null reference”, and section 8.7.2, line 6 which states that an assignment to a null reference creates a new variable in the global scope.   IE does this, and I assume that Gecko does as well.

But setting the value of an undeclared variable must throw an error according to E3 section 8.7.1, line 3, which states that fetching the value of a null reference creates a ReferenceError exception. IE does this. If Gecko creates a variable in some scope rather than throwing a ReferenceError exception then clearly they have produced a situation in which a program running in Gecko has different semantics than when running in the browser used by the other 90% of the world.

Such situations are, as CJ, very painful for developers — mitigating this pain is why my colleagues and I went to the massive trouble and expense of defining the specification in the first place!  However, if that is the case then Gecko is not actually in violation of the specification thanks to E3 section 16, which states:

“An implementation may provide additional types, values, objects, properties, and functions beyond those described in this specification. This may cause constructs (such as looking up a variable in the global scope) to have implementation-defined behaviour instead of throwing an error (such as ReferenceError).”  [Emphasis added]

The E3 authors explicitly added the parenthetical clauses to make Gecko-like behaviour legal, though discouraged.  However, the clause is necessary — without this clause it becomes very difficult to define certain browser-object-model/script-engine interactions in a manner which does not (a) make both IE and Navigator technically noncompliant with the spec, (b) drag lots of extra-language browser semantics into the language specification and (c) make it difficult to extend the language in the future.

We earnestly wished to avoid all these situations, so the rule became “any error situation may legally have non-error semantics.” This is in marked contrast to, say, the ANSI C specification which rigidly defines what error messages a compliant implementation must produce under various circumstances.


As I noted above, this article produced immediate pushback from readers who said that CJ’s claim was wrong, that Gecko does the expected thing in this scenario, and suggested that he submit a reproducer of the defect.

Brendan Eich, the original designer of JavaScript and later CEO of Mozilla who stepped down after supporting anti-equality measures in California, said that I was “misreading” the specification, and that it was not intended to imply that any property can be referenced without error.

I have no idea what Brendan meant by this; the specification seems very clear to me; it specifically calls out that lookups in global scope need not throw.

All in all, the second half of this episode of FAIC seems to have been a waste of time and effort for all concerned.

Running Me Ragged

A reader of the previous episode asked me

Why are there two types of multidimensional arrays? What is the difference between the arr(x)(y) and arr(x,y)notations?

Good question. There are two kinds of multidimensional arrays, called “rectangular” and “ragged“. (Or “jagged”; either is common.)

A rectangular array is, well, rectangular. In VBScript you say

Dim MyArray(3,2)

and you get an array with indices:

(0,0) (0,1) (0,2)
(1,0) (1,1) (1,2)
(2,0) (2,1) (2,2)
(3,0) (3,1) (3,2)

which makes a nice rectangle. A three-dimensional array makes a rectangular prism, and so on up into the higher dimensions.

Now, as I mentioned earlier, JavaScript does not have multidimensional arrays. A clever trick to simulate multidimensional arrays in JavaScript is to make an array of arrays:

var x = new Array(
  new Array(1, 2, 3),
  new Array(4, 5),
  new Array(6, 7, 8, 9));

Dereferencing the outer array gives you the inner array, which can then be dereferenced
itself:

print(x[2][0]); // 6

But you notice something about the indices if we write them out as before:

[0][0]  [0][1]  [0][2]
[1][0]  [1][1]
[2][0]  [2][1]  [2][2]   [2][3]

The indices make a ragged pattern, not a straight rectangular pattern.

You can have ragged higher dimensional arrays as well, though allocating all the sub-arrays gets to be a royal pain, and I recommend against it.

There are often times when you want ragged arrays even in a language that supports rectangular multi-dimensional arrays, so VBScript supports both. If you say

MyArray(2,3)

then you are talking to a rectangular two-dimensional array. If you say

MyArray(2)(3)

then you are talking to a one dimensional array that contains another one dimensional array.

 

 

“For Each” vs. “for in”

While we’re on the subject of semantic differences between seemingly similar syntaxes, let me just take this opportunity to quickly answer a frequently asked question: why doesn’t for-in enumerate a collection?

A VB programmer is used to this printing out every item in a collection:

For Each Item In MyCollection
  Print Item
Next 

VB programmers introduced to JavaScript always make this mistake:

for (var item in myCollection)
  print(item);

and they are always surprised when this prints out a bunch of unexpected strings, or perhaps nothing at all.

The difference is quite simple.  In VBScript For Each enumerates the members of a collection. In JavaScript, for-in enumerates the properties of an object. In JavaScript if you have

var foo = new Object();
foo.bar = 123;
foo.baz = 456; 

then you can enumerate the properties:

for (var prop in foo)
  print (prop + " : " + foo[prop]) 

JavaScript needs such a control flow structure because it has expando objects and sparse arrays. You might not know all the properties of an object or members of an associative array. It’s not like VBScript where objects have fixed members and arrays are indexed by dense integer tuples. VBScript doesn’t need this ability, so it doesn’t have it.

Incidentally, in order to implement the for-in loop we needed to extend the functionality exposed by a dispatch object. Hence IDispatchEx which gives the caller the ability to enumerate dispids and go from dispid back to name.

In JScript to enumerate members of a collection, use the Enumerator object:

for (var enumerator = new Enumerator(myCollection) ; 
  !enumerator.atEnd(); 
  enumerator.moveNext())
{
  var item = enumerator.item();
  // ... 

The reaction I get from people who have not seen object-oriented enumerators before is usually “yuck!” This is an unfortunate reaction, as enumerator objects are extremely powerful. Unlike lexical For Each loops, enumerators are first-class objects. You can take out multiple enumerators on a collection, store them, pass them around, recycle them, all kinds of good stuff.

The semantics of the for in loop in JScript.NET are kind of a hodgepodge of both styles, with several interesting extensions. First off, if you pass an enumerator object itself to the JScript.NET for in loop, we enumerate it. If the argument is an object (or a primitive convertible to an object) then we enumerate its properties as JScript Classic does. If it is a CLR array, we enumerate its first dimension indices. If it is a collection, we fetch an enumerator and enumerate that. Otherwise, you’ve passed a non-enumerable object and we throw an exception.


There were a number of good responses to this article:

I like that you showed a common mistake of VBScript developers moving to JavaScript; what about VBScript developers moving to VB proper? What mistakes to they commonly make?

The advice I gave to the reader was to read Paul Vick’s blog, www.panopticoncentral.net I’m pleased that Paul is still blogging all these years later!

Here’s a clever trick for doing enumeration by passing in a function. We make a helper function, and then call it with the function to execute on each item:

function enumerate( coll, f )
{
  for( var en = new Enumerator(coll); 
    !en.atEnd(); 
    en.moveNext() )
  {
    f( coll.Item() );
  }
}
... 
enumerate(collection, function(item) { ... });

Though that is slick I am generally not that big a fan of mixing functional and imperative programming in cases where there’s an existing language construct that does the job.

I do sometimes need the ability to iterate property names in VBScript because it is often unclear what the properties of an object are; not all objects are well-documented.

The problem is that a lot of OLE Automation objects do not expose a mechanism for doing so; it can be tricky to go from an instance of an object to its type information.

Why are VBScript and JavaScript different in this regard?

VBScript and JavaScript were invented by different people at different companies at different times to solve different problems, so it should not be surprising that the languages are in many ways different.

Can we expect any enhancements to VBScript in this area?

We stopped adding new features to VBScript in 2001, so, I would not expect anything, no.

 

JScript and VBScript Arrays

Earlier I alluded to the fact that JavaScript arrays are objects but VBScript arrays are not. What’s up with that?

It’s kind of strange.

Consider the properties of a JavaScript array. A JavaScript array is

  • one dimensional.
  • associative; that is, indexed by strings. Numeric indices are actually converted to strings internally.
  • sparse: arr[1] = 123; arr[1000000] = 456; gives you a two-member array, not a million-member array.
  • an object with properties and methods.

Whereas a VBScript array is

  • multi-dimensional.
  • indexed by integer tuples.
  • dense.
  • not an object.

It is hard to come up with two things that could be more different and yet both called “array”!

As you might expect, JScript and VBScript arrays have completely different implementations behind the scenes. A JScript array is basically just a simple extension of the existing JScript expando object infrastructure, which is implemented as a (rather complicated) hash table. A VBScript array is implemented using the SAFEARRAY data structure, which is pretty much just a structure wrapped around a standard “chunk of memory” C-style array.

Since all the COM objects in the world expect VBScript-style arrays and not JScript-style arrays, making JScript interoperate with COM is not always easy. I wrote an object called VBArray into the JScript runtime to translate VBScript-style arrays into JScript arrays, but it is pretty kludgy. And though I wrote some code to go the other way — to turn JScript arrays into VBScript arrays — there were just too many thorny issues involving object identity and preservation of information for us to actually turn it on. There weren’t exactly a whole lot of users demanding the feature either, so that part of the feature got cut. (If I recall correctly, my colleague Peter Torr wrote some COM code to do that before he came to work at Microsoft. He might still have it lying around.)

Things got even weirder when I wrote the code to interoperate between CLR arrays and JScript.NET arrays, but that’s another story.


As I port this article over in 2019, I note that Peter is still at Microsoft, designing great developer experiences. Back in the early days — 1997 or thereabouts I think — I was answering JavaScript questions on USENET and Peter kept giving answers that were better than mine. I emailed him and asked if he’d be interested in working on the design of the language itself; that may have been the single email that I sent that got the biggest return on investment for Microsoft. 🙂

There were a number of good reader follow-up questions to this post. A selection:

The VBArray object is useful when we have an existing array in hand, but can we have a tool usable from JScript that produces a new one?

I always meant to add that to the runtime but never got around to it, sorry! I did add better support in JScript.NET, but that’s not super useful, I know.

How can I marshal a JScript array object to C#?

We designed the JScript array object interfaces and implementations long, long before C# was even thought of; there’s no obvious way to do so that I know of. Nowadays with dynamic in C# there might be a way to do it, but I’ve never tried.

Is there a way in VBScript to simulate for-in in JavaScript? That is, iterate over the keys, rather than the values, of a collection?

Nope, sorry.

 

Why does VBScript have Execute, ExecuteGlobal and Eval?

JavaScript has an extremely powerful (and almost always misused, but that’s another story) feature: eval takes a string at runtime and treats that string as though it were part of the compile-time text of the program. I added that feature to VBScript version 5, but I did it with three methods: Execute ExecuteGlobaland Eval

Why three, when JavaScript makes do with one? Let’s start by examining in detail what the JavaScript eval function does.

The JavaScript eval function takes a string, treats the string as JScript code, compiles the string, executes the resulting code, and returns the value of the last expression evaluated while running the code.

In JavaScript (and many other C-like languages) there is a fairly weak distinction between a statement and an expression. For example, this is perfectly legal JavaScript:

function foo()
{
  1;
  2;
  3 + 4;
}

This doesn’t do much; it doesn’t even return a value! But that’s not the compiler’s
problem. The behaviour of the statement 3+4; for instance is to add three to four and discard the result.

Also note that semicolons are semi-optional; more on that in a later post.

When you say eval("3+4") in JavaScript you get seven — the compiler adds the semicolon on, executes the statement 3+4; and returns the result of the last expression computed.

Now consider how JavaScript evaluates expressions that reference variables. The implementation of evalis smart enough to follow JScript’s rules for inner scopes shadowing outer scopes:

var x = 20;
function foo()
{
  var x = 10;
  print(eval("x"));
  // 10 -- eval uses local
}

This seems reasonable. But what if you evaluate a declaration?

var x = 20;
function foo()
{
  eval("var x = 10");
}
foo();
print(x);
// 20 -- declaration was local to foo.

Maybe it’s silly to want to add a declaration using eval. But hold on: as we already discussed, named functions are basically just variables with functions as values. Suppose you wanted to add a function dynamically:

function foo()
{
  eval("function bar(){ return 123; }");
  print(bar()); // 123
}
foo();
print(bar()); // fails

Why does the latter fail? Because the eval is done in the activation of the function foo, so function bar is local to foo. When the activation of foo goes away, so does local bar

The long and short of it is that if you want to affect the global name space, you have to do it explicitly. For example:

var bar;
function foo()
{
  eval("function barlocal(){ return 123; } bar = barlocal;");
}
foo();
print(bar());
// succeeds, bar is a global function.

(And of course, bar now refers to a closure. If foo took any arguments, they would be captured by barlocal.)

Now suppose you were tasked with implementing eval in VBScript, as I was. A few salient facts might spring to mind:

  • VBScript doesn’t have first class functions, so this trick with assigning a local function into global scope won’t work. (VBScript has a very weak form of first class functions that I’ll discuss later.)
  • But contrariwise, it would be a real pain in the rear if the VBScript’s eval equivalent couldn’t access local variables, and worked only at global scope.
  • VBScript does not have this weird property that expressions are statements. In fact, you can’t determine whether you’re looking at an expression or a statement lexically thanks to the assignment and equality operators being the same. Suppose you see X=Y — does that mean “set variable X to the value of Y” or does that mean “compare X to Y, leave both the same, and produce True or False“? Obviously we want to be able to do both, but how do we tell the difference?

There are three things that we need to do:

  • evaluate expressions
  • execute statements using local scope
  • execute statements using global scope.

My philosophy is when you have three things to do, implement three methods. Hence, we have Eval, which takes an expression and returns its value, Execute, which takes a group of statements and executes them in local scope, and ExecuteGlobal which executes them in global scope.

“I understand why you need to distinguish between Eval and Execute,” I hear you say, “but why have both Execute and ExecuteGlobal? Why not just add an optional IsGlobal flag to Execute?”

Good question. First of all, in my opinion it is bad coding style to implement public methods which have very different behaviour based on the value of a flag.  You do two things, have two methods.

Second, Boolean flags are a bad idea because sometimes you want to extend the method even more. VBScript has this problem in the runtime — a lot of the methods take an argument which is either 0 for “case insensitive” or 1 for “case sensitive” or a valid LCID, for “case sensitive in this locale”. What a mess! (Worse, 1 is a valid locale identifier: Arabic-with-neutral-sublanguage.)

In the case at hand, I suppose an enumerated type would be superior to a Boolean and extensible to boot, but still, it makes my skin crawl to see one public method that does two things based on a flag where two methods will do.


Commentary from 2019:

This article produced some interesting reader responses:


You do have a ExecuteGlobal of sorts in JavaScript using the new Function(…) notation. When you define a function in this way, it uses in the global scope rather than the containing scope. Add to that the JavaScript “feature” where variables declared without var are added to the global scope, and you get the effect of a ExecuteGlobal.

Good point; use it like this:

var x = 20;
function foo()
{
  var x = 30;
  var bar = new Function("x = 10");
  bar();
}
print(x); // 20

It seems that eval cannot distinguish between block statements and object literals! Compare eval("value={1:2,3:4}") to value=eval("{1:2,3:4}");

Great example! eval takes a statement; An object literal is not a legal statement, and so automatic semi insertion will not insert a semi.

Arrrrr! Cap’n Eric be learnin’ about threadin’ the harrrrd way

Avast ye scurvy dogs, it be National Talk Like A Pirate Day!

A scurvy bilge rat commented on the preceding discussion about putting apartment threaded objects in Session scope:

Back in the era of the NT4 Option Pack I wrote a lot of code that involved stashing Scripting.Dictionary objects in both session and application scope. […] I forget now which version of the runtime changed the threading model they were registered with and broke everything for me.

Shiver me timbers! That be my fault. Sorry about that.

When you create an ActiveX object, the COM runtime code checks the registry to see if the object is marked as participating in the Apartment, Free or Both threading models.  We’ll go into the difference between Free and Both at another time.

(UPDATE: I don’t believe I ever did.)

Now, when I was a young swabbie seven years ago I was given the task of implementing the Scripting.Dictionary object, and I didn’t yet understand all the stuff I just told you maties about threading.  In one build that was released to the public I accidentally marked the dictionary as Both, even though it is a Single Threaded Apartment object. So when lubbers would put a dictionary into Session scope, it would be called by multiple threads at multiple times, in violation of the apartment contract.  As long as there were only readers, it was generally OK, but as soon as there were readers and writers, it would usually crash and die.

And of course when we corrected the mistake, all those pages went from sometimes-crashing-but-fast to not-crashing-but-slow. That was my first majorly customer-impacting mistake, and probably the worst I ever personally made.

(UPDATE: Surely I have made worse since, but it really was very bad. Our code review protocols were not strong in those days. More on that below.)

Speaking of mistakes, there was another interesting performance mistake in early releases of the Scripting.Dictionary object. It uses a very simple hash table for rapid lookup, but of course hash tables require that the hash function distribute hashes broadly given a narrow distribution of keys.  I screwed up the hash algorithm, and one of the consequences was that hashing on a string consisting of five digits was likely to go to a very small number of hash buckets.

We discovered all this the day that msn.com decided to store every zip code in the United States in a Scripting.Dictionary object in Session scope!  Perf of msn.com went way south, way fast.

The combination of the two mistakes above led the ASP team to write their own string table object, that really was Both threaded and blindingly fast. Arr!


There was a lot of good reader response to this article, and a number of commenters went with the silly pirate theme:

So yer the bilge rat who caused that! I meant to ask you about it, arrr. To this day I be not using dictionary object because of a bad experience with it building some scurvy shopping carts.

When I boarded Microsoft a few years back for some Commerce Server demos, I asked a mate there about that bug (and if it still existed). He was most scurvy in his reply. Yarrr.

By the way, why was On Error Goto 0 not documented in earlier versions VBScript? Some lubber VB developer suggested that I try it, and I was very surprised back then that it worked. Were there any other undocumented scurvy features like that? What about easter eggs? Aarr.

Arr, you have to keep in mind that the VBScript documentation “team” at the time was one guy. Actually, not even one guy — Fred spent some time documenting other stuff as well I believe. Now, don’t get me wrong — Fred was a great guy, a lot of fun to work with, and very competent. But there simply was not enough time, budget and manpower to do a really proper job on the script engine documentation. A few things fell through the cracks now and then.

Documentation is extremely expensive. Writing it the first time is not so bad. Translating every page into 26 languages, that gets real expensive real fast.

Arrr! Havin’ spilled the beans, swabby, you best be protectin’ ye precious cannon balls from enemy swords. Many a tall ship crashed on the rocks of the Scripting.Dictionary. Aye, she was a most gnarly beast, for sure.

So, how did a green eared bilge monkey (I mean that in the nicest piratey way) like you come to possess the Scripting.Dictionary beast with nary a review by a superior officer? The captain must surely have been afire that day with many unruly mates on the plank, no?

Well, bygones begone, mate! Let’s heave a pint with a merry yo ho to brave Lippert’s mighty confession this day!

Arr, we certainly had code reviews, but the script team in the early days was pretty cowboyish.

The dictionary object shared its registration code with an object that really was Both threaded, and that fact led to the defect. In that situation even experienced code reviewers fall into the trap of “this code has been reviewed before, we can skip reviewing it this time.” As time went on we became more and more hard core about reviewing every line of every change.

ARR! So ye be the scurvy squad what made yon Dictionary object walk th’ plank! If I was a younger man, I’d a’ strung ya up and keelhauled ye afterwards!

Seriously, though — as much of a mistake that was, it’s good to see that you’re willing to owe up to it. It’s probably not proof against making an even bigger and more far-reaching mistake, but it also says a lot about the caliber of person you are.

Have you yourself ever used any third-party components to replace the Dictionary object, that are also thread-safe? And if so, which one(s)?

As I mentioned in the original article, the ASP team wrote their own “lookup table component”, which you used to be able to download from their site. I have no idea where it is now though.

 

Hard Core Denotational Semantics

Some of the readers of the Lambda blog were discussing my earlier throwaway line about Waldemar Horwat:

The august Waldemar Horwat — who was at one time the lead Javascript developer at AOL-Time-Warner-Netscape — once told me that he considered Javascript to be just another syntax for Common Lisp. I’m pretty sure he was being serious.

One user commented:

Mozilla’s CVS tree still contains the original implementation of Javascript… written in Common Lisp.

I can’t look at the Mozilla sources for legal reasons, so I can’t say for sure.  However, if you look at the drafts of the ECMAScript 4 specification that Waldemar was writing when he worked at Netscape, you’ll see that he uses this denotational semantics metalanguage to describe the operation of the ECMAScript language.  (This stands in marked contrast to the vague operational semantics used for the same purpose in the ECMAScript 1, 2 and 3 specifications.)

I vaguely recall that Waldemar had built a reference implementation of ECMAScript 4 in his metalanguage, and an implementation of the metalanguage in Common Lisp.  (Like I said, that guy is hard core.)  I hypothesize that this is the thing that the Lambda reader was talking about.  If someone could confirm or deny my hypothesis for me, I’d be interested to know.  It is unfortunate that I’m unable to look at this stuff, as I’m sure it would be fascinating.


UPDATE: This article makes a distinction between denotational semantics and operational semantics, and I could have taken the opportunity when it was originally published to discuss the difference in more detail.

Briefly: both are techniques for describing the semantics of a programming language. Denotational semantics is a more formal, mathematical approach where we associate programming language elements with mathematical objects, and then combinations of programming elements must be compositions of those objects.

Operational semantics is a more “algorithmic” approach where you describe what operations a virtual machine that implements the language would take. The original ECMAScript specifications were written as operational semantics. The ECMAScript 4 spec famously never shipped, and E5 went back to operational semantics.

The C# specification was deliberately written to mostly use neither technique; there are a few places where an operational approach is used, but the goal was to not have any “higher math” in the C# spec. It’s written in more or less plain English, and does not even carefully define important words such as “type”.