]> granicus.if.org Git - php/commitdiff
Fix #74170: locale information change after mime_content_type
authorSergei Turchanov <turchanov@farpost.com>
Thu, 29 Aug 2019 07:29:19 +0000 (17:29 +1000)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 20 Dec 2019 10:22:59 +0000 (11:22 +0100)
Some functions in libmagic (distributed with fileinfo extension) perform this sequence of calls:
func() {
setlocale(LC_TYPE, "C")
.. do some work ..
setlocale(LC_TYPE, "")
}

It effectively resets LC_TYPE if it that was set before the function call.

To avoid manipulations with current locale at all, the problematic functions
were modified to use locale-independent functions.

NEWS
ext/fileinfo/libmagic/funcs.c
ext/fileinfo/libmagic/readcdf.c
ext/fileinfo/libmagic/softmagic.c
ext/fileinfo/tests/bug74170.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 12f4edc672fb93e766296ddca089f190ea41d820..b178b9ddb8153a9b1348be481a17c8fccf2c039e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,10 @@ PHP                                                                        NEWS
 - CURL:
   . Implemented FR #77711 (CURLFile should support UNICODE filenames). (cmb)
 
+- Fileinfo:
+  . Fixed bug #74170 (locale information change after mime_content_type).
+    (Sergei Turchanov)
+
 - GD:
   . Fixed bug #78923 (Artifacts when convoluting image with transparency).
     (wilson chen)
index 8377bcc6a5c1e9d55ce04ba975047068176d38f1..027af0e5166adc8c43ea855b74b35a223b0c0815 100644 (file)
@@ -477,11 +477,9 @@ file_replace(struct magic_set *ms, const char *pat, const char *rep)
        zend_string *repl;
        size_t rep_cnt = 0;
 
-       (void)setlocale(LC_CTYPE, "C");
-
        opts |= PCRE2_MULTILINE;
        convert_libmagic_pattern(&patt, (char*)pat, strlen(pat), opts);
-       if ((pce = pcre_get_compiled_regex_cache(Z_STR(patt))) == NULL) {
+       if ((pce = pcre_get_compiled_regex_cache_ex(Z_STR(patt), 0)) == NULL) {
                zval_ptr_dtor(&patt);
                rep_cnt = -1;
                goto out;
@@ -503,7 +501,6 @@ file_replace(struct magic_set *ms, const char *pat, const char *rep)
        zend_string_release_ex(res, 0);
 
 out:
-       (void)setlocale(LC_CTYPE, "");
        return rep_cnt;
 }
 
index 4a3ddc60ffa42d0c9cf966164c998dac9f1fa125..6e93db1ec383a1d224425cf3580a7e2f016bb86f 100644 (file)
@@ -116,14 +116,24 @@ cdf_app_to_mime(const char *vbuf, const struct nv *nv)
 {
        size_t i;
        const char *rv = NULL;
+       char *vbuf_lower;
 
-       (void)setlocale(LC_CTYPE, "C");
-       for (i = 0; nv[i].pattern != NULL; i++)
-               if (strcasestr(vbuf, nv[i].pattern) != NULL) {
+       vbuf_lower = zend_str_tolower_dup(vbuf, strlen(vbuf));
+       for (i = 0; nv[i].pattern != NULL; i++) {
+               char *pattern_lower;
+               int found;
+
+               pattern_lower = zend_str_tolower_dup(nv[i].pattern, strlen(nv[i].pattern));
+               found = (strstr(vbuf_lower, pattern_lower) != NULL);
+               efree(pattern_lower);
+
+               if (found) {
                        rv = nv[i].mime;
                        break;
                }
-       (void)setlocale(LC_CTYPE, "");
+       }
+
+       efree(vbuf_lower);
        return rv;
 }
 
index d37ce0d255c5397144aa174cfa223a0614d6a28b..10f9aaaaa3c30fdbf3f1888c96b199a9b9cb6ed2 100644 (file)
@@ -422,27 +422,25 @@ flush:
 private int
 check_fmt(struct magic_set *ms, const char *fmt)
 {
-       pcre2_code *pce;
-       uint32_t re_options, capture_count;
+       pcre_cache_entry *pce;
        int rv = -1;
        zend_string *pattern;
 
        if (strchr(fmt, '%') == NULL)
                return 0;
 
-       (void)setlocale(LC_CTYPE, "C");
        pattern = zend_string_init("~%[-0-9\\.]*s~", sizeof("~%[-0-9\\.]*s~") - 1, 0);
-       if ((pce = pcre_get_compiled_regex(pattern, &capture_count, &re_options)) == NULL) {
+       if ((pce = pcre_get_compiled_regex_cache_ex(pattern, 0)) == NULL) {
                rv = -1;
        } else {
-               pcre2_match_data *match_data = php_pcre_create_match_data(capture_count, pce);
+               pcre2_code *re = php_pcre_pce_re(pce);
+               pcre2_match_data *match_data = php_pcre_create_match_data(0, re);
                if (match_data) {
-                       rv = pcre2_match(pce, (PCRE2_SPTR)fmt, strlen(fmt), 0, re_options, match_data, php_pcre_mctx()) > 0;
+                       rv = pcre2_match(re, (PCRE2_SPTR)fmt, strlen(fmt), 0, 0, match_data, php_pcre_mctx()) > 0;
                        php_pcre_free_match_data(match_data);
                }
        }
-       zend_string_release_ex(pattern, 0);
-       (void)setlocale(LC_CTYPE, "");
+       zend_string_release(pattern);
        return rv;
 }
 
diff --git a/ext/fileinfo/tests/bug74170.phpt b/ext/fileinfo/tests/bug74170.phpt
new file mode 100644 (file)
index 0000000..9e3cbd9
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Bug #74170 locale information change after mime_content_type
+--SKIPIF--
+<?php
+if (!class_exists('finfo'))
+       die('skip no fileinfo extension');
+if (!extension_loaded('intl'))
+       die('skip intl extension not enabled');
+if (setlocale(LC_CTYPE, 'ru_RU.koi8r') === false)
+       die('skip ru_RU.koi8r locale is not available');
+?>
+--FILE--
+<?php
+var_dump(setlocale(LC_CTYPE, 'ru_RU.koi8r'));
+var_dump(nl_langinfo(CODESET));
+var_dump(mime_content_type(__DIR__ . '/resources/test.ppt'));
+var_dump(nl_langinfo(CODESET));
+--EXPECT--
+string(11) "ru_RU.koi8r"
+string(6) "KOI8-R"
+string(29) "application/vnd.ms-powerpoint"
+string(6) "KOI8-R"