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);