Google brengt update uit voor Chrome OS-bug die door typefout werd veroorzaakt

Google heeft Chrome OS 91 bijgewerkt naar een nieuwe versie, waarmee een bug wordt verholpen waardoor gebruikers niet meer konden inloggen op hun Chromebook. Het lijkt erop dat een enkele typefout in de code de oorzaak was van de problemen.

De update brengt Chrome OS naar versie 91.0.4472.167 en moet de problemen verhelpen die ontstonden bij de release van 91.0.4772.165 eerder deze week. De stabiele versie van de update lijkt voor alle Chromebooks te zijn verschenen, merkt 9to5Google op. Gebruikers die niet kunnen inloggen op hun Chromebook, kunnen de update doorvoeren door deze in gastmodus te starten. Wie eerder de updates uitschakelde om problemen te voorkomen, kan de update nu alsnog doorvoeren om het OS bij te werken.

De problemen zijn waarschijnlijk te herleiden tot een enkele typfout, constateerden gebruikers van Reddit. Te zien is dat de code if (key_data_.has_value() & !key_data_->label().empty()) { is bijgewerkt naar if (key_data_.has_value() && !key_data_->label().empty()) {. De fout zat hem daarbij dus in de enkele & in plaats van de vereiste &&.

Gebruikers klaagden begin deze week dat ze niet meer konden inloggen bij hun Chromebook doordat hun wachtwoord niet meer werd herkend. Herstellen naar de fabrieksinstellingen of in het ergste geval een complete schone installatie via de Dev Mode zou uitkomst bieden voor gebruikers die hun systeem al hadden bijgewerkt naar de buggy update.

Door Olaf van Miltenburg

Nieuwscoördinator

22-07-2021 • 14:24

68

Submitter: cjpostma

Reacties (68)

68
68
48
3
0
14
Wijzig sortering
De oorspronkelijke bug is in de taal: een integer als boolean waarde interpreteren. In talen als Java is dit expliciet niet mogelijk en had deze fout dus niet voorgekomen. Dit is het gevaar als talen te veel toe laten; er moet een goede balans zijn tussen expressiviteit en de kans op bugs zoals deze.

Deze fout is makkelijk gemaakt en ik vind niet dat het de programmeur amper aan te rekenen is, het is een bekende kwetsbaarheid. Wel is er wat misgegaan met betrekking tot het controleren van access condities.
De oorspronkelijke bug is in de taal: een integer als boolean waarde interpreteren. In talen als Java is dit expliciet niet mogelijk en had deze fout dus niet voorgekomen. Dit is het gevaar als talen te veel toe laten; er moet een goede balans zijn tussen expressiviteit en de kans op bugs zoals deze.

Deze fout is makkelijk gemaakt en ik vind niet dat het de programmeur amper aan te rekenen is, het is een bekende kwetsbaarheid. Wel is er wat misgegaan met betrekking tot het controleren van access condities.
Ik kan niet helemaal volgen wat je bedoelt. Dit is ook geldige syntax in Java toch? Die kent ook bitwise ANDs.
Even geprobeerd: je hebt gelijk maar het is onmogelijk om met booleans het antwoord af te laten wijken. Da's ook logisch, op boolean niveau is er geen verschil. Ik ben benieuwd wat hier het verschil heeft gemaakt, daarvoor heb ik wat hulp van C++ experts nodig.
Het verschil is dat de 2de functie ook wordt uitgevoerd met een bitwise AND, terwijl dat met een logical AND niet gebeurt als er sowieso geen true meer uit kan komen (dus als de eerste expressie al als false evalueert)
Neem aan dat dat in C hetzelfde is maar dat heb ik al 15 jaar niet aangeraakt.
Oh, ja, dat kan best het probleem veroorzaken.
If the resulting value is false, the value of the conditional-and expression is false and the right-hand operand expression is not evaluated.
Dit geld niet voor bitwise AND.

Maar dat zou nog erger zijn, want dat betekend dat de code afhankelijk is van een side effect van de rechtse evaluatie. Dan is of label() of empty() dus niet zonder side effects (?) Ik ben er nog steeds niet helemaal uit.
Het is inderdaad zo dat label() en empty() geen side effects hebben. Echter controleert de eerste check of key_data_ uberhaupt een geldige waard heeft. Als dat niet het geval is dan zal het ophalen van de key_data_ waarde en het uitvoeren van label() op die waarde zorgen voor een null pointer exception.

Daardoor zorgt het uitvoeren van de tweede expressie voor problemen als de eerste expressie false evalueert.

[Reactie gewijzigd door Armada651 op 23 juli 2024 21:04]

Ah ja, dat zou het inderdaad verklaren, top! En dan kan je niet meer inloggen. Wel logisch achteraf gezien.Nou ja, beter dan te veel toestaan en er dan niet achter komen.
Of het gaat juist fout als de eerste expressie false is. Wellicht leidt de tweede expressie dan tot een exception.

Als het geen value heeft is label().IsEmpty wellicht ongeldig.
Net zo makkelijk als de not operator per ongeluk weglaten, of links van het haakje plaatsen in plaats van rechts. De syntax blijft fantastisch goed maar de uitkomst zo fantastisch slecht.

Automatische testen helpen, maar ik zou niet durven raden hoe bizar veel testen je nodig hebt om een OS dekkend te krijgen... te veel.
Maar ze zouden toch images moeten testen op testapparatuur? Dan hadden de ontwikkelaars ook meteen ondervonden dat ze niet meer konden inloggen.
Had begrepen dat deze update op het stabiele kanaal was verschenen. Was die code dan niet goed genoeg getest? Het lijkt me toch dat dat Dev channel er is om dit soort dingen te onderscheppen voor ze naar het grote publiek gaan...
Zelfs op het dev channel: Unit tests.

Dit had nooit mogen gebeuren of gemerged te worden.

[Reactie gewijzigd door Nimja op 23 juli 2024 21:04]

klinkt als iets wat prima voorkomen had kunnen worden door goede automated testing... beetje jammer om te zien dat een gigant zoals Google met zoiets faalt.
Kan je me uitleggen hoe zoiets te testen valt? Beide operators zijn namelijk gewoon valide.
Geautomatiseerd testen is niet het testen analyseren van code-syntax zoals je hier lijkt te suggereren.

In plaats daarvan, zet een systeem een testomgeving op, met bijvoorbeeld gebruikersnaam abc en wachtwoord xyz. Nu kijkt het systeem, wat als ik inlog met abc en xyz, dan moet ik waarnemen dat de inlog goed gaat. Vervolgens probeert het systeem in te loggen met abc en uvw, of 123 en xyz. In beide gevallen mag de inlog niet goed gaan. Worden aan al deze condities voldaan, dan is de test gehaald.

Deze tests worden tegenwoordig vaak bijvoorbeeld als Unit Testing geïmplementeerd, waarbij zeer specifieke stukjes code (het liefst beperkt tot een enkele functie met in en output) worden getest. Een functie die het inloggen checkt kan hiermee perfect getest worden.

In een goed opgezette ontwikkelomgeving worden bijvoorbeeld in het versiebeheersysteem (git) automatisch door de git-server alle unit-tests gedraait wanneer er een pull-request van een ontwikkelbranch naar een hoofdbranch wordt ge-pull request. Wanneer alle (bij een groter project wel duizenden) unit tests 100% behaald worden, alleen dan kan het pull-request geaccepteerd worden. Wordt niet aan alle tests voldaan, dan kan de code nooit in een (pre)release belanden.

[Reactie gewijzigd door Helium-3 op 23 juli 2024 21:04]

In een goed opgezette ontwikkelomgeving worden bijvoorbeeld in het versiebeheersysteem (git) automatisch door de git-server alle unit-tests gedraait wanneer er een pull-request van een ontwikkelbranch naar een hoofdbranch wordt ge-pull request.
Wel door de GitLab/Github server, maar niet door het versiebeheersysteem.

GitLab / GitHub zijn complete CI/CD platformen. Git (de versiebeheer component van het platform) doet werkelijk niets met je testen.
Je hebt 100% gelijk! Ik heb echter specifiek het woordje "in" gebruikt; waarmee ik bedoel dat het testen "in" het versiebeheer (met bijvoorbeeld pull-requests en branches) zit verwerkt, en niet gebeurt door de git-specificatie of broncode.
Automated testing zijn tests om menselijke interacties na te bootsen.
Zo'n test kijkt dus niet of & of && correct is, maar wel of het kan inloggen met het juiste wachtwoord/ de output van de check correct is.

[Reactie gewijzigd door Christoxz op 23 juli 2024 21:04]

Interessant dat zo'n simple fout zo veel gevolgen kan hebben.Je zou toch nog stukje code verwachten die dit opvangt of controleert
Zou het dan ook zo makkelijk te misbruiken zijn?
Dit is het stukje code dat het wachtwoord controleert. Je kunt moeilijk alles dubbel gaan implementeren en kijken of er twee keer hetzelfde uitkomt.
Klopt. Je kan al best wel wat afvangen met gesimuleerde gebruikerstests. Uiteraard niet alles, maar dit soort basale zaken die statische workflows beïnvloeden pik je er zo tussenuit.
Dit is prima met linting op te vangen
Niet helemaal.

Bij JavaScript kan je Quoke gebruiken dan zie dat de uitkomst verkeerd is.
Mwah, ik denk dat dit wel helemaal met linting of static code analysis op te vangen is hoor.
De bitwise & gebruiken voor boolean compare is gewoon nooit een goed idee. Mocht je niet && kunnen gebruiken omdat je er zeker van wilt zijn dat beide functies uitgevoerd worden na elkaar dan is in de if-statement niet de plek of kan een commentaartje voor linting uitzondering met uitleg ook geen kwaad.
De bitwise & gebruiken voor boolean compare is gewoon nooit een goed idee.
De bitwise & operator wordt juist constant gebruikt voor if-statements wanneer je wil checken of een bit flag aan staat:
if (nFlags & BITFLAG_TEST_1)
Ook kan de bit field afkomstig zijn van een functie:
if (GetFlags() & BITFLAG_TEST_1)
Echter zal je niet vaak zien dat beide parameters afkomstig zijn van een functie, dus wellicht is het redelijk als een static analyzer een waarschuwing geeft als beide kanten van de expressie functies zijn.
Dan ben je echter de byte operand aan het gebruiken waar hij voor bedoeld is en niet aan het misbruiken met booleans. In een typed language als c++ kan je prima een linter of static code analysis krijgen die deze twee usecases uit elkaar kan houden.
Ja, bitwise operatie op twee booleans is inderdaad ook vreemd.
Vaak zie je dat er een rule is die hierop een warning geeft, zodat je in ieder geval getriggered wordt om een uitzondering toe te voegen (of het anders op te lossen).
Door test code te schrijven die combinaties van key_data_ aanbied aan deze code waarin alle if then else combinaties een keer aan de beurt komen.

Dan de testen te draaien en kijken of alle verwachte paden bewandeld worden en resulteren in de goede aanroepen naar andere code. (als je interesse hebt, test-driveen development en iets met interfaces, mocks & stubs)
Volgens mij werken er gewoon nog mensen.
Klopt, en die maken helaas fouten. Ook het bedenken en schrijven van tests kunnen fout gaan maar het geeft wel een punt van controle. Grote bedrijven zouden dit eigenlijk in hun workflow moeten hebben opgenomen; sommige bedrijven passen zelfs test-driven development toe waarbij functionaliteit wordt geïmplementeerd aan de hand van unit tests. Ook niet heilig maar wel een mooie methode imho.
En daarom zouden ontwikkelaars gewoon een uurtje de tijden moeten nemen om zelf even de meest basale functies te testen en niet alles aan automatie proberen over te laten. Ik begrijp dat dat in veel gevallen veel efficiënter is maar ik loop zo vaak tegen bugs in software updates aan waarbij het gewoon overduidelijk is dat er nooit een mens naar de update heeft gekeken want dan waren ze in een paar minuten tijd al tegen overduidelijke bugs aangelopen.

Zo ook in dit geval. Hoe kan je nou missen dat je niet meer kan inloggen? Als een enkele dev die update had geïnstalleerd en proberen te doen wat iedere gebruiker doet, dan hadden ze er toch meteen achter gekomen?
Ik snap inderdaad niet waarom ze niet elke update door een redelijk aantal mensen laten testen. Desnoods mensen die een nightly-versie gebruiken of zo.
Achja, tests worden ook gewoon geschreven door mensen, dus ook niet waterdicht.
Als ik het voorbeeld zo zie krijg je mogelijk 1 terug ipv true, dus het resultaat zal mogelijk in de meeste gevallen nog steeds hetzelfde zijn.
Anoniem: 1532362 @cappie22 juli 2021 15:37
Ja, of, en ik zeg maar wat geks hoor, Je laat de updates in het stabiele release kanaal komen testen door een echt mens?
Ik bedoel ChromeOS wordt door miljoenen mensen gebruikt, en het is niet alsof Google te weinig personeel of geld heeft.
Is 1 persoon die een 'stable' update test echt teveel gevraagd?
dit was prima te voorkomen geweest door een correcte funtionele test (al dan niet geautomatiseerd).

Er wordt nog steeds zo vaak de denkfout gemaakt dat testen = geautomatiseerd testen.

Je kunt ook prima handmatig (niet geautomatiseerd testen), zonder ook maar naar letter code te hoeven kijken. Pas als je deze tests vaker moet doen, automatiseer je deze scenario's. Ook dan hoef je nog steeds niets van de code te hebben gezien. Je kijkt alleen naar de functionaliteit (in dit geval het inlog en valideringsproces). En dat dat correct moet werken. Een goede functionele tester (of, geautomatiseerde functionele test), valideert dit. En had deze fout dus ook kunnen ontdekken.

Waarschijnlijk is van het dogma "code testen" vangt alles af gebruik gemaakt. En nee dat is het dus niet.
Dit is precies de reden dat ik altijd enkele dagen wacht voordat ik een update installeer. Dat is misschien minder veilig, maar draagt wel bij aan de stabiliteit en compatibiliteit van je systeem.
.oisyn Moderator Devschuur® @Kastermaster22 juli 2021 14:45
Tenzij iedereen dat doet, dan ben je weer terug bij af ;)
Haha, dat is waar. Ik heb naast twee zakelijke apparaten gelukkig ook een game pc. Daarop draai ik updates als eerste. Werkt het niet, dan kan ik onder werktijd iig een backup resteren zonder dat ik daar last van heb 😉
Mensen die de nightly-versie o.i.d. draaien kunnen dat toch doen. Zij weten dan dat ze ongeteste programma's draaien.
Onder ChromeOS werkt dat niet zo. Die installeert op de achtergrond de updates (in slot A of B afhankelijk waarin je geboot bent) en bij de volgende start krijg je de andere slot (waar de update dus geïnstalleerd is)
Dat is wel heel slordig.
Niet zozeer dat de fout gemaakt werd, kan iedere developer overkomen, maar dat dit schijnbaar niet grondig getest is geweest alvorens de update te pushen naar honderdduizenden apparaten.
Zouden ze nog aan PR reviews doen of is dat niet hip meer?
Leuk, maar dat is ook niet 100% dekkend.
Is vast achterhaald, maar dat dit er niet eerder is uitgehaald door een statische analyse tool of zelfs al een unit/component test valt mij wel van ze tegen....
Waar is toch die cursor op het scherm, eff toets indrukken en kijken waar het verschijnt....
"...De problemen zijn waarschijnlijk te herleiden tot een enkele typfout, constateerden gebruikers van Reddit. Te zien is dat de code if (key_data_.has_value() & !key_data_->label().empty()) { is bijgewerkt naar if (key_data_.has_value() && !key_data_->label().empty()) {. De fout zat hem daarbij dus in de enkele & in plaats van de vereiste &&...."

Een type fout, dat overkomt de beste en in dit geval lees je er zo overheen. Wat mij verbaast is dat er tijdens de compilatie blijkbaar geen error is verschenen Een beetje compiler checkt toch de gehele syntax !?
Syntax is correct, het is compleet valide om een bitwise AND te gebruiken ipv een logical AND, maar het resultaat verschilt wel.
Dat gezegd hebbende: een moderne compiler waarschuwt hier wel voor, omdat een bitwise operator gebruiken in een context waar je een bool verwacht zeer waarschijnlijk een fout is.
Dat ook, maar je zou ook verwachten dat ze nog even de laatste images die stable moeten gaan opleveren op testapparaten gooien en dan was deze bug meteen aan het licht gekomen omdat ontwikkelaars niet meer hadden kunnen inloggen.
Weinig tech of dev kennis hier, maar wil Tweakers wel even bedanken voor het plaatsen van dit soort berichten (net als update / downloads) voor software !!! _/-\o_
Hoezo gebruiken de developers niet resharper? Die detecteert meteen dat het verkeerd is en vult code automatisch aan.
Whoops, dat is een vervelende typo die iedere developer kan overkomen. Ook een leuke om overheen te lezen bij het zoeken van de fout.
Bij ons is de regel dat een dergelijke bugfix ook voorzien wordt van een automated test zodat het probleem niet later nog eens terug komt.
Maar die bug had er toch bij elke test al uitgehaald moeten worden. Als je de boel compiled, uitrolt naar een test device en probeert in te loggen loopt je er al tegenaan?
Is de fout gemaakt door een verkeerd type (typefout) of door een foutje tijdens het typen (typfout)?

Op dit item kan niet meer gereageerd worden.