• Sign in
 

LATAM Team blog

Search Blogs
Tags
  • Cloud
  • Cluster
  • Crash
  • Desarrollo
  • Desenvolvimento
  • Directory Services
  • DST
  • Español
  • Exchange/Outlook
  • Hang
  • High Availability
  • IIS
  • Networking
  • Office
  • People
  • Performance
  • Português
  • PowerShell Scripts
  • Security
  • Setup
  • Sharepoint
  • SQL
  • Virtualization
  • Windbg Scripts
  • Windows
Blog - News

Where Are You Coming From Today?

Where are you now?

Follow us on:

Options
  • Blog Home
  • About
  • Share this
  • RSS for posts
  • Atom
  • RSS for comments
Archive
Archives
  • May 2013 (4)
  • April 2013 (5)
  • March 2013 (6)
  • February 2013 (3)
  • January 2013 (3)
  • December 2012 (2)
  • November 2012 (1)
  • October 2012 (4)
  • September 2012 (5)
  • August 2012 (2)
  • July 2012 (2)
  • June 2012 (3)
  • May 2012 (13)
  • April 2012 (6)
  • March 2012 (6)
  • February 2012 (4)
  • January 2012 (7)
  • December 2011 (11)
  • October 2011 (6)
  • September 2011 (1)
  • August 2011 (3)
  • July 2011 (7)
  • June 2011 (6)
  • May 2011 (5)
  • April 2011 (2)
  • March 2011 (13)
  • February 2011 (1)
  • January 2011 (5)
  • December 2010 (6)
  • November 2010 (1)
  • October 2010 (6)
  • September 2010 (2)
  • August 2010 (3)
  • July 2010 (3)
  • June 2010 (5)
  • May 2010 (1)
  • April 2010 (10)
  • March 2010 (21)
  • February 2010 (8)
  • January 2010 (3)
  • December 2009 (5)
  • November 2009 (5)
  • October 2009 (6)
  • September 2009 (8)
  • August 2009 (9)
  • July 2009 (1)
  • June 2009 (3)
  • May 2009 (2)
  • April 2009 (7)
  • March 2009 (4)
  • February 2009 (7)
  • January 2009 (7)
  • December 2008 (8)
  • November 2008 (7)
  • October 2008 (22)
  • September 2008 (17)
  • August 2008 (13)
  • July 2008 (11)
  • June 2008 (7)
  • May 2008 (3)
  • April 2008 (2)
  • March 2008 (6)
  • January 2008 (4)
  • December 2007 (9)
  • November 2007 (4)
  • October 2007 (3)
  • September 2007 (8)
  • August 2007 (4)
  • July 2007 (2)
  • June 2007 (5)
  • May 2007 (7)
  • April 2007 (9)
  • March 2007 (7)
  • February 2007 (6)
  • January 2007 (4)
  • December 2006 (14)
  • November 2006 (10)
  • October 2006 (10)
  • September 2006 (11)
  • August 2006 (15)
  • July 2006 (7)
  • June 2006 (14)
  • May 2006 (22)
  • April 2006 (16)
  • March 2006 (20)
  • January 2006 (1)

Desafio da Semana #12

TechNet Blogs > LATAM Team blog > Desafio da Semana #12

Desafio da Semana #12

LatamBlog
3 Nov 2006 5:11 PM
  • Comments 6

 

Por: Roberto Alexis Farah

 

Olá pessoal!

Tenho demorado para publicar novos artigos porque tenho usado meu tempo livre no desenvolvimento de duas ferramentas, uma delas pública que, em breve, vocês tomarão conhecimento através desse blog. ;)

 

No desafio de hoje abordarei dois problemas que estão entre os mais comuns que encontro em códigos VB.NET, C# e ASP.NET.

Embora ambos são abordados juntos aqui, na prática são problemas independentes.

 

 

CENÁRIO

 

Eis o código fonte. Pode ser traduzido para VB.NET, optei por fazer em C# simplesmente porque conheço mais:

 

namespace Demo

{

          class Program

          {

                   static void Main(string[] args)

                   {

                             string str = "Abcd";

                            

                             DoSomething(str);

                            

                   }

                  

                   static bool DoSomething(string str)

                   {

                             // Checa se string é nula/vazia.

                             if(0 == str.Length)

                             {

                                      return false;

                             }

                            

                             str = str.ToUpper();

                                     

                             Microsoft.Office.Interop.Word.Application msWord = null;

                                                                            

                             try

                             {

                                      msWord = new Microsoft.Office.Interop.Word.Application();

 

                                      object saveChanges = false;

                                      object missing         = null;

                            

                                      msWord.Quit(ref saveChanges, ref missing, ref missing);

 

                             }

                             catch(OutOfMemoryException ex)

                             {

                                      Console.WriteLine("Não há memória disponível...");

                             }

                             finally

                             {

                                      // Como liberar o objeto COM?

                             }

                            

                             return true;

                   }

          }

}

 

 

SINTOMA

 

