Während der Code-Analyse analysiert PVS-Studio den Datenfluss und betreibt variable Werte. Werte werden aus Konstanten entnommen oder aus bedingten Ausdrücken abgeleitet. Wir nennen sie virtuelle Werte. Vor kurzem haben wir sie verfeinert, um mit Konstanten mit mehreren Zeichen zu arbeiten. Dies ist der Grund, eine neue Diagnoseregel zu erstellen.
Einführung
Mehrzeichenliterale sind
implementierungsdefiniert , sodass verschiedene Compiler sie auf unterschiedliche Weise codieren können. Beispielsweise legen GCC und Clang einen Wert fest, der auf der Reihenfolge der Symbole im Literal basiert, während MSVC sie je nach Symboltyp (regulär oder Escape) verschiebt.
Beispielsweise wird das Literal 'T \ x65s \ x74' je nach Compiler auf unterschiedliche Weise codiert. Eine ähnliche Logik musste im Analysator hinzugefügt werden. Aus diesem Grund haben wir eine neue Diagnoseregel V1039 erstellt, um solche Literale im Code zu identifizieren. Diese Literale sind in plattformübergreifenden Projekten gefährlich, bei denen mehrere Compiler zum Erstellen verwendet werden.
Diagnose V1039
Schauen wir uns das Beispiel an. Der folgende Code, der von verschiedenen Compilern kompiliert wurde, verhält sich unterschiedlich:
#include <stdio.h> void foo(int c) { if (c == 'T\x65s\x74') // <= V1039 { printf("Compiled with GCC or Clang.\n"); } else { printf("It's another compiler (for example, MSVC).\n"); } } int main(int argc, char** argv) { foo('Test'); return 0; }
Das von verschiedenen Compilern kompilierte Programm druckt verschiedene Meldungen auf dem Bildschirm.
Bei einem Projekt, das einen bestimmten Compiler verwendet, fällt dies nicht auf. Bei der Portierung können jedoch Probleme auftreten. Daher sollten solche Literale durch einfache numerische Konstanten ersetzt werden, z. B. "Test" muss durch 0x54657374 geändert werden.
Um den Unterschied zwischen Compilern zu demonstrieren, schreiben wir ein kleines Dienstprogramm, das Sequenzen von 3 und 4 Symbolen wie 'GHIJ' und 'GHI' verwendet und deren Darstellung nach dem Kompilieren im Speicher anzeigt.
Dienstprogrammcode:
#include <stdio.h> typedef int char_t; void PrintBytes(const char* format, char_t lit) { printf("%20s : ", format); const unsigned char *ptr = (const unsigned char*)&lit; for (int i = sizeof(lit); i--;) { printf("%c", *ptr++); } putchar('\n'); } int main(int argc, char** argv) { printf("Hex codes are: G(%02X) H(%02X) I(%02X) J(%02X)\n",'G','H','I','J'); PrintBytes("'GHIJ'", 'GHIJ'); PrintBytes("'\\x47\\x48\\x49\\x4A'", '\x47\x48\x49\x4A'); PrintBytes("'G\\x48\\x49\\x4A'", 'G\x48\x49\x4A'); PrintBytes("'GH\\x49\\x4A'", 'GH\x49\x4A'); PrintBytes("'G\\x48I\\x4A'", 'G\x48I\x4A'); PrintBytes("'GHI\\x4A'", 'GHI\x4A'); PrintBytes("'GHI'", 'GHI'); PrintBytes("'\\x47\\x48\\x49'", '\x47\x48\x49'); PrintBytes("'GH\\x49'", 'GH\x49'); PrintBytes("'\\x47H\\x49'", '\x47H\x49'); PrintBytes("'\\x47HI'", '\x47HI'); return 0; }
Ausgabe des von Visual C ++ kompilierten Dienstprogramms:
Hex codes are: G(47) H(48) I(49) J(4A) 'GHIJ' : JIHG '\x47\x48\x49\x4A' : GHIJ 'G\x48\x49\x4A' : HGIJ 'GH\x49\x4A' : JIHG 'G\x48I\x4A' : JIHG 'GHI\x4A' : JIHG 'GHI' : IHG '\x47\x48\x49' : GHI 'GH\x49' : IHG '\x47H\x49' : HGI '\x47HI' : IHG
Ausgabe des Dienstprogramms, zusammengestellt von GCC oder Clang:
Hex codes are: G(47) H(48) I(49) J(4A) 'GHIJ' : JIHG '\x47\x48\x49\x4A' : JIHG 'G\x48\x49\x4A' : JIHG 'GH\x49\x4A' : JIHG 'G\x48I\x4A' : JIHG 'GHI\x4A' : JIHG 'GHI' : IHG '\x47\x48\x49' : IHG 'GH\x49' : IHG '\x47H\x49' : IHG '\x47HI' : IHG
Fazit
Die V1039-Diagnose wird im kürzlich veröffentlichten PVS-Studio-Analysegerät der Version
7.03 hinzugefügt. Sie können die neueste Version des Analysators auf der
Download-Seite herunterladen .