d5da15
From d77d726d206f16232df6edd80739720bb7011aea Mon Sep 17 00:00:00 2001
d5da15
From: Pali <pali@cpan.org>
d5da15
Date: Thu, 7 Oct 2021 22:35:51 +0200
d5da15
Subject: [PATCH] Fix memory leak in function encode_method()
d5da15
d5da15
Pull request https://github.com/dankogai/p5-encode/pull/72 fixed memory
d5da15
corruption but introduced a new memory leak as dst scalar is not mortal
d5da15
anymore and not every possible exit from every XS function properly release
d5da15
scalar's memory.
d5da15
d5da15
Fix this memory leak by making dst scalar mortal again. To not re-introduce
d5da15
that memory corruption, first store dst scalar into temporary variable and
d5da15
then save it into stack via ST(0) macro.
d5da15
---
d5da15
 Encode.xs | 23 ++++++++++++-----------
d5da15
 1 file changed, 12 insertions(+), 11 deletions(-)
d5da15
d5da15
diff --git a/Encode.xs b/Encode.xs
d5da15
index 4baf296..d173c96 100644
d5da15
--- a/Encode.xs
d5da15
+++ b/Encode.xs
d5da15
@@ -154,7 +154,7 @@ encode_method(pTHX_ const encode_t * enc, const encpage_t * dir, SV * src, U8 *
d5da15
     STRLEN sdone = 0;
d5da15
     /* We allocate slen+1.
d5da15
        PerlIO dumps core if this value is smaller than this. */
d5da15
-    SV *dst = newSV(slen+1);
d5da15
+    SV *dst = sv_2mortal(newSV(slen+1));
d5da15
     U8 *d = (U8 *)SvPVX(dst);
d5da15
     STRLEN dlen = SvLEN(dst)-1;
d5da15
     int code = 0;
d5da15
@@ -810,13 +810,12 @@ CODE:
d5da15
     tmp = encode_method(aTHX_ enc, enc->t_utf8, src, s, slen, check,
d5da15
                 &offset, term, &code, fallback_cb);
d5da15
     sv_catsv(dst, tmp);
d5da15
-    SvREFCNT_dec(tmp);
d5da15
     SvIV_set(off, (IV)offset);
d5da15
     RETVAL = (code == ENCODE_FOUND_TERM);
d5da15
 OUTPUT:
d5da15
     RETVAL
d5da15
 
d5da15
-SV *
d5da15
+void
d5da15
 Method_decode(obj,src,check_sv = &PL_sv_no)
d5da15
 SV *	obj
d5da15
 SV *	src
d5da15
@@ -828,6 +827,7 @@ PREINIT:
d5da15
     encode_t *enc;
d5da15
     U8 *s;
d5da15
     STRLEN slen;
d5da15
+    SV *ret;
d5da15
 INIT:
d5da15
     SvGETMAGIC(src);
d5da15
     SvGETMAGIC(check_sv);
d5da15
@@ -841,13 +841,13 @@ CODE:
d5da15
     s = modify ? (U8 *)SvPV_force_nomg(src, slen) : (U8 *)SvPV_nomg(src, slen);
d5da15
     if (SvUTF8(src))
d5da15
         utf8_safe_downgrade(aTHX_ &src, &s, &slen, modify);
d5da15
-    RETVAL = encode_method(aTHX_ enc, enc->t_utf8, src, s, slen, check,
d5da15
+    ret = encode_method(aTHX_ enc, enc->t_utf8, src, s, slen, check,
d5da15
               NULL, Nullsv, NULL, fallback_cb);
d5da15
-    SvUTF8_on(RETVAL);
d5da15
-OUTPUT:
d5da15
-    RETVAL
d5da15
+    SvUTF8_on(ret);
d5da15
+    ST(0) = ret;
d5da15
+    XSRETURN(1);
d5da15
 
d5da15
-SV *
d5da15
+void
d5da15
 Method_encode(obj,src,check_sv = &PL_sv_no)
d5da15
 SV *	obj
d5da15
 SV *	src
d5da15
@@ -859,6 +859,7 @@ PREINIT:
d5da15
     encode_t *enc;
d5da15
     U8 *s;
d5da15
     STRLEN slen;
d5da15
+    SV *ret;
d5da15
 INIT:
d5da15
     SvGETMAGIC(src);
d5da15
     SvGETMAGIC(check_sv);
d5da15
@@ -872,10 +873,10 @@ CODE:
d5da15
     s = modify ? (U8 *)SvPV_force_nomg(src, slen) : (U8 *)SvPV_nomg(src, slen);
d5da15
     if (!SvUTF8(src))
d5da15
         utf8_safe_upgrade(aTHX_ &src, &s, &slen, modify);
d5da15
-    RETVAL = encode_method(aTHX_ enc, enc->f_utf8, src, s, slen, check,
d5da15
+    ret = encode_method(aTHX_ enc, enc->f_utf8, src, s, slen, check,
d5da15
               NULL, Nullsv, NULL, fallback_cb);
d5da15
-OUTPUT:
d5da15
-    RETVAL
d5da15
+    ST(0) = ret;
d5da15
+    XSRETURN(1);
d5da15
 
d5da15
 bool
d5da15
 Method_needs_lines(obj)
d5da15
-- 
d5da15
2.31.1
d5da15