Hacker News new | past | comments | ask | show | jobs | submit login
I found a bug in the .NET framework and fixed it by hand-altering the DLL (nullspace.io)
332 points by antics on Aug 1, 2014 | hide | past | favorite | 118 comments

In situations like this, you can report the bug to Microsoft Connect:

1. Submit bug report. 2. Wait six months. 3. MS tech will post a comment, "this will be fixed in the next release". 4. Wait two more years. 5. Bug report will be closed as "won't fix".

This. One bug in IE9 clickOnce launching thanks to them changing how download prompting works.

1. Reported to connect whilst in preview release status. Closed. Reported again. Closed. FULL test cases provided.

2. We're a gold partner with a £500k spend a year on licenses. Partner support. 19 hours on the phone over 6 months, blame shifting between the IE and .net teams and a daily call to get the case closed without resolution. Got a registry patch from ass-end support after 4 months that we have to ship to 2000 users at 200 different companies rather than an upstream fix. This checks a check box in the security settings.

They broke their own product and won't fix it. Basically you can't use JS to redirect to a clickonce URL.

Now today, IIS just stopped serving shit with no errors, nothing. Can't get anything out of minidumps+windbg. Just stops. None of our code is running.

Who am I going to call?

Redhat that's who.

Yup. Its funny as a dot net dev you learn to really love a few ms things and really hate the others. C# is a brilliant language. Entity framework is an awesome ORM. But anything to do with deployment? IIS? So very much rage. I'm in charge of the build process on my team and I'm quickly becoming "that guy in the corner who swears all the time".

Your still not cursing as much as the guy building msi installers though...

Again, this. Even with WiX it's painful. HKLM vs HKCU + corporate deployment hell + why the fuck do I need two MSIs to bootstrap the CLR and VSTO. Argh.

I deal with VSTO, WiX, ClickOnce, IIS, COM, MSMQ and the usual bits. Pays well but it made my hair fall out and has taken a couple of years off my life at least.

I long for the gong to ring so I can go home to my MacBook and OpenBSD (where I truly belong).

I actually do that job too. That horror falls under the umbrella of "deployment."

Not a great fan of c#. It always dissolves into generic programming and constraint hell. Most of it is satisfying the compiler and working around shit (like non-serializable dictionaries), piss poor frameworks like MVC etc which have dubious lifecycle management for filters/attributes and state problems galore. Oh and sealed classes. Thanks bastards, I'll never need to mock them will I - oh wait!

Yes deployment is a broken pile of crap. We inevitably did an NIH and wrote a massive push deployment framework for that. Cost a fortune. And I look after our integration environment as well (TeamCity). TC is nice but the .Net toolchain is horrific. Requires so much maintenance it's unbelievable. Also everything is stateful meaning repeatability is a PITA.

I'm the sweary guy too. Usually "we should have used Java - we don't have to invent new wheels every two mins".

The only bit of our infrastructure that is reliable is some memcache boxes on CentOS which have been online without a reboot for over two years!!!

Give me a C compiler, preferably LLVM and let me leave all this behind.

I've had more luck then. Strange they first say it will be fixed and then later say it won't be fixed anyway, I always had the impression they had their stuff together at Connect. Slowly of course but I guess that's what's to be expected because of the sheer size (this is not in their defense, at all, just my idea of why that is). Probably also spend tons of time looking at issues posted by people thinking Connect is a Q&A like StackOverFlow. Anyway for the 6 or so bugs I filed, all for the C++ compiler, the flow was

1. Submit bug report. 2. Get response like "we're looking into it" 3. Wait 2 to 5 months

4a. MS tech (or sometimes event Stephan T. Lavavej himself) posts a comment, "this will be fixed in the next release" 5. Bug report closed as fixed 6. Wait x time where x mainly depends on the point in time of the release cycle where 1 occurred. The later 1, the smaller x. You've gotta time those bugs to get them fixed quickly :P

4b: "won'tfix" / "by design" i.e. I got an explanation of what I did wrong, or otherwise why it happens

4c: "deferred" i.e. posted something that can be worked around and considered too minor of an issue to fix soon

