Zeichenbeschränkung bei Ausgabe nicht-nullterminierter Strings



  • Als Debugging-Mechanismus haben die Funktionen unserer Bibliothek einen Makroaufruf, der als Argumente einen Formatstring für fprintf und die Parameter erhält.

    void wilde_funktion
    (
            struct datenstruktur*obj
    )
    {
            AUSGABE
            (
                    "Eingang mit obj: %p\n",
                    obj
            );
    
            /*...*/
    }
    

    Für einen HTTP-Parser haben wir eine Funktion, die die Addressen und die Längen von Headerfeldern (jeweils Name und Wert) übernimmt, Speicher über malloc reserviert, Name und Wert hier reinkopiert und in eine dynamische Arraystruktur speichert. Eine Eigenschaft der Headernamen und -Werte sind, dass diese nicht null-terminiert sind und auch nicht nullterminiert werden können, weil der Buffer noch von anderen Funktionen verwendet wird. Deswegen wird auch die Länge der Strings an diese Funktion übergeben.

    int http_header_set
    (
            struct http_header*const hhs,
            const char*const name,
            const size_t name_length,
            const char*const value,
            const size_t value_length
    )
    

    Alle Funktionen des HTTP-Modules befinden sich im Debugmodus, sprich, die Parameter der Funktionen sollen jetzt ausgegeben werden. Bisher haben wir uns mit einer ekelhaften Lösung zufriedengegeben - nämlich die Strings name und value einfach als nullterminierte Strings zu behandeln. Da zumindest auf der Linux-Testumgebung jedes Mal noch nach den Stringdaten Nullzeichen waren, hat dies keine Speicherverletzung hervorgerufen, aber man hat natürlich dennoch sehr viel mehr Ausgabe, als man erwarten würde von einem String, der eigentlich nur 10 Zeichen groß sein soll.

    Eingang mit hhs: 0x7ffcac810660, name: "Connection: keep-alive
    Pragma: no-cache"
    <USW>
    <USW>
    <USW>
    ", name_length: 10
    

    Das ist halt das Problem bei nicht-nullterminierten Strings, das wissen wir selber.
    Jetzt haben wir allerdings vor kurzer Zeit eine weitere Funktions eingefügt, mit der man über fputc gezielt einzelne Zeichen hintereinander ausgeben lassen kann, ohne ein '\0' in den Daten zu benötigen. Die Funktion gibt dabei KEINEN String zurück (was sie auch nicht darf - denn entweder würde dieser fprintf nicht wieder freigegeben werden, oder wir würden eine invalide Stackadresse mit einer nullterminierten Version des Strings zurückgeben - beides ist blöd).

    Die einzigen Möglichkeiten, die mir einfallen, um die Funktion irgendwie in fprintf aufrufen zu lassen - und dies nicht einmal gezielt - sind krude GNU Extensions über register_printf_function , oder komplexes Vor-Parsen der Werte und Einfügen der Längen in Meta-Formatstrings. Da das ganze aber auch auf Windows laufen muss (und später auch auf Systemen, die die Standard-C-Library verfügbar haben), ist ersteres keine Option.

    Ich sehe mich schon wieder im Debugmodus über eine Funktion null-terminerte Versionen der Strings erstellen sehen, aber davor wollte ich fragen, ob es hier jemanden gibt, dem eine gute Möglichkeit einfallen würde, das Problem zu lösen?

    Der Vorparser, über den ich nachgedacht habe, soll im Grunden nur Formatstrings der Art:

    "%%%lus"
    

    übernehmen, welcher dann im ersten Schritt umgewandelt wird zu:

    "%10s"
    

    , womit printf dann nur noch den String braucht, um davon 10 Zeichen auszugeben. Aber das ist auch relativ komplex ...

    Vielen Dank für etwaige Hilfe!



  • Ihr wollt also die Länge der Ausgabe von fprintf bei %s begrenzen?

    Was spricht gegen den * Modifier im Formatstring?
    Bei %s kann man mit dem .precision Modifier die maxiamal Länge angeben.

    Mit negativen Werten bei width kann man auch links oder rechtsbündig ausgeben.

    printf("%.*s", len, text);
    


  • DirkB schrieb:

    Was spricht gegen den * Modifier im Formatstring?

    Die Tatsache, dass wir blöd sind. m( Daran haben wir jetzt überhaupt nicht dran gedacht. Funktioniert aber super.

    Danke für den Hinweis. Ich sah mich jetzt schon massive Änderungen an den Funktionen vornehmen, das ist mir glücklicherweise erspart geblieben! Vielen Dank!



  • dachschaden_off schrieb:

    Die Tatsache, dass wir blöd sind.

    Ich hoffe, die Erkenntnis kam nicht zu überraschend. 🤡

    dachschaden_off schrieb:

    Funktioniert aber super.

    Schon am ersten Tag der Woche eine gute Tat. Dann kann ich ja Feierabend machen 😃



  • DirkB schrieb:

    dachschaden_off schrieb:

    Die Tatsache, dass wir blöd sind.

    Ich hoffe, die Erkenntnis kam nicht zu überraschend. 🤡

    Nein, nein - das finden wir mindestens drei Mal die Woche raus, insofern keine Überraschung. :p

    Trotzdem, nochmal danke!


Log in to reply