Protezione e condizioni di competizione

Un'altra area di interesse è quella relativa alla possibilità che problemi della protezione possano essere sfruttati da condizioni di competizione. Questa condizione si manifesta in diversi modi; negli argomenti che seguono sono illustrati alcuni aspetti problematici che è necessario evitare in fase di sviluppo.

Condizioni di competizione nel metodo Dispose

Se il metodo Dispose di una classe (per ulteriori informazioni, vedere Programmazione coerente con la procedura di Garbage Collection) non è sincronizzato, è possibile che il codice di pulitura all'interno del metodo Dispose possa essere eseguito più di una volta, come mostrato nell'esempio riportato di seguito.

Sub Dispose()
    If Not (myObj Is Nothing) Then
       Cleanup(myObj)
       myObj = Nothing
    End If
End Sub 
[C#]
void Dispose() 
{
    if( myObj != null ) 
    {
        Cleanup(myObj);
        myObj = null;
    }
}

Poiché l'implementazione di Dispose non è sincronizzata, Cleanup può essere chiamato dal primo thread e quindi dal secondo thread prima che _myObj sia impostato su null. Il problema di protezione dipende dalle operazioni effettuate durante l'esecuzione del codice Cleanup. Un problema di maggiore importanza legato all'utilizzo di implementazioni di Dispose non sincronizzate coinvolge l'utilizzo di handle di risorse come i file. L'eliminazione di elementi non corretti può provocare l'utilizzo dell'handle errato e comportare problemi di vulnerabilità della protezione.

Condizioni di competizione nei costruttori

In alcune applicazioni, altri thread possono accedere ai membri delle classi prima che sia completata l'esecuzione dei costruttori di classe. Se si verifica questa condizione, esaminare tutti i costruttori di classe per accertarsi che non vi siano problemi di protezione o sincronizzare i thread, se necessario.

Condizioni di competizione per oggetti memorizzati nella cache

Il codice che consente la memorizzazione nella cache delle informazioni di protezione o nel quale viene utilizzata l'operazione Assert per la protezione dall'accesso di codice può essere vulnerabile a condizioni di competizione se altre parti della classe non sono sincronizzate in modo corretto, come mostrato nell'esempio riportato di seguito.

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 
[C#]
void SomeSecureFunction() 
{
    if(SomeDemandPasses()) 
    {
        fCallersOk = true;
        DoOtherWork();
        fCallersOk = false();
    }
}
void DoOtherWork() 
{
    if( fCallersOK ) 
    {
        DoSomethingTrusted();
    }
    else 
    {
        DemandSomething();
        DoSomethingTrusted();
    }
}

Se sono presenti altri percorsi di DoOtherWork che è possibile chiamare da un altro thread con lo stesso oggetto, la pretesa può essere aggirata da un chiamante non attendibile.

Se nella cache sono memorizzate informazioni di protezione, esaminare il codice per ricercare eventuali problemi di protezione.

Condizioni di competizione nei distruttori

Le condizioni di competizione possono verificarsi anche in un oggetto che fa riferimento a una risorsa statica o non gestita che viene resa disponibile nel distruttore. Se più oggetti condividono una risorsa modificata in un distruttore di classe, è necessario sincronizzare l'accesso a tale risorsa per tutti gli oggetti.

Vedere anche

Indicazioni per la generazione di codice protetto