<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Martin Plante</title>
    <link>http://blogs.xceedsoft.com/plantem/</link>
    <description>Open window on development at Xceed </description>
    <language>en-us</language>
    <copyright>Xceed Software Inc.</copyright>
    <lastBuildDate>Tue, 19 Apr 2005 13:17:39 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.8.5223.0</generator>
    <managingEditor>plantem@xceedsoft.com</managingEditor>
    <webMaster>plantem@xceedsoft.com</webMaster>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p dir="ltr" style="MARGIN-RIGHT: 0px">
      I just got bitten by the .NET Framework COM interrop. We had a problem with Xceed
      Zip ActiveX used in a .NET application. If the application was handling the ZipPreprocessingFile
      event and changed the sFilename parameter (BSTR*, or ByRef String if you wish), <strong>sometimes</strong> the
      library did not change the filename in the resulting zip file.
   </p>
        <p>
      That "sometimes" was the mysterious part, though I had a good idea where the problem
      was. The method which fires the ZipPreprocessingFile event makes a dangerous, but
      up until now valid assumption. The kind of assumption that would make <a href="http://blogs.msdn.com/oldnewthing/">Raymond
      Chen</a> or <a href="http://pluralsight.com/blogs/dbox/">Don Box</a> real mad. It
      took for granted that the BSTR address would change if the callee was to change the
      BSTR. I made this assumption based on two facts:
   </p>
        <ol>
          <li>
         A BSTR is an immutable entity. If you need to modify one, you <strong>should</strong> create
         a copy with the new content. 
      </li>
          <li>
            <p dir="ltr">
            If the implementation of a function that takes a BSTR reference parameter assigns
            a new BSTR to the parameter, it must free the previously referenced BSTR. (written
            "as is" in MSDN)
         </p>
          </li>
        </ol>
        <p>
      The .NET code that reproduces the problem does a very simple thing:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
      sFilename = sFilename &amp; "new"
   </p>
        </blockquote>
        <p dir="ltr">
      Normally, languages will work with the provided BSTR* as is. And if a modification
      occurs, they will allocate the required new BSTR, copy chars from the old BSTR, then
      free it. The new string cannot have the same address as the old one.
   </p>
        <p dir="ltr">
      In .NET, the COM interrop is actually making a copy of the BSTR to create a System.String,
      work with that System.String throughout the function, then checks if the
      string changed before returning control to the COM caller, making either a call to
      SysReAllocString on the old BSTR, using the String as the "psz" parameter, or simply
      freeing the old BSTR, then allocate the new one based on the String.
   </p>
        <p dir="ltr">
      Bam! Turns out SysReAllocString or SysAllocString <strong>sometimes</strong> reallocate
      the new BSTR at the <strong>same address</strong> as the old one. Can't argue against
      that. My bad.
   </p>
        <p dir="ltr">
      Three things to conclude with that:
   </p>
        <ol dir="ltr">
          <li>
            <div>You can never use what you experiment as a proof of concept. Experiments and
            tests are always a subset of the big picture.
         </div>
          </li>
          <li>
            <div>Don't try to make assumptions larger than the initial statement. Assuming that
            a pointer wouldn't change just because a BSTR* parameter must be freed if changed
            was stretching the actual fact.
         </div>
          </li>
          <li>
            <div>Optimizations may sound good, but can always introduce more problems. Simplicity
            is bliss.
         </div>
          </li>
        </ol>
        <p>
      By the way, I realized I could try a very simple VB6 test. If once the old BSTR is
      freed any new BSTR can end-up at the same address, does it mean that a VB6 application
      modifying the sFilename parameter <strong>twice</strong> can reproduce the same
      bug? Absolutely! My VB6 sample application did this in ZipPreprocessingFile:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
      sFilename = sFilename &amp; ".foo"<br />
      sFilename = sFilename &amp; ".bar"
   </p>
        </blockquote>
        <p dir="ltr">
      Turns out files are <strong>sometimes</strong> renamed, <strong>sometimes</strong> not...
      Sometimes, I feel like an...
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d" />
      </body>
      <title>Bitten by the .NET Framework COM interrop</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d.aspx</link>
      <pubDate>Tue, 19 Apr 2005 13:17:39 GMT</pubDate>
      <description>&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   I just got bitten by the .NET Framework COM interrop. We had a problem with Xceed
   Zip ActiveX used in a .NET application. If the application was handling the ZipPreprocessingFile
   event and changed the sFilename parameter (BSTR*, or ByRef String if you wish), &lt;strong&gt;sometimes&lt;/strong&gt; the
   library did not change the filename in the resulting zip file.
