Zum Inhalt springen

Blog ·

Ein Umwandlungsskript, das zu weit lief

Ein Typografieskript krümmte einen Apostroph in einem Zitat von Programmausgabe, in einem Artikel, den es nie hätte anfassen dürfen. Jede Prüfung blieb grün.

Von Provibr

Französisch und Italienisch verlangen einen typografischen Apostroph statt eines geraden, und es gibt einen Test, der das durchsetzt. Dieses Zeichen unmittelbar in eine Quelldatei zu schreiben ist unzuverlässig: je nachdem, wie die Datei entsteht, kann eine Shell, ein Heredoc oder ein Bearbeitungswerkzeug es wieder in das gerade Zeichen zurückverwandeln. Also schreiben wir das gerade Zeichen und lassen danach ein kleines Skript laufen, das es umwandelt.

Dieses Skript maskiert Code. Alles innerhalb von Backticks und alles innerhalb eines eingezäunten Blocks bleibt unberührt, denn ein Apostroph in einem Codefragment würde das Fragment verändern, und der Faktenvergleich würde zu Recht rot werden.

Es lief als Glob über einen ganzen Sprachordner. Es wandelte einen Apostroph innerhalb eines Zitats von Programmausgabe um, in einem Artikel aus einer anderen Runde, der zufällig im selben Ordner lag.

Die Maskierung war richtig und das Ziel war falsch

Die Zeile, die es beschädigte, war ein Zitat dessen, was ein Befehl ausgegeben hatte, in Guillemets als laufende Prosa gesetzt statt als Code ausgezeichnet. Etwas von der Form Locking administration user's password. Dieser Apostroph gehört der Maschine, die ihn ausgegeben hat, und ihn zu krümmen lässt den Artikel behaupten, die Maschine habe etwas gesagt, was sie nicht gesagt hat.

Die Maskierungsregel stimmt. Backticks und eingezäunte Blöcke sind Code. Ein Zitat von Programmausgabe, das als Prosa gesetzt ist, ist nicht als Code ausgezeichnet und lässt sich beim Blick auf die Zeichen nicht von Prosa unterscheiden, denn genau das ist es: Prosa, die eine Maschine zitiert.

Der Defekt liegt also nicht in der Maskierung. Er liegt in der Auswahl. Drei Artikel aus anderen Runden wurden von einem Skript verändert, das geschrieben war, um vier anzufassen.

Warum die Bauprüfung es nicht bemerkte

Das ist der Teil, der über ein einzelnes Skript hinaus allgemein gilt.

Unsere Artikel werden erzeugt. Die Quelle ist Markdown, die Ausgabe sind eingecheckte erzeugte Dateien, und es gibt eine Prüfung, die aus der Quelle neu baut und verlangt, dass das Ergebnis Byte für Byte gleich dem Eingecheckten ist. Laufen die auseinander, wird sie rot.

Sie liefen nicht auseinander. Das Skript änderte die Quelle, der Bau lief, die Ausgabe wurde aus der geänderten Quelle neu erzeugt, und die beiden stimmten vollkommen überein. Die Prüfung beantwortet „ist die Ausgabe mit der Quelle stimmig“, was eine echte Frage ist und nicht diese. Nichts in der Kette beantwortet „hat diese Runde nur das geändert, was sie ändern sollte“.

Der Typografietest ebenso wenig, aus demselben Grund umgekehrt: ein gekrümmter Apostroph ist im Französischen das richtige Zeichen. Die Änderung machte die Datei regelkonformer und nicht weniger.

Das Einzige, was es zeigte, war git status auf Pfaden außerhalb der eigenen Dateien der Runde. Das ist jetzt die Regel: listen Sie nach jeder Umwandlung die geänderten Dateien auf und bestätigen Sie, dass jede einzelne davon Ihnen gehört.

Die Regel, die daraus folgt

Lassen Sie ein Umwandlungsskript auf den Dateinamen Ihrer eigenen Runde laufen. Niemals auf einem Glob über ein Verzeichnis.

Aufgeschrieben klingt das selbstverständlich, und beim Schreiben war es das nicht, denn ein Glob über einen Sprachordner ist der natürliche Weg, „die französischen Artikel umwandeln“ auszudrücken, und das Skript hatte eine richtige Sicherheitseigenschaft, die es sicher wirken ließ: es verlangt mindestens eine Ersetzung je Datei, damit ein Lauf, der still nichts tut, keinen Erfolg melden kann. Diese Prüfung betrifft den leeren Erfolg. Über den Umfang sagt sie nichts.

Eine Sicherheitsprüfung, die davor schützt, zu wenig zu tun, ist keine Sicherheitsprüfung dagegen, zu viel zu tun. Das sind getrennte Eigenschaften, und sie brauchen getrennte Mechanismen.

Zwei kleinere Fassungen desselben Problems

Die Runde, die darauf stieß, stieß auch auf zwei Übersetzungsfehler aus derselben Familie: etwas, das gegen Bearbeitung immun hätte sein sollen, war nicht als solches gekennzeichnet.

