diff options
author | David Mitchell <davem@iabyn.com> | 2019-03-26 08:56:55 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2019-03-26 08:56:55 +0000 |
commit | 657ed7c1c190e7fad1bac2979944d07245bbeea4 (patch) | |
tree | 7480856165f8332e23579d0feb3c3894360e1f92 /gv.c | |
parent | e40cca748f05c81e1929ed625407afbe7c79d4dd (diff) | |
download | perl-657ed7c1c190e7fad1bac2979944d07245bbeea4.tar.gz |
fix leak in package name lookup
S_parse_gv_stash_name() mallocs a temporary buffer when scanning package
names longer than 64 bytes. Depending on how it exits the function, it
doesn't always free the buffer afterwards. Change the function so that
there are only two exit points (which free the buffer) and make other bits
of code goto those two points.
Can be reproduced with e.g.
&{"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'x"}
Similar code is already present in t/op/stash_parse_gv.t
Diffstat (limited to 'gv.c')
-rw-r--r-- | gv.c | 13 |
1 files changed, 9 insertions, 4 deletions
@@ -1636,7 +1636,7 @@ S_parse_gv_stash_name(pTHX_ HV **stash, GV **gv, const char **name, if (!*stash) *stash = PL_defstash; if (!*stash || !SvREFCNT(*stash)) /* symbol table under destruction */ - return FALSE; + goto notok; *len = name_cursor - *name; if (name_cursor > nambeg) { /* Skip for initial :: or ' */ @@ -1666,7 +1666,7 @@ S_parse_gv_stash_name(pTHX_ HV **stash, GV **gv, const char **name, *gv = gvp ? *gvp : NULL; if (!*gv || *gv == (const GV *)&PL_sv_undef) { Safefree(tmpfullbuf); /* free our tmpfullbuf if it was used */ - return FALSE; + goto notok; } /* here we know that *gv && *gv != &PL_sv_undef */ if (SvTYPE(*gv) != SVt_PVGV) @@ -1707,15 +1707,20 @@ S_parse_gv_stash_name(pTHX_ HV **stash, GV **gv, const char **name, MUTABLE_HV(SvREFCNT_inc_simple(PL_defstash)); } } - Safefree(tmpfullbuf); /* free our tmpfullbuf if it was used */ - return TRUE; + goto ok; } } } *len = name_cursor - *name; + ok: + Safefree(tmpfullbuf); /* free our tmpfullbuf if it was used */ return TRUE; + notok: + Safefree(tmpfullbuf); /* free our tmpfullbuf if it was used */ + return FALSE; } + /* Checks if an unqualified name is in the main stash */ PERL_STATIC_INLINE bool S_gv_is_in_main(pTHX_ const char *name, STRLEN len, const U32 is_utf8) |