} STMT_END
void
+
+
+/* This function assumes that pat has the same utf8-ness as sv.
+ * It's the caller's responsibility to ensure that this is so.
+ */
+
Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
va_list *const args, SV **const svargs, const I32 svmax, bool *const maybe_tainted,
const U32 flags)
#endif
NV nv;
STRLEN float_need; /* what PL_efloatsize needs to become */
- STRLEN gap;
const char *dotstr = ".";
STRLEN dotstrlen = 1;
I32 efix = 0; /* explicit format parameter index */
if (has_precis) {
U8* ve = (subnormal ? vlnz + 1 : vend);
- SSize_t vn = ve - (subnormal ? vfnz : vhex);
+ SSize_t vn = ve - v0;
if ((SSize_t)(precis + 1) < vn) {
bool overflow = FALSE;
if (v0[precis + 1] < 0x8) {
Perl_warner(aTHX_ packWARN(WARN_PRINTF), "%" SVf, SVfARG(msg)); /* yes, this is reentrant */
}
- /* output mangled stuff ... */
- if (c == '\0')
- --q;
- eptr = p;
- elen = q - p;
-
- /* ... right here, because formatting flags should not apply */
- SvGROW(sv, SvCUR(sv) + elen + 1);
- p = SvEND(sv);
- Copy(eptr, p, elen, char);
- p += elen;
- *p = '\0';
- SvCUR_set(sv, p - SvPVX_const(sv));
+ /* mangled format: output the '%', then continue from the
+ * character following that */
+ sv_catpvn_nomg(sv, p, 1);
+ q = p + 1;
svix = osvix;
continue; /* not "break" */
}
}
+ /* append esignbuf, filler, zeros, eptr and dotstr to sv */
+
{
- STRLEN need, have;
+ STRLEN need, have, gap;
/* signed value that's wrapped? */
assert(elen <= ((~(STRLEN)0) >> 1));
- have = esignlen + zeros + elen;
- if (have < zeros)
+
+ /* Most of these length vars can range to any value if
+ * supplied with a hostile format and/or args. So check every
+ * addition for possible overflow. In reality some of these
+ * values are interdependent so these checks are slightly
+ * redundant. But its easier to be certain this way.
+ */
+
+ have = elen;
+
+ if (have >= (((STRLEN)~0) - zeros))
croak_memory_wrap();
+ have += zeros;
+
+ if (have >= (((STRLEN)~0) - esignlen))
+ croak_memory_wrap();
+ have += esignlen;
need = (have > width ? have : width);
gap = need - have;
- if (need >= (((STRLEN)~0) - SvCUR(sv) - dotstrlen - 1))
+ if (need >= (((STRLEN)~0) - dotstrlen))
croak_memory_wrap();
- SvGROW(sv, SvCUR(sv) + need + dotstrlen + 1);
- }
+ need += dotstrlen;
+
+ if (need >= (((STRLEN)~0) - (SvCUR(sv) + 1)))
+ croak_memory_wrap();
+ need += (SvCUR(sv) + 1);
+
+ SvGROW(sv, need);
p = SvEND(sv);
if (esignlen && fill == '0') {
SvUTF8_on(sv);
*p = '\0';
SvCUR_set(sv, p - SvPVX_const(sv));
+ }
if (vectorize) {
esignlen = 0;