Hah. I filed a bug via MS Connect years ago and it was eventually fixed in release. It may take time, but it sometimes works.

Funny, I had something to do with this code back in the day! I'm guessing it was a copy+paste bug and they copied from the LambdaCompiler, which uses StrongBox<T> for its closed-over parameters[1], since StrongBox<T>.Value is a field. The idea was to have the closures be really fast.

The history of ET compiler: it started with LINQ in .NET 3.5. Originally it was pretty simple and just handled expressions. In .NET 4.0 we merged the entire codebase with the IronPython/IronRuby compiler trees, expanding the "expression trees" to handle statements. IIRC, it can generate almost any IL construct that you might need, and is usually a lot easier to work with. But we found .NET's runtime compiler (DynamicMethod) was a bit too slow for a lot of use cases. It also wasn't supported on some CLR configurations. To address this we wrote an interpreter and some heuristics to switch from interpreted to compiled. But the actual System.Linq.Expressions.Interpreter must have happened after 4.0, because I don't remember that at all. Instead we just shipped it as a shared library used by IronPython and IronRuby.

Here's the normal ExpressionQuoter: https://github.com/IronLanguages/main/blob/7be8b73e246bfb029...

And here was the interpreter. I don't see the ExpressionQuoter, so either that's a newer fork of the code that was rolled into System.Core, or maybe a completely new implementation. https://github.com/IronLanguages/main/tree/master/Runtime/Mi...

IIRC, ExpressionQuoter was mainly to support the Quote expression, and was always a bit buggy. The 3.5 version was seriously messed up, and our prerelease versions of .NET 4.0 also had various bugs, and very few tests. I tried to fix it by having it use the same reuse closure mechanism as the normal compiler. Funny that same feature caused issues later on.

[1] one might wonder: why use StrongBox<T>, essentially boxing every parameter, rather than just generating a type with only the right fields? The reason was that generating a type in .NET 4.0 timeframe was absurdly slow. Like, a few hundred per second slow. I think this has been largely fixed now, but it was a huge performance problem for Iron* language runtimes back in the day

So, do you think this is Dino's fault? :P

Hah. Or Tomas. Not sure. The S.L.E.Interpreter is after my time :)

It might be my fault... The DLR interpreter got rolled into .NET native so that ETs could be interpreted (hence the weird EETypeRva:0x01588388 error). I actually did the initial set of work on that having had experience w/ the DLR interpreter and handed that off to the .NET team. I probably did the expression quoter but I don't quite remember :(

One thing I'll point out though, it's a Field on StrongBox<T> for correctness not performance - the field needs to be capable of being passed by reference to get consistently correct semantics. That's simply not possible on .NET native using the interpreter so it will end up with copy in / copy out semantics (which could break people but it's pretty unlikely). Also StrongBox<T> pre-existed the DLR expression compiler and was originally added w/ LINQ's ETs in 3.5 so we were also just re-using what they had already done. IronPython actually had Reference<T> early on which grew into the DLR's version and then finally converged back on StrongBox<T>.

Aha! Good call on the ByRef. Totally had forgot about that. Yeah, that was very important for correctness.

Should have just used dotPeek instead of ilspy and writing IL code by hand. Recompiling would have certainly been easier. http://www.jetbrains.com/decompiler/

---Author here---

AWESOME TIP, stoked to try it out, thanks!

