Warum wird strtok() als unsicher angesehen?

Lesezeit: 4 Minuten

Benutzer-Avatar
Benutzer541686

Welche Funktion(en) von strtok ist unsicher (in Bezug auf Pufferüberlauf), auf die ich achten muss?

Was mir ein bisschen komisch vorkommt ist das strtok_s (was “sicher” ist) in Visual C++ hat einen zusätzlichen “Kontext”-Parameter, aber es sieht so aus, als wäre es auf andere Weise gleich … ist es das gleiche oder ist es tatsächlich anders?

  • Vielleicht, weil beide Argumente von strtok Zeiger auf char sind, sodass strtok möglicherweise kein Abschlusszeichen erreicht, das einen lokalen Puffer überläuft?

    – Heisenbug

    14. Mai 2011 um 2:21 Uhr

  • @0verbose: Hm … aber gilt das nicht für alle C-Saiten?

    – Benutzer541686

    14. Mai 2011 um 2:22 Uhr

  • Sie können sich die Implementierung ansehen: openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/… . Werde ich mir auch ansehen.

    – Heisenbug

    14. Mai 2011 um 2:28 Uhr

  • Nebenbei bemerkt, warum sollte man das immer noch verwenden, wenn es das gibt Strep

    – Mel

    14. Mai 2011 um 2:33 Uhr

  • Ich denke, der Kontext in strtok_s besteht darin, es Thread-sicher zu machen, wie strtok_r

    – Platsch

    14. Mai 2011 um 2:34 Uhr

Gemäß dem Abschnitt strtok_s von dieses Dokument:

6.7.3.1 Die Funktion strtok_s Die Funktion strtok_s behebt zwei Probleme in der Funktion strtok:

  1. Ein neuer Parameter, s1max, verhindert, dass strtok_s außerhalb der tokenisierten Zeichenfolge gespeichert wird. (Die in Token unterteilte Zeichenfolge ist sowohl eine Eingabe als auch eine Ausgabe der Funktion, da strtok_s Nullzeichen in der Zeichenfolge speichert.)
  2. Ein neuer Parameter, ptr, eliminiert den statischen internen Zustand, der verhindert, dass strtok wiedereintrittsfähig ist (Unterabschnitt 1.1.12). (Die ISO/IEC 9899-Funktion wcstok und die ISO/IEC 9945 (POSIX)-Funktion strtok_r beheben dieses Problem auf identische Weise.)

  • +1 Ich hatte dieses Dokument nicht gesehen, scheint die Antwort genau zu erklären. 🙂

    – Benutzer541686

    14. Mai 2011 um 2:37 Uhr

  • Beachten Sie, dass diese Spezifikation von strtok_s() stammt aus dem (optionalen) Anhang K von ISO/IEC 9899:2011, und seine Definition unterscheidet sich von der Microsoft-Spezifikation von strtok_s().

    – Jonathan Leffler

    30. September 2017 um 21:20 Uhr

Benutzer-Avatar
Bob

Daran ist nichts unsicher. Sie müssen nur verstehen, wie es funktioniert und wie man es benutzt. Nachdem Sie Ihren Code und Komponententest geschrieben haben, dauert es nur ein paar zusätzliche Minuten, um den Komponententest mit valgrind erneut auszuführen, um sicherzustellen, dass Sie innerhalb der Speichergrenzen arbeiten. Die Manpage sagt alles:

FEHLER

Seien Sie vorsichtig, wenn Sie diese Funktionen verwenden. Wenn Sie sie verwenden, beachten Sie Folgendes:

  • Diese Funktionen ändern ihr erstes Argument.
  • Diese Funktionen können nicht auf konstante Zeichenfolgen angewendet werden.
  • Die Identität des begrenzenden Charakters geht verloren.
  • Das strtok() -Funktion verwendet beim Parsen einen statischen Puffer, ist also nicht Thread-sicher. Verwenden strtok_r() wenn dir das wichtig ist.

  • Ich habe eine kleine Änderung bzgl strtok_s… weißt du zufällig, wie es anders ist?

    – Benutzer541686

    14. Mai 2011 um 2:25 Uhr

  • Ich bin damit nicht vertraut, aber es klingt wie strtok_r. Wenn Sie zwei oder mehr Zeichenfolgen gleichzeitig tokenisieren, benötigen Sie eine davon. Wenn Sie nur mit einem zu tun haben, müssen Sie es nicht verwenden.

    – Bob

    14. Mai 2011 um 2:35 Uhr

  • Um mehr zu verdeutlichen, behält strtok eine versteckte Statis-Referenz in Ihrer Zeichenfolge bei. Wenn Sie es mit mehr als einer Zeichenfolge aufrufen, ist die Referenz falsch. strtok_r/s zwingt Sie, die Referenz auf die Funktion bereitzustellen.

    – Bob

    14. Mai 2011 um 2:39 Uhr

  • es darf nicht sein Sie wer läuft strtok in einem anderen Thread. Es könnte dein Plugin sein. Oder vielleicht wird Ihr Code in einer Bibliothek verwendet, die in einem anderen Thread der ebenfalls verwendeten Haupt-App ausgeführt wird strtok. Oder vielleicht beschließen Sie einfach, Ihren Code eines Tages multithreadingfähig zu machen, nachdem Sie vergessen haben, dass es eine gibt strtok dort anrufen.

    – Gabe

    14. Mai 2011 um 4:20 Uhr

  • Daran ist nichts unsicher. Entfernen Sie diesen Satz. Sie haben buchstäblich den Abschnitt in der Manpage zitiert, der besagt, dass es nicht Thread-sicher ist.

    – Wyck

    8. April um 15:08 Uhr

strtok ist sicher in Visual C++ (aber nirgendwo anders), da es lokalen Threadspeicher verwendet, um seinen Zustand zwischen Aufrufen zu speichern. Überall sonst wird die globale Variable verwendet, um den strtok()-Zustand zu speichern.

Aber selbst in VC++, wo strtok Thread-sicher ist, ist es immer noch etwas seltsam – Sie können strtok()s nicht gleichzeitig auf verschiedene Strings im selben Thread anwenden. Dies würde zum Beispiel nicht gut funktionieren:

     token = strtok( string, seps );
     while(token)
     {
        printf("token=%s\n", token)
        token2 = strtok(string2, seps);
        while(token2)  
        {
            printf("token2=%s", token2);
            token2 = strtok( NULL, seps );
        }
        token = strtok( NULL, seps );
     }

Der Grund, warum es nicht gut funktionieren würde, ist, dass für jeden Thread nur ein Zustand im lokalen Speicher des Threads gespeichert werden kann, und hier würde man 2 Zustände benötigen – für die erste Zeichenfolge und für die zweite Zeichenfolge. Während also strtok mit VC++ Thread-sicher ist, ist es nicht reentrant.

Was strtok_s (oder strtok_r überall sonst) bietet – einen expliziten Zustand, und damit wird strtok wiedereintrittsfähig.

Wenn Sie keine ordnungsgemäß nullterminierte Zeichenfolge haben; Sie werden in einem Pufferüberlauf enden. Beachten Sie auch (das habe ich auf die harte Tour gelernt), dass sich strtok anscheinend NICHT um interne Zeichenfolgen kümmert. IE mit “hello”https://stackoverflow.com/”world” wird “hello”https://stackoverflow.com/”world” analysieren, während “hello/world” in “hello world” analysiert wird. Beachten Sie, dass es am / geteilt wird und die Tatsache ignoriert, dass es sich in einer Klammer befindet.

1382760cookie-checkWarum wird strtok() als unsicher angesehen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy