Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Jun 2014 07:59:41 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Pedro Giffuni <pfg@freebsd.org>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, Stefan Farfeleder <stefanf@freebsd.org>, src-committers@freebsd.org
Subject:   Re: svn commit: r267675 - head/lib/libc/regex
Message-ID:  <20140621072634.I921@besplex.bde.org>
In-Reply-To: <53A48D62.4060801@FreeBSD.org>
References:  <201406201529.s5KFTAEB068038@svn.freebsd.org> <20140620182311.GA1214@mole.fafoe.narf.at> <53A48D62.4060801@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help

> El 6/20/2014 1:23 PM, Stefan Farfeleder escribi=F3:
>> On Fri, Jun 20, 2014 at 03:29:10PM +0000, Pedro F. Giffuni wrote:
>>> ...
>>> Log:
>>>    regex: Make use of reallocf().
>>>=20
>>>    Use of reallocf is useful in libraries as we are not certain the
>>>    application will exit after NULL.
>>> ...
>>>    This somewhat reduces portability but if since you are building
>>>    this as part of libc it is likely you have our non-standard
>>>    reallocf(3) already.

It also somewhat increases namespace pollution.

>>> Modified: head/lib/libc/regex/regcomp.c
>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D
>>> --- head/lib/libc/regex/regcomp.c=09Fri Jun 20 13:26:49 2014=20
>>> (r267674)
>>> +++ head/lib/libc/regex/regcomp.c=09Fri Jun 20 15:29:09 2014=20
>>> (r267675)
>>> @@ -1111,7 +1111,7 @@ allocset(struct parse *p)
>>>   {
>>>   =09cset *cs, *ncs;
>>>=20
>>> -=09ncs =3D realloc(p->g->sets, (p->g->ncsets + 1) * sizeof(*ncs));
>>> +=09ncs =3D reallocf(p->g->sets, (p->g->ncsets + 1) * sizeof(*ncs));
>>>   =09if (ncs =3D=3D NULL) {
>>>   =09=09SETERROR(REG_ESPACE);
>>>   =09=09return (NULL);
>>> @@ -1174,7 +1174,7 @@ CHadd(struct parse *p, cset *cs, wint_t
>>>   =09if (ch < NC)
>>>   =09=09cs->bmp[ch >> 3] |=3D 1 << (ch & 7);
>>>   =09else {
>>> -=09=09newwides =3D realloc(cs->wides, (cs->nwides + 1) *
>>> +=09=09newwides =3D reallocf(cs->wides, (cs->nwides + 1) *
>>>   =09=09    sizeof(*cs->wides));
>>>   =09=09if (newwides =3D=3D NULL) {
>>>   =09=09=09SETERROR(REG_ESPACE);
>>=20
>> I don't think these changes are OK. If reallocf() fails here, the
>> cs->wides pointer will be freed and later freeset() will call
>> free(cs->wides), probably crashing. The other cases are most probably
>> similar though I haven't examined them closely.
>>=20
>
> OK ...
>
> I don't think there is any problem:
>
> If reallocf fails, newwides will be set to NULL and if free() is called i=
t=20
> doesn't do anything when the argument is NULL.
>
> Also freeset() is meant to be called to "free a now-unused set" and it is=
 not=20
> called within the library. I would think using a value when the allocatio=
n=20
> has failed is a much more serious issue than attempting to fail to free i=
t=20
> after trying to use it. ;-).

It doesn't look OK to me.  It turns the careful use of newwides, etc.,
into garbage, and leaves a garbage pointer in cs->wides, etc., to cause
problems later.  It might work without this careful use of a temporary
variable, but even that is not clear.  Consider:

- start with a consistent data structure with some pointers to malloced
   storage in it; foo->p say
- simple reallocf() allocation strategy:
     foo->p =3D reallocf(foo->p, size)
     if (foo->p =3D=3D NULL)
       return (ERROR);
   This leaves the data structure consistent if and only if the only thing
   in it relevant to p is p itself, with foo->p serving as a flag for
   validity.
- more complicated reallocf() allocation strategy:
     foo->p =3D reallocf(foo->p, size)
     if (foo->p =3D=3D NULL) {
       foo->psize =3D 0;
       foo->pvalid =3D 0;
       foo->foovalid =3D 0;
       ...
       return (ERROR);
     }
   This still can't do things like cleaning up what foo->p points to, since
   reallocf() clobbered that.
This shows that reallocf() is only useful in simple cases.  In general, you
must keep the pointer valid to clean things up:
     newp =3D reallocf(foo->p, size)
     if (newp =3D=3D NULL) {
       for (i =3D 0; i < foo->psize; i++)
 =09free(foo->p[i]);
       foo->p =3D NULL;
       foo->psize =3D 0;
       foo->pvalid =3D 0;
       foo->foovalid =3D 0;
       ...
       return (ERROR);
     }

Of course, malloc never fails so all this error checking is more a source
of complexity and bugs than useful.

Re-quoting/recovering some context:

@ Modified: head/lib/libc/regex/regcomp.c
@ =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
@ --- head/lib/libc/regex/regcomp.c=09Fri Jun 20 13:26:49 2014=09(r267674)
@ +++ head/lib/libc/regex/regcomp.c=09Fri Jun 20 15:29:09 2014=09(r267675)
@ @@ -1111,7 +1111,7 @@ allocset(struct parse *p)
@  {
@  =09cset *cs, *ncs;
@=20
@ -=09ncs =3D realloc(p->g->sets, (p->g->ncsets + 1) * sizeof(*ncs));
@ +=09ncs =3D reallocf(p->g->sets, (p->g->ncsets + 1) * sizeof(*ncs));
@  =09if (ncs =3D=3D NULL) {
@  =09=09SETERROR(REG_ESPACE);
@  =09=09return (NULL);

This code shows that even Henry didn't know how to program memory allocatio=
n
in 1988.  The code was much worse in 4.4BSD-Lite2:

old@ =09=09if (p->g->sets =3D=3D NULL)
old@ =09=09=09p->g->sets =3D (cset *)malloc(nc * sizeof(cset));
old@ =09=09else
old@ =09=09=09p->g->sets =3D (cset *)realloc((char *)p->g->sets,
old@ =09=09=09=09=09=09=09nc * sizeof(cset));

This just leaked memory.  It was improved by assigning to ncs and by
removing the pre-C90 and C++ casts.  Now it is unimproved by turning the
careful use of ncs into garbage and leaving garbage in *p.

old@ =09=09if (p->g->setbits =3D=3D NULL)
old@ =09=09=09p->g->setbits =3D (uch *)malloc(nbytes);
old@ =09=09else {
old@ =09=09=09p->g->setbits =3D (uch *)realloc((char *)p->g->setbits,
old@ =09=09=09=09=09=09=09=09nbytes);
old@ =09=09=09/* xxx this isn't right if setbits is now NULL */
old@ =09=09=09for (i =3D 0; i < no; i++)
old@ =09=09=09=09p->g->sets[i].ptr =3D p->g->setbits + css*(i/CHAR_BIT);
old@ =09=09}

Honest memory mismanagement.  It just assumes that malloc() and realloc()
can't fail.  In -current, the function is much simpler and doesn't have
this code.  I think part of the simplication is to use realloc() of NULL
instead of malloc() to start up.

@ @@ -1174,7 +1174,7 @@ CHadd(struct parse *p, cset *cs, wint_t=20
@  =09if (ch < NC)
@  =09=09cs->bmp[ch >> 3] |=3D 1 << (ch & 7);
@  =09else {
@ -=09=09newwides =3D realloc(cs->wides, (cs->nwides + 1) *
@ +=09=09newwides =3D reallocf(cs->wides, (cs->nwides + 1) *
@  =09=09    sizeof(*cs->wides));
@  =09=09if (newwides =3D=3D NULL) {
@  =09=09=09SETERROR(REG_ESPACE);
@ @@ -1203,7 +1203,7 @@ CHaddrange(struct parse *p, cset *cs, wi
@  =09=09CHadd(p, cs, min);
@  =09if (min >=3D max)
@  =09=09return;
@ -=09newranges =3D realloc(cs->ranges, (cs->nranges + 1) *
@ +=09newranges =3D reallocf(cs->ranges, (cs->nranges + 1) *
@  =09    sizeof(*cs->ranges));
@  =09if (newranges =3D=3D NULL) {
@  =09=09SETERROR(REG_ESPACE);
@ @@ -1227,7 +1227,7 @@ CHaddtype(struct parse *p, cset *cs, wct
@  =09for (i =3D 0; i < NC; i++)
@  =09=09if (iswctype(i, wct))
@  =09=09=09CHadd(p, cs, i);
@ -=09newtypes =3D realloc(cs->types, (cs->ntypes + 1) *
@ +=09newtypes =3D reallocf(cs->types, (cs->ntypes + 1) *
@  =09    sizeof(*cs->types));
@  =09if (newtypes =3D=3D NULL) {
@  =09=09SETERROR(REG_ESPACE);
@ @@ -1350,7 +1350,7 @@ enlarge(struct parse *p, sopno size)
@  =09if (p->ssize >=3D size)
@  =09=09return 1;
@=20
@ -=09sp =3D (sop *)realloc(p->strip, size*sizeof(sop));
@ +=09sp =3D (sop *)reallocf(p->strip, size*sizeof(sop));
@  =09if (sp =3D=3D NULL) {
@  =09=09SETERROR(REG_ESPACE);
@  =09=09return 0;

Similarly in 4 more cases, except most of them weren't in old versions.

@ @@ -1368,7 +1368,7 @@ static void
@  stripsnug(struct parse *p, struct re_guts *g)
@  {
@  =09g->nstates =3D p->slen;
@ -=09g->strip =3D (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));
@ +=09g->strip =3D (sop *)reallocf((char *)p->strip, p->slen * sizeof(sop))=
;
@  =09if (g->strip =3D=3D NULL) {
@  =09=09SETERROR(REG_ESPACE);
@  =09=09g->strip =3D p->strip;

This was the only realloc() that had not been cleaned up, so using
reallocf() has a chance of improving it.  It still has the pre-C90 and
C++ casts.  But there is an obvious new bug visible without reading more
than the patch context:
- the local variable might not be needed now, since the variable assigned
   to, g->strip, is different from the variable realloced, p->strip
- on realloc failure, p->strip becomes invalid
- the error handling is completely broken.  It points g->strip at the old
   (now deallocated) storage.  This is immediate use of the garbage pointer
   created by using reallocf().

Clearly, only realloc() code of the form "p =3D realloc(p, size);", where t=
he
pointer assigned to is the same as the pointer realloced, can be improved
by blindly converting it to use reallocf().

The last function is most interesting.  It seems to be to reduce the size.
So an allocation failure is even less likely than usually, except lots of
small allocations and reallocations are more likely to waste space than
save it.  But if failure occurs it is almost harmless, and the error
handling of keeping using the previous allocation was good.  Maybe Henry
knew how to program memory allocation after all.  (The last function
survived previously-unchanged from 4.4BSDLite-2 except for removing K&R
support and 'register'.)

Bruce
From owner-svn-src-head@FreeBSD.ORG  Sat Jun 21 00:53:57 2014
Return-Path: <owner-svn-src-head@FreeBSD.ORG>
Delivered-To: svn-src-head@freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115])
 (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
 (No client certificate requested)
 by hub.freebsd.org (Postfix) with ESMTPS id 8C422155;
 Sat, 21 Jun 2014 00:53:57 +0000 (UTC)
Received: from svn.freebsd.org (svn.freebsd.org
 [IPv6:2001:1900:2254:2068::e6a:0])
 (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
 (Client did not present a certificate)
 by mx1.freebsd.org (Postfix) with ESMTPS id 5E8FA2CC7;
 Sat, 21 Jun 2014 00:53:57 +0000 (UTC)
Received: from svn.freebsd.org ([127.0.1.70])
 by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s5L0rvKk038938;
 Sat, 21 Jun 2014 00:53:57 GMT
 (envelope-from jhibbits@svn.freebsd.org)
Received: (from jhibbits@localhost)
 by svn.freebsd.org (8.14.8/8.14.8/Submit) id s5L0rvH7038936;
 Sat, 21 Jun 2014 00:53:57 GMT
 (envelope-from jhibbits@svn.freebsd.org)
Message-Id: <201406210053.s5L0rvH7038936@svn.freebsd.org>
From: Justin Hibbits <jhibbits@FreeBSD.org>
Date: Sat, 21 Jun 2014 00:53:57 +0000 (UTC)
To: src-committers@freebsd.org, svn-src-all@freebsd.org,
 svn-src-head@freebsd.org
Subject: svn commit: r267697 - head/sys/dev/adb
X-SVN-Group: head
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-BeenThere: svn-src-head@freebsd.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: SVN commit messages for the src tree for head/-current
 <svn-src-head.freebsd.org>
List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-head>,
 <mailto:svn-src-head-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/svn-src-head/>;
List-Post: <mailto:svn-src-head@freebsd.org>
List-Help: <mailto:svn-src-head-request@freebsd.org?subject=help>
List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-head>,
 <mailto:svn-src-head-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Sat, 21 Jun 2014 00:53:57 -0000

Author: jhibbits
Date: Sat Jun 21 00:53:56 2014
New Revision: 267697
URL: http://svnweb.freebsd.org/changeset/base/267697

Log:
  No need to check if devd is running before posting an event.

Modified:
  head/sys/dev/adb/adb_buttons.c
  head/sys/dev/adb/adb_kbd.c

Modified: head/sys/dev/adb/adb_buttons.c
==============================================================================
--- head/sys/dev/adb/adb_buttons.c	Sat Jun 21 00:45:44 2014	(r267696)
+++ head/sys/dev/adb/adb_buttons.c	Sat Jun 21 00:53:56 2014	(r267697)
@@ -118,37 +118,32 @@ abtn_receive_packet(device_t dev, u_char
 
 	switch (cmd) {
 	case 0x0a:	/* decrease brightness */
-		if (devctl_process_running())
-			devctl_notify("PMU", "keys", "brightness",
-			    "notify=down");
+		devctl_notify("PMU", "keys", "brightness",
+		    "notify=down");
 		break;
 
 	case 0x09:	/* increase brightness */
-		if (devctl_process_running())
-			devctl_notify("PMU", "keys", "brightness", "notify=up");
+		devctl_notify("PMU", "keys", "brightness", "notify=up");
 		break;
 
 	case 0x08:	/* mute */
 	case 0x01:	/* mute, AV hardware */
-		if (devctl_process_running())
-			devctl_notify("PMU", "keys", "mute", NULL);
+		devctl_notify("PMU", "keys", "mute", NULL);
 		break;
 	case 0x07:	/* decrease volume */
 	case 0x02:	/* decrease volume, AV hardware */
-		if (devctl_process_running())
-			devctl_notify("PMU", "keys", "volume", "notify=down");
+		devctl_notify("PMU", "keys", "volume", "notify=down");
 		break;
 	case 0x06:	/* increase volume */
 	case 0x03:	/* increase volume, AV hardware */
-		if (devctl_process_running())
-			devctl_notify("PMU", "keys", "volume", "notify=up");
+		devctl_notify("PMU", "keys", "volume", "notify=up");
 		break;
 	case 0x0c:	/* mirror display key */
 		/* Need callback to do something with this */
 		break;
 	case 0x0b:	/* eject tray */
-		if (devctl_process_running())
-			devctl_notify("PMU", "keys", "eject", NULL);
+		devctl_notify("PMU", "keys", "eject", NULL);
+		break;
 	case 0x7f:	/* numlock */
 		/* Need callback to do something with this */
 		break;

Modified: head/sys/dev/adb/adb_kbd.c
==============================================================================
--- head/sys/dev/adb/adb_kbd.c	Sat Jun 21 00:45:44 2014	(r267696)
+++ head/sys/dev/adb/adb_kbd.c	Sat Jun 21 00:53:56 2014	(r267697)
@@ -424,7 +424,7 @@ adb_kbd_receive_packet(device_t dev, u_c
 
 	mtx_lock(&sc->sc_mutex);
 		/* 0x7f is always the power button */
-		if (data[0] == 0x7f && devctl_process_running()) {
+		if (data[0] == 0x7f) {
 			devctl_notify("PMU", "Button", "pressed", NULL);
 			mtx_unlock(&sc->sc_mutex);
 			return (0);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140621072634.I921>