<div dir="ltr"><div>    TAO VERSION: 2.3.0<br></div><div>    ACE VERSION: 6.3.0</div><div><br></div><div>    HOST MACHINE and OPERATING SYSTEM:</div><div>        Windows 7, Winsock2</div><div><br></div><div>    COMPILER NAME AND VERSION (AND PATCHLEVEL):</div><div>        Visual studio 2012 express VC11 version 17.00.61030 for x86</div><div><br></div><div>    THE $ACE_ROOT/ace/config.h FILE [if you use a link to a platform-</div><div>    specific file, simply state which one]:</div><div>        config-win32.h</div><div><br></div><div>    THE $ACE_ROOT/include/makeinclude/platform_macros.GNU FILE [if you</div><div>    use a link to a platform-specific file, simply state which one</div><div>    (unless this isn't used in this case, e.g., with Microsoft Visual</div><div>    C++)]:</div><div>        MSVC used</div><div><br></div><div>    CONTENTS OF $ACE_ROOT/bin/MakeProjectCreator/config/default.features</div><div>    (used by MPC when you generate your own makefiles):</div><div>        -</div><div><br></div><div>    AREA/CLASS/EXAMPLE AFFECTED:</div><div>        Failed fetching of IOR via HTTP.</div><div><br></div><div>    DOES THE PROBLEM AFFECT:</div><div>        COMPILATION?</div><div>            No.</div><div>        LINKING?</div><div>            No.</div><div>        EXECUTION?</div><div>            Yes, behavior is wrong. TAO and my application are affected.</div><div>        OTHER (please specify)?</div><div>            -</div><div><br></div><div>    SYNOPSIS:</div><div>        There are two issues noticed when fetching IOR via HTTP, by using orb->string_to_object() function.</div><div>        Because of these issues this functions fails in fetching IOR, in both cases with error.</div><div><br></div><div>    DESCRIPTION:</div><div>        First issue is that TAO_HTTP_Reader::receive_reply (void) function in HTTP_Handler.cpp</div><div>        expects string "200 OK" as mandatory in HTTP response. However, for Ericsson and NSN systems</div><div>        I was connecting with my app, URL for Naming service IOR points to a file on web server which</div><div>        contains IOR string. HTTP response in both Ericsson and NSN cases contains just IOR string, there</div><div>        are no HTTP response headers. Because of that this function fails in reading IOR.</div><div><br></div><div>        Second issue is a bug and it's more serious. It is in the same function as first issue,</div><div>        TAO_HTTP_Reader::receive_reply (void) in HTTP_Handler.cpp. HTTP response data is read and</div><div>        placed into list of "ACE_Message_Block"s, each of MTU size. These blocks are after that</div><div>        concatenated into one string in function TAO_HTTP_Parser::parse_string in HTTP_Parser.cpp.</div><div>        The problem is that "ACE_Message_Block"s created in TAO_HTTP_Reader::receive_reply are NOT</div><div>        zero terminated and TAO_HTTP_Parser::parse_string uses ACE_OS::strlen in </div><div><span style="white-space:pre-wrap">       </span>ACE_String_Base<ACE_CHAR_T>::operator+= (const ACE_CHAR_T* s) in String_Base.cpp.</div><div>       This operator is used for concatenation of "ACE_Message_Block"s as C strings.</div><div>        "strlen" expects each of these blocks to be zero terminated and produces unpredictable results</div><div>        with a lot of garbage bytes in resulting IOR string. Luckily, while testing the code I've noticed</div><div>        that eventually "strlen" encounters zero byte after at most 50 bytes, well after the end of</div><div>        ACE_Message_Block, so it does not cause more damage than putting garbage into final IOR string.</div><div><br></div><div>    REPEAT BY:</div><div>        CORBA::Object_var obj=orb->string_to_object("<a href="http://xxxxxxxxxxxxxxxxxxxxxxxxxx" target="_blank">http://xxxxxxxxxxxxxxxxxxxxxxxxxx</a>");</div><div>        URL should be a file on web server containing IOR string and no HTTP response headers should be present, this is to reproduce only first issue.</div><div><br></div><div>        Second issue (bug) is always appearing if there is at least one "ACE_Message_Block" containing response which is not zero terminated.</div><div>        Proper zero termination could happen only by chance if the next byte after "ACE_Message_Block" is zero or if HTTP response</div><div>        is such that contains zero bytes, which is unlikely.</div><div><br></div><div>    SAMPLE FIX/WORKAROUND:</div><div>        Here is a complete modified TAO_HTTP_Reader::receive_reply() function with issues corrected.</div><div><br></div><div>int</div><div>TAO_HTTP_Reader::receive_reply (void)</div><div>{</div><div>  size_t num_recvd = 0;</div><div>  char buf [MTU+1];</div><div>  char *buf_ptr = 0;</div><div>  size_t bytes_read = 0;</div><div><br></div><div>  // Receive the first MTU bytes and strip the header off.</div><div>  // Note that we assume that the header will fit into MTU bytes.</div><div>  if (peer ().recv_n (buf, MTU, 0, &num_recvd) >= 0)</div><div>    {</div><div>      //Make sure that response type is 200 OK</div><div><span style="white-space:pre-wrap">                   </span>// It could be "IOR:" also!!!</div><div>      if (ACE_OS::strstr (buf,"200 OK") == 0)</div><div><span style="white-space:pre-wrap">                 </span>{</div><div><span style="white-space:pre-wrap">                                </span>// If response is pure IOR string it should begin with "IOR:" without any white spaces before it</div><div><span style="white-space:pre-wrap">                               </span>// This could be modified in future to skip leading white spaces if there is a possibility that there are white spaces before "IOR:" string</div><div><span style="white-space:pre-wrap">                            </span>if (*buf == 0 || ACE_OS::strstr (buf,"IOR:") != buf)<span style="white-space:pre-wrap">  </span>// *buf==0 is here because strstr returns buf when buf is empty string</div><div><span style="white-space:pre-wrap">                                   </span>TAOLIB_ERROR_RETURN ((LM_ERROR,</div><div><span style="white-space:pre-wrap">                                                                                                                  </span>"TAO (%P|%t) - HTTP_Reader::receive_reply, Response is not 200 OK nor IOR:\n" ), -1);</div><div><span style="white-space:pre-wrap">                  </span>}</div><div><br></div><div>      // Search for the header termination string "\r\n\r\n", or "\n\n". If</div><div>      // found, move past it to get to the data portion.</div><div>      if ((buf_ptr = ACE_OS::strstr (buf,"\r\n\r\n")) != 0)</div><div>        buf_ptr += 4;</div><div>      else if ((buf_ptr = ACE_OS::strstr (buf, "\n\n")) != 0)     //for compatibility with JAWS</div><div>        buf_ptr += 2;</div><div>      else</div><div>        buf_ptr = buf;</div><div><br></div><div>      // Determine number of data bytes read. This is equal to the</div><div>      // total bytes read minus number of header bytes.</div><div>      bytes_read = num_recvd - (buf_ptr - buf);</div><div><br></div><div>    }</div><div>  else</div><div>    {</div><div>      TAOLIB_ERROR_RETURN ((LM_ERROR,</div><div>                         "TAO (%P|%t) - HTTP_Reader::receive_reply, error while reading header\n"), -1);</div><div>    }</div><div><br></div><div>  // ***************************************************************</div><div>  // At this point, we have stripped off the header and are ready to</div><div>  // process data. buf_ptr points to the data</div><div><br></div><div>  ACE_Message_Block* temp = 0;</div><div>  ACE_Message_Block* curr = this->mb_;</div><div><br></div><div>  ACE_NEW_RETURN (temp,</div><div>                  ACE_Message_Block (bytes_read + 1),<span style="white-space:pre-wrap">  </span>// Added "+1" to make room for byte 0 to make 0 terminated string.</div><div>                  -1);</div><div>  curr->cont (temp);</div><div>  curr = curr->cont ();</div><div><br></div><div>  // Copy over all the data bytes into our message buffer.</div><div>  if (curr->copy (buf_ptr, bytes_read) == -1)</div><div>    {</div><div>      TAOLIB_ERROR_RETURN ((LM_ERROR, "TAO (%P|%t) - HTTP_Reader::receive_reply, error copying data into Message_Block\n"), -1);</div><div>    }</div><div><br></div><div><span style="white-space:pre-wrap">  </span>// 0 - terminate string</div><div><span style="white-space:pre-wrap">  </span>*curr->wr_ptr () = 0;</div><div>  curr->wr_ptr (1);</div><div><br></div><div>  // read the rest of the data into a number of ACE_Message_Blocks and</div><div>  // chain them together in a link list fashion</div><div>  num_recvd = 0;</div><div><br></div><div>  do</div><div>  {</div><div>    if (curr->space () == 0)</div><div>    {</div><div>      ACE_NEW_RETURN (temp,</div><div>                      ACE_Message_Block (MTU + 1),<span style="white-space:pre-wrap">     </span>// Added "+1" to make room for byte 0 to make 0 terminated string.</div><div>                      -1);</div><div>      curr->cont (temp);</div><div>      curr = curr->cont ();</div><div>    }</div><div><br></div><div>  if (peer ().recv_n (curr->wr_ptr (), curr->space (), 0, &num_recvd) >= 0)</div><div>    {</div><div>      // Move the write pointer</div><div>      curr->wr_ptr (num_recvd);</div><div><br></div><div><span style="white-space:pre-wrap">                 </span>// 0 - terminate string</div><div><span style="white-space:pre-wrap">                  </span>*curr->wr_ptr () = 0;</div><div>      curr->wr_ptr (1);</div><div><br></div><div>      // Increment bytes_read</div><div>      bytes_read += num_recvd;</div><div><br></div><div>    }</div><div>  else</div><div>    {</div><div>      TAOLIB_ERROR_RETURN ((LM_ERROR,</div><div>                         "TAO (%P|%t) - HTTP_Reader::receive_reply, Error while reading header\n"), -1);</div><div>    }</div><div>  } while (num_recvd != 0);</div><div><br></div><div>  // Set the byte count to number of bytes received</div><div>  this->bytecount_ = bytes_read;</div><div><br></div><div>  return 0;</div><div>}</div><div><br></div><div><br></div>-- <br><div><div><br></div><div>Jovan Bunjevački.<br></div></div>
</div>