Thread: Oops in fe-auth.c

Oops in fe-auth.c

From
Magnus Hagander
Date:
I've been debugging some really weird crashes in libpq on win32, and I
think I've finally found the reason for the heap corruption that shows up
in msvc debug mode.

When run in debug mode, the runtime for msvc will *zero-pad the entire
buffer* in a strncpy() call. This in itself is not bad (just slow), but it
shows a rather bad bug in libpq.

In a bunch of places in fe-auth.c, we do:
strncpy(PQerrormsg, libpq_gettext("out of memory\n"), PQERRORMSG_LENGTH);


Except when calling it, the size of the buffer is 256 bytes. But
PQERRORMSG_LENGTH is 1024.

Naturally, this causes a heap corruption. It doesn't happen in production,
because the string length fits as long as there is no padding.

One way to get around this on win32 is to just use snprintf() instead of
strncpy(), since it doesn't pad. But that's just hiding the underlying
problem, so I think that's a really bad fix.

I assume the comment in the header:* NOTE: the error message strings returned by this module must not* exceed
INITIAL_EXPBUFFER_SIZE(currently 256 bytes).
 

refers to this, but it's hard to guarantee that from the code since it's
translated strings.

I see a comment in fe-connect.c that has                 
* XXX fe-auth.c has not been fixed to support PQExpBuffers,


Given this, I'll go ahead and fix fe-connect to support PQExpBuffers,
unless there are any objections. Also, is this something we shuold
backpatch - or just ignore since we've had no actual reports of it in the
field?

//Magnus



Re: Oops in fe-auth.c

From
Tom Lane
Date:
Magnus Hagander <magnus@hagander.net> writes:
> When run in debug mode, the runtime for msvc will *zero-pad the entire
> buffer* in a strncpy() call. This in itself is not bad (just slow), but it
> shows a rather bad bug in libpq.

[squint]  That is the specified behavior of strncpy on every platform,
not only msvc.  If there's a bug here why didn't we notice it long ago?

> Given this, I'll go ahead and fix fe-connect to support PQExpBuffers,
> unless there are any objections.

I'm not against that, but I question what bug you've really found.
        regards, tom lane


Re: Oops in fe-auth.c

From
Magnus Hagander
Date:
On Mon, Jul 23, 2007 at 10:28:57AM -0400, Tom Lane wrote:
> Magnus Hagander <magnus@hagander.net> writes:
> > When run in debug mode, the runtime for msvc will *zero-pad the entire
> > buffer* in a strncpy() call. This in itself is not bad (just slow), but it
> > shows a rather bad bug in libpq.
> 
> [squint]  That is the specified behavior of strncpy on every platform,
> not only msvc.  If there's a bug here why didn't we notice it long ago?

Hmm. Interesting - I see that now if I look at
http://www.opengroup.org/onlinepubs/007908799/xsh/strncpy.html.

That's very interesting - but my debugger very much shows me that the
buffer size is 256 bytes (INITIAL_EXPBUFFER_SIZE), and passes
1024 (PQERRORMSG_LENGTH) as the size of the buffer...

Perhaps we've just never hit one of those codepaths before. Previously, it
was only used for out of memory errors - the gssapi code adds a few places
where it's used in other cases, and this is where it crashed for me.

> > Given this, I'll go ahead and fix fe-connect to support PQExpBuffers,
> > unless there are any objections.
> 
> I'm not against that, but I question what bug you've really found.

I never actually tested if it crashes on mingw, but looking some more at it
it really should - once one of these errors happen.

//Magnus


Re: Oops in fe-auth.c

From
Magnus Hagander
Date:
Magnus Hagander wrote:
> On Mon, Jul 23, 2007 at 10:28:57AM -0400, Tom Lane wrote:
>>> Given this, I'll go ahead and fix fe-connect to support PQExpBuffers,
>>> unless there are any objections.
>> I'm not against that, but I question what bug you've really found.
> 
> I never actually tested if it crashes on mingw, but looking some more at it
> it really should - once one of these errors happen.

Hm. Much easier than that - the code is new in HEAD. 8.2 did
fprintf(stderr). And HEAD still does that in at least one case.

Anyway, I'll go ahead with the patch I wrote since it does Seem Nicer to
actually use the PQexpbuffer code there, and the patch was rather
trivial, but it's certainly not something to backpatch then...

I also found at least one other place in libpq where it still does
fprintf(stderr). That should probably be fixed at the same time, right?

//Magnus


Re: Oops in fe-auth.c

From
Tom Lane
Date:
Magnus Hagander <magnus@hagander.net> writes:
> I also found at least one other place in libpq where it still does
> fprintf(stderr). That should probably be fixed at the same time, right?

Yeah, we should be using the error message buffer if at all possible.
        regards, tom lane


Re: Oops in fe-auth.c

From
Tom Lane
Date:
Magnus Hagander <magnus@hagander.net> writes:
>> I never actually tested if it crashes on mingw, but looking some more at it
>> it really should - once one of these errors happen.

> Hm. Much easier than that - the code is new in HEAD. 8.2 did
> fprintf(stderr). And HEAD still does that in at least one case.

> Anyway, I'll go ahead with the patch I wrote since it does Seem Nicer to
> actually use the PQexpbuffer code there, and the patch was rather
> trivial, but it's certainly not something to backpatch then...

It does look like there is a risk in 8.2 and before, though:
the fe-auth.c code has a lot of snprintf's with PQERRORMSG_LENGTH,
which should all be INITIAL_EXPBUFFER_SIZE according to that header
comment.  snprintf typically doesn't write more than it has to,
but if there ever were a message exceeding INITIAL_EXPBUFFER_SIZE
we'd be at risk of a memory clobber.  So that should be changed
as far back as it does that.  Do you want to take care of it?
I can if you don't want to.
        regards, tom lane


Re: Oops in fe-auth.c

From
Magnus Hagander
Date:
Tom Lane wrote:
> Magnus Hagander <magnus@hagander.net> writes:
>>> I never actually tested if it crashes on mingw, but looking some more at it
>>> it really should - once one of these errors happen.
> 
>> Hm. Much easier than that - the code is new in HEAD. 8.2 did
>> fprintf(stderr). And HEAD still does that in at least one case.
> 
>> Anyway, I'll go ahead with the patch I wrote since it does Seem Nicer to
>> actually use the PQexpbuffer code there, and the patch was rather
>> trivial, but it's certainly not something to backpatch then...
> 
> It does look like there is a risk in 8.2 and before, though:
> the fe-auth.c code has a lot of snprintf's with PQERRORMSG_LENGTH,
> which should all be INITIAL_EXPBUFFER_SIZE according to that header
> comment.  snprintf typically doesn't write more than it has to,
> but if there ever were a message exceeding INITIAL_EXPBUFFER_SIZE
> we'd be at risk of a memory clobber.  So that should be changed
> as far back as it does that.  Do you want to take care of it?
> I can if you don't want to.

Oh, didn't realize that one.

I can take a look at that as well, once I'm done with this one. Seems
easy enough - I'll leave you to focus on the more difficult stuff :-)

//Magnus