Re: buffer overrun (Re: Nowy bug w Outlooku...)

Autor: Marcin 'Qrczak' Kowalczyk (qrczak_at_knm.org.pl)
Data: Mon 24 Jul 2000 - 12:34:29 MET DST


24 Jul 2000 08:47:22 GMT, Slawomir Marczynski <slawek_at_arcadia.tuniv.szczecin.pl> pisze:

> I nic tu nie ma do rzeczy jezyk programowania.

Ma. Dowód poniżej:

> int i = 0;
> char buffer[80*sizeof(char)] = "";
> while(i < sizeof(buffer) - sizeof(char))
> {
> char c = get();
> if(c == EOF) break;
> buffer[i++] = get();
> }

Porównanie indeksu tablicy znaków z sizeof (char) świadczy co najmniej
o niechlujstwie. To przypadkiem zadziała, bo zawsze sizeof (char) == 1,
ale zapis jest bez sensu. sizeof (char) nie reprezentuje tutaj liczby
bajtów w znaku, tylko liczbę znaków.

W szczególności gdyby wszędzie zamienić char na wchar_t, to się
wysypie, bo sizeof (buffer) jest wciąż w bajtach, mimo że zapis
sugeruje że autor chciał się uniezależnić od rozmiaru elementu tablicy.

Druga sprawa. Ten kod źle zadziała kiedy w tekście będzie znak '\xFF'
(zakładając że EOF == -1, co zwykle jest prawdą).

Trzecia sprawa. Wołasz get() dwa razy... Ten błąd natychmiast wyjdzie
przy testowaniu, ale dwa poprzednie już nie! Przy czym dwa poprzednie
są specyficzne dla języków C i C++.

Czego to jest "dowód"? Tego, jak łatwo można zrobić błędy nawet
demonstrując, jak tych błędów uniknąć. Jasne, że w każdym języku
można robić różne błędy, ale nie w każdym jest tak samo łatwo. To tak,
jakby argumentować, że ochraniacze kolan przy jeździe na rolkach nie
mają nic do rzeczy, bo i tak można sobie wybić zęby.

W C, w porównaniu z innymi językami, robić głupie błędy jest
wyjątkowo łatwo, zwłaszcza że programy są kilkukrotnie dłuższe niż
w językach wyższego poziomu i zajmują się nieciekawymi technicznymi
szczegółami. Na dodatek w C wiele błędów ma nieprzewidywalne skutki.

W większości języków nie używa się buforów stałej wielkości, nie
operuje się na rozmiarach w bajtach, nie koduje się napotkania
końca pliku jako szczególnej wartości tego samego typu co znak, nie
alokuje się pamięci ręcznie, nie ma arytmetyki wskaźników, nie ma
niezainicjowanych zmiennych, nie ma rzutowania wskaźników na inny typ,
nie można spowodować zamazania stosu ani odwołania do przypadkowego
adresu pamięci - a dostępne mechanizmy, których nie ma w C, powodują,
że te wszystkie konstrukcje nie są w ogóle potrzebne.

-- 
 __("<  Marcin Kowalczyk * qrczak_at_knm.org.pl http://qrczak.ids.net.pl/
 \__/            GCS/M d- s+:-- a23 C+++$ UL++>++++$ P+++ L++>++++$ E-
  ^^                W++ N+++ o? K? w(---) O? M- V? PS-- PE++ Y? PGP+ t
QRCZAK                5? X- R tv-- b+>++ DI D- G+ e>++++ h! r--%>++ y-


To archiwum zostało wygenerowane przez hypermail 2.1.7 : Tue 18 May 2004 - 20:24:01 MET DST