summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorAaron Crane <arc@cpan.org>2015-07-07 18:16:36 +0100
committerAaron Crane <arc@cpan.org>2015-07-15 14:26:06 +0100
commit46e58bd2391172ab5e4a73c29fb3313bebcf00bc (patch)
tree73a9c44d058a2d156c312fd951cfaf5b10569e27 /sv.c
parent638ca15aeec3bf86124489c8c913c5b42d4fee16 (diff)
downloadperl-46e58bd2391172ab5e4a73c29fb3313bebcf00bc.tar.gz
Document and ensure that sv_catpvf() does no argument ordering
sv_catpvf() and friends ultimately end up calling sv_vcatpvfn_flags() with a C-style va_list argument (rather than with an array of SV pointers). When the sprintf implementation in sv_vcatpvfn_flags() is called with a va_list it always ignores any attempt by the format string to reorder the arguments. This reasonable limitation is now documented, and the implementation throws an exception when it encounters this situation. Minimal tests for these exceptions have been added to XS::APItest.
Diffstat (limited to 'sv.c')
-rw-r--r--sv.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/sv.c b/sv.c
index e0f80d036a..210150b23d 100644
--- a/sv.c
+++ b/sv.c
@@ -9193,7 +9193,7 @@ Perl_newSVpvf_nocontext(const char *const pat, ...)
=for apidoc newSVpvf
Creates a new SV and initializes it with the string formatted like
-C<sprintf>.
+C<sv_catpvf>.
=cut
*/
@@ -10490,8 +10490,10 @@ Perl_sv_catpvf_mg_nocontext(SV *const sv, const char *const pat, ...)
/*
=for apidoc sv_catpvf
-Processes its arguments like C<sprintf> and appends the formatted
-output to an SV. If the appended data contains "wide" characters
+Processes its arguments like C<sv_catpvfn>, and appends the formatted
+output to an SV. As with C<sv_catpvfn> called with a non-null C-style
+variable argument list, argument reordering is not supported.
+If the appended data contains "wide" characters
(including, but not limited to, SVs with a UTF-8 PV formatted with %s,
and characters >255 formatted with %c), the original SV might get
upgraded to UTF-8. Handles 'get' magic, but not 'set' magic. See
@@ -10515,7 +10517,8 @@ Perl_sv_catpvf(pTHX_ SV *const sv, const char *const pat, ...)
/*
=for apidoc sv_vcatpvf
-Processes its arguments like C<vsprintf> and appends the formatted output
+Processes its arguments like C<sv_catpvfn> called with a non-null C-style
+variable argument list, and appends the formatted
to an SV. Does not handle 'set' magic. See C<sv_vcatpvf_mg>.
Usually used via its frontend C<sv_catpvf>.
@@ -10669,8 +10672,13 @@ S_F0convert(NV nv, char *const endbuf, STRLEN *const len)
=for apidoc sv_vcatpvfn_flags
Processes its arguments like C<vsprintf> and appends the formatted output
-to an SV. Uses an array of SVs if the C style variable argument list is
-missing (NULL). When running with taint checks enabled, indicates via
+to an SV. Uses an array of SVs if the C-style variable argument list is
+missing (NULL). Argument reordering (using format specifiers like C<%2$d>
+or C<%*2$d>) is supported only when using an array of SVs; using a C-style
+C<va_list> argument list with a format string that uses argument reordering
+will yield an exception.
+
+When running with taint checks enabled, indicates via
C<maybe_tainted> if results are untrustworthy (often due to the use of
locales).
@@ -11337,6 +11345,9 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
if ( (width = expect_number(&q)) ) {
if (*q == '$') {
+ if (args)
+ Perl_croak_nocontext(
+ "Cannot yet reorder sv_catpvfn() arguments from va_list");
++q;
efix = width;
used_explicit_ix = TRUE;
@@ -11381,9 +11392,12 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
if (*q == '*') {
q++;
if ( (ewix = expect_number(&q)) ) {
- if (*q++ == '$')
+ if (*q++ == '$') {
+ if (args)
+ Perl_croak_nocontext(
+ "Cannot yet reorder sv_catpvfn() arguments from va_list");
used_explicit_ix = TRUE;
- else
+ } else
goto unknown;
}
asterisk = TRUE;
@@ -11450,9 +11464,12 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p
if (*q == '*') {
q++;
if ( (epix = expect_number(&q)) ) {
- if (*q++ == '$')
+ if (*q++ == '$') {
+ if (args)
+ Perl_croak_nocontext(
+ "Cannot yet reorder sv_catpvfn() arguments from va_list");
used_explicit_ix = TRUE;
- else
+ } else
goto unknown;
}
if (args)