imtrobin

Hi

When using a temporary ostringstream, VC++ 8 SP1 seems to have a buffer overrun. The below code works before in older VC++.

#include <iostream>

using namespace std;

#include <sstream>

int main ()

{

cout << static_cast <std::ostringstream&>(std::ostringstream () << "" << "TEST").str ().c_str ();

return 0;

}

The console output is

0041774BTESTPress any key to continue . . .

It should be just

TESTPress any key to continue . . .



Re: Visual C++ Language Temporary ostringstream buffer overflow

Holger Grund

I'm not sure since I don't have a toolchain installed here, but this looks like improved conformance work.

The key thing here is which operator<< overloads are implemented as members and which are not. std:Surprisestringstream() returns a rvalue of type std:Surprisestringstream (that is what previous version of VC++ got wrong and to certain extent VC8 still does). Member operators work just fine on rvalues. However, the nonmember operators have a signature like

std:Surprisestringstream& operator<<( std:Surprisestringstream& s, ... )

A nonconst reference cannot be bound to an rvalue.

IIRC, the operator taking a const void* is a member operator and is therefore a viable function. The const char* one is a nonmember operator and therefore is not. Hence, overload resolution selects the former.

Note that, the case is different for the second << expression. operator<< returns a std:Surprisestringstream& which is an lvalue, hence the nonmember overload is viable and in fact is a better match (the conversion sequence for the second argument is a proper subset of the one for the const void* case).

-hg





Re: Visual C++ Language Temporary ostringstream buffer overflow

einaros

Right on the money. And for what it's worth, any newer gcc will do the same.

If you really do want to use such a horrid syntax (and I believe the "fix" shows how horrid it really is), you could pull a call to the global operator such as "cout << static_cast<ostringstream&>(operator << (ostringstream(), "TEST")).str();"

As for non-const rvalue references, I doubt that this behaviour will change much anytime soon, as it's likely to break a lot of existing code.





Re: Visual C++ Language Temporary ostringstream buffer overflow

Holger Grund

einaros wrote:
Right on the money. And for what it's worth, any newer gcc will do the same.

If you really do want to use such a horrid syntax (and I believe the "fix" shows how horrid it really is), you could pull a call to the global operator such as "cout << static_cast<ostringstream&>(operator << (ostringstream(), "TEST")).str();"

As for non-const rvalue references, I doubt that this behaviour will change much anytime soon, as it's likely to break a lot of existing code.

I don't quite agree, I'm afraid. We've been hearing these arguments regarding nonconst reference binding for a decade now. There are a couple of cases where the generated code silently fails (or at least does something very odd - e.g.

http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=1848959&SiteID=1 )

Your fix is really ill-formed C++ for the same reasons why overload resolution doesn't consider it and there are alternatives, which aren't really worse (e.g. use a fake manipulator such as std:Surprisestringstream() << std:Big Smileec << "" << "TEST").

I don't really see the advantage of having everything in a single statement in this case.

-hg





Re: Visual C++ Language Temporary ostringstream buffer overflow

einaros

Holger Grund wrote:

einaros wrote:
Right on the money. And for what it's worth, any newer gcc will do the same.

If you really do want to use such a horrid syntax (and I believe the "fix" shows how horrid it really is), you could pull a call to the global operator such as "cout << static_cast<ostringstream&>(operator << (ostringstream(), "TEST")).str();"

As for non-const rvalue references, I doubt that this behaviour will change much anytime soon, as it's likely to break a lot of existing code.

I don't quite agree, I'm afraid. We've been hearing these arguments regarding nonconst reference binding for a decade now. There are a couple of cases where the generated code silently fails (or at least does something very odd - e.g.

http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=1848959&SiteID=1 )


Well I never said I agreed either, but that seems to be the current state of things, not only at MSFT. The EDG front-end happily accepts it as well. GCC and Comeau, on the other hand, complains as they should.

Holger Grund wrote:

Your fix is really ill-formed C++


Hence the double quotes around "fix" Wink


Holger Grund wrote:

for the same reasons why overload resolution doesn't consider it and there are alternatives, which aren't really worse (e.g. use a fake manipulator such as stdTongue Tiedtringstream() << std:ec << "" << "TEST").

I don't really see the advantage of having everything in a single statement in this case.



And that's my point exactly, in case that was unclear in my previous post. Not only is that syntax unlikely to compile across vendors (and versions), but being as obscure as it is, my opinion is that you needlessly make yourself vulnerable to compiler bugs. The less consistent the front-end vendors seem to be about any one concept, the more likely are there to be bugs related to that concept.