Ungeeigneter Quellcode-Stil oder Formatierung

Beschreibung

Ungeeigneter Quellcode-Stil oder Formatierung tritt auf, wenn Quellcode nicht den gewünschten Stil- oder Formatierungskonventionen für Einrückung, Leerzeichen, Kommentare oder andere stilistische Elemente folgt. Inkonsistente Formatierung macht Code schwerer zu lesen und zu verstehen, was die kognitive Last für Code-Review und Wartung erhöht. Obwohl Stil oberflächlich erscheinen mag, kann inkonsistente Formatierung logische Fehler verbergen und Sicherheitsschwachstellen während des Code-Reviews schwerer erkennbar machen.

Risiko

Ungeeignete Formatierung hat indirekte Sicherheitsimplikationen. Inkonsistente Einrückung kann den tatsächlichen Kontrollfluss verbergen, sodass sicherheitsrelevante Codeblöcke anders erscheinen als sie tatsächlich sind. Code-Reviewer können Schwachstellen in schlecht formatiertem Code übersehen. Copy-Paste-Fehler sind bei inkonsistenter Formatierung wahrscheinlicher. Sicherheitstools können Schwierigkeiten haben, nicht-standardmäßige Formatierung zu parsen. Irreführende Einrückung kann dazu führen, dass Entwickler das Codeverhalten falsch verstehen. Der berühmt "goto fail"-Bug (CVE-2014-1266) wurde durch irreführende Einrückung verborgen.

Lösung

Etablieren und setzen Sie Code-Stilrichtlinien für das Projekt durch. Verwenden Sie automatisierte Formatierer (Prettier, Black, clang-format, gofmt) im Entwicklungsworkflow. Konfigurieren Sie IDEs zum Formatieren beim Speichern. Verwenden Sie Pre-Commit-Hooks zum Durchsetzen der Formatierung. Fügen Sie Stilprüfungen in CI/CD-Pipelines ein. Verwenden Sie Linter zum Erkennen von Stilverletzungen. Wählen Sie etablierte Stilrichtlinien (Google, Airbnb, PEP 8) anstatt eigene zu erstellen. Dokumentieren Sie Abweichungen von Standardstilen. Verwenden Sie Editor-Konfigurationen (.editorconfig) um Konsistenz über Tools hinweg zu erhalten.

Häufige Auswirkungen

AuswirkungDetails
AndereBereich: Ändere

Erhöhte analytische Komplexität - Inkonsistenter Stil macht Code schwerer zu verstehen und zu überprüfen.
AndereBereich: Ändere

Reduzierte Wartbarkeit - Schlecht formatierter Code ist schwerer sicher zu modifizieren.
AndereBereich: Ändere

Verbergen logischer Fehler - Irreführende Formatierung kann tatsächliches Codeverhalten verschleiern.

Beispielcode

Anfälliger Code

// Anfällig: Irreführende Einrückung (ähnlich dem "goto fail"-Bug)
static int verify_signature(const unsigned char *sig, size_t siglen,
                           const unsigned char *data, size_t datalen)
{
    int result = -1;

    if (!sig || !data)
        goto fail;

    if (siglen == 0)
        goto fail;

    // Anfällig: Diese Zeile wird IMMER ausgeführt, aber Einrückung suggeriert
    // sie ist Teil der obigen if-Anweisung
    if (siglen != EXPECTED_SIZE)
        goto fail;
        goto fail;  // WIRD IMMER Ausgeführt - Signaturprüfung umgangen!

    // Dieser Code wird nie erreicht
    result = perform_actual_verification(sig, data);

fail:
    return result;
}
// Anfällig: Inkonsistente Formatierung verbirgt Logikfehler
public class VulnerableProcessor {

    public void processRequest(Request request)
    {
        // Inkonsistenter Klammerstil
        if(request.isAuthenticated()){
            processAuthenticated(request);
        }else
        // Fehlende Klammern - nur erste Anweisung ist bedingt!
        if (request.isAdmin())
            grantAdminAccess(request);
            grantFullPermissions(request);  // WIRD IMMER Ausgeführt!

        // Anfällig: Irreführende Einrückung
        if (request.getData() != null)
            validateData(request);
            processData(request);  // Sieht bedingt aus, ist es aber nicht!

        // Inkonsistente Abstände machen Vergleich schwer lesbar
        if(request.getCount()==0||request.getCount( )>100) {
            // Was prüft das eigentlich?
        }
    }

