User since
2003-08-04
14371
Artikel
ModeratorIn
Danke an alle! Ich habe jetzt jedenfalls wieder einiges meinem (kleinen) C/C++-Wissen hinzugefügt. Ich habe jetzt einfach am Anfang "genügend Speicher" alloziert.
Ich habe noch etwas in den Namenskonventionen für die Nodes geändert und überprüfe das jetzt, damit ich auch alle nötigen Informationen wirklich habe...
User since
2003-08-04
2145
Artikel
ModeratorIn + EditorIn
[quote=renee,29.04.2005, 09:03]Ich habe jetzt einfach am Anfang "genügend Speicher" alloziert.[/quote]
"genügend Speicher" ist so eine Sache, und sicherlich Quell der meisten Sicherheitslücken in C-Programmen: Wenn der Benutzer dann - aus Versehen oder Absicht - doch mal mehr Daten eingibt, als du vorgesehen hast, kommt es schnell zum "Buffer Overflow", der es dem Benutzer ermöglicht, eigenen Binärcode auszuführen.
So etwas kümmert einen meist nicht, so lange das Programm vom Benutzer lokal und ohne erweiterte Rechte ausgeführt wird (der Benutzer bekommt durch Fehleingaben nicht mehr Rechte, als er schon hat), aber wenn man Serversoftware schreibt, oder das Programm irgendwann Teil einer Web-Applikation wird, hat man eine schöne Hintertür für einen Angreifer eingebaut.
Also, wenn man in C/C++ mit den eingebauten Feldern hantiert, sollte man immer die Grenzen prüfen. Das bedeutet explizit bei Arrays-of-char, dass man z.B. strncat() statt strcat() benutzt und strncpy() statt strcpy. So hat man die Kontrolle, wieviele Zeichen tatsächlich maximal angehängt oder kopiert werden, und dass es nie mehr sind, als der Zielstring verträgt.
User since
2003-08-04
7321
Artikel
ModeratorIn
und statt sprintf z.B. snprintf :)
User since
2003-08-04
2145
Artikel
ModeratorIn + EditorIn
Stimmt, den hatte ich vergessen. :)
User since
2003-08-04
14371
Artikel
ModeratorIn
Ich mache es jetzt so, dass ich vor jedem strncat abfrage, ob noch genügend "freier Platz" ist. Und bei strncat gebe ich ja explizit an, wieviele Zeichen maximal angefügt werden sollen.
Sonst noch Vorschläge??
User since
2003-08-04
7321
Artikel
ModeratorIn
[quote=renee,29.04.2005, 12:35]Sonst noch Vorschläge??[/quote]
gibst du auch immer ein Byte weniger an?
int len = 8;
char *buffer = (char *)malloc(len);
strncpy(buffer, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", len-1);
oder besser
int len = 8;
char *buffer = (char *)malloc(len+1);
strncpy(buffer, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", len);
viel spass! :)
User since
2004-07-19
1776
Artikel
HausmeisterIn
Wenn man sich als verwöhnter Perl Programmierer an C wagt, macht es sich vielleicht auch nicht schlecht, zur Speicherverwaltung einen Garbage Collector zu benutzen (z.B. den klassischen
Boehm-Demers-Weiser conservative garbage collector). In aller Regel bringt das keine Performancenachteile, manchmal sogar Vorteile, je nach Allokationsschema.
Hier ein kleines Beispiel:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <gc/gc.h>
#include <setjmp.h>
#include <string.h>
#include <stdio.h>
jmp_buf exception_handler;
// Praktische Makros für die Speicherreservierung
#define GC_NEW_ARRAY(type, dim) \
(type *)GC_MALLOC((dim) * sizeof(type))
#define GC_NEW_ATOMIC_ARRAY(type, dim) \
(type *)GC_MALLOC_ATOMIC((dim) * sizeof(type))
#define GC_RESIZE_ARRAY(array, type, dim) \
(array) = (type *)GC_REALLOC((array), (dim) * sizeof(type))
// "Idiotensichere" Stringverkettung
char *gc_strcat(char *dest, char *src) {
if (dest)
GC_RESIZE_ARRAY(dest, char, strlen(dest) + strlen(src) + 1);
else
dest = GC_NEW_ATOMIC_ARRAY(char, strlen(src) + 1);
if (!dest)
longjmp(exception_handler, 1);
return strcat(dest, src);
}
// Testprogramm
int main(void) {
// Exception handler installieren
if (setjmp(exception_handler)) {
fputs("Out of memory!\n", stderr);
return 1;
}
// Standardeingabe zeilenweise auslesen und verketten
char *buf = NULL;
char line[1024];
while (!feof(stdin)) {
if (fgets(line, 1023, stdin))
buf = gc_strcat(buf, line);
}
// Alles wieder ausgeben
puts(buf);
// Um das Freigeben des Speichers brauchen wir uns nicht
// weiter zu kümmern.
return 0;
}
(edit: Beispiel eingefügt)\n\n
<!--EDIT|murphy|1114779453-->
When C++ is your hammer, every problem looks like your thumb.
User since
2003-08-04
14371
Artikel
ModeratorIn
Das Programm, das ich erweitert habe, wird nur intern in unserer kleinen Projektgruppe verwendet, da ist die Lösung auch so in Ordnung. Ich schaue erst, ob der anzuhängende Teilstring noch "dranpasst" oder ob dann die maximale Länge überschritten wird. Nur dann wenn es noch "dranpasst", werden die Strings mit strncat konkateniert...
Aber gut zu wissen, dass sich hier doch so viele mit C auskennen ;)
User since
2003-08-04
7321
Artikel
ModeratorIn
[quote=renee,29.04.2005, 16:09]Aber gut zu wissen, dass sich hier doch so viele mit C auskennen ;)[/quote]
nach C++, die beste Sprache der Welt!
:)
User since
2004-07-19
1776
Artikel
HausmeisterIn
Um off-topic zu bleiben: Objective-C finde ich viel besser und mächtiger als C++ -- außerdem ist der GNU Objective-C Compiler nicht so buggy wie der C++ Compiler ;)
When C++ is your hammer, every problem looks like your thumb.