summaryrefslogtreecommitdiff
path: root/mg.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2019-04-16 15:28:16 +0100
committerDavid Mitchell <davem@iabyn.com>2019-04-16 16:09:38 +0100
commit44955e7de88913c476b06c9046ed65775b693da7 (patch)
treed5afc09100218c18192c8af6e27bccaacf23e12a /mg.c
parentdc88277553b8a9ac3a811430ac94cdcd73f44e69 (diff)
downloadperl-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.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/mg.c b/mg.c
index 320e2d39bb..afe452fc5d 100644
--- a/mg.c
+++ b/mg.c
@@ -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);