Réutilisation du code par rapport à la communication accidentelle

L'un des bogues les plus critiques et les plus critiques pour le consensus (CVE-2018-17144) a récemment été découvert dans le logiciel Bitcoin Core, qui possédait auparavant un historique presque immaculé. Jimmy Song a écrit une excellente ventilation de ce bogue.

En résumé, il existe 4 cas dans lesquels le logiciel Bitcoin Core doit vérifier les doubles dépenses. Au départ, les 4 cas partageaient le même flux d'exécution de code. Après quelques itérations subtiles du code sur plusieurs années, l’un des 4 cas («un seul tx-double-dépensé dans un bloc») a été ignoré, ce qui permettrait à un mineur de tromper potentiellement certains nœuds pour qu’il accepte un bloc. qui gonfle l'offre de Bitcoin.

La nature de ce bug me rappelle le conflit constant entre:

(a) le besoin de réutilisation et d'optimisation du code

(b) le danger de tomber pour ce que j'appelle une aisance accidentelle: des choses similaires non pas par dessein, mais par accident

La commodité accidentelle crée un terrain fertile pour refactoriser les cauchemars et les insectes potentiels comme CVE-2018–17144.

Commune accidentelle

Quelques antécédents, si vous n’êtes pas familier avec le génie logiciel:
 
Dans le logiciel, il existe cette grande vision des composants logiciels parfaitement modulaires, similaires à leurs homologues d’ingénierie physique. Il y a une bonne raison pour que vous n'ayez pas à transporter un type de chargeur ou un câble USB différent où que vous soyez.

Il y a donc toujours eu de fortes pressions en faveur de la réutilisation du code. L'écriture de code redondant est souvent mal vue. Pourquoi le même travail deux fois quand vous pouvez le faire une fois?

Il existe également une longue tradition de réinvention du logiciel qui donne à la réutilisation du code une priorité encore plus élevée dans la liste des priorités. La réutilisation des codes est souvent considérée comme l’une des «meilleures pratiques» de l’industrie. Un jeune développeur de logiciels en herbe pourrait être enclin à penser que la réutilisation du code ne présente aucun inconvénient.

Mais il y a un danger caché - et je ne crois pas que cela soit enseigné correctement dans les écoles - de la réutilisation extrême du code.

Une réutilisabilité extrême du code signifie la fusion de deux morceaux de code d'aspect similaire en un seul, quels que soient leurs cas d'utilisation et leur intention d'origine.

Ce qui souvent aboutit à un code qui a une commodité accidentelle.

La raison pour laquelle une communication accidentelle est mauvaise n’est peut-être pas évidente, mais il suffit de maintenir un projet logiciel suffisamment volumineux pendant une longue période pour comprendre pourquoi.

C'est mauvais parce que les exigences du produit changent et que le logiciel est un produit en constante évolution, jamais fini.

Ce problème de cible constamment en mouvement est quelque chose d'assez unique au logiciel. Si vous êtes un ingénieur en structure, vous n'êtes pas censé transformer une maison en une tour de 20 étages ou une voiture en une soucoupe volante. Pourtant, dans les logiciels, nous le faisons constamment.

Lorsque les exigences du produit et les cas d'utilisation changent, les hypothèses sous-jacentes pour lesquelles le logiciel a été initialement écrit pourraient ne plus être applicables.

Ainsi, cette fière pièce de code commun que vous avez refactorisée (mais que vous avez maintenant complètement oubliée) ne fonctionne plus comme vous le pensez.

J’ai perdu le compte du nombre de projets de refactorisation ou de bugs méchants que j’ai vus et qui sont le résultat direct d’une optimisation prématurée ou d’une commotion accidentelle - au point où j’évite maintenant des choses comme Héritage, comme une peste.

Les choses qui ont une commodité accidentelle révéleront rapidement leurs différences quand elles évolueront au-delà de leur état initial. Toute rigidité dans le code serait alors un énorme fléau à éliminer.

Plus le code contient de couches de commodités accidentelles, plus il est facile de naviguer dans un champ de mines. CVE-2018-17144 en est un parfait exemple.