    // Methoden mit völlig unterschiedlicher Formatierung
    public void methodOne(){System.out.println("one");}

    public void methodTwo()
    {
        System.out.println("two");
    }

    public void methodThree() { System.out.println("three"); }
}
# Anfällig: Inkonsistente Python-Einrückung
class VulnerableAuth:
    def authenticate(self, username, password):
        """Prüft Benutzeranmeldedaten."""
        if username == "admin":
          # 2-Leerzeichen-Einrückung
          if password == "secret":
             # 3-Leerzeichen-Einrückung - inkonsistent!
             return True
        # Tab und Leerzeichen gemischt - kann IndentationError verursachen
	    if self.check_db(username, password):  # Tab hier!
            return True
        return False

    def validate_input(self,input):  # Kein Leerzeichen nach Komma
        if input is None:
            return False
        if len(input)>100:  # Keine Leerzeichen um Operator
            return False
        #Kein Leerzeichen nach Raute in Kommentar
        return True

    # Inkonsistente Leerzeilen zwischen Methoden


    def another_method( self ):  # Seltsame Abstände
        """Irgendeine Methode."""
        pass
// Anfällig: Inkonsistente JavaScript-Formatierung
class VulnerableService{
    constructor() {
        this.data = []
    }  // Fehlende Semikolons

    // Methode 1: K&R-Stil
    processData(data) {
        if (data) {
            return data.map(x=>x*2)  // Inkonsistente Arrow-Function-Abstände
        }
    }

    // Methode 2: Allman-Stil
    validateInput(input)
    {
        if (!input)
        {
            return false;
        }
        return true;
    }

    // Methode 3: Einzeiler-Chaos
    async fetchData(id){try{const r=await fetch('/api/'+id);return r.json();}catch(e){console.log(e)}}

    // Inkonsistente Anführungszeichenstile
    getMessage() {
        return "Hallo " + 'Welt' + `!`;
    }
}

Korrigierter Code

// Korrigiert: Konsistenter Stil verhindert irreführende Einrückung
static int verify_signature(const unsigned char *sig, size_t siglen,
                           const unsigned char *data, size_t datalen)
{
    int result = -1;

    /* Korrigiert: Immer Klammern verwenden, auch für einzelne Anweisungen */
    if (!sig || !data) {
        goto fail;
    }

    if (siglen == 0) {
        goto fail;
    }

    if (siglen != EXPECTED_SIZE) {
        goto fail;
    }

    /* Korrigiert: Codestruktur ist jetzt klar */
    result = perform_actual_verification(sig, data);

fail:
    return result;
}

/* Korrigiert: Konsistente Anwendung der Stilrichtlinie */
/*
 * Verwendete Stilkonventionen:
 * - 4-Leerzeichen-Einrückung
 * - Öffnende Klammer auf gleicher Zeile
 * - Immer Klammern für if/else/while/for verwenden
 * - Leerzeichen nach Schlüsselwörtern (if, while, for)
 * - Kein Leerzeichen vor Funktionsaufruf-Klammern
 */
// Korrigiert: Konsistente Java-Formatierung
public class FixedProcessor {

    public void processRequest(Request request) {
        // Korrigiert: Konsistenter Klammerstil (K&R)
        if (request.isAuthenticated()) {
            processAuthenticated(request);
        } else if (request.isAdmin()) {
            // Korrigiert: Immer Klammern verwenden
            grantAdminAccess(request);
            grantFullPermissions(request);
        }

        // Korrigiert: Klarer Kontrollfluss
        if (request.getData() != null) {
            validateData(request);
            processData(request);
        }

        // Korrigiert: Konsistente Abstände
        if (request.getCount() == 0 || request.getCount() > 100) {
            handleInvalidCount(request);
        }
    }

