[HN Gopher] Google broke a conditional statement that verifies p... ___________________________________________________________________ Google broke a conditional statement that verifies passwords on Chrome OS Author : stalfosknight Score : 139 points Date : 2021-07-22 18:32 UTC (4 hours ago) (HTM) web link (arstechnica.com) (TXT) w3m dump (arstechnica.com) | jeffbee wrote: | This is clearly a typo that happened to stomp some logic that is | not covered by a test. The review 3002282 includes the bug, which | deletes one of the & from a && operator. It says it was cherry- | picked from review 2994464, which does not change that line. So, | slip of the backspace key plus poor testing. | tyingq wrote: | Yeah, the biggest thing to me here is that there's no "login | succeeded" unit test, integration test, manual test, etc. | Whatever customer logged in first was the first person to | actually run the code. | SahAssar wrote: | Just reading the title it sounded very much like "Single Point of | Failure: The (Fictional) Day Google Forgot To Check Passwords": | https://www.youtube.com/watch?v=y4GB_NDU43Q | jedimastert wrote: | I love Tom's speculative fiction talks. He tells such a good | story. | lmilcin wrote: | Umm... no automated tests? Junior engineers responsible for | security of half of the world without proper code review? | tpmx wrote: | Half of the world? We're talking primarily north-american | school kids. | | https://trends.google.com/trends/explore?q=chromebook | wil421 wrote: | Can the link be updated to the one below? The link above goes | directly to the comments section and collapses the article, | ?comments=1 is the culprit. | | https://arstechnica.com/gadgets/2021/07/google-pushed-a-one-... | stalfosknight wrote: | HN won't let me edit the URL. :/ | wil421 wrote: | Dang or someone else will probably see it. I didn't think | you'd be able to do it yourself. | dang wrote: | Fixed now. Thanks! | dboreham wrote: | This has happened so many times in recent years to high profile | services and OSes. You'd think it'd be a test case. | black_puppydog wrote: | That's not "bricking" as the title suggests. Sorry, word police | incoming. :P | snvzz wrote: | What it means is: They push crap to users with no testing. | | Testing would have caught this. | schemescape wrote: | Maybe pushing updates to users _is_ their test process? I doubt | they 're the only ones doing this, sadly. | [deleted] | Traster wrote: | I bet the post-mortem for this is going to be fun. How this | wasn't covered by multiple unit tests, a code review and a roll | out strategy is.... impressive. | sneak wrote: | Bitwise & versus logical && is a classic, right up there with | an assignment in a comparison (when an equality check is | intended), = for ==. | | That this was missed is pretty surprising, given that it's | Google and the stakes involved in the encryption/key management | code in a secure platform device. | | I wonder if we'll even get a postmortem, as this simply cannot | happen unless several someones all Seriously Fucked Up | simultaneously. | | - code error (expected, humans are fallible) | | - review error (less expected, this is the kind of thing code | review exists for) | | - static analysis / linting check failure | | - integration test failure (interactive login no longer works | on this build) | | This is a massive, overlapping fuckup. Heads should probably | roll here, especially given that when you opt in to ChromeOS as | a user, Google now has "one job" (DFIU). | nogridbag wrote: | I've seen the = instead of == in the wild with disastrous | results: the assignment was on an ORM backed object, e.g. | // accidentally mutates all names to Sam and persists to the | DB myList.filter { myDomainObj.name = 'Sam' } | | But it makes me wonder why our programming languages would | use characters which can often lead to this type of error. | sneak wrote: | If you consider a linter part of a programming language, | most, when properly configured, do not permit this. It's | just the syntax that does; professionals do not rely on | syntax validity alone but employ linting, code review, | static analysis, and integrations tests on top. | | The gradient of professionalism in our industry is very | wide, and the slope is quite shallow. | | To your point, however, many languages (such as Go, | developed and used by Google, the organization under | discussion) have designed their syntax now to completely | avoid this type of error even being possible. | galangalalgol wrote: | what is the difference between linting and static | analysis? Coverity, cppcheck etc, what are those? You | mention integration tests, but not unit test, do you | value unit test? | tmp_anon_22 wrote: | > type of error even being possible | | I mean its still possible to forget the ":" character and | its still possible to mentally scan a PR and see "=" and | miss that it should have been a "==". | edflsafoiewq wrote: | = vs == isn't possible in Go because of the | statement/expression distinction. The benefits of | allowing assignment to be an expression are too small | compared to the problems it causes. x == | 1 // oops, meant = // x == 1 evaluated but not used | if x = 1 { ... } // oops, meant == // syntax error: | assignment x = 1 used as value | nightfly wrote: | I'm a fan of programming languages using := for assignment | for this reason | AnimalMuppet wrote: | Look, I know that this is an enormously bad bug, but... | | Google has a codebase that numbers multiple billions of | lines. Using := means typing multiple billions of extra | characters. That adds up. And it wouldn't even have | prevented this bug! | | All checks have costs. As Emerson said, "A stitch in time | saves nine. So we make 1000 stitches, that by doing so we | may save nine." | anyfoo wrote: | Once more I hope this is satire, but as so often on the | Internet it is surprisingly hard to tell. | samtheprogram wrote: | This reminds me of Silicon Valley's main character | preferring tabs to spaces because they use less bytes, | despite his own product being for... compression! | | I personally prefer spaces so that under any | circumstances, the code reads the same as the author | intended (whether you're in an editor or viewing a file | with a CLI tool). Are we really counting bytes in this | day and age? | anyfoo wrote: | The problem is not even with "easy to mix up operators" for | this, it's about languages without a strong and static | enough type system. While the particular problem Google hit | is a bit more subtle (involving undefined behavior), in the | majority of cases a strongly typed language would not allow | expressions that accidentally mix up = and ==, as they | often resolve to different types. | | In C "if (foo = bar)" and "if (foo == bar)" are both legal, | because pretty much any type can be automatically coerced | into a boolean. In many modern languages that is not the | case. (Of course if you have assignments as expressions you | are still screwed if foo and bar are both boolean to begin | with, so some languages got away with that, too. And for | fairness I should say that C at the very least warns if you | don't explicitly put parentheses around the assignment, | nowadays.) | crazygringo wrote: | > _in the majority of cases a strongly typed language | would not allow expressions that accidentally mix up = | and ==, as they resolve to different types._ | | That's not true at all. | | Whenever you're intending to compare equality, they're | usually going to be the same type _already_ unless you | 're being really slopping in a scripting language like | JavaScript or PHP -- but even then they're _usually_ two | numbers, two strings, or two booleans. | | The whole problem here is where foo and bar are _both_ | integers, or booleans, or whatever you want, and instead | of typing "if (foo == bar)" you type "if (foo = bar)". | | Strong typing does _nothing whatsoever_ to help in this | common situation. | anyfoo wrote: | No. It can help because the _result_ of the expression | would have a different type, one that "if" does not | accept. If a and b are integers, then the expression "a = | b" is an integer too, but "a == b" is a boolean. In a | strongly typed language, you can assume that "if" only | accepts booleans. | Guidii wrote: | "Heads should probably roll here..." | | Google has a blameless post-mortem process (see | https://sre.google/sre-book/postmortem-culture/) which | essentially boils down to: | | 0) We want to fix the situation. By the time the post-mortem | happens, that should already be done. | | 1) We want to make sure this never happens again. In order to | do that we need to understand as much as we can about what | happened. | | 2) We want everyone to share everything they know about the | event. If the participants worry about fallout, they will be | compelled to cover up. | | 3) Most failures happen at a number of points, so you need to | dig in deeply if you want to get full value out of the | "event". | | 4) Good post-mortems lead to process fixes to reduce (or | eliminate?) the chance of similar events, or to make fixes | throughout the code base. | | The other thing is that after the post-mortem, all of the | folks involved have learned from it. Usually they're better | engineers because of that expensive lesson you've just paid | for. | | Disclaimer: Googler, participant in several post-mortems, | opinions my own. | agilob wrote: | RedHat once committed wrong value of MTWO variable, it was 2, | there was another variable called TWO which also had value of | 2. It was fixed a few months later with a commit like "change | value of MTWO to -2".Sorry, but can't find it find now | james_in_the_uk wrote: | Straight up negligence. | kps wrote: | I'm quite surprised there isn't a compiler warning for a | bitwise operator at the root of a condition. I've been | writing `if ((flags & FLAG) != 0)` for decades years for | nothing?!? | fierro wrote: | _glances at screen_ LGTM | brundolf wrote: | Especially since it's so easy to lint for. This isn't some | cross-file memory mishandling bug, it's a single token that's | being used where it shouldn't be | mdoms wrote: | > Heads should probably roll here, | | I disagree. It's obviously a major balls up by multiple | people, but at the end of the day this is an organizational | failure. You don't fire people for this, you learn from it | and fix the organizational holes that caused it. | sneak wrote: | Someone is responsible for the organizational units and | their processes. | | By that logic, almost no individual failure is a firing | offense. Many people in the organization are responsible | for ensuring that the processes themselves overlap in ways | that exclude the possibility of failures like this. | | I'm talking about the meta-failure in management's | oversight of the processes. There is belt person, and there | is suspenders person, and there is a third person who makes | sure there are both belt person and suspenders person on | staff and that they don't go on vacation at the same time. | | Somewhere above the team lead and below the CEO there is | someone who didn't do their job. | nicoburns wrote: | > By that logic, almost no individual failure is a firing | offence | | I'd probably agree with that. Firing should be for | extreme negligence, or sustained underperformance. | idiotsecant wrote: | >extreme negligence | | If this doesn't qualify, what does? | vlovich123 wrote: | This isn't extreme negligence of any single individual. | If there are linters/compiler warnings that should have | caught this, this is an organizational failure that can | be remedied and the manager/TL should be taking a bit of | a hit here as having those enabled is best practices. | Since it's ChromeOS I imagine there's a dedicated team | managing the build infra and it's not using the base set | of things that Google3 protects you with, so the fault | may lie in that organization a bit as an oversight. | | Then there's obviously the automated testing strategy, | manual testing strategy and sanitizer strategy that | missed this. | | The net result is extreme negligence but to me this kind | of failure speaks to several layers going wrong at once | rather than one person fucking up badly. Organizationally | you try to defend against these kinds of failures with | multiple layers of defenses. | | Now if this was a malicious internal attack that should | be investigated but I'd hate to have to seriously | reprimand anyone who typo'ed & instead of &&. | ectopod wrote: | The GGGP is talking about failures at a higher level. Not | reprimanding the coder who missed an ampersand, but the | manager who was ultimately responsibly for ensuring there | was a functioning process for catching this sort of | nonsense. | sneak wrote: | I would say this is negligence, but perhaps not extremely | so. | anyfoo wrote: | You are all very quick to judge. I don't work for Google | so I don't know what happened, but consider the | possibility that this may have been a freak accident. | That piece of code for example might only be on a path | that is not activated when testing, or it may be executed | but not have the same fatal effect. | | And before anyone comes along and says "well, every | possible path should be tested then": That would be | absolutely impossible even if the halting problem wasn't | a thing (which it very much is). Even if you somehow have | utopian "100% code coverage", that does not mean you have | tested every possible input resulting in every possible | state combination. | | I bet every one of us has a story about an old bug that | only manifested years[1] later because of the confluence | of many unfortunate things, one that takes half an hour | to tell. | | [1] Or even decades, in some cases that then made it to | the HN front page. | nicoburns wrote: | This is the sort of thing that most linting tools will | catch, so it's a bit worse than that I think. You | shouldn't need _any_ test coverage to catch this. | admax88q wrote: | The way you fix organizational/process failures is not by | firing the person in charge of them every time they fail | to catch something. | | How many breaking bugs have _NOT_ shipped due to the | current processes. Your approach suggests that there is | some perfect process manager out there who will let no | bugs like this ship (whilst not dropping any other | business priorities mind you) that they just haven't | hired yet into this position. | | This isn't as big of a bug as people on HN want it to be. | A few months from few people will remember, and even | fewer will care. | AnimalMuppet wrote: | There is a story (perhaps apocryphal) of a salesman who | lost a $10 million deal for IBM. He was sure he was going | to be fired. Some bigwig (Watson himself, maybe?) talked | him through what had gone wrong. The salesman asked, | "Aren't you going to fire me?" The bigwig said, "I just | spent 10 million dollars training you." | yupper32 wrote: | > By that logic, almost no individual failure is a firing | offense. | | That's pretty close to how it should be. That's the core | premise of the no-blame post-mortem culture that's great | about some companies. | | As long as you go through the port-mortem process, which | includes doing your best to prevent this from happening | again (which may include changing organizational | processes, testing strategies, etc), then everyone can | move on with their lives. | | Firing happens when you have a history of performing | below your level. Never for a single engineering failure. | sneak wrote: | This isn't an engineering failure. Everyone writes bugs. | yupper32 wrote: | Engineering process is still engineering in my book, but | if it helps: | | Firing happens when you have a history of performing | below your level. Never for a single process failure. | mdoms wrote: | > By that logic, almost no individual failure is a firing | offense. | | Correct. | aeturnum wrote: | I don't think we know enough from this to say. | | It's possible that this bug made it into the wild because | the organizational structure made remedies impossible. In | that case you probably don't fire anyone, though maybe you | reassign some folks. | | It's also possible that the organizational structure | indicates that a person or a group of people is responsible | for this and they failed to do that job. If that's the case | then it might very well make sense to fire folks. It also | might not. | | I think it's important for poor performance to have | consequences[1] and I also think that people leave jobs all | the time and it's fine to decide that someone should leave | their place in the org with a positive reference and look | elsewhere for work (perhaps in another part of goog). | | [1] for moral and company culture reasons if nothing else. | chovybizzass wrote: | i've never worked on a project (even TDD) that did that level | of testing detail. | contravariant wrote: | Wait so are the devices bricked or not? The title says bricked | but as far as I can tell people just can't log in temporarily | until the fix is rolled out. | penagwin wrote: | It's a soft lock for sure, given it requires a software update | to use you could likely consider this a soft brick too. | | It's not a hard brick to your point. | dang wrote: | Ok, we've done our bit to counter brick dilution in the title | above. | sneak wrote: | No, they are not bricked. The term has become ridiculously | diluted in practice to mean "hard, breaking bug". | secondcoming wrote: | Edit: Someone has explained the issue below | | I don't understand how that broke anything? | | The C++ codegen for && and & is the same: bool | good(bool a, bool b) { return a && b; } good(bool, | bool): mov eax, edi | and eax, esi ret bool bad(bool | a, bool b) { return a & b; } bad(bool, bool): | mov eax, edi and eax, esi ret | | [0] https://godbolt.org/z/84MMqTehs | taeric wrote: | The short circuiting was preventing undefined behavior on the | second expression. | | That is, yes, it is the same with booleans. Now try with | expressions. | formerly_proven wrote: | The code is: key_data.has_value() && | !key_data_->label().empty() | | key_data is probably something like an std::optional, so short- | circuit evaluation guards the dereferencing of the optional. If | you write this with a binary and, no short-circuit evaluation | can happen, so undefined behavior ensues. | | I wanna point out that std::optional, in the typical C++ | stance, has a "I know what I'm doing" API and a "Humans make | mistakes API": optional->... is UB if the optional is empty, | optional.value()... raises an exception. Arguably, in code like | this you probably only want to use the latter kind of API. (The | pattern of "operator can UB, equivalent method asserts pre- | condition" is very common in the C++ standard library) | jeffbee wrote: | Correct, key_data_ is a base::Optional<KeyData>. Chromium's | base::Optional is very similar to std::optional, but predates | c++17. | tmiahm wrote: | The difference is your example uses bool values, the code in | question uses expressions that (should) evaluate to bool. && is | short-circuited if a is false, such that b is not evaluated. | [deleted] | skinkestek wrote: | The company who no longer recognizes doublequotes nor their own | verbatim operator? | | The one who flags chess videos? | | Closes decade old accounts without any kind of explanation? | | Absolutely believable. | | Wouldn't surprise if this too is related to relying on their | Artificial Stupidity^HIntellingence systems. | iamcreasy wrote: | The article says the problem bricked their laptop - but I was | under the assumption that you can create a non-google | account/guest account on Chrome OS to use the device. | tuxoko wrote: | I haven't touched C++ in forever, but as a C programmer it looks | insane that you can do dot operator and -> operator on the same | variable and not cause compiler error... | tyingq wrote: | I'm baffled that there's no test for this, manual or otherwise, | before this rolls out to production. That you can change ChromeOS | code in the login path, and the very first time it's exercised is | by an end customer. | mouzogu wrote: | Couldn't this be caused by a bad merge? | | Not sure how Google manages their merging and release process but | there are conceivably several stages where a bad merge can occur | and go unnoticed - possibly at a stage close to release and after | testing. | tmp_anon_22 wrote: | At an established company merging is an incredibly incredibly | locked down process. There are usually multiple barriers of | automation and people, entire release teams who all have to be | stoned at the wheel to miss anything odd getting through. | fouric wrote: | From the article: | | > The line should read "if (key_data_.has_value() && | !key_data_->label().empty()) {" but instead of "&&"--the C++ | version of the "AND" operator--the bad update used a single | ampersand, breaking the second half of the conditional statement. | | Someone correct me if I'm wrong, but this seems like it wouldn't | be possible in a language that didn't conflate boolean values | with bitvectors. | | Edit: I was wrong[1]. | | [1] https://news.ycombinator.com/item?id=27923785 | CobrastanJorji wrote: | Forgive my poor C++, but has_value() sounds like a bool, and | empty() sounds like a bool. Why wouldn't "bool1 & bool2" work | correctly? | kevinmgranger wrote: | If I had to guess, the second expression depends on the first | being true. So if `has_value()` is false, perhaps | `key_data_->label()` is undefined behavior. | dataflow wrote: | Dereferencing via key_label_-> has undefined behavior when | !key_label_.has_value(), so the compiler treats that case the | same as if key_label_.has_value(). Or to put it another way, | the compiler reasons that key_label_ must have had a value | (since you dereferenced it), and thus optimizes out the check | for `has_value()` (since clearly it was unnecessary). | myko wrote: | Would this optimization not have been on the beta/canary | channel? I assumed they were but perhaps not since this was | not caught. | dataflow wrote: | I don't know how their builds work or where their | templates are instantiated but it's possible that the | compiler doesn't see this optimization until LTO and that | they don't do LTO until stable releases? It would seem | strange though, I'd have thought beta would have LTO. | anyfoo wrote: | Yeah that would be a very weird choice. LTO itself can | have bugs, or (as we speculate here) unmask existing | bugs. Plus, even that aside, you'd hopefully test exactly | the build that you will release before you release it. | | As I wrote in another comment, this could still be the | result of a freak accident and not have shown up in | testing, though (but since I know nothing about the | process or the code there, it could be anything). | fouric wrote: | Ahhh, so it was a problem with lazy evaluation (and the | lack thereof when using &), and not type coercion, like I | initially thought. | kbelder wrote: | I think this is a unpopular opinion, but I consider | taking advantage of short-circuiting in boolean | operations to be a code smell. At least for me, it seems | very fragile and I'd much rather break the conditional | logic out explicitly. | | But I like to write as much like assembly as I can in | every language. Each line of code should do one and only | one thing. | dataflow wrote: | I used to only put short-circuits when I really needed | short-circuit behavior, thinking it improved readability. | But after getting by the implicit type conversions over | and over (as well as nags from every compiler) I just | decided it was a bad idea in C++. I'd still do it in a | safer language, but in C++ I'm convinced you should just | use && even when you only need & for bools. | dataflow wrote: | Yeah it has nothing to do with type coercion. I'm baffled | a linter doesn't catch this though. & for bools should | just be prohibited altogether. If people really want & | for bool, they can just cast to an integer type and use & | with that (which generates its own warnings | appropriately). | gpderetta wrote: | the problem is that bitwise & and | are routinely used | for their non-shortcircuiting behaviour in boolean | expressions, so it is hard for the compiler to flag this | as an error. | | Many linters and static analysis tools do flag them | though as these days it is not considered good practice. | anyfoo wrote: | Why would you even need non-shortcircuiting behavior in | boolean expressions? Because either side of the operator | has side effects that you want to happen unconditionally? | Please just write it out as an extra statement then | instead of hammering it into place with an implicit | coercion to an integer type only so you can abuse bitwise | AND and OR only to force that side effect to... you can | see why this is probably not the most elegant idea. | slavik81 wrote: | Matt Godbolt gave an example of a significant performance | hit caused by unnecessary short-circuiting in his CppCon | 2019 talk[1]. EDIT: Deleted tangent. | | [1]: https://youtu.be/HG6c4Kwbv4I?t=45m | dataflow wrote: | > & and | are routinely used for their non- | shortcircuiting behaviour in boolean expressions | | Really? I can't recall a single case of this with 'bool' | in any codebase in my recent memory. I only see it with | integers. And even if it's somehow routine for your | codebases with bool (why?!), surely it's not routine | inside a _conditional expression_ , so at least they can | prohibit it there? | xmprt wrote: | So instead of short circuiting like that code should when | it uses &&, it instead makes an assumption about the first | part of the boolean expression because otherwise the code | would have undefined behavior? | dataflow wrote: | Yeah. More specifically, it just inserts whatever | behavior it likes for the undefined scenario, which in | this case is "the same behavior as in the defined | scenario". | grishka wrote: | Certainly won't compile in Java. | taeric wrote: | Oddly... It would? Try: Map<String, | Boolean> map = ... if (map.containsKey("hello") & | map.get("hello")) { ... | shawnz wrote: | In fact you can apply the single ampersand & operator to | booleans in Java, and just like in the example here it has | the same behaviour as && but with no short-circuiting. | grishka wrote: | Huh. I didn't know that. | wyager wrote: | The most general solution here is to use algebraic types and | pattern match on the value being "None" or "Some data". | Trollmann wrote: | You can use `and` and its siblings instead of && and similar in | C++11. Most people here, and in other boards, will try to | convince you that it hurts readability because 'that's how we | always did it' (read I'm used to it and don't like change). | gavinray wrote: | I was surprised to read that `and`, `and_eq`, `xor`, etc are | all supported "secondary/alternative operators" | | Never seen them used, but I use them in my C++ code when I | have to write it to accomplish something else: | | https://en.cppreference.com/w/cpp/language/operator_alternat. | .. | inetknght wrote: | I used to use them. Then I was burned by some Very | Opinionated managers and coworkers who didn't like seeing | new things. It wasn't a hill I was willing to die on; | there's more important things to argue about in C++. | fouric wrote: | I am also of the opinion that `and` is more readable than | `&&` (and isn't as easy to typo in a catastrophic way) - | although my main point was about the weaker type system. | qalmakka wrote: | C++ definitely hasn't a weaker type system than "newer" | languages like Java - if any, it is much more richer and | complex than most languages out there. What's happening | here is a type conversion that has to be in place due to C | not having a boolean type until 1999. C++ attempts to | construct a boolean from the argument of an `if()`, and | given that bool can be constructed from int, the conversion | succeedes. | | You can define your own conversion operators to boolean, | too, which are very useful for stuff like smart pointers | and similar classes that may or may not have a value. | struct A { std::string value; | explicit operator bool() const { return | this->value.size(); } }; // ... | A a {}; if (!a) { // ... } | fouric wrote: | "Not as weak as Java" is not a very interesting | benchmark, as Java _also_ has a poor type system. C++ 's | type system is pitiable relative to those of Rust, | Haskell, OCaml, and SML. | | Moreover, in addition to being less expressive than them, | C++'s type system is also _weak_ , in formal sense, by | allowing many implicit type conversions - which is one of | the issues that I was complaining about. The fact that it | "has to be in place due to C not having a boolean type | until 1999" doesn't make it any less weak. | dylan604 wrote: | That so sounds like an error I would make and not some superDev | working at the Googs making around 4x the amount of money I | make. | myko wrote: | They're just people. If you want to get in you probably | could, with some effort. | anyfoo wrote: | Not sure why you think a "superDev" would be less susceptible | to simple typos? | [deleted] | shawnz wrote: | Other than this particular edge case it's not obvious to me why | bitwise operators shouldn't be applicable to boolean values. | Aren't they just single-bit vectors? | | Of course it makes sense that logical operators wouldn't be | applicable to numeric types, but why the reverse? | phkahler wrote: | >> Other than this particular edge case it's not obvious to | me why bitwise operators shouldn't be applicable to boolean | values. | | That is a really good question. At some point they decided | that true=1 and false=0 but I'm not sure how deep that goes. | In particular what does ! actually do in this context? | qalmakka wrote: | If you stop integer values from being implicitly convertible | to booleans, you break the language and its compatibility | with C. | | The inverse is debatable, though. I honestly don't see why | someone would do bitwise operations on boolean, unless they | really wish to die a slow death from thousand cuts. Integer | promotion rules make even the simplest operations a wild | mess, and there's nothing in the standard that prevents bool | from having a sizeof equal to int (thus further complicating | everything). | | It might be sensible for newer language revisions to consider | deprecating certain operators from being applied to bool, | given that there is a strong change that 99% of the time | their use is not on purpose, but I guess it depends on how | much disruptive such change would turn out to be. | shawnz wrote: | I don't think the other poster was imagining a language | that retained compatibility with C, but rather a new | language altogether. Of course it would be impossible to | change this aspect of the language if retaining | compatibility with C was a requirement. | | > I honestly don't see why someone would do bitwise | operations on boolean | | For example, you might _want_ the behaviour shown here of | not short-circuiting. Or you might want to create a bitwise | function that also allows calling on single-bit (i.e. | boolean) values. | gmfawcett wrote: | This is one of those times when, for all its verbosity, Ada got | it right. For boolean conjunction you must choose between | writing "A and B", or "A and then B". The "and then" version is | short circuiting, while the bare "and" version is not. | gene91 wrote: | This is a typo of missing an ampersand. If the author were | writing Ada, it would have been a typo of missing a "then". | How is it different? | shawnz wrote: | Visual Basic also has this distinction (but the keywords are | "And" and "AndAlso") | dolni wrote: | If you've been in tech for a while, this is one of those things | that makes you sigh and shake your fist at "move fast and break | stuff" as a strategy. | ipsum2 wrote: | Google's philosophy isn't "move fast and break stuff". It's | probably the opposite - "move slow and be careful". These | things happen. | throwntoday wrote: | That's more about challenging the status quo not bad project | management. | Animats wrote: | The reason this happened is that it wasn't followed by "Google | hit by 143 defective product lawsuits". | kevincox wrote: | I don't think they could possibly be sued for this. They would | just be responsible for fixing or refunding the product. In | this case they issued a "fix". | | It is the same as when a car is defective. They don't get sued, | they do a recall and fix it. ___________________________________________________________________ (page generated 2021-07-22 23:00 UTC)