This API can't handle references, yet everyone keeps forgetting that it
can't and that you should DEREF upfront. Fix every type of this issue
once and for all by moving the reference handling to this Zend API.
Closes GH-18761.
This allows us to avoid a call to `zend_ini_str` which took 6% of the
profile on my i7-4790 for a call to `http_build_query`. Now we can just
grab the value from the globals.
In other files this can avoid some length recomputations.
Conversion of floating point to integer values is undefined if the
integral part of the float value cannot be represented by the integer
type. We need to cater to that explicitly (in a manner similar to
`zend_dval_to_lval_cap()`).
Closes GH-17689.
Besides that it is not needed, it is not proper C, and Clang warns that
"forward references to 'enum' types are a Microsoft extension"
(`-Wmicrosoft-enum-forward-reference`).
The behaviour is weird in the sense that the reference must get
unwrapped. What ended up happening is that when destroying the old
reference the sources list was not cleaned properly. We add handling for
that. Normally we would use use ZEND_TRY_ASSIGN_STRINGL but that doesn't
work here as it would keep the reference and change values through
references (see bug #26639).
Closes GH-16272.
* Pull zend_string* from INI directive
* Ensure that mail.force_extra_parameters INI directive does not have any nul bytes
* ext/standard: Make php_escape_shell_cmd() take a zend_string* instead of char*
This saves on an expensive strlen() computation
* Convert E_ERROR to ValueError in php_escape_shell_cmd()
* ext/standard: Make php_escape_shell_arg() take a zend_string* instead of char*
This saves on an expensive strlen() computation
* Convert E_ERROR to ValueError in php_escape_shell_arg()
Because the default characters are defined in the stub file, and the
stub file is UTF-8 (typically), the characters are encoded in the string
as UTF-8. When using a different character encoding, there is a mismatch
between what mb_trim expects and the UTF-8 encoded string it gets.
One way of solving this is by making the characters argument nullable,
which would mean that it always uses the internal code path that has the
unicode codepoints that are defaulted actually stored as codepoint
numbers instead of in a string.
Co-authored-by: @ranvis
When mbstring.encoding_translation=1, and PHP receives an (RFC1867)
form-based file upload, and the Content-Disposition HTTP header contains
a filename for the uploaded file, PHP will internally invoke mbstring
code to 1) try to auto-detect the text encoding of the filename, and if
that succeeds, 2) convert the filename to internal text encoding.
In such cases, the candidate text encodings which are considered during
"auto-detection" are those listed in the INI parameter
mbstring.http_input. Further, mbstring.http_input is one of the few
contexts where mbstring allows the magic string "pass" to appear in
place of an actual text encoding name.
Before mbstring's encoding auto-detection function was reimplemented,
the old implementation would never return "pass", even if "pass" was the
only candidate it was given to choose from. It is not clear if this was
intended by the original developers or not. This behavior was the result
of some rather subtle details of the implementation.
After mbstring's auto-detection function was reimplemented, if the new
implementation was given only one candidate to choose, and it was not
running in 'strict' mode, it would always return that candidate, even
if the candidate was the non-encoding "pass".
The upshot of all of this: Previously, if
mbstring.encoding_translation=1 and mbstring.http_input=pass, encoding
conversion of RFC1867 filenames would never be attempted. But after
the reimplementation, encoding 'conversion' would occur (uselessly).
Further, in December 2022, I reimplemented the relevant bit of
encoding conversion code. When doing this, I never bothered to
implement encoding/decoding routines for the non-encoding "pass",
because I thought that they would never be used. Well, in the one case
described above, those routines *would* have been used, had they
actually existed. Because they didn't exist, we get a nice NULL pointer
dereference and ensuing segfault instead.
Instead of 'fixing' this by adding encoding/decoding routines for the
non-encoding "pass", I have modified the function which the RFC1867
form-handling code invokes to auto-detect input encoding. This function
will never return "pass" now, just like the previous implementation.
Thanks to the GitHub user 'tstangner' for reporting this bug.
When investigating another bug reported by GitHub user 'tstangner',
I discovered that PHP segfaults when the INI parameter
zend.script_encoding is set to "pass". This bug dates back to
December 2022 (caused by yours truly in 953864661a).
If any PHP users in the wild were actually setting zend.script_encoding
to "pass" (which would be an utterly useless thing to do), I expect that
someone would have filed a bug report by now. The absence of such bug
reports is evidence that nobody is doing this.
Hence, it seems that the best fix is simply to disallow "pass" as a
choice for zend.script_encoding. The internal function
'php_mb_zend_encoding_list_parser' which I am modifying to accomplish
this has no other in-tree callers, aside from the 'exif' extension.
Further, exif only calls the function with a few hard-coded values, and
none of them are the string "pass", so this change will not have any
impact on exif.
While __php_mempcpy is only used by ext/standard/crypt_sha*, the
mempcpy "pattern" is used everywhere.
This commit removes __php_mempcpy, adds zend_mempcpy and transforms
open-coded parts into function calls.
Thanks to Maurício Fauth for finding and reporting this bug.
The bug was introduced in October 2022. It originally only affected
text encodings which do not have a fixed byte width per characters
and for which mbstring does not have an mblen_table. However, I recently
made another change to mbstring, such that mb_substr no longer relies
on the mblen_table even if one is available. Because of this change,
the bug earlier introduced in October 2022 now affected a greater
number of text encodings, including UTF-8.
For GB18030, it is not generally possible to identify character
boundaries without scanning through the entire string. Therefore,
implement mb_strcut using a similar strategy as the mblen_table based
implementation in mbstring.c. The difference is that for GB18030, we
need to look at two leading bytes to determine the byte length of a
multi-byte character.
The new implementation is 4-5x faster for short strings, and more than
10x faster for long strings. (Part of the reason why this new code has
such a great performance advantage is because it is replacing code
based on the older text conversion filters provided by libmbfl, which
were quite slow.)
The behavior is the same as before for valid GB18030 strings; for
some invalid strings, mb_strcut will choose different 'cut' points
as compared to before. (Clang's libFuzzer was used to compare the
old and new implementations, searching for test cases where they had
different behavior; no such cases were found.)