Compartilhar via


Protegendo a manipulação de exceção

No Visual C++ e Visual Basic, uma expressão de filtro mais acima na pilha é executado antes de qualquer Finalmente instrução. O catch bloco associado ao filtro será executado após a Finalmente instrução. Para obter mais informações, consulte Using User-Filtered exceções. Esta seção examina as implicações de segurança desta ordem. Considere o seguinte exemplo de pseudocódigo ilustra a ordem na quais declarações de filtro e Finalmente instruções para executar.

void Main() 
{
    try 
    {
        Sub();
    } 
    except (Filter()) 
    {
        Console.WriteLine("catch");
    }
}
bool Filter () {
    Console.WriteLine("filter");
    return true;
}
void Sub() 
{
    try 
    {
        Console.WriteLine("throw");
        throw new Exception();
    } 
    finally 
    {
        Console.WriteLine("finally");
    }
}                      

Esse código imprime a seguir.

Throw
Filter
Finally
Catch

O filtro é executado antes do Finalmente instrução, para que os problemas de segurança podem ser introduzidos por qualquer coisa que faz com que um estado onde a execução de outro código pode tirar proveito de alterar. Por exemplo:

try 
{
    Alter_Security_State();
    // This means changing anything (state variables,
    // switching unmanaged context, impersonation, and 
    // so on) that could be exploited if malicious 
    // code ran before state is restored.
    Do_some_work();
} 
finally 
{
    Restore_Security_State();
    // This simply restores the state change above.
}

Esse pseudocódigo permite que um filtro de nível superior da pilha para executar código arbitrário. Outros exemplos de operações que tem um efeito semelhante são temporária representação da identidade de outra, definindo um sinalizador interno que ignora algumas verificação de segurança, ou alterar a cultura associada ao thread. A solução recomendada é apresentar um manipulador de exceção para isolar alterações do código para o estado do segmento dos chamadores. blocos de filtro. No entanto, é importante que o manipulador de exceção introduzidos corretamente ou não esse problema será corrigido. O exemplo a seguir alterna a cultura da interface do usuário, mas qualquer tipo de alteração de estado do segmento pode estar exposto de forma semelhante.

YourObject.YourMethod()
{
   CultureInfo saveCulture = Thread.CurrentThread.CurrentUICulture;
   try {
      Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");
      // Do something that throws an exception.
}
   finally {
      Thread.CurrentThread.CurrentUICulture = saveCulture;
   }
}
Public Class UserCode
   Public Shared Sub Main()
      Try
         Dim obj As YourObject = new YourObject
         obj.YourMethod()
      Catch e As Exception When FilterFunc
         Console.WriteLine("An error occurred: '{0}'", e)
         Console.WriteLine("Current Culture: {0}", 
Thread.CurrentThread.CurrentUICulture)
      End Try
   End Sub

   Public Function FilterFunc As Boolean
      Console.WriteLine("Current Culture: {0}", Thread.CurrentThread.CurrentUICulture)
      Return True
   End Sub

End Class

A correção correta neste caso é dispor existente tente/Finalmente bloquear em um tente/catch bloco. Simplesmente ao introduzir um throw catch cláusula existente para o tente/Finalmente bloco não corrige o problema, conforme mostrado no exemplo a seguir.

YourObject.YourMethod()
{
    CultureInfo saveCulture = Thread.CurrentThread.CurrentUICulture;

    try 
    {
        Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");
        // Do something that throws an exception.
    }
    catch { throw; }
    finally 
    {
        Thread.CurrentThread.CurrentUICulture = saveCulture;
    }
}

Isso não corrigir o problema porque o Finalmente declaração não foi executado antes do FilterFunc obtém o controle.

O exemplo a seguir corrige o problema, garantindo que o Finalmente cláusula foi executado antes de oferecer uma exceção até os chamadores blocos de filtro de exceção.

YourObject.YourMethod()
{
    CultureInfo saveCulture = Thread.CurrentThread.CurrentUICulture;
    try  
    {
        try 
        {
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");
            // Do something that throws an exception.
        }
        finally 
        {
            Thread.CurrentThread.CurrentUICulture = saveCulture;
        }
    }
    catch { throw; }
}

Consulte também

Conceitos

Diretrizes para Codificação Segura