Temos dois problemas e dois sintomas no código acima.

 

Primeiro Sintoma:

 

Algumas vezes o código acima pode sofrer um crash por NullReferenceException quando o parâmetro ‘str’ é utilizado, como na comparação com str.Length.

 

Caso real: Em incidentes que trabalhei esse tipo de exceção costuma surpreender os desenvolvedores que assumem erroneamente que os parâmetros de métodos estão sendo testados antes do uso.

 

 

Segundo Sintoma:

 

Sempre que o componente Word é utilizado ele nunca é liberado da memória.

 

Caso real: Em incidentes que trabalhei esse foi o problema número um relacionado a contador de instância de componentes no COM+ usados via .NET nunca decrementarem quando supostamente liberados da memória!

 

 

OBJETIVO

 

Identifique ambos PROBLEMAS e proponha uma SOLUÇÃO para cada um deles.

 

 

Até semana que vem!

 

  • 6 Comments
Desenvolvimento , Português
Comments
Comments
  • Marcondes
    4 Nov 2006 11:18 AM

    Olá Farah!!!

    Aqui vai minha solução

    PRIMEIRO SINTOMA:

    A premissa de que "sempre teremos o parâmetro inicializado e com valores pronto para eu usar" é sempre a causa de problemas em runtime quando estamos com os aplicativos em produção. Os cenários são sempre diferentes daqueles que pressupomos durante o desenvolvimento. Eu tenho comigo a seguinte premissa sempre: "toda vez que meu código depender de dados externos, nunca irei confiar na sua origem". Pode parecer um pouco absurdo, pq no caso de um método de um programa que você mesmo desenvolveu e que você mesmo está utilizando, a fonte dos dados é você :) portanto você não estaria confiando nem em você. Mas essa é a regra de ouro: você muita vezes acaba dando tiro no próprio pé, portanto, mais vale uma verificação em código do que uma bronca em produção.

    O primeiro problema apresentado se encontra dentro do método DoSomething(...). A verificação if (0 == str.Length) { ... está errada pois pressupõe que o parâmetro str não seja nulo. Este teste apenas vale para testar se a string passada é vazia (string vazia não é igual a parâmetro nulo). Portanto, para resolver este problema, basta utilizarmos o método estático da classe String que verifica para nós se a string é nula. Assim, o trecho de código novo ficaria assim:

    static bool DoSomething(string str)

    {

     // Checa se string é nula/vazia.

     if(String.IsNullOrEmpty(Length))

     {

        return false;

     }

     str = str.ToUpper();

     (......)

    SEGUNDO SINTOMA:

    O segundo sintoma é causado principalmente pelo desconhecimento de muitos desenvolvedores do funcionamento interno do interop COM .NET: no exemplo do código postado, o objeto do word só será liberado (se um dia for!!!!) quando o garbage collector coletar o wrapper .NET criado para realização das chamadas ao COM do word. Em outras palavras, o comportamento é não determiniístico e portanto você poderá ficar com recursos não gerenciados (no caso o objeto COM da instância do WORD) carregados na memória. Quando o wrapper foi criado, internamento o objeto COM do WORD foi acionado (na verdade, o método AddRef da interface IUnknown foi chamado), adicionando um contador para a instância Word criada. Pois bem, para liberar de vez o objeto, precisamos zerar a contagem de referência. Para fazer isso, precisamos utilizar o método

    system.runtime.interopservices.marshal.finalreleasecomobject

    para liberar o recurso COM não gerenciado da memória. Essa feature que eu estou utilizando, assim como a da string no caso 1, são recursos do framework 2.0.

    Assim, para liberar o objeto WORD, fazemos o seguinte:

    try

    {

    msWord = new Microsoft.Office.Interop.Word.Application();

    object saveChanges = false;

    object missing         = null;

    msWord.Quit(ref saveChanges, ref missing, ref missing);

    }

    catch(OutOfMemoryException ex)

    {

    Console.WriteLine("Não há memória disponível...");

    }

    finally

    {

    // Como liberar o objeto COM? ASSIM DESTE JEITO ;)

    System.Runtime.InteropServices.Marshal.Finalreleasecomobject(msWord);

    msword = null;

    }

    Lembrando que se estivéssemos no framework 1.1, poderíamos liberar o objeto da mesma forma só que utilizando o método ReleaseComObject dentro de um loop até que o retorno do método fosse zero (0) (isso pq o ReleaseComObject liberava apenas uma referência do contador).

    É isso aí Farah!

    Super abraço!

    Marcondes                                      

  • Roberto Farah
    9 Nov 2006 1:29 PM

    Oi Marcondes!

    Muito completo e didático seu post! Estou me perguntando se ainda preciso publicar a resposta. :)

    Obrigado

  • Weber Ress
    27 Nov 2006 2:59 PM

    Olá Marcondes, td bem ?

    Da forma que vc definiu "str", ela estaria vulnerável a ataques de Buffer Overflow. Correto ?

    []'s !

    Weber Ress

  • Marcondes
    27 Nov 2006 8:07 PM

    Olá Weber, tudo bem?

    a definição da variável str é do tipo string, um objeto gerenciado dentro do CLR. Como o parâmetro do método DoSomethind é do tipo string, e este é o único ponto de entrada para o método, não estamos permitindo que haja qualquer tipo de acesso direto ao endereçamento do objeto string, o valor lido do parâmetro (não importa o que seja) será interpretado como o tamanho total da string. Não vamos ter problema de buffer overflow.

    []´s

  • Weber Ress
    2 Jan 2007 1:42 PM

    Olá ! Feliz 2007 !! :-)

    O código abaixo é suscetível a Buffer Overflow, pois não estou verificando qual o tamanho de Name *antes* de copiar para NameBuffer, que possui um tamanho limitado.

    void SayHello(char * Name)

    {

    char NameBuffer[256];

    strcpy(NameBuffer,Name);

    printf("Hello %s",NameBuffer);

    }

    Da forma que vc colocou no comentário anterior, como um ambiente CLR se protegeria de uma situação como esta ? Entendi que o acesso direto a memória é impedido através do CLR, mas este novo cenário seria tratado pelo CLR ?

    []'s !!

    Weber Ress

  • Roberto Farah
    2 Jan 2007 2:15 PM

    Olá Weber,

    O código que você colocou é suscetível a buffer overflow sim. No ambiente CLR o risco de buffer overflow é bastante minimizado, entretanto, se você fizer chamadas para código não gerenciado via, por exemplo, C# ou VB.NET, você fica sujeito aos problemas típicos de código nativo.

    Esse artigo esclarece bem isso:

    http://msdn.microsoft.com//msdnmag/issues/04/04/securitybriefs/

    Em relação a Buffer Overflow em código nativo, como no exemplo que você colocou, há dois artigos meus falando sobre isso:

    Desafio Da Semana #8 - Crash - Buffer Overflow

    http://blogs.technet.com/latam/archive/2006/07/24/443173.aspx

    Desafio Da Semana #9 - Como explorar um Buffer Overflow

    http://blogs.technet.com/latam/archive/2006/08/11/446117.aspx

    []s,

    Roberto

