diff options
author | David Mitchell <davem@iabyn.com> | 2019-04-16 15:28:16 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2019-04-16 16:09:38 +0100 |
commit | 44955e7de88913c476b06c9046ed65775b693da7 (patch) | |
tree | d5afc09100218c18192c8af6e27bccaacf23e12a /mg.c | |
parent | dc88277553b8a9ac3a811430ac94cdcd73f44e69 (diff) | |
download | perl-44955e7de88913c476b06c9046ed65775b693da7.tar.gz |
fix locale leak on zero-length strings
For example the following leaked:
use locale;
my $le = "" le "";
When a comparison is done within locale scope, PERL_MAGIC_collxfrm
magic is added to the SV. However, the value set for mg_len is the length
of the collated string, not the malloced size of the buffer. This means
that mg_len can be set to zero, which by convention, means that mg_ptr
shouldn't be freed.
For now, fix by putting special-cased code in S_mg_free_struct. After
5.30.0 is out, I'll probably add a PERL_MAGIC_collxfrm-specific svt_free
vtable method.
The symptoms were that valgrind / Address Sanitizer found fault with
lib/locale.t
Diffstat (limited to 'mg.c')
-rw-r--r-- | mg.c | 8 |
1 files changed, 7 insertions, 1 deletions
@@ -556,12 +556,18 @@ S_mg_free_struct(pTHX_ SV *sv, MAGIC *mg) const MGVTBL* const vtbl = mg->mg_virtual; if (vtbl && vtbl->svt_free) vtbl->svt_free(aTHX_ sv, mg); - if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) { + + if (mg->mg_type == PERL_MAGIC_collxfrm && mg->mg_len >= 0) + /* collate magic uses string len not buffer len, so + * free even with mg_len == 0 */ + Safefree(mg->mg_ptr); + else if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) { if (mg->mg_len > 0 || mg->mg_type == PERL_MAGIC_utf8) Safefree(mg->mg_ptr); else if (mg->mg_len == HEf_SVKEY) SvREFCNT_dec(MUTABLE_SV(mg->mg_ptr)); } + if (mg->mg_flags & MGf_REFCOUNTED) SvREFCNT_dec(mg->mg_obj); Safefree(mg); |