Hallo pl,
strstr() ist deutlich schneller als bstrstr() und solange es sich um nullterminierte Strings handelt wie die boundary in der 1. Zeile ist strstr() völlig korrekt eingesetzt.
unsigned char *mem;
mem = (char*)malloc(content_length);
fread(mem,content_length,1,stdin);
Du liest content_length
bytes aus stdin
in den Buffer mem
. Dieser Buffer ist nicht mit einem 0-Byte terminiert.
unsigned char *offs; // Wanderzeiger Offset
int blen = 0; // Boundary Length
char *boundary;
if( offs = strstr(mem, "\r\n")){
Du rufst strtr()
mit mem
als Such-Buffer auf. strstr()
sucht nach der gewünschten Zeichenfolge im Suchbuffer bis die Zeichenfolge gefunden wurde oder bis das terminierende 0-Byte gefunden wurde.
Du hast kein terminierendes 0-Byte, sondern höchstens zufällig eins im Payload. Wenn also kein "\r\n"
gefunden wird, hast du einen out-of-bounds read.
Das gleiche gilt für spätere strstr()
-Calls mit offs
als Suchbuffer:
if( h = strstr(offs, "\r\n\r\n") ){
Außerdem hast du vermutlich noch einen zweiten Bug:
bstrstr(offs, content_length, boundary, blen)
Ich kenne die Implementation von bstrstr()
nicht, aber das zweite Argument wird vermutlich die Länge des Suchbuffers angeben. Du gibst hier content_length
an, das ist aber falsch: offs
zeigt nicht auf das erste Byte des Buffers, sondern auf ein Byte irgendwo mitten drin. Du hast also nicht mehr content_length
als Länge, sondern content_length - (offs - mem)
.
Außerdem ist deine Befüllung von pnew
buggy.
hlen = h - offs;
header = (char*)malloc(hlen);
memcpy(header,offs,hlen);
offs = h;
Du kopierst den Header in einen Buffer, mit memcpy()
. Der Header-String ist also nicht 0-terminiert.
if( h = strstr(header,"Content-Type") ){
Du lässt strstr()
auf einen nicht-0-terminierten Buffer los. Wenn also kein "Content-Type"
gefunden werden konnte, hast du einen out-of-bounds read.
pnew->content_type = (char*)malloc(hlen);
sprintf(pnew->content_type,"%s",h+14);
Du allozierst hlen
Bytes für pnew->content_type
. Du terminierst aber an Byte hlen+1
:
pnew->content_type[hlen] = 0;
Das ist ein out-of-bounds write, du musst hlen+1
Bytes allozieren. Aber eigentlich kannst du das manuelle terminieren auch weglassen, denn das macht dein sprintf()
-Call bereits. pnew->filename
und pnew->name
terminierst du ja auch nicht manuell.
h = strstr(header,"name");
for(int i = 0; i < hlen; i++){
if(h[i] == 34) h[i] = 0;
}
Rückgabewert prüfen! Was, wenn strstr()
kein name
im Suchbuffer finden kann? Dann arbeitest du mit NULL
.
pnew->value = (char*)malloc(vlen);
memcpy(pnew->value,offs,vlen);
pnew->value[vlen] = 0;
Hier das gleiche. Du allozierst vlen
Bytes, schreibst aber an Byte vlen+1
.
pnew->next = NULL;
while( *par != NULL ){
par = &(*par)->next;
}
*par = pnew;
Das kann ich nicht überprüfen, weil mir die Definitionen fehlen und die Info, was par
ist. Aber es lässt meine Spinnensinne klingeln…
LG,
CK