Developpez.com

Le Club des Développeurs et IT Pro

Des ingénieurs découvrent une faille dans le compilateur RyuJIT embarqué dans .NET Framework 4.6

Qui peut générer du code de façon aléatoire

Le 2015-07-30 21:42:51, par Stéphane le calme, Chroniqueur Actualités
Un peu plus tôt cette semaine, des ingénieurs ont découvert une faille dans le compilateur RyuJIT embarqué dans de l’environnement d’exécution .NET 4.6 qui affecte le modèle d’appel Tail Call Optimization. « Les méthodes que vous appelez peuvent prendre des paramètres avec des valeurs différentes de celles que vous avez passées », a expliqué Nick Craver, développeur logiciel sur Stack Overflow, l’un des sites web du réseau Stack Exchange qui propose des questions et réponses sur un large choix de thèmes concernant la programmation informatique. Il a travaillé en coordination avec un autre développeur logiciel de la même plateforme appelé Marc Gravell.

Un bug qui a été difficile à repérer parce qu’il ne se produit que lorsque les optimisations sont activées. Cela signifie que vous pouvez développer votre application, l'exécuter dans Visual Studio et tout fonctionnera parfaitement bien. Ce n’est que lorsque vous compilerez une build de production que le problème va se produire. Craver explique qu’arrêter le débogueur change le comportement et cache souvent le problème. Ce dernier a été remarqué à Stack Overflow parce que son code de mise en cache HTTP ne fonctionnait pas avec le nouvel environnement d'exécution, conduisant à l’obtention de résultats imprévisibles. Jetez plutôt un œil sur le code ci-dessous qui met en exergue le problème.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void Set<T>(string key, T val, int? durationSecs, bool sliding, bool broadcastRemoveFromCache = false)
{
    SetWithPriority<T>(key, val, durationSecs, sliding, CacheItemPriority.Default);
}

void SetWithPriority<T>(string key, T val, int? durationSecs, bool isSliding, CacheItemPriority priority)
{
    key = KeyInContext(key);

    RawSet(key, val, durationSecs, isSliding, priority);
}

void RawSet(string cacheKey, object val, int? durationSecs, bool isSliding, CacheItemPriority priority)
{
    var absolute = !isSliding && durationSecs.HasValue 
                   ? DateTime.UtcNow.AddSeconds(durationSecs.Value) 
                   : Cache.NoAbsoluteExpiration;
    var sliding = isSliding && durationSecs.HasValue 
                  ? TimeSpan.FromSeconds(durationSecs.Value) 
                  : Cache.NoSlidingExpiration;

    HttpRuntime.Cache.Insert(cacheKey, val, null, absolute, sliding, priority, null);
}
Les ingénieurs expliquent que, dans la dernière chaîne et UNIQUEMENT QUAND L’OPTIMISATION EST ACTIVEE, RawSet() est incorrectement optimisée. Par exemple, ils ont appelé Set( T ) avec le paramètre durationSecs a qui était attribuée la valeur 3600, valeur qui a été modifiée de façon aléatoire une fois passée à la méthode RawSet. Elle pouvait par exemple devenir 50, 30, 47 ou même null.

Ils ont exhorté la communauté à désactiver RyuJIT en production en attendant qu’un correctif soit disponible et ont contacté Microsoft pour lui faire part du problème.

Par le biais de Rich Lander, un développeur faisant partie de l’une de ses équipes, Microsoft a reconnu le problème, avançant que l’équipe responsable de RyuJIT a résolu le problème et travaille déjà sur un correctif qui sera disponible en téléchargement. « Ce problème est de nature étriquée dans le sens où votre code doit utiliser des types de données spécifiques, les transmettre de manière spécifique puis exécuter des opérations spécifiques. Très peu de programmes sauront satisfaire l'ensemble de ces caractéristiques qui s’avèrent nécessaires pour déclencher ce bug de génération de code. Nous avons examiné ce problème pour déterminer s’il est exploitable. Nous n’avons pas identifié d’exploit, mais nous lançons les modifications dans notre processus au même rythme que nous l’aurions fait s’il s’agissait d’un exploit ».

Il a expliqué que l’équipe .NET a fourni une analyse détaillée suite à des dizaines de milliers de tests dont les statistiques suggèrent que la majorité des développeurs .NET ne feront pas l’expérience de ce problème. « Nous avons de nombreux tests intensifs sur les bibliothèques de notre .NET Framework (par exemple System.Xml). Nous n’avons pas été en mesure de trouver un seul cas où s’est manifesté ce problème sur de grandes portions de code. Du point de vue de la production, less propriétés Web importantes de Microsoft ont été exécutés sur des préversions du .NET Framework 4.6 pendant des mois sans que ce problème ne soit déclenché ».

Microsoft a tenu à remercier l’équipe des développeurs qui lui ont communiqué le problème.

Source : blog Nick Craver, blog MSDN
  Discussion forum
8 commentaires
  • lankoande
    Membre confirmé
    En tout cas ces ingénieurs mérite bien plus que de simple remerciements !
    Encore bravo à eux pour cette découverte.
  • Uther
    Expert éminent sénior
    Pour le coup, il semblerait que c'est l'optimiseur le responsable et pas le débogueur. Ce n'est pas la première fois et probablement pas la dernière qu'un compilateur à ce genre de bug lié à une optimisation.
  • LSMetag
    Expert confirmé
    Bravo encore à ces ingénieurs pour cette découverte.

    Ce qui est appréciable aussi, c'est que Microsoft ait pris en compte et corrigé ce bug, malgré, apparemment, la très faible probabilité qu'il se produise.

    On a vraiment l'impression qu'avec Windows 10, c'est la révolution chez Microsoft.
  • Uther
    Expert éminent sénior
    Encore heureux qu'ils le corrigent. J'imagine mal la réputation qu'ils se feraient s'ils refusaient de corriger un tel bug sur ce qui est censé être le fer de lance de leurs outils.
  • 23JFK
    Membre expert
    Envoyé par Uther
    Pour le coup, il semblerait que c'est l'optimiseur le responsable et pas le débogueur. Ce n'est pas la première fois et probablement pas la dernière qu'un compilateur à ce genre de bug lié à une optimisation.
    Ne peut-on plus rattacher un processus en cours d'exécution au débogueur de Microsoft ?
  • lankoande
    Membre confirmé
    Envoyé par 23JFK
    Si les débogueurs ne font plus leur job, ça va devenir compliqué d'avoir un code secure.
    A ta place je ne dirai pas çà ! Je dirai plutôt que c'est la preuve qu'en informatique aucun travail ne peut être parfait.
    Quelqu'en soit ton professionnalisme, tes compétences ou ton expérience, tu auras toujours quelque chose à apprendre des autres
  • behall
    Membre à l'essai
    Hum pour rattacher un exécutable au debugger il vaut mieux qu'il soit compilé en debug sinon le debugger ne peut pas faire grand chose, et compiler en mode debug débraie la plupart des optimisations des compilateurs. Donc une erreur de l'optimiseur se voit rarement en debug, c'est tout le problème. Maintenant je restai sur de la méfiance envers les optimiseurs (en C en particulier) certains optimiseurs se basant sur une façon de programmer fixée et sinon le résultat pouvant être surprenant voire épouvantable.
  • 23JFK
    Membre expert
    Si les débogueurs ne font plus leur job, ça va devenir compliqué d'avoir un code secure.