[augeas-devel] [PATCH 3 of 4] Check for (some) allocation failures

David Lutterkort dlutter at redhat.com
Fri May 9 05:13:14 UTC 2008


On Fri, 2008-05-09 at 00:50 -0400, James Antill wrote:
> On Thu, 2008-05-08 at 18:33 -0700, David Lutterkort wrote:
> >  
> >  static struct re *make_re_rep(struct re *exp, int min, int max) {
> >      struct re *re = make_re(ITER);
> > -    re->exp = exp;
> > -    re->min = min;
> > -    re->max = max;
> > +    if (re) {
> > +        re->exp = exp;
> > +        re->min = min;
> > +        re->max = max;
> > +    }
> >      return re;
> >  }
> 
>  IMO you have to be really careful when you implicitly pass reference
> ownership, I think what you really want here (dito. make_re_binop) is:
> 
>  static struct re *make_re_rep(struct re *exp, int min, int max) {
>      struct re *re = make_re(ITER);
> -    re->exp = exp;
> -    re->min = min;
> -    re->max = max;
> +    if (re) {
> +        re->exp = ref(exp);
> +        re->min = min;
> +        re->max = max;
> +    }
> +    unref(exp, re); /* don't leak what was passed in on failure */
>      return re;
>  }

No, the usage is correct; the tortuous comment in ref.h about 'taking
ownership' and 'receiving ownership' tries to explain that: MAKE_RE_REP
receives ownership of EXP, meaning that after it returns EXP belongs to
whatever it did with it, not the caller of MAKE_RE_REP anymore.

The (badly documented) convention in the PARSE_* and MAKE_RE_* functions
in fa.c is that they receive ownership for the RE's in their arguments,
and give ownership of whatever they return to their caller.

> ...so the interface always consumes the reference, this makes the
> calling code correct:
> 
>     if (match(regexp, '?')) {
>         re = make_re_rep(re, 0, 1);
>     } else if (match(regexp, '*')) {
>         re = make_re_rep(re, 0, -1);
>     } else if (match(regexp, '+')) {
>         re = make_re_rep(re, 1, -1);
>     }

Preceding the above snippet in PARSE_REPEATED_EXP is
        struct re *re = parse_simple_exp(regexp, error);

Here, PARSE_SIMPLE_EXP returns an RE that is now owned by
PARSE_REPEATED_EXP; the block you qoute passes that ownership on to
MAKE_RE_REP, and gets a new RE back that is again owned by
PARSE_REPEATED_EXP; by and large, that ownership is passed up to the
caller of PARSE_REPEATED_EXP

> ...although the three different usages of the "re" symbol now, in that
> one function is a bit ... interesting :).

True; using the same symbol is meant to emphasize how ownership is
passed around, but I am just realizing that it's a nice leak when
make_re_rep fails. Ugh.

David





More information about the augeas-devel mailing list