Thread: Collection of memory leaks for ECPG driver

Collection of memory leaks for ECPG driver

From
Michael Paquier
Date:
Hi all,

Please find attached a patch aimed at fixing a couple of memory leaks
in the ECPG driver. Coverity (and sometimes I after reading some other
code paths) found them.
Regards,
--
Michael

Attachment

Re: Collection of memory leaks for ECPG driver

From
Michael Meskes
Date:
On Mon, Jun 08, 2015 at 01:57:32PM +0900, Michael Paquier wrote:
> Please find attached a patch aimed at fixing a couple of memory leaks
> in the ECPG driver. Coverity (and sometimes I after reading some other
> code paths) found them.

And some are not correct it seems. But then some of the code isn't either. :)

> diff --git a/src/interfaces/ecpg/compatlib/informix.c b/src/interfaces/ecpg/compatlib/informix.c
> index d6de3ea..c1e3dfb 100644
> --- a/src/interfaces/ecpg/compatlib/informix.c
> +++ b/src/interfaces/ecpg/compatlib/informix.c
> @@ -672,6 +672,7 @@ intoasc(interval * i, char *str)
>      if (!str)
>          return -errno;
>  
> +    free(str);
>      return 0;
>  }

This function never worked it seems, we need to use a temp string, copy it to str and then free the temp one.

> diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c
> index 55c5680..12f445d 100644
> --- a/src/interfaces/ecpg/ecpglib/connect.c
> +++ b/src/interfaces/ecpg/ecpglib/connect.c
> @@ -298,7 +298,8 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
>          envname = getenv("PG_DBPATH");
>          if (envname)
>          {
> -            ecpg_free(dbname);
> +            if (dbname)
> +                ecpg_free(dbname);
>              dbname = ecpg_strdup(envname, lineno);
>          }

This is superfluous, at least with glibc. free()'s manpage clearly says "If
ptr is NULL, no operation is performed.", so why should we check again? Or do
we have architectures where free(NULL) is not a noop?

> diff --git a/src/interfaces/ecpg/preproc/descriptor.c b/src/interfaces/ecpg/preproc/descriptor.c
> index 053a7af..ebd95d3 100644
> --- a/src/interfaces/ecpg/preproc/descriptor.c
> +++ b/src/interfaces/ecpg/preproc/descriptor.c

Do we really have to worry about these in a short running application like a precompiler, particularly if they add more
thana simple free() command?
 

But then, you already did the work, so why not. Anyway, please tell me if you want to update the patch or if I should
commitwhatever is clear already.
 

Michael

-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Meskes at (Debian|Postgresql) dot Org
Jabber: michael.meskes at gmail dot com
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL



Re: Collection of memory leaks for ECPG driver

From
Michael Paquier
Date:
On Mon, Jun 8, 2015 at 9:22 PM, Michael Meskes wrote:
> On Mon, Jun 08, 2015 at 01:57:32PM +0900, Michael Paquier wrote:
>> diff --git a/src/interfaces/ecpg/compatlib/informix.c b/src/interfaces/ecpg/compatlib/informix.c
>> index d6de3ea..c1e3dfb 100644
>> --- a/src/interfaces/ecpg/compatlib/informix.c
>> +++ b/src/interfaces/ecpg/compatlib/informix.c
>> @@ -672,6 +672,7 @@ intoasc(interval * i, char *str)
>>       if (!str)
>>               return -errno;
>>
>> +     free(str);
>>       return 0;
>>  }
>
> This function never worked it seems, we need to use a temp string, copy it to str and then free the temp one.

And the caller needs to be sure that str actually allocates enough
space.. That's not directly ECPG's business, still it feels
uncomfortable. I fixed it with the attached.