Eine Zwischenspeicheranweisung stand in der Quelle als nackte Prosa statt in Backticks. Zwei Sprachen übersetzten sie, was aus einem Schlüsselwort eine Wendung macht, und eine davon machte zusätzlich aus einer Dauer von einem Jahr einen Plural. Keines von beiden fängt der Faktenvergleich ab, denn dieser Vergleich deckt ab, was in Backticks steht und was eine Ziffer ist, und ein nacktes Schlüsselwort ist keines von beidem. Die Reparatur besteht darin, es in allen neun Sprachen als Token auszuzeichnen, wonach der Vergleich es dauerhaft abdeckt.

Das zweite war eine Tabelle mit Oberflächenbeschriftungen. Der englische Artikel benutzte sie, um zu zeigen, dass zwei Namenslisten auseinandergelaufen waren, und sagte ausdrücklich, dass das Auseinanderlaufen auf Englisch gemessen wurde. Sechs der acht Übersetzungen übersetzten die Tabelle. Ein übersetztes Namenspaar ist keine mildere Fassung der Messung; es ist eine andere Messung, die nie vorgenommen wurde. Das rückgängig zu machen kostete 26 Ersetzungen.

Beide Fehler haben dieselbe Gestalt wie der Apostroph: ein Stück Text, das Daten und keine Sprache ist, an einer Stelle, an der nichts es als Daten kennzeichnet.

Was eine Prüfung beantwortet, ist enger als das, was sie zu beantworten scheint

Die drei hier beteiligten Mechanismen sind jeder für sich richtig, und jeder beantwortete eine Frage neben der, auf die es ankam.

PrüfungDie Frage, die sie beantwortetDie Frage, die sie nicht beantwortet
Die Prüfung des Inhaltsbausist die erzeugte Ausgabe mit der Quelle stimmighat diese Änderung nur beabsichtigte Dateien berührt
Der Typografietestbenutzt diese Datei die richtigen Zeichen für ihre Sprachestehen diese Zeichen an den richtigen Stellen
Die eigene Wache des Skriptshat diese Datei mindestens eine Ersetzung bekommenhat irgendeine Datei eine Ersetzung bekommen, die sie nicht hätte bekommen dürfen

Keiner davon ist schlecht entworfen. Der Fehler ist die Annahme, dass eine Wand aus grünen Prüfungen Abdeckung darstellt, während sie tatsächlich die Abdeckung dessen darstellt, woran jemand gedacht hat.

Das billigste Gegenmittel dafür ist keine weitere Prüfung. Es ist, sich den Diff auf der Ebene der Dateinamen anzusehen, bevor irgendetwas eingecheckt wird, das ein Skript erzeugt hat.

Was wir aufschreiben würden

  1. Begrenzen Sie eine Umwandlung auf die Dateien Ihrer eigenen Runde. Ein Glob über ein Verzeichnis ist kein Umfang, sondern eine Kategorie.
  2. Eine Wache dagegen, zu wenig zu tun, sagt nichts darüber, zu viel zu tun. Das sind verschiedene Eigenschaften.
  3. Ein Zitat von Programmausgabe ist Daten. Zeichnen Sie es als Code aus, sonst behandelt eine Textumwandlung es als Sprache.
  4. Eine Stimmigkeitsprüfung zwischen Quelle und Ausgabe ist blind für eine Änderung an beiden. Sie beantwortet die Übereinstimmung und nicht die Absicht.
  5. Eine Änderung, die eine Datei richtiger macht, ist am schwersten zu bemerken, denn jedes Qualitätssignal zeigt in die richtige Richtung.
  6. Lesen Sie die Dateiliste Ihres eigenen Diffs. Sie ist die einzige Prüfung, die die Frage nach dem Umfang beantwortet.
  7. Alles, was ein Schlüsselwort ist, gehört in der Quelle in Backticks, in jeder Sprache, sonst übersetzt es jemand und kein Test wird sich daran stören.
  8. Eine übersetzte Messung ist eine erfundene Messung. Wenn der Sinn einer Tabelle ist, dass zwei Dinge sich unterscheiden, ist die Tabelle Beleg und keine Prosa.

Zur Klarheit: der Schaden wurde zurückgenommen, die Runde endete mit der Inhaltsprüfung bei 815 von 815 erzeugten Dateien Byte für Byte gleich, der Web-Suite bei 4546 grün, den Paket-, Gateway- und Werkzeugsuiten bei 7236 grün, dem Faktenvergleich über 1240 Absätze ohne Befund, Links bei 81 von 81, Tabellen bei 99 von 99 und dem Layoutdurchlauf bei 108 von 108 bei 390 Pixeln gegen einen Produktionsbuild. Der Typografietest wurde mit zwei gepflanzten Defekten rot bewiesen und war danach grün. Nicht bewiesen: es gibt einen Leser je Übersetzung, drei Sprachen wurden nur auf Layout, Typografie und HTTP-Status geprüft, und die aus früheren Runden zitierten Zahlen wurden hier nicht neu gemessen.

Aus der Plattformarbeit an Provibr. Was ein zweiter Leser in denselben acht Artikeln fand, steht in Drei Fehler, die kein Skript sehen konnte, und was neun Kataloge mit einem festen Satz Bedienelemente anstellen, steht in Sechzehntausend Schlüssel, neun Sprachen.

Fangen Sie mit einem Host und einem Agenten an

Konto erstellen, den Agenten mit einem einzigen Befehl installieren und Ihren ersten Proxmox-Host verbinden. Die Testphase läuft 14 Tage und fragt nicht nach Zahlungsdaten.