    // Korrigiert: Konsistente Methodenformatierung
    public void methodOne() {
        System.out.println("one");
    }

    public void methodTwo() {
        System.out.println("two");
    }

    public void methodThree() {
        System.out.println("three");
    }
}

/*
 * Stilrichtlinie: Google Java Style
 * - 4-Leerzeichen-Einrückung (keine Tabs)
 * - 100-Zeichen-Zeilenlimit
 * - Klammern erforderlich für alle Kontrollstrukturen
 * - Eine Anweisung pro Zeile
 */
# Korrigiert: PEP-8-konformes Python
class FixedAuth:
    """Authentifizierungs-Handler nach PEP 8."""

    def authenticate(self, username: str, password: str) -> bool:
        """Prüft Benutzeranmeldedaten.

        Args:
            username: Der zu authentifizierende Benutzername
            password: Das zu verifizierende Passwort

        Returns:
            True wenn Authentifizierung erfolgreich, sonst False
        """
        # Korrigiert: Konsistente 4-Leerzeichen-Einrückung
        if username == "admin":
            if password == "secret":
                return True

        if self.check_db(username, password):
            return True

        return False

    def validate_input(self, user_input: str) -> bool:
        """Validiert Benutzereingabe.

        Args:
            user_input: Die zu validierende Eingabe

        Returns:
            True wenn gültig, sonst False
        """
        # Korrigiert: Konsistente Abstände um Operatoren
        if user_input is None:
            return False

        if len(user_input) > 100:
            return False

        # Korrigiert: Leerzeichen nach Raute in Kommentaren
        return True

    def another_method(self) -> None:
        """Platzhalter-Methode."""
        pass


# Stil: PEP 8
# - 4-Leerzeichen-Einrückung
# - Leerzeichen um Operatoren
# - Leerzeilen zwischen Top-Level-Definitionen
# - Zwei Leerzeilen um Klassendefinitionen
// Korrigiert: Konsistente JavaScript/ES6-Formatierung
class FixedService {
    constructor() {
        this.data = [];
    }

    // Korrigiert: Konsistenter Methodenstil
    processData(data) {
        if (data) {
            return data.map((x) => x * 2);
        }
        return [];
    }

    // Korrigiert: Konsistente Klammerplatzierung
    validateInput(input) {
        if (!input) {
            return false;
        }
        return true;
    }

    // Korrigiert: Lesbare async-Methode
    async fetchData(id) {
        try {
            const response = await fetch(`/api/${id}`);
            return response.json();
        } catch (error) {
            console.error('Fetch-Fehler:', error);
            throw error;
        }
    }

    // Korrigiert: Konsistenter Anführungszeichenstil (einfache Anführungszeichen)
    getMessage() {
        return 'Hallo Welt!';
    }
}

/*
 * Stil: Airbnb JavaScript Style Guide
 * - 2-Leerzeichen-Einrückung
 * - Einfache Anführungszeichen für Strings
 * - Semikolons erforderlich
 * - Leerzeichen um Operatoren
 * - Kein abschließendes Leerzeichen
 */

// ESLint- und Prettier-Konfiguration stellen Konsistenz sicher

CVE-Beispiele

  • CVE-2014-1266: Apples "goto fail"-SSL-Schwachstelle wurde durch irreführende Einrückung verborgen, die eine kritische Sicherheitsumgehung als Teil des Fehlerbehandlungscodes erscheinen ließ.

Verwandte CWEs

  • CWE-1076: Insufficient Adherence to Expected Conventions (Eltern)
  • CWE-546: Suspicious Comment (Kind)
  • CWE-547: Use of Hard-coded, Security-relevant Constants (Kind)
  • CWE-1099: Inconsistent Naming Conventions for Identifiers (Kind)

Referenzen

  1. MITRE Corporation. "CWE-1078: Inappropriate Source Code Style or Formatting." https://cwe.mitre.org/data/definitions/1078.html

  2. Google Style Guides. https://google.github.io/styleguide/

  3. PEP 8 - Style Guide for Python Code. https://peps.python.org/pep-0008/