&lt;/p&gt;
&lt;p&gt;
   That "sometimes" was the mysterious part, though I had a good idea where the problem
   was. The method which fires the ZipPreprocessingFile event makes a dangerous, but
   up until now valid assumption. The kind of assumption that would make &lt;a href="http://blogs.msdn.com/oldnewthing/"&gt;Raymond
   Chen&lt;/a&gt; or &lt;a href="http://pluralsight.com/blogs/dbox/"&gt;Don Box&lt;/a&gt; real mad. It
   took for granted that the BSTR address would change if the callee was to change the
   BSTR. I made this assumption based on two facts:
&lt;/p&gt;
&lt;ol&gt;
   &lt;li&gt;
      A&amp;nbsp;BSTR is an immutable entity. If you need to modify one, you &lt;strong&gt;should&lt;/strong&gt; create
      a copy with&amp;nbsp;the new content. 
   &lt;li&gt;
      &lt;p dir=ltr&gt;
         If the implementation of a function that takes a BSTR reference parameter assigns
         a new BSTR to the parameter, it must free the previously referenced BSTR. (written
         "as is" in MSDN)
      &lt;/p&gt;
   &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
   The .NET code that reproduces the problem does a very simple thing:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   sFilename = sFilename &amp;amp; "new"
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   Normally, languages will work with the provided BSTR* as is. And if a modification
   occurs, they will allocate the required new BSTR, copy chars from the old BSTR, then
   free it. The new string cannot have the same address as the old one.
&lt;/p&gt;
&lt;p dir=ltr&gt;
   In .NET, the COM interrop is actually making a copy of the BSTR to create a System.String,
   work with&amp;nbsp;that System.String&amp;nbsp;throughout the function, then checks if the
   string changed before returning control to the COM caller, making either a call to
   SysReAllocString on the old BSTR, using the String as the "psz" parameter, or simply
   freeing the old BSTR, then allocate the new one based on the String.
&lt;/p&gt;
&lt;p dir=ltr&gt;
   Bam! Turns out SysReAllocString or SysAllocString&amp;nbsp;&lt;strong&gt;sometimes&lt;/strong&gt; reallocate
   the new BSTR at the &lt;strong&gt;same address&lt;/strong&gt; as the old one. Can't argue against
   that. My bad.
&lt;/p&gt;
&lt;p dir=ltr&gt;
   Three things to conclude with that:
&lt;/p&gt;
&lt;ol dir=ltr&gt;
   &lt;li&gt;
      &lt;div&gt;You can never use what you experiment as a proof of concept. Experiments and
         tests are always a subset of the big picture.
      &lt;/div&gt;
   &lt;li&gt;
      &lt;div&gt;Don't try to make assumptions larger than the initial statement. Assuming that
         a pointer wouldn't change just because a BSTR* parameter must be freed if changed
         was stretching the actual fact.
      &lt;/div&gt;
   &lt;li&gt;
      &lt;div&gt;Optimizations may sound good, but can always introduce more problems. Simplicity
         is bliss.
      &lt;/div&gt;
   &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
   By the way, I realized I could try a very simple VB6 test. If once the old BSTR is
   freed any new BSTR can end-up at the same address, does it mean that a VB6 application
   modifying the sFilename parameter &lt;strong&gt;twice&lt;/strong&gt; can&amp;nbsp;reproduce the same
   bug? Absolutely! My VB6 sample application did this in ZipPreprocessingFile:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   sFilename = sFilename &amp;amp; ".foo"&lt;br&gt;
   sFilename = sFilename &amp;amp; ".bar"
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   Turns out files are &lt;strong&gt;sometimes&lt;/strong&gt; renamed, &lt;strong&gt;sometimes&lt;/strong&gt; not...
   Sometimes, I feel like an...
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=46ab4fbc-eaf8-40a1-9505-89cc2c7fb30d" /&gt;</description>
      <category>COM;Zip</category>
    </item>
  </channel>
</rss>