Bug#754901: invalid code issue

Matthias Klose doko at debian.org
Fri Aug 8 09:46:08 UTC 2014


Control: reassign -1 libapache2-mod-perl2

the code is from this macro:

#define MP_ENV_HV_STORE(hv, key, val) STMT_START {              \
        I32 klen = strlen(key);                                 \
        SV **svp = hv_fetch(hv, key, klen, FALSE);              \
                                                                \
        if (svp) {                                              \
            sv_setpv(*svp, val);                                \
        }                                                       \
        else {                                                  \
            SV *sv = newSVpv(val, 0);                           \
            (void)hv_store(hv, key, klen, sv, FALSE);           \
            modperl_envelem_tie(sv, key, klen);                 \
            svp = &sv;                                          \
        }                                                       \
        MP_TRACE_e(MP_FUNC, "$ENV{%s} = \"%s\";", key, val);    \
                                                                \
        SvTAINTED_on(*svp);                                     \
    } STMT_END


from the upstream report:

The only dead store deleted in modperl_env_table_populate is

  Deleted dead store 'sv = sv.5_31;

and that's ok because we have a clobber of 'sv' in this path.

  <bb 7>:
  _29 = _22->val;
  sv.5_31 = Perl_newSVpv (my_perl_7(D), _29, 0);
  sv = sv.5_31;
  _33 = _22->key;
  Perl_hv_common_key_len (my_perl_7(D), hv_10, _33, klen_26, 36, sv.5_31, 0);
  _35 = _22->key;
  Perl_sv_magic (my_perl_7(D), sv.5_31, 0B, 101, _35, klen_26);
  # DEBUG svp => &sv
  sv ={v} {CLOBBER};

  <bb 8>:
  # svp_2 = PHI <&sv(7), svp_28(6)>
  # DEBUG svp => svp_2
  _41 = my_perl_7(D)->Itainting;
  if (_41 != 0)
    goto <bb 9>;
  else
    goto <bb 10>;

  <bb 9>:
  _42 = *svp_2;
  Perl_sv_magic (my_perl_7(D), _42, 0B, 116, 0B, 0);

but a use-after-free here through *svp_2.  Prettified preprocessed souce
looks like

        SV **svp = ((SV**) Perl_hv_common_key_len(my_perl,
(hv),(elts[i].key),(klen),((0)) ? (0x20 | 0x10) : 0x20,((void *)0),0));
        if (svp) {
          Perl_sv_setpv(my_perl, *svp,elts[i].val);
        } else {
          SV *sv = Perl_newSVpv(my_perl, elts[i].val,0);
          (void)((SV**) Perl_hv_common_key_len(my_perl,
(hv),(elts[i].key),(klen),(0x04|0x20),(sv),((0))));
          Perl_sv_magic(my_perl, sv,(SV *)((void *)0),'e',elts[i].key,klen);
          svp = &sv;
        }
        if (0) modperl_trace(__func__, "$ENV{%s} = \"%s\";", elts[i].key,
elts[i].val);
        (void)({
          if(((my_perl->Itainting))){Perl_sv_magic(my_perl, (*svp),((void
*)0),'t',((void *)0),0);

so 'sv' is declared inside the 'else' but you make its address escape
through the 'svp' variable declared in the outer block.

Invalid.

A fix is to move the declaration of SV *sv up one block.



More information about the pkg-perl-maintainers mailing list