Defenzivní programování

Z Wikipedie, otevřené encyklopedie
Skočit na: Navigace, Hledání

Defenzivní programování je forma návrhu softwaru, která se snaží zaručit jeho nepřetržitou funkčnost i za podmínek použití, ke kterým nebyl původně navržen. Snaží se eliminovat tzv. Murphyho zákony. Ty říkají, že cokoliv se může potenciálně pokazit, se zaručeně pokazí. Defenzivní forma návrhu se aplikuje především, pokud by mohlo selhání softwaru vést ke katastrofickým, či velmi nákladným scénářům.

Při defenzivním programování autor předpokládá, že okolní svět se snaží za každou cenu zničit jeho dílo, a tudíž svůj program připravuje na všechny možné situace, které by ho mohly poškodit. Autor tedy očekává, že uživatelé budou posílat nesmyslné, či záludné vstupy, nebudou dodržovat stanovený kontrakt atd. Jedním z cílů defenzivního programování je zabránit poškození vlastních dat, či stavu programu, ale na druhou stranu a reagovat benevolentně. Je třeba mít na paměti, že největším nebezpečím pro program je autor sám a tudíž by měl hlídat hlavně sebe a důsledek své práce. Programátor myslí dopředu, musí ošetřit všechny možné stavy, výjimky a chybové situace v kódu.

Defenzivní programování také brání proti SQL injection, DNS útokům, neoprávněnému přístupu a dalším útokům zevnějšku. Podporuje tzv. audity kódu, při kterých dochází ke kontrole čitelnosti a snadnému porozumění kódu.

Zásady defenzivního programování[editovat | editovat zdroj]

  • Všechna data jsou důležitá, dokud se neprokáže opak
  • Všechna vstupní data jsou potenciálně nebezpečná, dokud se neprokáže opak
  • Veškerý kód je nebezpečný, dokud se neprokáže opak

Techniky defenzivního programování[editovat | editovat zdroj]

Znovupoužití kvalitního kódu[editovat | editovat zdroj]

Znovupoužití staršího ověřeného kódu je jednou z nejlepších a hlavně nejlevnějších technik, je třeba ale dávat pozor na to, aby starší kód splňoval dnešní požadavky. Jako příklad lze uvést rozdílnost kódování (UTF-8 vs. ASCII), architekturu systému (32-bit vs. 64-bit), offline vs. online návrh. Kód napsaný před rokem 1990 je v drtivé většině případů zranitelný na sql injection útoky.

Ošetření I/O[editovat | editovat zdroj]

Vstupy programu představují druhou největší hrozbu (po autorovi samotném). Vstupy uživatelů jsou nevyzpytatelné a na nesprávně zvolené vstupy by měl programu umět reagovat. Stejně tak musí zabezpečit odolnost proti přímým útokům na program, jako například vkládání kódu do vstupu, procházení file-systémem, příchozí data ze sítě atd.

Pro každý vstup by měl autor programu definovat množinu validních vstupů a nebrat žádné jiné. Dále definovat chování nekorektních vstupů, např. přerušení programu, nové zadání, varování….

Například uživatel má do programu zadat množství peněz, autor programu by měl zkontrolovat, jestli zadal číslo, jestli je dostatečně velké, jaký symbol se používá pro oddělení desetinných míst, kolik desetinných míst uživatel zadal a jestli číslo není složené (23+74).

Výstupy programu by neměly navenek prozrazovat více, než je nutné, autoři by se měli držet zásady maximálního utajení dat.

Vynucování dodržení kontraktu[editovat | editovat zdroj]

Z vnějších zdrojů by měli autoři metod vynucovat dodržení kontraktu povinně, z vnitřních zdrojů většinou jen v před-produkčních verzích pro účely testování, aby kontroly neubíraly na rychlosti programu.

Vstupní, výstupní podmínky a invarianty[editovat | editovat zdroj]

Vstupní podmínky by se měly kontrolovat před každým provedení kritické operace. Výstupní podmínky se kontrolují po dokončení operace.

Invarianty datových struktur by se měli kontrolovat před provedením operace na těchto strukturách. Invarianty se většinou vynucují pomocí příkazů Assert (zkontrolovat nenulovost, délku pole, platnost odkazu…).

Invariant neohraničeného pole kontroluje, že současná velikost není menší, než alokovaná velikost. Dále, že alokovaná velikost pole je menší, než největší možná alokovaná velikost a nakonec, že alokovaná velikost pole není menší, než 2.

Vnější hranice systému[editovat | editovat zdroj]

Vnitřní hranice systému se ošetřují pomocí obsluhy chyb a následným volání programových výjimek. Obecně lze říci, že pokud lze po vzniklé chybě obnovit stav programu a pokračovat, měl by programátor použít v kódu kontrolované výjimky (jejichž ošetření je vynucené překladačem)., nebo vlastní konstrukty na ošetření.

Pro ošetření chyb, po kterých nelze obnovit stav programu a pokračovat se využívají nekontrolované výjimky (jejichž ošetření není vynutitelné překladačem).

Testování[editovat | editovat zdroj]

Testování přispívá ke kvalitnímu kódu, představuje příslib včasné detekce chyb v programu a ve výsledku snížení počtu chyb v kódu. Správné testování vychází s přesné dokumentace chování programu.

Kanonizace[editovat | editovat zdroj]

Autor by si měl dávat pozor, aby kontrolovaná událost nešla obejít více způsoby. Jako příklad lze uvést programové ošetření v kódu na unixovém systému, aby uživatel nechtěl po programu soubor „/etc/passwd“. Pokud ale uživatel zadá „/etc/./passwd“, soubor mu může být programem vydán a kontrolu obejde.

Nízká tolerance[editovat | editovat zdroj]

Proaktivní přístup zabraňuje potenciálním chybám kódu. Program by se měl držet zásady, že co nezná, decentně odmítá, nebo na tu vůbec nereaguje.

Další techniky[editovat | editovat zdroj]

Kontrola struktur konstantních velikostí (přetečení zásobníku), opatrná práce s řetězci, kódování a autentifikace vzdálených systémů, princip KISS a další…

Zdroje[editovat | editovat zdroj]