Page 1 of 1 (6 items)
  • © 2013 Microsoft Corporation.
  • Terms of Use
  • Trademarks
  • Privacy & Cookies
  • 5.6.426.415
  • TechNet
  • Products
  • IT Resources
  • Downloads
  • Training
  • Support
Products
  • Windows
  • Windows
    Server
  • System
    Center
  • Internet
    Explorer
 
  • Office
  • Office 365
  • Exchange
    Server
 
  • SQL Server
  • SharePoint
    Products
  • Lync
  • See all products »
Resources
  • Evaluation Center
  • Learning Resources
  • Microsoft IT Camps
  • Microsoft Technical Communities
  • Microsoft Virtual Academy
  • Script Center
  • Server and Tools Blogs
  • Solution Accelerators
  • TechNet Blogs
 
  • TechNet Flash Newsletter
  • TechNet Gallery
  • TechNet Library
  • TechNet Magazine
  • TechNet Subscriptions
  • TechNet Video
  • TechNet Wiki
  • Windows Sysinternals
  • Virtual Labs
Solutions
  • Networking
  • Cloud and Datacenter
  • Security
  • Virtualization
Updates
  • Service Packs
  • Security Bulletins
  • Microsoft Update
Trials
  • Windows Server 2012
  • System Center 2012 SP1
  • Microsoft SQL Server 2012 SP1
  • Windows 8 Enterprise
  • See all trials »
Related Sites
  • Microsoft Download Center
  • TechNet Evaluation Center
  • Drivers
  • Compatability & Converters
  • Windows Sysinternals
  • TechNet Gallery
Training
  • Training Catalog
  • Class Locator
  • Microsoft Virtual Academy
  • Free Windows Server 2012 courses
  • Free Windows 8 courses
  • SQL Server training
  • e-Learning overview
Certifications
  • Certification overview
  • MCSA: Windows 8
  • Windows Server Certification (MCSE)
  • Private Cloud Certification (MCSE)
  • SQL Server Certification (MCSE)
Other resources
  • TechNet Events
  • Second shot for certification
  • Born To Learn blog
  • IT Camps
Support by product
  • Exchange Server
  • Forefront Server
  • Forefront Edge Security
  • Forefront Server Security
  • Internet Explorer
  • Office
  • SharePoint
 
  • SQL Server
  • System Center
  • Windows Server
  • Windows XP
  • Windows Vista
  • Windows 7
  • Windows 8
Other support links
  • Microsoft Premier Online
  • Microsoft Fix It Center
  • TechNet Forums
  • MSDN Forums
  • Security Bulletins & Advisories
  • International support solutions
  • Log a support ticket
  • Look up event IDs and error codes
Not an IT pro?
  • Microsoft Customer Support
  • Microsoft Community Forums