This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Perl_sv_vcatpvfn_flags: set locale at most once
authorDavid Mitchell <davem@iabyn.com>
Sat, 20 May 2017 14:51:31 +0000 (15:51 +0100)
committerDavid Mitchell <davem@iabyn.com>
Wed, 7 Jun 2017 08:11:03 +0000 (09:11 +0100)
commitbc37e90eb33540fa29c5be8911e2d2e25dc669df
tree1d16177dd35f6361e405ae4f49ec89b1c93ec7e3
parent9cc0d8397eaa8e121e0d8f44e86a19132c12a899
Perl_sv_vcatpvfn_flags: set locale at most once

Calls to external snprintf-ish functions or that directly access
PL_numeric_radix_sv are supposed to sandwich this access within

    STORE_LC_NUMERIC_SET_TO_NEEDED();
    ....
    RESTORE_LC_NUMERIC();

The code in Perl_sv_vcatpvfn_flags() seems to have gotten a bit confused
as to whether its trying to only set STORE_LC_NUMERIC_SET_TO_NEEDED()
once, then handle one of more %[aefh] format elements, then only
restore on exit. There is code at the end of the function which says:

    RESTORE_LC_NUMERIC();   /* Done outside loop, so don't have to save/restore
                               each iteration. */

but in practice various places within this function (and its helper
function S_format_hexfp() inconsistently repeatedly do
STORE_LC_NUMERIC_SET_TO_NEEDED(); and sometime do RESTORE_LC_NUMERIC().

This commit changes it so that STORE_LC_NUMERIC_SET_TO_NEEDED() is called
at most once, the first time a % format involving a radix point is
encountered, and does RESTORE_LC_NUMERIC(); exactly once at the end of the
function.

Note that while calling STORE_LC_NUMERIC_SET_TO_NEEDED() multiple times
is harmless, its quite expensive, as each time it has to check whether
it's in the scope of 'use locale'. RESTORE_LC_NUMERIC() is cheap if
STORE_LC_NUMERIC_SET_TO_NEEDED() earlier determined that there was nothing
to do.
sv.c