On Fri, Nov 24, 2006 at 06:42:28PM +0100, Andre Poenitz wrote:

> On Wed, Nov 22, 2006 at 02:32:28AM +0100, Enrico Forestieri wrote:
> > On Tue, Nov 21, 2006 at 07:21:13PM +0100, Andre Poenitz wrote:
> > > On Fri, Nov 17, 2006 at 07:27:43PM -0000, [EMAIL PROTECTED] wrote:
> > > > +protected:
> > > > +       iter_type
> > > > +       do_get(iter_type iit, iter_type eit, std::ios_base & b,
> > > > +               std::ios_base::iostate & err, long & v) const
> > > > +       {
> > > > +               std::string s;
> > > > +               s.resize(64);
> > > > +               for (int i = 0; iit != eit && isNumpunct(*iit); ++i, 
> > > > ++iit)
> > > > +                       s[i] = static_cast<char>(*iit);
> > > > +               string_num_get_facet f;
> > > > +               f.get(s.begin(), s.end(), b, err, v);
> > > 
> > > Doesn't that mean you access uninitialized memory at the end of s?
> > 
> > You mean when/if I read more than 64 wide chars, right?
> 
> Then, and also when there are less than 64 characters.
> 
> Then s.end() will point at s.begin() + 64 and f.get will access the
> range from the real end up to 64 as far as I can tell.

Hmmm, if my info are correct I think I'm doing right:

 void string::resize(size_type n, char c)
    The string stored in the string object is resized to n characters.
    The second argument is optional, in which case the value c = 0 is
    used. If provided and the string is enlarged, the extra characters
    are initialized to c.

Hence, I am not reading uninitialized memory and f.get stops reading
when encountering the first 0.

> > What about the attached patch?
> > 
> > -- 
> > Enrico
> 
> > Index: src/support/docstring.C
> > ===================================================================
> > --- src/support/docstring.C (revision 16007)
> > +++ src/support/docstring.C (working copy)
> > @@ -464,10 +464,17 @@ protected:
> >     do_get(iter_type iit, iter_type eit, std::ios_base & b,
> >             std::ios_base::iostate & err, long & v) const
> >     {
> > +           int const leap = 64;
> > +           int size = leap;
> >             std::string s;
> > -           s.resize(64);
> > -           for (int i = 0; iit != eit && isNumpunct(*iit); ++i, ++iit)
> > +           s.resize(size);
> > +           for (int i = 0; iit != eit && isNumpunct(*iit); ++i, ++iit) {
> > +                   if (i >= size) {
> > +                           size += leap;
> > +                           s.resize(size);
> > +                   }
> >                     s[i] = static_cast<char>(*iit);
> > +           }
> >             string_num_get_facet f;
> >             f.get(s.begin(), s.end(), b, err, v);
> 
> What about 'reserve' and  s += static_cast<...>
> 
> This happens to correct the other issue as well.

Yes, this is more elegant and I don't need to initialize the memory,
so reserve() can be used in place of resize(). Thanks for your hint!

I am going to commit the attached patch.

-- 
Enrico
Index: src/support/docstring.C
===================================================================
--- src/support/docstring.C     (revision 16020)
+++ src/support/docstring.C     (working copy)
@@ -465,9 +465,9 @@ protected:
                std::ios_base::iostate & err, long & v) const
        {
                std::string s;
-               s.resize(64);
-               for (int i = 0; iit != eit && isNumpunct(*iit); ++i, ++iit)
-                       s[i] = static_cast<char>(*iit);
+               s.reserve(64);
+               for (; iit != eit && isNumpunct(*iit); ++iit)
+                       s += static_cast<char>(*iit);
                string_num_get_facet f;
                f.get(s.begin(), s.end(), b, err, v);
 

Reply via email to