PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit getcwd



KRibel
16-02-2007, 21:54
HI Leute,

habe folgendes Problem.

Ich möchte das Arbeitsverzeichnis meines Programms auslesen. Ich möchte das alles dynamisch machen, da ich nicht weiß wie lang das Arbeitsverzeichnis sein wird.

Bis jetzt habe ich folgenden Quellcode:



int i = 3;
char workingDir[5];

while (1)
{
if ( getcwd( workingDir , i ) == NULL ) break;
i++;
}


Aus dieser Website (http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=245&rl=1) entnehme ich, dass getcwd NULL zurückgibt, wenn die Größe, die ich an die Funktion übergebe, kleiner ist als der Pfadname.
Deswegen habe ich die Schleife geschrieben. Mit i++ übergebe ich ständig einen neuen Wert an getcwd. Wenn ich es richtig verstanden habe, erweitert getcwd mit malloc das Array wenn die Größe, die an getcwd übergeben wird, für den Pfadnamen ausreicht.

Nur funktioniert meine Schleife nicht. Das Array wird nicht erweitert.

Was mache ich falsch? Ich finde den Fehler nicht.

Gruß
Konstantin

anda_skoa
16-02-2007, 23:13
Nein, getcwp, wenn es in der POSIX Variante benutzt wird, hat keinerlei Speicherallokierung.

D.h. entweder du handhabst das selbst (bleibt portabel), oder du benutzt die linuxspezifische Ausprägung (nicht POSIX kompatibel, geht nur unter Linux) und übergibst NULL als "buf" und 0 als "size"

Ciao,
_

KRibel
17-02-2007, 14:14
Also ich habe folgenden Quellcode ausprobiert und es funktioniert.



char puffer[0];

getcwd(puffer,90);

printf("%s\n", puffer);

Gruß
Konstantin

anda_skoa
17-02-2007, 15:05
Das ist gewagt, ich denke es wäre sinnvoller das spezifizierte Verhalten der Linuxvariante zu benutzen.

Und free() nicht vergessen

Ciao,
_

panzi
22-02-2007, 00:20
Das sollte funktionieren (ist aber nicht ansi):

#include <unistd.h>

char path[PATH_MAX] = {0};

getcwd(path,PATH_MAX);

Eventuell kannst dir aber ein Funktion wie diese schreiben:

#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>

#include <stdio.h>

#ifndef PATH_MAX
# define PATH_MAX 256
#endif

char * get_cwd() {
size_t size = PATH_MAX;
char * path = NULL;

for(;;) {
path = malloc(size);

if(path == NULL) {
break;
}

if(getcwd(path,size) == NULL) {
free(path);
path = NULL;

if(errno == ERANGE) {
size *= 2;
}
else {
break;
}
}
else {
break;
}
}

return path;
}

int main() {
char * cwd = get_cwd();

puts(cwd);

/* free()-en nicht vergessen! */
free(cwd);

return 0;
}

Kopier das in eine Datei mit den Namen getcwd.c und es kompeliert mit:

gcc -Wall -pedantic -ansi -O2 -g getcwd.c -o getcwd

panzi
22-02-2007, 00:31
Also ich habe folgenden Quellcode ausprobiert und es funktioniert.



char puffer[0];

getcwd(puffer,90);

printf("%s\n", puffer);

Gruß
Konstantin

Natürlich funktioniert der Code. Es funktionieren auch all die anderen Programme die Pufferüberläufe haben. Trotzdem sind das schwere Sicherheitslücken!! Über diesen Code könnte ein Angreifer Code einschleusen, wenn er einen Ordner anlegen kann, der im Ordnernamen code enthält (unwarscheinlich, weil einige Zeichen nicht gehn, trotzdedm möglich). Auf alle fälle wird bei längeren Ordnernamen dein Programm mit einen Speicherzugriffsfehler (segmentation fault) abstürzen, da falsche Bereiche im Speicher überschreioben werden.

Wenn du folgendes Programm kompelierst (ohne -Ox, denn optimierungen ändern alles) gibt es dir "hallo" aus:

#include <string.h>
#include <stdio.h>

int main() {
char a = 0;
char b = 0;
char c = 0;
char d = 0;
char e = 0;
char buf[1] = {0};

strcpy(buf, "hallo");
printf("%c%c%c%c%c%c\n",buf[0],a,b,c,d,e);

return 0;
}

Beängstigend, oder?

Ohne dem a,b,c,d,e würden Teile deines Stacks überschrieben werden. unter anderen auch die Rücksprungadresse, also wo im Code nach der aktuellen Funktion weitergemacht werden soll. Wenn man die Adresse auf eigenen Code (den man über den selben Fehler einschleust) setzen kann, kann man Code reinschmugeln. Auf die art funktionieren schlimmer Weiße noch immer die meisten Sicherheitslücken. Finde ich schrecklich. C-Puffer zu verwenden sollte verboten werden. Eine Pufferklasse zu implementieren, die die Grenzen überprüft, ist kein so schlimmer overhead. Das sollte einmal gemacht werden und dann nur noch die verwendet werden. Dann gäbs zig Sicherheitslücken nicht mehr.