>> diff --git a/src/interfaces/ecpg/ecpglib/connect.c b/src/interfaces/ecpg/ecpglib/connect.c
>> index 55c5680..12f445d 100644
>> --- a/src/interfaces/ecpg/ecpglib/connect.c
>> +++ b/src/interfaces/ecpg/ecpglib/connect.c
>> @@ -298,7 +298,8 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
>>               envname = getenv("PG_DBPATH");
>>               if (envname)
>>               {
>> -                     ecpg_free(dbname);
>> +                     if (dbname)
>> +                             ecpg_free(dbname);
>>                       dbname = ecpg_strdup(envname, lineno);
>>               }
>
> This is superfluous, at least with glibc. free()'s manpage clearly says "If
> ptr is NULL, no operation is performed.", so why should we check again? Or do
> we have architectures where free(NULL) is not a noop?

The world is full of surprises, and even if free(NULL) is a noop on
modern platforms, I would rather take it defensively and check for a
NULL pointer as Postgres supports many platforms. Other code paths
tend to do already so, per se for example ECPGconnect.

>> diff --git a/src/interfaces/ecpg/preproc/descriptor.c b/src/interfaces/ecpg/preproc/descriptor.c
>> index 053a7af..ebd95d3 100644
>> --- a/src/interfaces/ecpg/preproc/descriptor.c
>> +++ b/src/interfaces/ecpg/preproc/descriptor.c
>
> Do we really have to worry about these in a short running application like a precompiler, particularly if they add
morethan a simple free() command? 

Perhaps I am overdoing it. I would have them for correctness (some
other code paths do so) but if you think that the impact is minimal
there then I am fine to not modify descriptor.c.

> But then, you already did the work, so why not. Anyway, please tell me if you want to update the patch or if I should
commitwhatever is clear already. 

A new patch is attached.
Regards,
--
Michael

Attachment

Re: Collection of memory leaks for ECPG driver

From
Michael Meskes
Date:
On Mon, Jun 08, 2015 at 10:50:25PM +0900, Michael Paquier wrote:
> And the caller needs to be sure that str actually allocates enough
> space.. That's not directly ECPG's business, still it feels

But there is no way for us to fix this as we want to implement the API as
defined in Informix.

> uncomfortable. I fixed it with the attached.

Thanks, committed.

> The world is full of surprises, and even if free(NULL) is a noop on
> modern platforms, I would rather take it defensively and check for a
> NULL pointer as Postgres supports many platforms. Other code paths
> tend to do already so, per se for example ECPGconnect.

Right, that's because they were developed before free received the safeguard, or the programmer simply didn't know at
thatpoint in time. Unless I'm mistaken we have other code that only calls free() without an additional safeguard, so
whyshuld ecpglib be special? If you don't like it using both approaches, feel free to remove the check in the other
case.:)
 

More seriously, though, does anyone know of any platform where free(NULL) is *not* a noop?

I don't like adding stuff just because of the world being full of surprises.
There may also be other functions not working as advertized. Wouldn't that
then mean we cannot use any function nor provided by ourselves?

> Perhaps I am overdoing it. I would have them for correctness (some
> other code paths do so) but if you think that the impact is minimal
> there then I am fine to not modify descriptor.c.

Sorry, I wasn't referring to descriptor.c but to the whole preproc/ subtree. But as I already said, since we went
throughthe effort we can of course apply it.
 

Will be in my next push.

Thanks.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Meskes at (Debian|Postgresql) dot Org
Jabber: michael.meskes at gmail dot com
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL



Re: Collection of memory leaks for ECPG driver

From
Michael Paquier
Date:
On Fri, Jun 12, 2015 at 10:01 PM, Michael Meskes <meskes@postgresql.org> wrote:
> On Mon, Jun 08, 2015 at 10:50:25PM +0900, Michael Paquier wrote:
> Right, that's because they were developed before free received the safeguard, or the programmer simply didn't know at
thatpoint in time. Unless I'm mistaken we have other code that only calls free() without an additional safeguard, so
whyshuld ecpglib be special? If you don't like it using both approaches, feel free to remove the check in the other
case.:) 

Well, I can send patches...

> More seriously, though, does anyone know of any platform where free(NULL) is *not* a noop?

