Шматкратнасць выкарыстання кода супраць выпадковай звычайнасці

Нядаўна ў праграмным забеспячэнні Bitcoin Core была выяўлена адна з самых непрыстойных, адзіна важных памылак (CVE-2018–17144), якая да гэтага мела амаль бездакорную гісторыю. Jimmy Song напісаў выдатную разбіўку гэтай памылкі.

Кароткае рэзюмэ памылкі заключаецца ў тым, што ёсць 4 выпадкі, калі праграмнае забеспячэнне Bitcoin Core неабходна праверыць на двайныя выдаткі. Усе 4 выпадкі першапачаткова падзялялі адно і тое ж выкананне кода. Пасля некалькіх тонкіх ітэрацый кода на працягу некалькіх гадоў, адзін з 4 выпадкаў ("single-tx-double-tro-to-in-a-block") прапушчаны, што дазволіць шахцёру патэнцыйна падмануць некаторыя вузлы, каб прыняць блок што завышае пастаўкі биткойна.

Характар ​​гэтай памылкі нагадвае мне пастаянны канфлікт паміж:

(а) неабходнасць выкарыстання кода і яго аптымізацыі

(б) небяспека трапіць у тое, што я называю выпадковасцю: рэчы, якія падобныя не па канструкцыі, а выпадкова

Выпадковая звычайнасць стварае ўрадлівую глебу для перабудовы кашмараў і патэнцыйных памылак, як CVE-2018–17144.

Выпадковая звычайнасць

Некаторыя фону, калі вы не знаёмыя з інжынерыяй праграмнага забеспячэння:
 
У праграмным забеспячэнні існуе цудоўнае бачанне, што кампаненты праграмнага забеспячэння цалкам модульныя - падобна на іх тэхнічныя інжынерныя аналагі. Ёсць добрая прычына, што вам не трэба насіць зарадную прыладу ці USB-провад дзе заўгодна.

Такім чынам, заўсёды быў моцны штуршок для паўторнага выкарыстання кода. Напісанне лішняга кода часта нахмурылася. Навошта адна і тая ж праца двойчы, калі ты можаш зрабіць гэта адзін раз?

Існуе таксама доўгая гісторыя вынаходніцтва колаў праграмнага забеспячэння, што дае паўторнаму выкарыстанню кода яшчэ большы прыярытэт у спісе прыярытэтаў. Выкарыстанне кода часта лічыцца адной з найлепшых практык галіны. Пачатковы малодшы распрацоўшчык праграмнага забеспячэння можа схіляцца да думкі, што для паўторнага выкарыстання кода няма нуля.

Але ёсць схаваная небяспека - і я не веру, што ў школах гэтага матэрыялу калі-небудзь належным чынам выкладаецца - пра крайняе выкарыстанне кода.

Экстрэмальнае выкарыстанне кода азначае згортванне любых двух падобных элементаў кода ў адзін, незалежна ад выпадкаў іх выкарыстання і першапачатковага намеру.

Якая шмат разоў атрымліваецца з кодам, які мае выпадковасць.

Магчыма, не зусім зразумела, чаму выпадковая звычайная з'ява дрэнная, але трэба толькі падтрымліваць досыць вялікі праект праграмнага забеспячэння на працягу доўгага перыяду, каб зразумець, чаму.

Гэта дрэнна, таму што мяняюцца патрабаванні да прадукцыі і праграмнае забеспячэнне - гэта пастаянна развіваецца, ніколі не зусім гатовы прадукт.

Гэтая праблема, якая пастаянна рухаецца-мэта, - гэта нешта цалкам унікальнае для праграмнага забеспячэння. Калі вы інжынер-будаўнік, вы не плануеце ператварыць дом у 20-ці павярховую шматпавярховую машыну альбо аўтамабіль у лятучы сподак. Але ў праграмным забеспячэнні мы гэта пастаянна робім.

Калі патрабаванні да прадукту і выпадкі выкарыстання мяняюцца, асноўныя здагадкі, што праграмнае забеспячэнне першапачаткова было напісана, больш не могуць быць прыдатныя.

Так што ганарлівы фрагмент агульнага кода, які вы аднавілі (але цяпер ужо зусім забыліся), ужо не працуе так, як вы думаеце.

Я страціў падлік таго, колькі балючых праектаў рэфактарынгу альбо непрыемных памылак я бачыў, якія з'яўляюцца непасрэдным вынікам заўчаснай аптымізацыі альбо выпадковай распаўсюджанасці - да таго, як я зараз пазбягаю такіх рэчаў, як спадчыннасць, як чума.

Рэчы, якія маюць выпадковую агульнасць, хутка выявяць свае адрозненні, калі яны развіваюцца за межы свайго першапачатковага стану. Любая жорсткасць у агульнасці кода тады магла б пазбавіцца.

Чым больш у кодзе слаёў выпадковых выпадкаў, тым больш па мінным полі знаходзіцца для навігацыі. CVE-2018–17144 - выдатны прыклад таму.