This kinda goes against a popular theory that Microsoft mine JetBrains for Visual Studio functionality improvement ideas (or more likely the blog author just doesn't work on VS or w/ the VS dev team all that much)

Awesome read btw!

I did this once with GCC.

"But GCC's open source!" you say.

Well, GCC is next-to-impossible to compile for a target other than the host, especially if the target isn't x86 or ARM; and GCC maintainers insist on precise test cases to vet a bug, even if the issue is immediately obvious from reading the source code and the bug only occurs in certain very complex situations.

(/me looks forward to the day Clang/LLVM becomes the default on Linux…)

> Well, GCC is next-to-impossible to compile for a target other than the host, especially if the target isn't x86 or ARM;

You're exaggerating. I had no problems compiling gcc 3.something targeting MIPS-I on an x86 Linux host.

I can't tell if you're being sarcastic. Generally, compiling GCC to target another architecture involves not only recreating most of the root directory structure (notably include files) of the target on the host, but also compiling libc, bintools, and a few other more obscure libraries. And this all needs to be done in the correct order (which involves something like compiling half of libc before compiling GCC, and compiling the rest of libc afterward).

Maybe in 3.x and MIPS it "just worked". My experience is 4.x and Tilera. Myself and another engineer dumped a week into that sinkhole before giving up.

Clang/LLVM on the other hand… ./configure && make && make install. No other wacky dependencies or build steps. And it generates better code in many cases (particularly when dealing with structures).

Depends on the approach.

In some distributions, say, Debian, there are readily available cross-compiler packages (like g++-4.4-arm-linux-gnueabi). I haven't rebuilt gcc, but the approach must be to pull package's source, add a patch and run the build - then debian/rules and myriad of various helper scripts will take the hassle of doing everything. Just can't be the other way since package builds are automated.

And there are other tools, like buildcross that also automate the job.

Have you tried to use buildroot ? http://buildroot.uclibc.org/

Unfortunately this had to cooperate with an existing root environment on the target, so buildroot (as fantastic as it is) was not an option.

> I can't tell if you're being sarcastic.

I'm not. The process is well described, it tells you exactly prerequisites, in which order to build them, and how to configure the directory structure for building gcc itself.

It worked for me the very first time I tried it.

Though I needed only a freestanding implementation, so I didn't bother with compiling libc. I believe that cross-compiling libc can be painful.

There are scripts that do this for you, but yeah it's still a bit wonky. Also, unless you're talking about some completely unexplored target architecture, there are entire root filesystems available already for cross compilation.

I tried to compile GCC for ARM (from X86 Windows), and it was a nightmare

> Windows

> nightmare

Not exactly sure what you were expecting. GCC on Windows is already wonky enough (MinGW? MinGW-w64?), I have no Idea how one can voluntarily try compiling GCC on Windows, let alone a cross compiler.

Back in the day, crosstool was a solid way to build cross-compilers:


I haven't really kept up with the latest stuff, but I've seen mentions of crosstool-ng, which may be a newer take on it:


So, no, it's not next-to-impossible. It's a little complicated, and that's why these projects exist, but my memory of crosstool was that it made it trivially easy: run the script, let it compile for a bit, and voila, you now have a brand-new cross-compiler toolchain.

I've used crosstool-ng as recently as 8ish months ago, so I will agree: it's not even remotely next-to-impossible but instead very very possible, and, I'd venture to say, almost easy.

Cross-compiling and Canadian-cross isn't fun but isn't that bad. There are good projects out there to help in the process. http://crosstool-ng.org/ is a good project that can make it much easier. They have Canadian-cross support but I haven't used it.

Just recently I wrote https://github.com/ikonst/LongPathFix to work around a clang/gcc issue, cause it seemed easier than going through the hoops of building clang for Win32, understanding its code and writing a patch good enough to be accepted.

I feel like a "freetard" "greybeard" "basement-dweller" (insert-your-own-pejorative-here) saying this, but: yet another reason why I will never ever base my livelihood on a closed ecosystem. Open source is certainly not a panacea, but needing to do something like this is just ridiculous.

As the former opposite of the freetard and greybeard, a mere corporate VB peon, you are 100% spot on.

Most of the commercial software dev stuff is like regularly salting and sandpapering your genitals. And I'm not talking about fine grit paper either. Even relatively popular fields like .Net are painful on a daily basis.

I really like to see inside the black boxes when they inevitably go wrong. Hell getting a backtrace out of a dump file on windows from commercial software is an art in itself for example.

I had the fortune of inheriting a Sun SparcStation 20 in 1999 that was being thrown out. That and NetBSD literally drove a spike through my mind and entirely destroyed my conception of proprietary closed source software. I really wouldn't touch it now but the money sorting out all the shitty little problems is pretty good, even if it tries to stab you in the face 5 times a day. There's lots of work as well unlike my preferred field of Unix and C.

So I agree with you but I'm a slut for cash and unreliable black boxes of software is good money even if it does feel like I'm the IT equivalent of a STD ridden stripper.

The point of free software is you can do what you want with it, including fixing it if needs be. I believe Stallman started the movement from frustration that he couldn't fix a problem in some software he used.

I know a lot of people here balk at the idea of paying for tooling, but Red Gate's Reflector[1] is absolutely amazing for situations like this. Not only is it a decompiler, but it allows you to decompile at debug-time and step into third party libraries.

Assuming they haven't been obfuscated, this is an extremely useful tool. I've used it to track down a number of issues within Visual Studio itself and within some of the non-open sourced components of Roslyn.

[1] http://www.red-gate.com/products/dotnet-development/reflecto...

Don't pay for Reflector. Throw JetBrains some more money - DotPeek [1] integrates nicely with ReSharper, or you can use it on its own for free.

I think the latest build can also provide PDBs to Visual Studio on the fly by acting as a source server (insane).

After years of Reflector being a free tool, Redgate added a time-bomb to new downloads and released a statement [2]

[1]: http://www.jetbrains.com/decompiler/

[2]: https://web.archive.org/web/20110205074826/http://www.red-ga...

You are justifying closed-source tools by using a closed-source tool to debug your closed-source tools?

That's exactly how the windows ecosystem works. Everything is pay per view.

By the time we've got the PO's signed if it was open source then I'd have solved the problem at hand.

To get around this, defensive purchasing is required: at least one VS ultimate license, at least one MSDN sub, ANTS profiler, IDA Pro, Azure VM allocation ready to roll for test machines and two guys who actually know something about all this.

This is the safety belt cost: about $30000 + $120k a person

I take issue with the authors use of the word "patch". He's not actually patching the DLL, just decompiling and recompiling which are quite familiar for most programmers. There might be some black magic associated with this particular DLL that we non-.net programmers doesn't understand.

I would personally be very careful with the recompiling dance, at least in other languages, as alignments and such might come out of place. A patch feels much less dangerous if this is something that is to be deployed.

(I always also try to rig such builds so that the build bombs if the dependencies change. That way it doesn't survive version changes without forcing someone to take a long hard look at it.)

Why wasn't the DLL signed? Is this not a thing?

DLLs are signed. But they aren't checked every time a DLL is loaded. It absolutely obliterates load time if you have to go through every byte of all your DLLs and hash them. (You have the option to turn this on within the registry, though)

Signing is almost useless in .Net. And it's certainly not in place for security purposes.

Signing wouldn't have addressed this because they're creating a new, modified executable. So they just make that one unsigned.

Sidebar: I haven't done deep C# in several years, since moving to F#.

This code is getting to look butt-ugly. It is not a good thing if it continues like this. We already have C++. Don't need another one.

Don't worry, each new version of C# gets more features from F# and Scala, this year we will get more syntax sugar and an extensible compiler (with proper IDE support - unlike F#): https://roslyn.codeplex.com/wikipage?title=Language%20Featur... . They will add pattern matching and maybe something more interesting in the version after that. There aren't too many practical reasons to pick F# over C# today and soon there will be even less. Lesson to learn: don't pick *ML language as a foundation. I am glad that Scala is evading F#'s academic fate.

F#'s academic fate? I'm curious as to why you think this. I'm guessing you are of the opinion Haskell is forever trapped in academia?

I do both C# and F#. But, at this point I think in ML no matter what which language I'm using. That said, though I'm delighted by F#, there are things that I really miss about C#:

* Haskell's type classes are awesome, and neither F# nor C# have them. But, you can realize them with a really simple pattern in C# whereas in F# you have to resort to reflection or generic hacks[1] (but inline functions usually make such hacks nicer in F#).

* Sum types are awesome. F# realizes them in two ways: with discriminated unions and pattern matching (mainly), or with abstract classes and inheritance. Both are powerful approaches, but the latter is particularly useful when you need unbounded sum types. Unfortunately, inheritance is somewhat crippled in F# because you can't define protected members (though you can override them). I find myself needing this when I'm designing a solution rather than merely implementing one. For instance, I find that designing a language/compiler is much easier with C# than with idiomatic F#.

* This is kind of a summary of the first two points: idiomatic C# is a better dynamic language, and I'm not referring to the `dynamic` keyword, though it certainly helps. I've created some really nice and secure APIs by making use of user-defined conversions. System.Linq.Xml is a good example of what I'm talking about.

* Finally, idiomatic C# is a nicer classical OO language than idiomatic F#. This is kind of obvious since F# is a "functional language" with OO features whereas C# is an OO language with functional features. But, when I say classical OO, I mean the Smalltalk style OO that came before C++. Alan Kay defined that kind of OOP as (1) Encapsulation, (2) Message Passing, and (3) extreme late binding. Neither C# nor F# quite has (2) and (3), but C# gets me the closest without coloring too far outside of the lines. Of course, this begs the question that OO is better than functional. Having done both for a long time, I'm convinced that it is the case (though I do think learning functional programming is the fastest path to getting good at OO). Lamentably, I can't yet defend this point too vigorously because I've only just discovered the joy or Smalltalk. But, here is a preview of sorts: Imagine being able to update a database schema and having your statically-typed code continue to run without needing to recompile.

[1] http://stackoverflow.com/questions/9868327/f-type-constraint...

"Of course, this begs the question that OO is better than functional. Having done both for a long time, I'm convinced that it is the case (though I do think learning functional programming is the fastest path to getting good at OO). Lamentably, I can't yet defend this point too vigorously because I've only just discovered the joy or Smalltalk."

Shoot me an email. Would love to chat some time. I've been doing OO for 20+ years and have become a big FP fan in the last 5.

I might would go OOP in a large commercial setting, but for small team startup-type work, pulling in all of that wiring and structure for delivering an MVP just looks crazy to me. Even for large greenfield projects, it makes more sense to me to start in the REPL, code the minimum amount necessary, and then "grow" your class structure as you start needing all that OOP goodness.

Wow, that is some fancy work. Though I shudder to think about deploying and maintaining that fix, and bringing new developers up to speed on why and how it was done.

I was also about to tell him to skip all the ildasm stuff and just use the online reference source (referencesource.microsoft.com) ... but that assembly isn't in there. So I guess ildasm was the best option.

The fact that you can even do this without setting off a ton of alarmbells about failed checksums is what really scares me.

The fact that people think you shouldn't be able to do this is what really scares me. :)

I should be able to change the software on my own machine, stored on and running on hardware I own, in whatever way I desire and have it do what I want. (And in practice I have - opening a binary in a hex editor and changing a few bytes is not at all beyond me.)

Of course you should be. But it still should generate warnings and force you to override some fairly impressive 'do you know what you are doing?' warnings.

> But it still should generate warnings

No it should not. DLL is basicly a reusable software library.

What you are suggesting makes no sense. I will give you B+ for confidence.

Thank you very much for explaining to me what a DLL is, I had absolutely no idea.

No problem.

How would you enforce that? First, hashing every byte of every loaded DLL destroys your runtime.

Second, if you're able to modify one DLL, you could overwrite whatever DLL was tasked with computing the checksum.

You can produce and consume signed libraries in .NET very easily. In practice it's becoming less common as .NET becomes more open.

As an aside, OP says he works with Bart De Smet and they're messing with expression trees. I bet that this is work related to Cortana and the expression trees are used for compiling standing Rx (Reactive Extensions) queries which Cortana uses extensively on the phone and in the cloud.

They recompiled with the new binaries.

I did the same for the Invoke-RestMethod cmdlet in PowerShell 3.0: http://nivot.org/blog/post/2013/05/07/PowerShell-Masochistic...

Wow, how did I not know about this ExpressionBlock class! There's always another gem waiting in the framework :D

I wish i knew about it about a year ago for a project I did.

My knowledge of the GAC is out of date but isn't a bit of a security hole that you can replace that DLL?

They didn't replace it - it looks like they created a new assembly with its own strong name, registered it alongside the 'official' assembly, and referenced their assembly in place of the .NET native assembly at compile time.

What's maybe surprising is that the C# compiler generated code 'adopts' the types in their hacked expressions library. But the C# compiler, wherever it depends on particular types that need to exist for it to do its thing, has always generally relied on finding those types by -name-, not by -name and assembly strong name-.

For example, the C# 3 compiler understands the calling and declaration syntax of extension methods, but to compile an extension method, it requires an Attribute type - System.Runtime.CompilerServices.ExtensionAttribute - which was only introduced into .NET in v3.5. But if you make an attribute class with that name available to the C# compiler, you can compile code using C#3 extension method syntax against the .NET 2.0 framework libraries.

You need to be a local administrator to write to the GAC by default. See http://msdn.microsoft.com/en-us/library/yf1d93sz(v=vs.110).a...

So if you can modify the files in the GAC, you're already compromised at that point.

Writing to the GAC is easy, but assemblies in the GAC are strongly-named. Actually replacing one without the private key would require forging a signature, which is what parent was probably referring to. You can give an assembly the same name, but if it's signed with a different key it gets a different strong name (and therefore goes in a slightly different directory).

I don't think it's a replacement, since signing the new DLL would require a new key. (GAC DLL identity basically comes down to name + signing key. So even if you call it System.Whatever, it has a unique identity)

The real news here is that this is considered special.

In most other languages, they'd have forked the source, fixed it, recompiled it for their own uses and submitted a pull request or patch.

I'm a big .NET fan, but the fact that we have to jump through such hoops to find and fix a bug, and then still have near certainty that we're going to have to reapply the patch for many updates to come, well, that's just a bit sad. It feels rather last-century, to be honest. Microsoft could save a lot of double work if they'd just open source .NET and attach a decent process to it. They can still be the Linus. Just consider my patches.

---Author here---

I should disclose that I actually work for Microsoft, and still chose the hard way. Fuck the police!

For sure, those who complain about Microsoft not being open source are obviously trying to cover the fact that they are bad at reading assembly language.


That's the key word that should let you know an attempt at humor was imminent.


That, and they're too poor to buy IDA Pro.

> and still chose the hard way

Chose? Unless you work on the team that made that DLL, it's likely you'd be jumping through hoops even internally.

From good source here:

You don't actually jump through hoops. All you get to do is submit the bug, which gets logged in the bucket of thousands of other bugs.

Then the PMs will gather for bug triage for the next release, which have to compete with the next shiny project features. Nobody wants to fix bugs that only one developer has. It's just not worth it. This bug has existed for years, and it is likely you could modify your code to generate different byte code.

So the bug likely won't be fixed for a while.

I love .NET. I am just describing the reality of the process of bug fixing. Also, if you fix it, who knows what else will regress. That also imposes a bias towards not fixing these kinds of bugs.

> Nobody wants to fix bugs that only one developer has. It's just not worth it. … Also, if you fix it, who knows what else will regress. That also imposes a bias towards not fixing these kinds of bugs.

This is an interesting cognitive hazard: it's relatively easy to measure the cost of paying a developer to fix a bug and possible to estimate the cost of getting it wrong but there's no way to measure the cost to everyone who encountered it but never did the work to reduce it to a testcase and file a bug report.

Worse, it's very hard to measure the cost of people who choose to use something else. Repeat that cycle a few times and a fairly high percentage of the people you will hear from are in the “never change anything less than critical” camp.

... Or also never fix anything that we won't be able to sell and make money from (this is, the next shiny thing, whatever it happens to be at the time).

The cognitive hazard is a good observation.

But I think the most important one is the imbalance of interest, which is where open source shines: MS gets zero value from fixing this bug and a lot of value from adding new features, but for this one developer this bug could have been the most important issue on the road to his company's "value" (their own product's ship date).

I wonder whether we'll see more of a hybrid model where companies either use something like Red Hat's RHEL / Fedora level of support split or a time-delayed OSS release so they can have some period of proprietary advantage while allowing customers access and allowing some chance for major outside contributions or tangents. Arguably Apple is doing something not entirely unlike that but they haven't hit the right balance yet.

i'm glad someone who works at the company like you was able to enlighten us as to microsoft's internal practices

oh wait

Apply some common sense, you think they let MS employees just commit to any codebase they like? And this is leaving aside all the annoying steps of locating their repository, figuring out how to build it, testing, finding out the right person to send the patch to, going through code review.

"you think they let MS employees just commit to any codebase they like?"

That's pretty much how it works at Google. The code owners have to review and approve your change (and can reject it), but it's common (even encouraged) to commit a bugfix or new feature to someone else's project.

How is that any different than a central maintainer of Linux accepting patches and reviewing them before they go in?

The only difference is that you can see the source and test on your own machine first.

MS employees don't have to commit to any codebase they like, but they should be able to obtain the actual source, so that "with enough eyes, all bugs are shallow".

Actually anyone can obtain the source, it's publicly available.

Not sure why you got down voted. I know Microsoft is open sourcing chunks of .net now. Perhaps that chunk wasn't one of them?

Actually...I heard Google has developed a lot of infrastructure to allow for this: one repository, you can submit changes that are then automatically routed for review and test and such.

It's one of the things Nadella has talked about, and plans to address over time (the extreme compartmentalism of and fierce "not made here" attitude a lot of departments/groups within Microsoft have developed over the past few decades.

On the other hand, a defense of NIH: http://www.joelonsoftware.com/articles/fog0000000007.html

There are ways to get rid of NIH without losing code quality, testings, responsibility, etc. Nadella in particular is talking about encouraging collaboration between departments.

PS: While the linked article is very relevant here, I'm getting tired of people always linking to Joel's blog -- he's not the definitive software spokesperson; has strong opinions which have been shaped by years at Microsoft - and a lot of his opinions are boxed into those views.

If you pay any attention to Microsoft, their business practices, news, reports, blogs, etc... then you would know the parent comment is pretty much spot on.

Off topic, but I really enjoyed your post about writing a Python lexer/parser in Haskell. Thanks for that!


Thanks! I really appreciate it! :D

You chose the really hard way, the reference source is public - http://referencesource.microsoft.com :P

---Author here---

It wasn't that hard. It took us about 30 minutes (thanks largely to the fact that Bart is a genius.) Besides, that's not actually the source of this DLL. We are on .NET native, and for that matter, a bleeding-edge build that's only available here at MS.

Out of curiosity, would you have been able to read the actual source if you wanted?

Microsoft already publishes the source code for the .net framework (and I think other projects like asp.net and mvc) at referencesource.microsoft.com

They do, but interestingly that particular assembly is not included. Or at least I couldn't find it there.

The namespace appears to have changed or something, I found it here:


Note: also MSFT employee, don't work on .NET though.

---Author here---

I work at MS, and we're using a slightly exotic version of this DLL. Please pardon the differences. :)

---Author here---

Yeah, I've never tried, but I have a copy of the actual Windows source tree, so I'm guessing the answer is yes.

And an extension called Ref12 will also allow you to browse to the online code from Visual Studio.

Aren't you allowed to send a git (err tfs) pull request there at least within the company?

I've read several places that even Microsoft is not standardized on a source control management, some use tfs, some svn, some git, etc.

Don't think of MS as a single monolith. They're a hundred businesses of various sizes that just happen to share the same HR department.

> use tfs, some svn, some git, etc you can go onto MS's job board and find Rails, iOS, and Node positions. :-D

Different VCS is suited to different things. Perforce is great for gargantuan codebases with strong oversight requirements. Git is a poor choice if you check in lots of binaries. SVN is pretty widespread and supported natively by a lot of tools.

I know of some teams even still using visual source safe for legacy reasons.

1) You can file bug reports against .NET and they get fixed. (Typically very slowly, but that's enterprise vendors for you...)

2) The tools they used to find & fix the bug are all based on fully-specified, documented, and supported mechanisms: ildasm and ilasm are stock .NET tools, and ilspy is using Mono's IL decompiler/compiler library.

