<div dir="ltr">:)) Well, I've just noticed that initial "buf" is also not zero terminated.<div>For strstr this is critical.<br><div>So here is the fix with this correction included:</div><div><br></div><div><div> SAMPLE FIX/WORKAROUND:</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> // Zero terminate buf.</div><div><span style="white-space:pre"> </span>buf[num_recvd]=0;</div><div> //Make sure that response type is 200 OK</div><div><span style="white-space:pre"> </span>// It could be "IOR:" also!!!</div><div> if (ACE_OS::strstr (buf,"200 OK") == 0)</div><div><span class="" style="white-space:pre"> </span>{</div><div><span class="" style="white-space:pre"> </span>// If response is pure IOR string it should begin with "IOR:" without any white spaces before it</div><div><span class="" style="white-space:pre"> </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 class="" style="white-space:pre"> </span>if (*buf == 0 || ACE_OS::strstr (buf,"IOR:") != buf)<span class="" style="white-space:pre"> </span>// *buf==0 is here because strstr returns buf when buf is empty string</div><div><span class="" style="white-space:pre"> </span>TAOLIB_ERROR_RETURN ((LM_ERROR,</div><div><span class="" style="white-space:pre"> </span>"TAO (%P|%t) - HTTP_Reader::receive_reply, Response is not 200 OK nor IOR:\n" ), -1);</div><div><span class="" style="white-space:pre"> </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 class="" style="white-space:pre"> </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 class="" style="white-space:pre"> </span>// 0 - terminate string</div><div><span class="" style="white-space:pre"> </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 class="" style="white-space:pre"> </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 class="" style="white-space:pre"> </span>// 0 - terminate string</div><div><span class="" style="white-space:pre"> </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></div></div><div class="gmail_extra"><br><div class="gmail_quote">2016-04-20 11:08 GMT+02:00 BJovke . <span dir="ltr"><<a href="mailto:bjovan@gmail.com" target="_blank">bjovan@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><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><span class="HOEnZb"><font color="#888888"><div><br></div><div><br></div>-- <br><div><div><br></div><div>Jovan Bunjevački.<br></div></div>
</font></span></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div><br></div><div>Jovan Bunjevački.<br></div></div>
</div>