[C++] StackBufferOverflow in shop.cpp

  • Moin.


    Da ich immernoch am ausprobieren sämtlicher Tools und Hilfestellungen bin und heute random die Option zum "AdressSanitizer" in Visual Studio gefunden habe, dachte ich schadet es nicht wenn ich einen potenziellen und offensichtlichen Fehler mit euch teile. Gleichzeitig empfehle ich jedem angehenden Entwickler folgendes Video hier:


    Bitte melden Sie sich an, um dieses Medienelement zu sehen.


    -------------------------------------------------------------------------------------------------------------------------


    Was zum Fick?


    Ums kurz zu erklären, was tun wir in den folgenden drei Zeilen Code?

    Code
    1.     char name[36];
    2.     snprintf(name, sizeof(name), "%-20s(#%-5d) (x %d)", item_table->szName, (int) item.vnum, item.count);
    3.     sys_log(0, "SHOP_ITEM: %-36s PRICE %-5d", name, item.price);


    1) Wir erstellen ein char array im Stack mit der Länge / Größe 36. Also können genau 35 Zeichen + im Optimalfall (üblicherweise) der Null-Terminator '\0' reingeschrieben werden ins Array.

    2) Wir schreiben einen formatierten String in den Buffer, grob gesagt. Eigentlich streamen wir den formatierten String in ihn, aber gut.

    3) Wir geben den String als Teilkomponente in der sys_log aus, dafür benutzen wir den Variablennamen für das Char-Array also 'name'. Was eig. nur ein Pointer auf das erste Zeichen im Array ist, wenn mans so will. Beim Ausgeben liest dann das Programm von diesem Pointer aus im Speicher die Stellen und gibt sie aus bis ein '\0' - Terminator kommt.


    Setzen wir doch mal einfach Werte in den formattierten String ein und schauen uns z.B an was passiert wenn ich als Serverbetreiber '100x Zen-Bohne' im Shop verkaufen möchte und in die shop_item in der Datenbank so eintrage:


    Code
    1. Zen-Bohne (#70102) (x 100)


    Sieht harmlos aus oder? Wie viele Zeichen sind das? (Es sind genau 36)

    Es fehlt also der Platz für den Nullterminator im char array, snprintf wird das Array nicht vergrößern. Stattdessen findet man bei der Recherche folgendes über den Rückgabewert der 'printf' - Funktionen:


    Wir haben ein Char Array der Größe 36 erstellt und genau 36 Zeichen reingeschrieben. Demnach ist dieser 'string' wenn mans so sehen möchte nicht null terminiert. Der char - Array resultiert also eig. in sowas hier was wir nicht wollten:

    Code
    1. Zen-Bohne (#70102) (x 100)¼±µÎ


    Es werden mehr Zeichen repräsentiert als angegeben (36), weil im Speicher nun zufällig erst nach 4 random Zeichen der Nullterminator kommt. Das könnten auch 500 Zeichen sein, oder gar keiner. Also wenn ihr noch keinen Crash beim Hochfahren des Servers hattest, hattet ihr entweder einen wirklich schlauen Compiler der das erkannt und die Gefahr gebannt hat oder einfach Glück.


    Wie fixxe ich das nun?


    Ganz einfach, macht den Buffer entsprechend größer. Theoretisch reicht es, ihn auf 40-50 zu setzen. Ich nehm jetzt einfach 512 um ultra sicher zu sein (Nutze damit mehr Speicher im Stack, ist aber unproblematisch, weils schnell wieder gecleared wird und nicht dauerhaft da bleibt):


    shop.cpp

    Suchen

    Code
    1. char name[36];
    2. snprintf(name, sizeof(name), "%-20s(#%-5d) (x %d)", item_table->szName, (int) item.vnum, item.count);
    3. sys_log(0, "SHOP_ITEM: %-36s PRICE %-5d", name, item.price);


    Ersetzen mit

    Code
    1. char name[512];
    2. snprintf(name, sizeof(name), "%-20s(#%-5d) (x %d)", item_table->szName, (int) item.vnum, item.count);
    3. sys_log(0, "SHOP_ITEM: %-36s PRICE %-5d", name, item.price);


    Was lernen wir daraus?

    Wir sollten alle Tools nutzen die es gibt um unser Programm bestmöglichst zu härten und Bugs vorzubeugen.

    Bugs erst zu fixxen, wenn sie auftauchen ist keine Good Practice. Vieles kann vorher schon verhindert werden.

  • Dieses Thema enthält 4 weitere Beiträge, die nur für registrierte Benutzer sichtbar sind, bitte registrieren Sie sich oder melden Sie sich an um diese lesen zu können.