3) You can compile an app against your own builds of any of the standard libraries if you want (including mscorlib, with caveats) and run it, so a fix like this can be deployed and maintained as much as you like, even if it's not Great Engineering.

4) This hand-patched DLL wouldn't corrupt any other app on your system, and you can ship and version it yourself, so it wouldn't break as a result of a system-wide .NET hotfix or anything like that. .NET's fully-specified ABI also means that it will work across all supported platforms.

5) Mono is open source, so you could always ship against mono and mono's mscorlib (both open source, naturally) if you absolutely can't wait for a .NET bugfix to ship AND you're unwilling to patch the dll yourself.

People love to bitch about .NET, but it actually provides a really good ecosystem here. Very little of it is truly a black box, the spec is extremely readable and precise about the things it covers, IL disassembly is extremely readable, IL disassembly fed through a decompiler like ILspy/dotPeek is doubly readable, debugging is straightforward even without symbols, and recompilation/patching is trivial because everything is well-specified and there's a robust open source library for it. (Even if there wasn't a library, you could just use the standard ildasm/ilasm pair.)

Oh, and you can compile native no-kidding C/C++ to .NET targeting the same instruction set and get all the benefits of the above. If you want to.

I completely agree with everything you said. Exactly how are we disagreeing?

My point is that MS should open source .NET. With a good governance process (super dictatorial no problem! Just be open so we can chip in). It's good for them and for us .NET devs. There's nothing to lose. Like you write, there's a lot of things great about .NET. But being closed source is a disadvantage.

