Hi
Ich bringe mir gerade C bei, über einen Udemy Kurs. Momentan behandeln
wir Strings, speziell strncpy. Jetzt habe ich ein kleines Programm
geschrieben, dessen Ergebnis ich nicht ganz nachvollziehen kann. Was
genau geschieht bei tempName2, so dass der Inhalt ein anderer ist als
bei tempName? strlen von tempName is ebenfalls 19 und nicht 9? Meine
Vermutung ist, dass ich strncpy falsch anwende oder ein wichtiges Detail
unterschlage. :(
1
#include<stdio.h>
2
#include<stdlib.h>
3
#include<string.h>
4
5
intmain()
6
{
7
charmyString[]="My Name is Gerd";// Length is 16, Size is 16+Null terminator
Output:
myString: My Name is Gerd
tempName: My Name i
tempName2: My Name iMy Name i
myString: strlen= 15, sizeof= 16
tempName: strlen= 9, sizeof= 10
tempName2: strlen= 19, sizeof= 10
Process returned 0 (0x0) execution time : 0.029 s
Press any key to continue.
Danke und Gruß,
Gerd schrieb:> Ich bringe mir gerade C bei, über einen Udemy Kurs. Momentan behandeln> wir Strings, speziell strncpy.
Du solltest wohl zuerst die Manuals lesen. Da steht u.a.
"Warning: If there is no null byte
among the first n bytes of src, the string placed in dest will
not be null-terminated.
"
https://www.manpagez.com/man/3/strncpy/
leo
Einen Tipp an Anfänger: vergiss einfach, dass es strncpy gibt[1]. Die
ist für eine spezielle Andwendung entworfen worden (Festweitendatensätze
füllen, z.B. Lochkarten) und nur aus Versehen in die String-Library
gerutscht ;-) Durch die (für andere Anwendung) zusätzliche nötige
Drumrumprogrammiererei geht ihr Nutzen gegen Null.
[1] strtok auch
Gerd schrieb:> tempName2: My Name iMy Name i
Weil tempName2 das \0 fehlt (siehe Antwort von leo), wird einfach bei
tempName (liegt weiter oben auf dem Stack) weitergelesen.
zitter_ned_aso schrieb:> weil du die beiden char-Arrays nicht initialisiert hast.
Alternativ kann man die Ziele auch nach strncpy() sicherheitshalber
terminieren:
1
strncpy(tempName,myString,sizeof(tempName)-1);
2
strncpy(tempName2,myString,sizeof(tempName2)-1);
3
tempName[sizeof(tempName)-1]='\0';
4
tempName2[sizeof(tempName2)-1]='\0';
Vorteil: Es muss nur noch jeweils ein Byte geschrieben werden, um die
Strings sicher zu terminieren.
Eine vorsorgliche Initialisierung, wie Du sie vorschlägst, füllt das
Array komplett, wovon viele Bytes durch das nachfolgende strncpy() dann
nochmals überschrieben werden.
leo schrieb:> Du solltest wohl zuerst die Manuals lesen. Da steht u.a.
Hallo leo
habe ich bereits gelesen.
Frage:
Warum funktioniert das bei tempName, aber nicht bei tempName2? Der Code
für tempName und tempName2 ist identisch, oder übersehe ich da etwas?
Gruß,
foobar schrieb:> Einen Tipp an Anfänger: vergiss einfach, dass es strncpy gibt[1]. Die> ist für eine spezielle Andwendung entworfen worden (Festweitendatensätze> füllen, z.B. Lochkarten) und nur aus Versehen in die String-Library> gerutscht ;-) Durch die (für andere Anwendung) zusätzliche nötige> Drumrumprogrammiererei geht ihr Nutzen gegen Null.
Ja, vergesst, dass es Buffer Overflows gibt und schreibt weiterhin
Murks-Software mit Sicherheitslücken. Man muss den Geheimdiensten ja
auch eine Chance lassen.
Das hier beschriebene Verhalten entsteht ja dadurch, dass der
Nullterminator fehlt. Und Du willst jetzt alles bis zum Nullterminator
in einen Puffer quetschen ? Der ist im Zweifelsfall zu klein, und Du
überschreibst irgendwas, das dahinter steht. Es gibt auch genug Leute,
die Dir Deine Eingangsdaten so zu manipulieren versuchen, dass genau
dieser Fall eintritt.
fop schrieb:> foobar schrieb:>> Einen Tipp an Anfänger: vergiss einfach, dass es strncpy gibt[1]. Die>> ist für eine spezielle Andwendung entworfen worden (Festweitendatensätze>> füllen, z.B. Lochkarten) und nur aus Versehen in die String-Library>> gerutscht ;-) Durch die (für andere Anwendung) zusätzliche nötige>> Drumrumprogrammiererei geht ihr Nutzen gegen Null.>> Ja, vergesst, dass es Buffer Overflows gibt und schreibt weiterhin> Murks-Software mit Sicherheitslücken. Man muss den Geheimdiensten ja> auch eine Chance lassen.> Das hier beschriebene Verhalten entsteht ja dadurch, dass der> Nullterminator fehlt. Und Du willst jetzt alles bis zum Nullterminator> in einen Puffer quetschen ? Der ist im Zweifelsfall zu klein, und Du> überschreibst irgendwas, das dahinter steht. Es gibt auch genug Leute,> die Dir Deine Eingangsdaten so zu manipulieren versuchen, dass genau> dieser Fall eintritt.
"Du wolltest schon immer coole C++-Programme schreiben?"
Dann geh zu dem Typ, der aussieht, als wären nicht all seine
Nahrungsergänzungsmittel legal erwerbbar.
> Ja, vergesst, dass es Buffer Overflows gibt und schreibt weiterhin> Murks-Software mit Sicherheitslücken.
Mein Tipp ging eher in die Richtung, dass die Benutzung von strncpy
gerade nicht das adäquate Mittel ist! Ob ich statt strcpy strncpy
benutze, hilft exakt gar nichts. Statt bei strcpy wild im Speicher zu
schreiben, wird bei strncpy wild im Speicher gelesen (der spätere
Nutzer) und leakt evtl direkt Daten. Silent truncation ist eh der
falsche Ansatz (ist schon genug drüber geschrieben worden) - eine
explizite Prüfung mit passender Behandlung ist der korrekte Weg. Wer
glaubt, dass er mit den "n"-Funktionen was für die Sicherheit tut, ist
auf dem Holzweg.
fop schrieb:> foobar schrieb:>> Einen Tipp an Anfänger: vergiss einfach, dass es strncpy gibt[1].> Ja, vergesst, dass es Buffer Overflows gibt und schreibt weiterhin> Murks-Software mit Sicherheitslücken. Man muss den Geheimdiensten ja> auch eine Chance lassen.
strncpy ist broken by design. Wenn der Zielpuffer größer ist als der
Quellstring mit Nullterminator, werden unnötig viele Nullen geschrieben.
Wenn er dagegen kleiner ist als der Quellstring, wird die eine Null, die
zwingend erforderlich ist, einfach weggelassen. Man muss die Funktion
also so verwenden, dass man als Zielgröße ein Byte weniger als die Größe
des Ziels angibt und von Hand eine Null in das letzte Byte schreibt.
> Das hier beschriebene Verhalten entsteht ja dadurch, dass der> Nullterminator fehlt.
… und zwar weil strncpy in dem Glauben verwendet wurde, dass es sowas
nicht macht. Ich möchte gar nicht wissen, wie viele Sicherheitslücken
genau deshalb so rumgeistern.
strncpy ist hier nicht die Lösung, sondern das Problem.
> Und Du willst jetzt alles bis zum Nullterminator in einen Puffer quetschen?
Er will vermutlich nur eine besser geeignete Funktion als strncpy
verwenden. Bei manchen Compilern gibt es eine Funktion strlcpy, die
nicht Standard ist, aber dafür das tut, was man eigentlich von ihr
erwartet.