I recall reading that some past versions of SunOS crashed, but it is
rather old...
--
Michael



Re: Collection of memory leaks for ECPG driver

From
Tom Lane
Date:
Michael Paquier <michael.paquier@gmail.com> writes:
> On Fri, Jun 12, 2015 at 10:01 PM, Michael Meskes <meskes@postgresql.org> wrote:
>> More seriously, though, does anyone know of any platform where free(NULL) is *not* a noop?

> I recall reading that some past versions of SunOS crashed, but it is
> rather old...

Yeah, SunOS 4.x had issues here, but it's long dead.  More to the point,
both C89 and Single Unix Spec v2 clearly say that free(NULL) is a no-op;
and it's been many years since we agreed that we had no interest in
supporting platforms that didn't meet at least those minimum standards.
So there is no need to worry about any code of ours that does free(NULL).

But having said that, I would not be in a hurry to remove any existing
if-guards for the case.  For one thing, it makes the code look more
similar to backend code that uses palloc/pfree, where we do *not* allow
pfree(NULL).  There's also the point that changing longstanding code
creates back-patching hazards, so unless there's a clear gain it's best
not to.
        regards, tom lane



Re: Collection of memory leaks for ECPG driver

From
Michael Meskes
Date:
On Sat, Jun 13, 2015 at 12:02:40AM -0400, Tom Lane wrote:
> But having said that, I would not be in a hurry to remove any existing
> if-guards for the case.  For one thing, it makes the code look more
> similar to backend code that uses palloc/pfree, where we do *not* allow
> pfree(NULL).  There's also the point that changing longstanding code
> creates back-patching hazards, so unless there's a clear gain it's best
> not to.

Makes sense, but there is no point in adding hos if-guards to old code that
doesn't have it either,right?

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Meskes at (Debian|Postgresql) dot Org
Jabber: michael.meskes at gmail dot com
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL



Re: Collection of memory leaks for ECPG driver

From
Michael Paquier
Date:
On Sat, Jun 13, 2015 at 6:25 PM, Michael Meskes <meskes@postgresql.org> wrote:
> On Sat, Jun 13, 2015 at 12:02:40AM -0400, Tom Lane wrote:
>> But having said that, I would not be in a hurry to remove any existing
>> if-guards for the case.  For one thing, it makes the code look more
>> similar to backend code that uses palloc/pfree, where we do *not* allow
>> pfree(NULL).  There's also the point that changing longstanding code
>> creates back-patching hazards, so unless there's a clear gain it's best
>> not to.
>
> Makes sense, but there is no point in adding hos if-guards to old code that
> doesn't have it either,right?

In any case, whatever the final decision done here, I just wanted to
point out that there is still a leak in connect.c. Per se the attached
patch, that does not check for a NULL pointer before ecpg_free because
other code paths in the routine patched don't do so. So you get
something locally consistent ;)
--
Michael

Attachment

Re: Collection of memory leaks for ECPG driver

From
Michael Meskes
Date:
On Sun, Jun 14, 2015 at 08:43:13PM +0900, Michael Paquier wrote:
> point out that there is still a leak in connect.c. Per se the attached
> patch, that does not check for a NULL pointer before ecpg_free because
> other code paths in the routine patched don't do so. So you get
> something locally consistent ;)

Thanks, committed.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Meskes at (Debian|Postgresql) dot Org
Jabber: michael.meskes at gmail dot com
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL



Re: Collection of memory leaks for ECPG driver

From
Michael Paquier
Date:
On Mon, Jun 15, 2015 at 9:33 PM, Michael Meskes <meskes@postgresql.org> wrote:
> On Sun, Jun 14, 2015 at 08:43:13PM +0900, Michael Paquier wrote:
>> point out that there is still a leak in connect.c. Per se the attached
>> patch, that does not check for a NULL pointer before ecpg_free because
>> other code paths in the routine patched don't do so. So you get
>> something locally consistent ;)
>
> Thanks, committed.

Thanks.
-- 
Michael