Re "you can ship and version it yourself"... yeah, now that's where this gets onto shaky ground, isn't it... redistributing recompiled versions of .NET code? That's not really inside the licensing rules, is it.

>(Typically very slowly, but that's enterprise vendors for you...)

Ah yes, that's why you pay $$$ for software :).

I've very rarely heard of shops running forked, re-compiled runtimes for languages like python or ruby.

Normally if you find a bug in the core you might try to monkeypatch but many times that won't work so you have to suck it up and just work around it.

There's actually a bunch of shops running forked and recompiled runtimes for languages like python and ruby. I happen to work for a company who maintained such a fork (Ruby Enterprise Edition, by Phusion), and we weren't the only ones who had forks. Most famous were the MBARI patches, made by a guy who worked at MBARI and needed those for running ruby in a submarine or something :P The patches were actually very impressive, despite coming from a biology research institute.

(Note that these were forks because they changed aspects of Ruby that were not in line with Ruby's general purposeness, so they were not allowed to merge into mainline Ruby)

OK, but my point still stands since the vast majority of companies are not maintaining their own forks. In the rare situation where they need something special they'll rely on someone upstream, like your company, to fork it for them. Most companies that run into a bug in the core runtime will just workaround it.

I work at a startup that uses almost all open source tools for our stack. To not be able to fork, fix, pull request a bug in software seems...barbaric to me.

What they're doing here is monkeypatching the language runtime. That's not trivial in most languages, least of all ones which typically rely on a centralized install of that language runtime to function.

The way they did this, only the program that needs this fix is actually using their monkeypatched Expressions library; other code on the same system - other libraries in the same application, even - will continue to use the standard .NET runtime classes. That's a pretty powerful capability, and not one that is necessarily made easier by an open language runtime.

no they aren't.

monkey patching refers to dynamic modifications of code/behaviour at runtime.

this is simply editing a file on the disk, which people cracking software have been doing for about 30 years (using exactly the same method).

Regarding open-sourcing .NET: did Microsoft not precisely do this (at least some of its components)? http://thenextweb.com/microsoft/2014/04/03/microsoft-cloud/

It's not that special, and they took one hell of a circuitous route to fix their bug. You can download the source and view the bug here:


---Author here---

We actually chose the most expedient route. The reason is, the source you link to is not actually the source of the DLL we were working with. That particular file is very similar, but the rest of the repot is very much different from the version we were working on. (I work at MS, and our project is kind of exotic in this case.)

I know what you mean, I like .NET too but there is a lot about working with it that feels very outdated these days.

I'm sad to report that I tried to replicate what the author did here and it didn't work...

I went to the weekly tech lead meeting, and when it was my turn to talk, I said: "I think we should increase out internal NuGet package release interval to every 18 hours. F--k the Police!"

People just looked at me weird.

Dude, that's not a DLL, it's a pile of half-digested scripting language. Real men patch in assembly.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact