PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Bufferoverflow?



blan
29.06.2007, 20:02
hi,

ich hab mir selbst ein fifo-buffer programmiert und ich bin mir nicht sicher warum das hier so ist: wenn ich diesen code hier benutze (auszug aus main())



while(TRUE)
{
int8_t data = 0xFF;

if(fifo_pop(fifo_rx, &data) == FIFO_SUCCESS)
{
uart_putc(data);
}
}


dann bekomm ich beim übertragen immer fehler in form von daten die nicht im fifo-buffer stehen. benutz ich aber folgenden code, der ja theoretisch das gleiche ist bekomm ich eine saubere übertragung:



while(TRUE)
{
int8_t *data = (int8_t*) malloc(1);

if(fifo_pop(fifo_rx, data) == FIFO_SUCCESS)
{
uart_putc(*data);
}

free(data);
}


ich hab den fifo-buffer mal in einem C-Programm implementiert und getest - scheint zu funktionieren. hier der code: http://nopaste.debianforum.de/6098

die ausgabe von dem prgramm sieht so aus:



104
97
108
108
111
97
98
99
0
----------------------------
h
----------------------------
97
108
108
111
97
98
99
0
0


was meint ihr dazu?

mfg blan

rXenon
29.06.2007, 20:28
Edit: Ich habe mich total geirrt... Bin irgendwie davon ausgegangen, du würdest dem Buffer etwas hinzufügen -.- Keine Ahnung wie ich mich so vertun konnte...

Warum die erste Variante nicht funktioniert kann ich so nicht sagen. Es wäre hiflreich, wenn du den Fehler etwas genauer erläutern könntest.

Was auch eine Alternative wäre: Anstatt in das Ziel des Pointers, der als Parameter mitgegeben wird, die Daten reinzuschreiben, könntest du auch einfach den Pointer auf den schon vorhandenen Datensatz zeigen lassen. Wäre jedenfalls eine noch sparsamere Methode.

blan
29.06.2007, 22:00
also auch wenn die variable data nicht in der while-schleife ist funktioniert es nicht.

mfg blan

NumberFive
30.06.2007, 08:24
eingendlich ist klar das das nicht funktioniert.

mich wundert das das teil nicht abstürtzt. Aber wahrscheinlich hast du im buffer nicht mehr wie ein Zeichen stehen fifo->fragment.size = 1

du kopiert's an die Stelle (speicher) mit unter mehr bytes als du reservt hast.

int8_t *data = (int8_t*) malloc(1); damit erzeugt du ein point auf dem Heap und dort darf jetzt schreiben. mit int8_t data = 0xFF; erzeugst ein lokale variale der Main Funktion die beim Rücksprung wieder hergestellt wird (push pop).

da ich aber nicht genau weiß wie malloc auf dem AVR realiesiert ist gehen mal davon aus das wie unter windows das GlobalAlloc realiesiert ist. und das es deshalb funktioniert.

Ich hoffe ich konntest einiger massen erklären es mir logisch aber mit dem erklären habe ich so meine probleme schon alleine wegen der legatenie.

Gruß

blan
30.06.2007, 12:51
versteh ich nicht ganz. wohin speichere ich mehr als ich reserviert habe - in die variable data? und wenn ja, warum - ich kopier doch nur ein byte in die variable und soviel sollte sie doch aufnehmen können?

mfg blan

blan
01.07.2007, 02:45
also so wie ich das jetzt sehe hab ich den fehler gefunden. der übeltäter war die funktion strlen() die ein null-terminated string erwartet und das ist nicht gegeben wenn ich die länge von einem zeichen herausfinden lassen will. strlen() hat dann einfach solange weitergezählt bis zufällig ein nullbyte im speicher kommt.

danke für die hilfe!

mfg blan

NumberFive
01.07.2007, 07:08
Das war zwar meine erste idee aber in deinem code segment verwendest du kein strlen auf data. das ist in der Funktion fifo_push aber nicht in der fifo_pop.

Wenn es läuft dann ist ja gut.

if(memcpy(data, fifo->data, fifo->fragment.size))

Damit kopierst du die fifo->fragment.size nach data wenn jetzt Data nur ein BYTE ist dann darf fragment.size nie grösser sein als 1. das war das was ich meinte.

wichtig währe in meinen augen halt das man variablen intialiseirt dann währe nämlich im zweiten beispiel das selbe passiert.

int8_t data = 0xFF;

int8_t *data = (int8_t*) malloc(1);
(*data) = 0xFF;

Erst jetzt hätte bei variablen den selben Inhalt.

Gruß