Sécurité et conditions de concurrence
Un autre problème concerne les risques de brèches dans la sécurité et leur exploitation par des conditions de concurrence critique. Ce problème peut se manifester de plusieurs façons : Les sous-rubriques suivantes mettent en avant certains des principaux pièges que le développeur doit éviter.
Conditions de concurrence critique dans la méthode Dispose
Si la méthode Dispose d'une classe (consultez Garbage Collection pour plus d'informations) n'est pas synchronisée, il est possible que le code de nettoyage à l'intérieur de Dispose soit exécuté plus d'une fois, comme illustré dans l'exemple suivant.
Sub Dispose()
If Not (myObj Is Nothing) Then
Cleanup(myObj)
myObj = Nothing
End If
End Sub
void Dispose()
{
if( myObj != null )
{
Cleanup(myObj);
myObj = null;
}
}
Comme cette implémentation Dispose n'est pas synchronisée, il est possible que Cleanup soit d'abord appelé par un thread puis par un deuxième thread avant que _myObj reçoive la valeur null. Qu'il s'agisse d'un problème de sécurité ou non dépend du résultat de l'exécution du code Cleanup. Un problème central lié aux implémentations Dispose synchronisées concerne l'utilisation de handles de ressource comme des fichiers par exemple. Une suppression inappropriée peut entraîner l'utilisation d'un handle incorrect, ce qui génère souvent des failles en matière de sécurité.
Conditions de concurrence critique dans des constructeurs
Dans certaines applications, il est parfois possible pour d'autres threads d'accéder à des membres de la classe avant l'exécution complète de leurs constructeurs de classe. Vous devez passer en revue tous les constructeurs de classe pour vous assurer qu'il n'y a pas de problème lié à la sécurité si cela doit se produire ou synchroniser des threads, si nécessaire.
Conditions de concurrence critique avec les objets mis en cache
Le code qui met en cache des informations de sécurité ou utilise l'opération assertion de la sécurité d'accès du code peut être également soumis à des conditions de concurrence critique si d'autres parties de la classe ne sont pas correctement synchronisées, comme illustré dans l'exemple suivant.
Sub SomeSecureFunction()
If SomeDemandPasses() Then
fCallersOk = True
DoOtherWork()
fCallersOk = False()
End If
End Sub
Sub DoOtherWork()
If fCallersOK Then
DoSomethingTrusted()
Else
DemandSomething()
DoSomethingTrusted()
End If
End Sub
void SomeSecureFunction()
{
if(SomeDemandPasses())
{
fCallersOk = true;
DoOtherWork();
fCallersOk = false();
}
}
void DoOtherWork()
{
if( fCallersOK )
{
DoSomethingTrusted();
}
else
{
DemandSomething();
DoSomethingTrusted();
}
}
S'il existe d'autres chemins vers DoOtherWork qui peuvent être appelés par un autre thread à l'aide du même objet, un appelant non fiable peut ignorer une demande sans la voir.
Si votre code met en cache des informations de sécurité, veillez à le passer en revue dans le cadre de cette faille.
Conditions de concurrence critique dans des finaliseurs
Des conditions de concurrence critique peuvent également se produire dans un objet qui référence une ressource statique ou non managée qu'il libère ensuite dans son finaliseur. Si plusieurs objets partagent une ressource manipulée dans un finaliseur de classe, les objets doivent synchroniser tous les accès à cette ressource.