Typing These 8 Characters Will Crash Almost Any App On Your Mountain Lion Mac 425
An anonymous reader writes "All software has bugs, but this one is a particularly odd one. If you type "File:///" (no quotes) into almost any app on your Mac, it will crash. The discovery was made recently and a bug report was posted to Open Radar. First off, it’s worth noting that the bug only appears to be present in OS X Mountain Lion and is not reproducible in Lion or Snow Leopard. That’s not exactly good news given that this is the latest release of Apple’s operating system, which an increasing number of Mac users are switching to. ... A closer look shows the bug is inside Data Detectors, a feature that lets apps recognize dates, locations, and contact data, making it easy for you to save this information in your address book and calendar."
Re:printf (Score:5, Informative)
Not likely. It crashes due to an assertion failure and subsequent exception being thrown.
Sure enough (Score:2, Informative)
The cause, and a fix (Score:5, Informative)
Landon Fuller has posted a gist on GitHub with an explanation of the bug and a binary patch to the affected library [github.com].
Re:No, It Doesn't (Score:3, Informative)
The bug is case sensitive; as the bug report says "The capital 'F' is important."
Please do not bother posting something so quickly, without looking into it.
Let's look at the stack trace (Score:5, Informative)
This is the stack trace mentioned in the article:
http://pastebin.com/UkhERvaA [pastebin.com]
Doesn't look like a c-string or printf issue to me at all.
Re:printf (Score:5, Informative)
I have also had the impression that assert() is a hack that shouldn't be used much (?).
$ man assert
NAME
assert -- expression verification macro
SYNOPSIS
#include
assert(expression);
DESCRIPTION
The assert() macro tests the given expression and if it is false, the
calling process is terminated. A diagnostic message is written to stderr
and the abort(3) function is called, effectively terminating the program.
If expression is true, the assert() macro does nothing.
The assert() macro may be removed at compile time with the cc(1) option
-DNDEBUG.
Somebody forgot to remove some debugging code, embarrassing but hardly something that hasn't happened before and definitely not the end of the world as we know it.
Re:printf (Score:3, Informative)
I agree with you, you couldn't abort on bad input.
However, based on my interpetation of what is happening, this isn't what is happening. My expecation is as follows:
The user types something in an address bar.
That string is passed to hypothetical function 'process_uri'.
'process_uri' sees that it is a file uri, and passes it to the hypothetical function 'process_file_uri'.
'process_file_url' sees that it wasn't given a file uri, and aborts.
The problem ISN'T that the use gave bad input. If process_uri was given a URI it didn't recognize, it would have generated a proper error and not called anything. If process_file_url was given a path to a file that didn't exist, it too would have generated a proper error. The problem IS that process_uri and process_file_uri have different expectations on what constitutes a proper file uri.
Re:printf (Score:3, Informative)
Not likely. It crashes due to an assertion failure and subsequent exception being thrown.
Yeah. Data Detectors on Macs is just like Semantic Desktop on KDE. When I make a fresh install of the OS, disabling these pesky little "features" is one of the first things I do. I'm glad somebody somewhere out there finds them useful but I definitely don't.
Re:WTF (Score:3, Informative)
I realise this is a troll, but for anyone thinking it might be real:
He's just need to restart Textedit, and all the documents he had open will still be there, still opened, in exactly the state they were in seconds before the crash. Snow Leopard documents don't need saving, they are constantly persisted whilst editing. Even if you have't yet given them a filename.
Re:printf (Score:5, Informative)
as a programmer myself, when coding something and a harmless and not completely unexpected input occurs, your program shouldn't crash, due to any reason, asserts included. Such a failure is sign of nothing but lazy programming and even lazier unit testing.
Sorry, but you are wrong.
By the time you fail an assertion, you better crash because you're not supposed to be there. The code in FRONT of the assertion is supposed to prevent that.
Assertions go between the input checking front, and the sane input needing rear. Their only purpose in life is to prevent an unknown state in the rear guts, not to do what should have been done up front.
Re:printf (Score:5, Informative)
And yet, unchecked input is the root of almost all software vulnerabilities
Re:printf (Score:5, Informative)
A bad string isn't exceptional
Especially when the interpretation of that "bad string" is supposed to be CASE INSENSITIVE and the "exception" occurs because one character is upper case.
URI are defined here [ietf.org], and the part that deals with the "file:" or "http:" part (called the "scheme") says this:
Emphasis mine.
This is a case of a programmer implementing a feature defined in a standard and ignoring the standard when doing so. Not lazy, just ignorant and stupid. Just like the ignorant stupid programmers who write javascript email address verifiers that refuse to accept valid email addresses because they contain characters like '+'. Those programmers should be shot.
It is case sensitive (Score:4, Informative)
After trying this in every app I could think of, and failing to crash them, it turns out that this is case sensitive.
Some dude has done a more detailed analysis over on github [github.com] but the long and short of it is that there is a specific check in the code for 'file://' and any other case will cause it to crash. All caps - crash. Capital F and the rest in lower-case - crash. All lower-case and a capital L - crash.
you obviously didn't read it (Score:4, Informative)
It's a commented assembly listing with a proposed hacky fix in assembly.
Re:printf (Score:5, Informative)
You don't understand what assert() is for.
It doesn't cause a crash. Quite the opposite. It is a way of deliberately causing program termination upon encountering an internal inconsistency; precisely so as to avoid a crash, a silent failure or some other undesirable behavior.
Obviously, in a bug-free program, assert() would never trigger and is therefore unnecessary. In the real world it is a useful safety net.
Note that assert() is sometimes used to catch runtime errors. That is indeed inappropriate. But you shouldn't condemn the tool because it is sometimes used incorrectly.
Re:printf (Score:5, Informative)
I used to think the same way about kernel panics in an operating system - I thought there was no reason why the system should ever halt. And then I had an OS class, where it was pointed out that halting is a quite valid choice when encountering an error condition that indicates that something has gone fundamentally wrong. For example, if you have an allocation bitmap that tells you what parts of your disk is in use, and what parts are free, it has a checksum, and the checksum is incorrect. It may very well be that the safest thing to do in this case is halt, rather than risk a write making it to the disk and overwriting a block that is in use. The user can reboot, and that will probably be the best way to recover from the error. It might be possible to display an error message, however since the code to display such a message is not often used, it's likely still on the disk (it was either never loaded, or was loaded and then swapped out of RAM). So you might think it's safe to try to read the disk still - but you have to set some state somewhere saying that under no circumstances should you write anything while you try to load this code. But what's to say that whatever state you set is working? Obviously something is broken, your checksum was wrong! And for that matter, if you need to swap something else out to load this new code in, you can't, because you've decided that writes are now unsafe. For that matter, maybe the disk is acting up - maybe it'll interpret a read command as a write, or take some other completely bogus action. Or maybe what you think is your memory-mapped disk is now really the network card, because some CPU configuration registers picked up a bad value. Bottom line; there are definitely good reasons to just stop a program, OS, or whatever when you detect an error that should never happen.
That said, this case is not one of those good reasons.
Re:printf (Score:5, Informative)
Then instead of an assert you should have a return error (or throw exception) statement.
No. Those can only ever be for foreseen error states. If they are not foreseen, then they are no documentable, and therefore the calling code can take no sensible action to react to the error or exception.
An assert is a documentation of something that's always true and will never fail. If it fails, that's a bug, and there's no graceful handling of bugs - if you could foresee them, you would have already fixed them.
The question is whether to only have them in debug builds or whether to have them in release builds too. Contrary to your ASSERTION, asserts aren't necessarily compiled out of release builds. The answer is they go in release builds too if the worst case scenario is data corruption from continuing in an unpredictable state.
None of this is in Programming 101. This is stuff you learn when you've been programming a long time.
Re:BRB (Score:4, Informative)
It produces a nice exception error message. Perfect for making Apple fanbois who claim that Macs never crash look like twats.