11PHP's custom printf functions
22=============================
33
4- You all know libc's ``printf() `` and family. This chapter will detail those many clones PHP declares and use, what's
4+ You all know libc's ``printf() `` and family. This chapter will detail those many clones PHP declares and use, what's
55their goal, why use them and when to use them.
66
7- .. note :: Libc's documentation about ``printf()`` and friends
7+ .. note :: Libc's documentation about ``printf()`` and friends
88 `is located here <https://www.gnu.org/software/libc/manual/html_node/Formatted-Output-Functions.html >`_
9-
9+
1010You know that those functions are useful, but sometimes don't provide enough functionalities.
11- Also, you know that
12- `adding format strings <https://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html >`_ to ``printf() ``
11+ Also, you know that
12+ `adding format strings <https://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html >`_ to ``printf() ``
1313family is not trivial, not portable and security risky.
1414
1515PHP adds its own printf-like functions to replace libc ones and to be used by the internal developer.
16- They will mainly add new formats, play with :doc: `zend_string<zend_strings> ` instead of
16+ They will mainly add new formats, play with :doc: `zend_string<zend_strings> ` instead of
1717``char * ``, etc... Let's see them together.
1818
19- .. warning :: You must master your libc default ``printf()`` formats. Read
19+ .. warning :: You must master your libc default ``printf()`` formats. Read
2020 `their documentation here <http://www.cplusplus.com/reference/cstdio/printf/ >`_.
21-
22- .. note :: Those functions are added **to replace** libc ones, that means that if you use ``sprintf()`` f.e, that won't
23- lead to libc's ``sprintf() ``, but to PHP replacement. Except the traditionnal ``printf() ``, everything else
21+
22+ .. note :: Those functions are added **to replace** libc ones, that means that if you use ``sprintf()`` f.e, that won't
23+ lead to libc's ``sprintf() ``, but to PHP replacement. Except the traditional ``printf() ``, everything else
2424 is replaced.
2525
26- Traditionnal use
27- ****************
26+ Traditional use
27+ ***************
2828
29- First of all, you should not use ``sprintf() ``, as that function doesn't perform any check and allows many buffer
29+ First of all, you should not use ``sprintf() ``, as that function doesn't perform any check and allows many buffer
3030overflow errors. Please, try to avoid using it.
3131
3232.. warning :: Please try to avoid using ``sprintf()`` as much as possible.
@@ -36,12 +36,12 @@ Then, you have some choice.
3636You know your result buffer size
3737--------------------------------
3838
39- If you know your buffer size, ``snprintf() `` or ``slprintf() `` will do the job for you. There is a difference in what
39+ If you know your buffer size, ``snprintf() `` or ``slprintf() `` will do the job for you. There is a difference in what
4040those functions return, but not in what those functions do.
4141
42- They both print according to the formats passed, and they both terminate your buffer by a ``NUL `` byte *'\\ 0' * whatever
43- happens. However, ``snprintf() `` returns the number of characters that could have been used, whereas ``slprintf() ``
44- returns the number of characters that have effectively been used, thus enabling to detect too-small buffers and string
42+ They both print according to the formats passed, and they both terminate your buffer by a ``NUL `` byte *'\\ 0' * whatever
43+ happens. However, ``snprintf() `` returns the number of characters that could have been used, whereas ``slprintf() ``
44+ returns the number of characters that have effectively been used, thus enabling to detect too-small buffers and string
4545truncation. This, is not counting the final *'\\ 0' *.
4646
4747Here is an example so that you fully understand::
@@ -52,12 +52,12 @@ Here is an example so that you fully understand::
5252
5353 r = snprintf(foo, sizeof(foo), "%s", str);
5454 /* r = 11 here even if only 7 printable chars were written in foo */
55-
55+
5656 /* foo value is now 'H' 'e' 'l' 'l' 'o' ' ' 'w' '\0' */
5757
5858``snprintf() `` is not a good function to use, as it does not allows to detect an eventual string truncation.
59- As you can see from the example above, "Hello world\\ 0" doesn't fit in an eight-byte buffer, that's obvious, but
60- ``snprintf() `` still returns you 11, which is ``strlen("Hello world\0") ``. You have no way to detect that the string's
59+ As you can see from the example above, "Hello world\\ 0" doesn't fit in an eight-byte buffer, that's obvious, but
60+ ``snprintf() `` still returns you 11, which is ``strlen("Hello world\0") ``. You have no way to detect that the string's
6161got truncated.
6262
6363Here is ``slprintf() ``::
@@ -68,10 +68,10 @@ Here is ``slprintf()``::
6868
6969 r = slprintf(foo, sizeof(foo), "%s", str);
7070 /* r = 7 here , because 7 printable chars were written in foo */
71-
71+
7272 /* foo value is now 'H' 'e' 'l' 'l' 'o' ' ' 'w' '\0' */
7373
74- With ``slprintf() ``, the result buffer ``foo `` contains the exact same string, but the returned value is now 7. 7 is
74+ With ``slprintf() ``, the result buffer ``foo `` contains the exact same string, but the returned value is now 7. 7 is
7575less than the 11 chars from the *"Hello world" * string, thus you can detect that it got truncated::
7676
7777 if (slprintf(foo, sizeof(foo), "%s", str) < strlen(str)) {
@@ -83,7 +83,7 @@ Remember:
8383* Those two function always ``NUL `` terminate the string, truncation or not. Result strings are then safe C strings.
8484* Only ``slprintf() `` allows to detect a string truncation.
8585
86- Those two functions are defined in
86+ Those two functions are defined in
8787`main/snprintf.c <https://github.com/php/php-src/blob/648be8600ff89e1b0e4a4ad25cebad42b53bed6d/main/snprintf.c >`_
8888
8989You don't know your buffer size
@@ -95,106 +95,106 @@ Remember that **you'll have to free** the buffer by yourself !
9595Here is an example::
9696
9797 #include <time.h>
98-
98+
9999 char *result;
100100 int r;
101101
102102 time_t timestamp = time(NULL);
103103
104104 r = spprintf(&result, 0, "Here is the date: %s", asctime(localtime(×tamp)));
105-
105+
106106 /* now use result that contains something like "Here is the date: Thu Jun 15 19:12:51 2017\n" */
107-
107+
108108 efree(result);
109109
110- ``spprintf() `` returns the number of characters that've been printed into the result buffer, not counting the final
110+ ``spprintf() `` returns the number of characters that've been printed into the result buffer, not counting the final
111111*'\\ 0' *, hence you know the number of bytes that got allocated for you (minus one).
112112
113- Please, note that the allocation is done using ZendMM (request allocation), and should thus be used as part of a
113+ Please, note that the allocation is done using ZendMM (request allocation), and should thus be used as part of a
114114request and freed using ``efree() `` and not ``free() ``.
115115
116- .. note :: :doc:`The chapter about Zend Memory Manager <../../memory_management/zend_memory_manager>` (ZendMM) details
116+ .. note :: :doc:`The chapter about Zend Memory Manager <../../memory_management/zend_memory_manager>` (ZendMM) details
117117 how dynamic memory is allocated through PHP.
118118
119- If you want to limit the buffer size, you pass that limit as the second argument, if you pass *0 *, that means
119+ If you want to limit the buffer size, you pass that limit as the second argument, if you pass *0 *, that means
120120unlimited::
121121
122122 #include <time.h>
123-
123+
124124 char *result;
125125 int r;
126126
127127 time_t timestamp = time(NULL);
128128
129129 /* Do not print more than 10 bytes || allocate more than 11 bytes */
130130 r = spprintf(&result, 10, "Here is the date: %s", asctime(localtime(×tamp)));
131-
131+
132132 /* r == 10 here, and 11 bytes were allocated into result */
133-
133+
134134 efree(result);
135135
136- .. note :: Whenever possible, try not to use dynamic memory allocations. That impacts performances. If you got the
136+ .. note :: Whenever possible, try not to use dynamic memory allocations. That impacts performances. If you got the
137137 choice, go for the static stack allocated buffer.
138138
139- ``spprintf() `` is written in
139+ ``spprintf() `` is written in
140140`main/spprintf.c <https://github.com/php/php-src/blob/648be8600ff89e1b0e4a4ad25cebad42b53bed6d/main/spprintf.c >`_.
141141
142142What about printf() ?
143143---------------------
144144
145- If you need to ``printf() ``, aka to print formatted to the output stream, use ``php_printf() ``. That function
146- internally uses ``spprintf() ``, and thus performs a dynamic allocation that it frees itself just after having sent it
145+ If you need to ``printf() ``, aka to print formatted to the output stream, use ``php_printf() ``. That function
146+ internally uses ``spprintf() ``, and thus performs a dynamic allocation that it frees itself just after having sent it
147147to the SAPI output, aka stdout in case of CLI, or the output buffer (CGI buffer f.e) for other SAPIs.
148148
149149Special PHP printf formats
150150--------------------------
151151
152- Remember that PHP replaces most libc's ``printf() `` functions by its own of its own design. You can have a look at
153- the argument parsing API which is easy to understand `from reading the source
152+ Remember that PHP replaces most libc's ``printf() `` functions by its own of its own design. You can have a look at
153+ the argument parsing API which is easy to understand `from reading the source
154154<https://github.com/php/php-src/blob/509f5097ab0b578adc311c720afcea8de266aadd/main/spprintf.c#L203> `_.
155155
156156What that means is that arguments parsing algo has been fully rewritten, and may differ from what you're used to in libc.
157- F.e, the libc locale is note taken care of in most cases.
157+ F.e, the libc locale is not taken care of in most cases.
158158
159159Special formats may be used, like *"%I64" * to explicitely print to an int64, or *"%I32" *.
160160You can also use *"%Z" * to make a zval printable (according to PHP cast rules to string), that one is a great addition.
161161
162162The formatter will also recognize infinite numbers and print "INF", or "NAN" for not-a-number.
163163
164- If you make a mistake, and ask the formatter to print a ``NULL `` pointer, where libc will crash for sure, PHP will
164+ If you make a mistake, and ask the formatter to print a ``NULL `` pointer, where libc will crash for sure, PHP will
165165return *"(null)" * as a result string.
166166
167- .. note :: If in a printf you see a magic *"(null)"* appearing, that means you passed a NULL pointer to one of PHP
167+ .. note :: If in a printf you see a magic *"(null)"* appearing, that means you passed a NULL pointer to one of PHP
168168 printf family functions.
169169
170170
171171Printf()ing into zend_strings
172172-----------------------------
173173
174- As :doc: `zend_string <zend_strings >` are a very common structure into PHP source, you may need to ``printf() `` into a
175- ``zend_string `` instead of a traditionnal C ``char * ``. For this, use ``strpprintf() ``.
174+ As :doc: `zend_string <zend_strings >` are a very common structure into PHP source, you may need to ``printf() `` into a
175+ ``zend_string `` instead of a traditional C ``char * ``. For this, use ``strpprintf() ``.
176176
177- Tha API is ``zend_string *strpprintf(size_t max_len, const char *format, ...) `` that means that the ``zend_string `` is
178- returned to you, and not the number of printed chars as you may expect. You can limit that number though, using the
179- first parameter (pass 0 to mean infinite); and you must remember that the ``zend_string `` will be allocated using the
177+ The API is ``zend_string *strpprintf(size_t max_len, const char *format, ...) `` that means that the ``zend_string `` is
178+ returned to you, and not the number of printed chars as you may expect. You can limit that number though, using the
179+ first parameter (pass 0 to mean infinite); and you must remember that the ``zend_string `` will be allocated using the
180180Zend Memory Manager, and thus bound to the current request.
181181
182182Obviously, the format API is shared with the one seen above.
183183
184184Here is a quick example::
185185
186186 zend_string *result;
187-
187+
188188 result = strpprintf(0, "You are using PHP %s", PHP_VERSION);
189-
189+
190190 /* Do something with result */
191-
191+
192192 zend_string_release(result);
193193
194194A note on ``zend_ `` API
195195-----------------------
196196
197197You may meet ``zend_spprintf() ``, or ``zend_strpprintf() `` functions. Those are the exact same as the ones seen above.
198198
199- They are just here as part of the separation between the Zend Engine and PHP Core, a detail that is not important for
199+ They are just here as part of the separation between the Zend Engine and PHP Core, a detail that is not important for
200200us, as into the source code, everything gets mixed together.
0 commit comments