Monday, March 8, 2021

Rachel True vs. iCloud

Jon Fingas (via Hacker News, Slashdot, Navin Kabra, 9to5Mac):

Actor and author Rachel True claims iCloud has effectively locked her out of her account due to the way her last name was written. Reportedly, her Mac thought lower-case “true” was a Boolean (true or false) flag, leading the iCloud software on the computer to seize up. The problem has persisted for over six months, she said.

True said she’d spent hours talking to customer service, and that Apple hadn’t stopped charging her for service.

This sort of bug can happen either due to too much static typing or not enough.

Previously:

7 Comments RSS · Twitter

Kevin Purcell

It's a shame that Venor Vinge never used this idea as a plot device in his "seminal work of the cyberpunk genre"

It would work on so many levels :-)

https://en.wikipedia.org/wiki/True_Names

Proper capitalization matters, people.

It's popular to blame type systems when errors like this occur, but I don't see how any reasonable type system, static or dynamic, would cause such a problem.

Are they calling EVAL on user input? That's not caused by the choice of type system. You can just as easily call exec() in Java, or fall to SQL injection by hand assembling a bad query in Haskell.

This is just bad programming.

What likely happened here is some kind of type coercion.

It’s popular to blame type systems when errors like this occur, but I don’t see how any reasonable type system, static or dynamic, would cause such a problem.

Type systems engender culture. (Conversely, devs who don’t feel comfortable with a type system move on to a different language.)

Here we have probably a case of deserialization. A dynamic type system doesn’t require that you simply take the properties you’re given and hope for the best, but it does encourage it. In contrast, a static type system doesn’t require you to first explicitly declare a model class, but it’s in its culture to be the common approach.

E.g., in C#, you might approach this problem by first defining a model class, where LastName is explicitly a string, like so:

public class Person
{
    public string LastName { get; set; }
}

Then you’d call some kind of deserialization on it:

var p = Serializer.Deserialize<Person>(inputString);

At this point, a person’s last name “True” would just be taken verbatim as the string, assuming a format like JSON where strings natively exist.

Instead, this dev’s (apparent) thought process was:

I’m not actually know what properties there are, because there’s no model object. The tooling isn’t helping me, as everything is dynamic.
So, I’ll iterate on the properties that do exist.
If they look vaguely like a duck, I’ll treat them as a duck, and by duck, I of course mean boolean.

@Sam Yes, it’s bad programming, not caused by the type system. But a more static approach would have prevented this sort of runtime error by making sure there was a code path to handle this case. And a more dynamic approach would have let the value keep flowing through without trying to figure out what type it was. SQLite even lets you insert values of the “wrong” type into the database.

Sören: That's why I was careful to prefix my response with "any reasonable type system". What we're seeing here is not the consequence of a *dynamic* type system, but of the *Javascript* type system.

"A dynamic type system doesn’t require that you simply take the properties you’re given and hope for the best, but it does encourage it."

How so? I've been using dynamically typed languages for 25 years and I struggle to imagine how such an error would be possible in any of them except Javascript. (Well, *maybe* Tcl.) How could you have such an error in Scheme, for example?

"If they look vaguely like a duck, I’ll treat them as a duck, and by duck, I of course mean boolean."

So did you mean to say "duck typing" instead of "dynamic typing" earlier in your comment? Duck typing is (usually?) dynamic, but not all dynamic typing is duck typing.

That’s why I was careful to prefix my response with “any reasonable type system”. What we’re seeing here is not the consequence of a dynamic type system, but of the Javascript type system.

I really don’t know what that means. It just seems like slander against JS, rather than any particular argument.

How so? I’ve been using dynamically typed languages for 25 years and I struggle to imagine how such an error would be possible in any of them except Javascript. (Well, maybe Tcl.) How could you have such an error in Scheme, for example?

I don’t follow. You can make the same error in C#; you’re just not encouraged to. Instead of explicitly defining a model, just use dynamic typing:

dynamic p = Serializer.Deserialize(inputString);

There, now you’ve shoved the problem one tier in the architecture further. The serialization format doesn’t handle it. The deserializer doesn’t handle it.

Does p have a property lastName? Who’s to say! Is it a string or a bool? Who knows! We’ll find out at runtime.

(Similarly, you can deserialize into a dictionary/hashtable.)

As Michael says, heck, the SQL driver might not even handle it. You take that blob and shove it into the database, and let it figure things out.

Or, heck, just set all columns to VARIANT.

In all of those cases, you’d be “fine”: more or less by accident, True would end up as the value in the database.

But if you declare a model ahead of time, you get a better mental model of what the values possibly could be, and why brute-forcing “if it looks like a bool, it probably is” can be a trap.

How could you have such an error in Scheme, for example?

When Lisp-based languages are ever in the history of anything used on large production websites, I might find out.

(I don’t know much about Lisp, so I can’t comment on how likely this bug would’ve been in it. I don’t think Lisp-to-JS transpilers are common. Nor in general do I commonly see companies advertising for a Lisp job at all, especially for running websites.

I can’t think of anything special about JS that makes this bug possible or likely in it. It’s simply a case of “we don’t know the type, and the language isn’t particularly helpful about it, so we’ll make guesses”. Like I said, I can easily write you that bug in C# as well. But, I think the bug would be more likely to occur in languages like JS, Ruby, Python, etc.)

So did you mean to say “duck typing” instead of “dynamic typing” earlier in your comment? Duck typing is (usually?) dynamic, but not all dynamic typing is duck typing.

This code (which we don’t know for sure is responsible for the bug) is arguably an example of duck typing, yes.

I’m not saying dynamic typing is responsible for the bug, or that static typing would’ve prevented it. I am saying that strong typing (writing a model class with explicit types) and static typing (compiling that model class, rather than having its types be evaluated at runtime) engenders a culture where developers think ahead of time whether the properties are the ones you’ll need, and whether their types are appropriate are appropriate for the data you’ll encounter.

The thought process that leads to “the machine can figure out what the type is supposed to be” is what, IMO, likely led to this bug.

(The other problematic thing about this code — again, with the assumption that this particular line of code is even responsible — is that the developer thought it appropriate to write their own ad-hoc type handling at all. There should’ve been a point where they’d stopped to think whether this was a problem better solved by someone else.)

Leave a Comment