Boost C++ Libraries: Ticket #3486: local_time::posix_time_zone_base::calc_zone Misuses String Iterator https://svn.boost.org/trac10/ticket/3486 <p> calc_zone() starts like this: </p> <blockquote> <p> void calc_zone(const string_type&amp; obj){ </p> <blockquote> <p> const char_type empty_string<a class="changeset" href="https://svn.boost.org/trac10/changeset/2" title="Add Boost Disclaimer">[2]</a> = {'\0'}; stringstream_type ss(empty_string); typename string_type::const_iterator sit = obj.begin(); string_type l_std_zone_abbrev, l_dst_zone_abbrev; </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> <em> get 'std' name/abbrev while(std::isalpha(*sit)){ </em></p> <blockquote> <p> ss &lt;&lt; *sit++; </p> </blockquote> <p> } </p> </blockquote> </blockquote> <p> Notice that sit is never compared against obj.end(). This code apparently assumes that some non-alpha character will appear, if only a null terminator. However, a checked STL flags *sit, in the conditional, as an error when trying to dereference the end iterator. </p> <p> The particular example I encountered in which it failed was when obj was a std::string, of length 9, containing "Australia". There is no non-alpha character before advancing the iterator to the end, so operator *() fails with: "string iterator not dereferencable" in MSVC 8 (<a class="missing wiki">DevStudio</a> 2005). </p> <p> I suggest changing the loop to the following: </p> <blockquote> <p> typename string_type::const_iterator it(obj.begin()); typename string_type::const_iterator end(obj.end()); <em> get 'std' name/abbrev while (it != send &amp;&amp; std::isalpha(*it)) { </em></p> <blockquote> <p> ss &lt;&lt; *it++; </p> </blockquote> <p> } </p> </blockquote> <p> (You can reuse end in the rest of the function, while you're at it!) </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/3486 Trac 1.4.3 Rob Stewart <robert.stewart@…> Thu, 24 Sep 2009 21:03:37 GMT <link>https://svn.boost.org/trac10/ticket/3486#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3486#comment:1</guid> <description> <p> Wow! Trac really munged the code I entered and I forgot to s/send/end/ in the suggested change. </p> <p> Later releases (I happened to have looked at the code from 1.33 when I copied the above) already do the equivalent of eit (obj_end). However, the bug remains, so here's the change needed for the trunk: </p> <blockquote> <p> while (it != obj_end &amp;&amp; std::isalpha(*it)) { </p> <blockquote> <p> ss &lt;&lt; *it++; </p> </blockquote> <p> } </p> </blockquote> </description> <category>Ticket</category> </item> <item> <author>Rob Stewart <robert.stewart@…></author> <pubDate>Thu, 24 Sep 2009 21:05:45 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/3486#comment:2 https://svn.boost.org/trac10/ticket/3486#comment:2 <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">fixed</span> </li> </ul> <p> I was just creating a local diff for 1.39 and realized that the iterator sit has been changed to a pointer, thus bypassing the checked iterator problem of the earlier version. </p> <p> Sorry for the noise! </p> Ticket