Boost C++ Libraries: Ticket #5187: uuid\seed_rng.hpp sha1_random_digest_state_ not random https://svn.boost.org/trac10/ticket/5187 <p> boost_1_45_0\boost\uuid\seed_rng.hpp </p> <p> static unsigned int * sha1_random_digest_state_() </p> <blockquote> <p> { </p> <blockquote> <p> <em> intentionally left uninitialized </em> ERROR 1: not uninitialized! static value always zero all. <em> ERROR 2: always return the same pointer of static value </em> should delete 'static' static unsigned int state[ 5 ]; return state; </p> </blockquote> <p> } </p> </blockquote> <p> unsigned int * ps = sha1_random_digest_state_(); </p> <blockquote> <p> unsigned int state[ 5 ]; </p> </blockquote> <blockquote> <p> std::memcpy( state, ps, sizeof( state ) ); <em> harmless data race </em></p> </blockquote> <p> <em> ERROR 1: not uninitialized! static value always zero all. </em> so state is all zero </p> <blockquote> <p> sha.process_bytes( (unsigned char const*)state, sizeof( state ) ); </p> </blockquote> <p> <em> ERROR 2: always return the same pointer of static value </em> so ps is same ( ps === ps) </p> <blockquote> <p> sha.process_bytes( (unsigned char const*)&amp;ps, sizeof( ps ) ); </p> </blockquote> <p> namespace boost { namespace uuids { namespace detail { </p> <p> <em> should this be part of Boost.Random? class seed_rng { static unsigned int * sha1_random_digest_state_() </em></p> <blockquote> <p> { </p> <blockquote> <p> <em> intentionally left uninitialized static unsigned int state[ 5 ]; return state; </em></p> </blockquote> <p> } </p> </blockquote> <blockquote> <p> void sha1_random_digest_() { </p> <blockquote> <p> boost::uuids::detail::sha1 sha; </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> unsigned int * ps = sha1_random_digest_state_(); </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> unsigned int state[ 5 ]; std::memcpy( state, ps, sizeof( state ) ); <em> harmless data race </em></p> </blockquote> </blockquote> <blockquote> <blockquote> <p> sha.process_bytes( (unsigned char const*)state, sizeof( state ) ); sha.process_bytes( (unsigned char const*)&amp;ps, sizeof( ps ) ); </p> </blockquote> </blockquote> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/5187 Trac 1.4.3 qiaozhiqiang@… Tue, 15 Feb 2011 01:15:59 GMT <link>https://svn.boost.org/trac10/ticket/5187#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5187#comment:1</guid> <description> <p> see this: </p> <p> boost_1_45_0\boost\uuid\seed_rng.hpp </p> <blockquote> <p> first time, state is all zero,sha1_random_digest_() will modify it. </p> </blockquote> <p> but always return the same pointer of static value, so ps is not random. </p> <pre class="wiki"> static unsigned int * sha1_random_digest_state_() { // intentionally left uninitialized /////////// // !!!!!!!! first time, state is all zero,sha1_random_digest_() will modify it. // but always return the same pointer of static value /////////// static unsigned int state[ 5 ]; return state; } unsigned int * ps = sha1_random_digest_state_(); unsigned int state[ 5 ]; std::memcpy( state, ps, sizeof( state ) ); // harmless data race sha.process_bytes( (unsigned char const*)state, sizeof( state ) ); ///////////////// // !!!!!!!! ERROR: sha1_random_digest_state_() always return the same pointer of the static value // so should delete next line?? //////////////// sha.process_bytes( (unsigned char const*)&amp;ps, sizeof( ps ) ); namespace boost { namespace uuids { namespace detail { // should this be part of Boost.Random? class seed_rng { static unsigned int * sha1_random_digest_state_() { // intentionally left uninitialized static unsigned int state[ 5 ]; return state; } void sha1_random_digest_() { boost::uuids::detail::sha1 sha; unsigned int * ps = sha1_random_digest_state_(); unsigned int state[ 5 ]; std::memcpy( state, ps, sizeof( state ) ); // harmless data race sha.process_bytes( (unsigned char const*)state, sizeof( state ) ); sha.process_bytes( (unsigned char const*)&amp;ps, sizeof( ps ) ); </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Steven Watanabe</dc:creator> <pubDate>Thu, 17 Feb 2011 03:05:56 GMT</pubDate> <title>component changed; owner set https://svn.boost.org/trac10/ticket/5187#comment:2 https://svn.boost.org/trac10/ticket/5187#comment:2 <ul> <li><strong>owner</strong> set to <span class="trac-author">Andy Tompkins</span> </li> <li><strong>component</strong> <span class="trac-field-old">None</span> → <span class="trac-field-new">uuid</span> </li> </ul> Ticket anonymous Thu, 17 Feb 2011 03:38:51 GMT <link>https://svn.boost.org/trac10/ticket/5187#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5187#comment:3</guid> <description> <pre class="wiki">the static value is always initialized, so we should delete "// intentionally left uninitialized" only ? but the ps in this line is different in different program, different build, different module, different DLL... so ps is random. static unsigned int * sha1_random_digest_state_() { // intentionally left uninitialized static unsigned int state[ 5 ]; return state; } sha.process_bytes( (unsigned char const*)&amp;ps, sizeof( ps ) ); </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Andy Tompkins</dc:creator> <pubDate>Sat, 05 Mar 2011 23:52:43 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5187#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5187#comment:4</guid> <description> <p> The static value does produce different values for me. Some compilers will initialize it in debug builds, or with certain flags. </p> <p> I believe this code is correct. Although I don't completely understand the data race. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Andy Tompkins</dc:creator> <pubDate>Sun, 09 Sep 2012 19:12:42 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/5187#comment:5 https://svn.boost.org/trac10/ticket/5187#comment:5 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">invalid</span> </li> </ul> <p> I'm finally getting back to this after some research and thinking. </p> <p> The static variable in <code>sha1_random_digest_state_()</code>, </p> <blockquote> <p> <code>static unsigned int state[5];</code> </p> </blockquote> <p> may be set to zero with some compilers / flags (often in debug builds). But the program _does_ change the values in it every time <code>sha1_random_digest_()</code> is called (at the bottom of the function). Thus the values in the <code>static unsigned int state[5];</code> are not constant for the duration of the program. So at worst it is initialized to zero, at best it does contain random data initially, but in either case it is changing data that is mixed in. </p> <p> The function <code>sha1_random_digest_();</code> uses many different kinds of allocation for unitialized data. It uses a static array in <code>sha1_random_digest_state_();</code>, it uses a local array in <code>sha1_random_digest_();</code>, <code>unsigned int state[5]</code>. It uses data on the heap as well, <code>unsigned int * p = new unsigned int</code>. </p> <p> <code>sha1_random_digest_state_()</code> does always return the same pointer and so in <code>sha1_random_digest_()</code>, <code>unsigned int * ps = sha1_random_digest_state_();</code> <code>ps</code> always points to the same data but the line we use it in, </p> <p> <code>sha.process_bytes( (unsigned char const*)&amp;ps, sizeof( ps ) );</code> </p> <p> does not use the value of <code>ps</code>, but the address of <code>ps</code>, <code>&amp;ps</code>, which is a value on the stack since this is a local variable. Thus <code>&amp;ps</code> is different each time. </p> <p> I still believe the code is correct. </p> <p> I am closing the ticket as "invalid" since the other choices do not seem to apply. </p> Ticket qiaozhiqiang@… Mon, 10 Sep 2012 01:47:26 GMT <link>https://svn.boost.org/trac10/ticket/5187#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5187#comment:6</guid> <description> <pre class="wiki"> "{{{sha.process_bytes( (unsigned char const*)&amp;ps, sizeof( ps ) );}}} does not use the value of {{{ps}}}, but the address of {{{ps}}}, {{{&amp;ps}}}, which is a value on the stack since this is a local variable." no, sha.process_bytes is use the ps value [4 bytes] pass by pointer. but ps value [address of static unsigned int state[5] ] will be different in different program, different build, different module, different DLL... see comment:3 Changed 19 months ago by anonymous //////////////////// "Thus the values in the static unsigned int state[5]; are not constant for the duration of the program. So at worst it is initialized to zero, at best it does contain random data initially." static unsigned int state[5] is a static function variable will be always initialized to zero in ISO C or ISO C++, static unsigned int state[5] === static unsigned int state[5] = {0,0,0,0,0} so, Yes, the code is correct. but the comments "// intentionally left uninitialized" is not correct. </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Andy Tompkins</dc:creator> <pubDate>Wed, 12 Sep 2012 01:15:18 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5187#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5187#comment:7</guid> <description> <p> I understand now. </p> <p> Thanks. </p> <p> Comment removed, rev 80501 </p> </description> <category>Ticket</category> </item> </channel> </rss>