From 1d7b6970f20a059c501e68927c9fb874bdb226bc Mon Sep 17 00:00:00 2001 From: Yasuo Ohgaki Date: Sat, 27 Jul 2013 05:46:11 +0900 Subject: [PATCH 1/9] Fixed bug #65336 --- NEWS | 4 ++++ ext/pgsql/pgsql.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 8f7bbd8c7cf..97c25dfc04c 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,10 @@ PHP NEWS . Fixed bug #65028 (Phar::buildFromDirectory creates corrupt archives for some specific contents). (Stas) +- Pgsql: + . Fixed bug #65336 (pg_escape_literal/identifier() scilently returns false). + (Yasuo) + ?? ??? 2013, PHP 5.4.18 - Core: diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 1b302668afc..796d8835c7f 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -4294,12 +4294,13 @@ static void php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAMETERS, int escape_l } if (pgsql_link == NULL && id == -1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot get default pgsql link"); RETURN_FALSE; } ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); if (pgsql == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot get default pgsql link"); + php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot get pgsql link"); RETURN_FALSE; } #ifdef HAVE_PQESCAPELITERAL From 02409669e4201ec2cb90f1e6df316dddbe04561e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 31 Jul 2013 03:01:19 +0400 Subject: [PATCH 2/9] Added support for glob symbols in blacklist entries (?, *, **) --- NEWS | 2 + ext/opcache/tests/blacklist.inc | 3 + ext/opcache/tests/blacklist.phpt | 16 ++- ext/opcache/tests/opcache-2.blacklist | 5 + ext/opcache/zend_accelerator_blacklist.c | 140 +++++++++++++++++------ 5 files changed, 129 insertions(+), 37 deletions(-) create mode 100644 ext/opcache/tests/blacklist.inc diff --git a/NEWS b/NEWS index d21126d45a1..60b2760b390 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ PHP NEWS limited case). (Arpad) - OPcahce: + . Added support for glob symbols in blacklist entries (?, *, **). + (Terry Elison, Dmitry) . Fixed bug #65338 (Enabling both php_opcache and php_wincache AVs on shutdown). (Dmitry) diff --git a/ext/opcache/tests/blacklist.inc b/ext/opcache/tests/blacklist.inc new file mode 100644 index 00000000000..a9db7514194 --- /dev/null +++ b/ext/opcache/tests/blacklist.inc @@ -0,0 +1,3 @@ + diff --git a/ext/opcache/tests/blacklist.phpt b/ext/opcache/tests/blacklist.phpt index f4a34723ada..57e4c306dd7 100644 --- a/ext/opcache/tests/blacklist.phpt +++ b/ext/opcache/tests/blacklist.phpt @@ -9,7 +9,13 @@ opcache.blacklist_filename={PWD}/opcache-*.blacklist --FILE-- --EXPECT-- Array @@ -17,4 +23,10 @@ Array [0] => /path/to/foo [1] => /path/to/foo2 [2] => /path/to/bar -) \ No newline at end of file + [3] => __DIR__/blacklist.inc + [4] => __DIR__/current.php + [5] => /tmp/path/?nocache.inc + [6] => /tmp/path/*/somedir +) +ok +1 diff --git a/ext/opcache/tests/opcache-2.blacklist b/ext/opcache/tests/opcache-2.blacklist index 4f6580a773b..575d9fab304 100644 --- a/ext/opcache/tests/opcache-2.blacklist +++ b/ext/opcache/tests/opcache-2.blacklist @@ -1 +1,6 @@ /path/to/bar +; wildcard and relative entires +blacklist.inc +./current.php +/tmp/path/?nocache.inc +/tmp/path/*/somedir diff --git a/ext/opcache/zend_accelerator_blacklist.c b/ext/opcache/zend_accelerator_blacklist.c index b09d0e54c3b..b11d41e1ecb 100644 --- a/ext/opcache/zend_accelerator_blacklist.c +++ b/ext/opcache/zend_accelerator_blacklist.c @@ -86,9 +86,9 @@ static void blacklist_report_regexp_error(regex_t *comp_regex, int reg_err) static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) { - char *regexp; - int i, j, clen, reg_err, end = 0, rlen = 6; + int i, reg_err; zend_regexp_list **regexp_list_it, *it; + char regexp[12*1024], *p, *end, *c, *backtrack = NULL; if (blacklist->pos == 0) { /* we have no blacklist to talk about */ @@ -96,36 +96,91 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) } regexp_list_it = &(blacklist->regexp_list); - for (i = 0; i < blacklist->pos; i++) { - rlen += blacklist->entries[i].path_length * 2 + 2; - /* don't create a regexp buffer bigger than 12K)*/ - if ((i + 1 == blacklist->pos) || ((rlen + blacklist->entries[i + 1].path_length * 2 + 2) > (12 * 1024))) { - regexp = (char *)malloc(rlen); - if (!regexp) { - zend_accel_error(ACCEL_LOG_ERROR, "malloc() failed\n"); - return; - } - regexp[0] = '^'; - regexp[1] = '('; + regexp[0] = '^'; + regexp[1] = '('; + p = regexp + 2; + end = regexp + sizeof(regexp) - sizeof("[^\\\\]*)\0"); - clen = 2; - for (j = end; j <= i; j++) { - - int c; - if (j != end) { - regexp[clen++] = '|'; - } - /* copy mangled filename */ - for (c = 0; c < blacklist->entries[j].path_length; c++) { - if (strchr("^.[]$()|*+?{}\\", blacklist->entries[j].path[c])) { - regexp[clen++] = '\\'; - } - regexp[clen++] = blacklist->entries[j].path[c]; + for (i = 0; i < blacklist->pos; ) { + c = blacklist->entries[i].path; + if (p + blacklist->entries[i].path_length < end) { + while (*c && p < end) { + switch (*c) { + case '?': + c++; +#ifdef ZEND_WIN32 + p[0] = '['; /* * => [^\\] on Win32 */ + p[1] = '^'; + p[2] = '\\'; + p[3] = '\\'; + p[4] = ']'; + p += 5; +#else + p[0] = '['; /* * => [^/] on *nix */ + p[1] = '^'; + p[2] = '/'; + p[3] = ']'; + p += 4; +#endif + break; + case '*': + c++; + if (*c == '*') { + c++; + p[0] = '.'; /* ** => .* */ + p[1] = '*'; + p += 2; + } else { +#ifdef ZEND_WIN32 + p[0] = '['; /* * => [^\\]* on Win32 */ + p[1] = '^'; + p[2] = '\\'; + p[3] = '\\'; + p[4] = ']'; + p[5] = '*'; + p += 6; +#else + p[0] = '['; /* * => [^/]* on *nix */ + p[1] = '^'; + p[2] = '/'; + p[3] = ']'; + p[4] = '*'; + p += 5; +#endif + } + break; + case '^': + case '.': + case '[': + case ']': + case '$': + case '(': + case ')': + case '|': + case '+': + case '{': + case '}': + case '\\': + *p++ = '\\'; + /* break missing intentionally */ + default: + *p++ = *c++; } } - regexp[clen++] = ')'; - regexp[clen] = '\0'; + } + + if (*c || i == blacklist->pos - 1) { + if (*c) { + if (!backtrack) { + zend_accel_error(ACCEL_LOG_ERROR, "Too long blacklist entry\n"); + } + p = backtrack; + } else { + i++; + } + *p++ = ')'; + *p++ = '\0'; it = (zend_regexp_list*)malloc(sizeof(zend_regexp_list)); if (!it) { @@ -138,11 +193,13 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist) blacklist_report_regexp_error(&it->comp_regex, reg_err); } /* prepare for the next iteration */ - free(regexp); - end = i + 1; - rlen = 6; + p = regexp + 2; *regexp_list_it = it; regexp_list_it = &it->next; + } else { + backtrack = p; + *p++ = '|'; + i++; } } } @@ -182,9 +239,9 @@ static void zend_accel_blacklist_loadone(zend_blacklist *blacklist, char *filena void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) #endif { - char buf[MAXPATHLEN + 1], real_path[MAXPATHLEN + 1]; + char buf[MAXPATHLEN + 1], real_path[MAXPATHLEN + 1], *blacklist_path = NULL; FILE *fp; - int path_length; + int path_length, blacklist_path_length; TSRMLS_FETCH(); if ((fp = fopen(filename, "r")) == NULL) { @@ -194,6 +251,11 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) zend_accel_error(ACCEL_LOG_DEBUG,"Loading blacklist file: '%s'", filename); + if (VCWD_REALPATH(filename, buf)) { + blacklist_path_length = zend_dirname(buf, strlen(buf)); + blacklist_path = zend_strndup(buf, blacklist_path_length); + } + memset(buf, 0, sizeof(buf)); memset(real_path, 0, sizeof(real_path)); @@ -230,7 +292,11 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) } path_dup = zend_strndup(pbuf, path_length); - expand_filepath(path_dup, real_path TSRMLS_CC); + if (blacklist_path) { + expand_filepath_ex(path_dup, real_path, blacklist_path, blacklist_path_length TSRMLS_CC); + } else { + expand_filepath(path_dup, real_path TSRMLS_CC); + } path_length = strlen(real_path); free(path_dup); @@ -247,6 +313,9 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) blacklist->pos++; } fclose(fp); + if (blacklist_path) { + free(blacklist_path); + } zend_accel_blacklist_update_regexp(blacklist); } @@ -254,7 +323,8 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) { glob_t globbuf; - int ret, i; + int ret; + unsigned int i; memset(&globbuf, 0, sizeof(glob_t)); From c10d7e1afc63f0a0eaadb115560cc3ca626eb245 Mon Sep 17 00:00:00 2001 From: Rui Hirokawa Date: Wed, 31 Jul 2013 08:17:15 +0900 Subject: [PATCH 3/9] MFH: fixed #65045: mb_convert_encoding breaks well-formed character. --- ext/mbstring/libmbfl/filters/mbfilter_utf8.c | 192 ++++++++--------- ext/mbstring/libmbfl/filters/mbfilter_utf8.h | 1 + .../libmbfl/filters/mbfilter_utf8_mobile.c | 199 ++++++++---------- .../tests/illformed_utf_sequences.phpt | 18 +- 4 files changed, 197 insertions(+), 213 deletions(-) diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c index fcee610533d..55397003437 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c @@ -79,7 +79,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_wchar = { mbfl_filt_conv_common_ctor, mbfl_filt_conv_common_dtor, mbfl_filt_conv_utf8_wchar, - mbfl_filt_conv_common_flush + mbfl_filt_conv_utf8_wchar_flush }; const struct mbfl_convert_vtbl vtbl_wchar_utf8 = { @@ -93,6 +93,17 @@ const struct mbfl_convert_vtbl vtbl_wchar_utf8 = { #define CK(statement) do { if ((statement) < 0) return (-1); } while (0) +int mbfl_filt_put_invalid_char(int c, mbfl_convert_filter *filter) +{ + int w; + w = c & MBFL_WCSGROUP_MASK; + w |= MBFL_WCSGROUP_THROUGH; + filter->status = 0; + filter->cache = 0; + CK((*filter->output_function)(w, filter->data)); +} + + /* * UTF-8 => wchar */ @@ -100,111 +111,104 @@ int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter) { int s, c1, w = 0, flag = 0; - if (c < 0x80) { - if (filter->status != 0) { - w = (filter->cache & MBFL_WCSGROUP_MASK) | MBFL_WCSGROUP_THROUGH; - CK((*filter->output_function)(w, filter->data)); - filter->status = 0; - filter->cache = 0; - } - if (c >= 0) { +retry: + switch (filter->status & 0xff) { + case 0x00: + if (c < 0x80) { CK((*filter->output_function)(c, filter->data)); - } - } else if (c < 0xc0) { - int status = filter->status & 0xff; - switch (status) { - case 0x10: /* 2byte code 2nd char: 0x80-0xbf */ - case 0x21: /* 3byte code 3rd char: 0x80-0xbf */ - case 0x32: /* 4byte code 4th char: 0x80-0xbf */ - filter->status = 0; - s = filter->cache | (c & 0x3f); - filter->cache = 0; - if ((status == 0x10 && s >= 0x80) || - (status == 0x21 && s >= 0x800 && (s < 0xd800 || s > 0xdfff)) || - (status == 0x32 && s >= 0x10000 && s < 0x110000)) { - CK((*filter->output_function)(s, filter->data)); - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */ - s = filter->cache | ((c & 0x3f) << 6); - c1 = (s >> 12) & 0xf; - if ((c1 == 0x0 && c >= 0xa0) || - (c1 == 0xd && c < 0xa0) || - (c1 > 0x0 && c1 != 0xd)) { - filter->cache = s; - filter->status++; - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - case 0x31: /* 4byte code 3rd char: 0x80-0xbf */ - filter->cache |= ((c & 0x3f) << 6); - filter->status++; - break; - case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */ - s = filter->cache | ((c & 0x3f) << 12); - c1 = (s >> 18) & 0x7; - if ((c1 == 0x0 && c >= 0x90) || - (c1 > 0x0 && c1 < 0x4) || - (c1 == 0x4 && c < 0x90)) { - filter->cache = s; - filter->status++; - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - default: - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - break; - } - } else if (c < 0xc2) { /* invalid: 0xc0,0xc1 */ - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } else if (c < 0xe0) { /* 2byte code first char: 0xc2-0xdf */ - if (filter->status == 0x0) { + } else if (c >= 0xc2 && c <= 0xdf) { /* 2byte code first char: 0xc2-0xdf */ filter->status = 0x10; - filter->cache = (c & 0x1f) << 6; - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - } else if (c < 0xf0) { /* 3byte code first char: 0xe0-0xef */ - if (filter->status == 0x0) { + filter->cache = c & 0x1f; + } else if (c >= 0xe0 && c <= 0xef) { /* 3byte code first char: 0xe0-0xef */ filter->status = 0x20; - filter->cache = (c & 0xf) << 12; - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - } else if (c < 0xf5) { /* 4byte code first char: 0xf0-0xf4 */ - if (filter->status == 0x0) { + filter->cache = c & 0xf; + } else if (c >= 0xf0 && c <= 0xf4) { /* 3byte code first char: 0xf0-0xf4 */ filter->status = 0x30; - filter->cache = (c & 0x7) << 18; + filter->cache = c & 0x7; } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; + mbfl_filt_put_invalid_char(c, filter); } - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - - if (flag) { - w |= MBFL_WCSGROUP_THROUGH; - CK((*filter->output_function)(w, filter->data)); + break; + case 0x10: /* 2byte code 2nd char: 0x80-0xbf */ + case 0x21: /* 3byte code 3rd char: 0x80-0xbf */ + case 0x32: /* 4byte code 4th char: 0x80-0xbf */ filter->status = 0; - filter->cache = 0; + if (c >= 0x80 && c <= 0xbf) { + s = (filter->cache<<6) | (c & 0x3f); + filter->cache = 0; + CK((*filter->output_function)(s, filter->data)); + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */ + s = (filter->cache<<6) | (c & 0x3f); + c1 = filter->cache & 0xf; + + if ((c >= 0x80 && c <= 0xbf) && + ((c1 == 0x0 && c >= 0xa0) || + (c1 == 0xd && c < 0xa0) || + (c1 > 0x0 && c1 != 0xd))) { + filter->cache = s; + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */ + s = (filter->cache<<6) | (c & 0x3f); + c1 = filter->cache & 0x7; + + if ((c >= 0x80 && c <= 0xbf) && + ((c1 == 0x0 && c >= 0x90) || + (c1 == 0x4 && c < 0x90) || + (c1 > 0x0 && c1 != 0x4))) { + filter->cache = s; + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x31: /* 4byte code 3rd char: 0x80-0xbf */ + if (c >= 0x80 && c <= 0xbf) { + filter->cache = (filter->cache<<6) | (c & 0x3f); + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + default: + filter->status = 0; + break; } return c; } +int mbfl_filt_conv_utf8_wchar_flush(mbfl_convert_filter *filter) +{ + int status, cache; + + status = filter->status; + cache = filter->cache; + + filter->status = 0; + filter->cache = 0; + + if (status != 0) { + mbfl_filt_put_invalid_char(cache, filter); + } + + if (filter->flush_function != NULL) { + (*filter->flush_function)(filter->data); + } + return 0; +} + /* * wchar => UTF-8 */ diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8.h b/ext/mbstring/libmbfl/filters/mbfilter_utf8.h index 07bf655022a..970ace6462a 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_utf8.h +++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8.h @@ -37,5 +37,6 @@ extern const struct mbfl_convert_vtbl vtbl_wchar_utf8; int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter); int mbfl_filt_conv_wchar_utf8(int c, mbfl_convert_filter *filter); +int mbfl_filt_conv_utf8_wchar_flush(mbfl_convert_filter *filter); #endif /* MBFL_MBFILTER_UTF8_H */ diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c b/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c index 62feca40b6f..f9b643c17de 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c @@ -37,6 +37,7 @@ #include "mbfilter_sjis_mobile.h" extern int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter); +extern int mbfl_filt_conv_utf8_wchar_flush(mbfl_convert_filter *filter); extern const unsigned char mblen_table_utf8[]; @@ -115,7 +116,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_docomo_wchar = { mbfl_filt_conv_common_ctor, mbfl_filt_conv_common_dtor, mbfl_filt_conv_utf8_mobile_wchar, - mbfl_filt_conv_common_flush + mbfl_filt_conv_utf8_wchar_flush }; const struct mbfl_convert_vtbl vtbl_wchar_utf8_docomo = { @@ -133,7 +134,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_kddi_a_wchar = { mbfl_filt_conv_common_ctor, mbfl_filt_conv_common_dtor, mbfl_filt_conv_utf8_mobile_wchar, - mbfl_filt_conv_common_flush + mbfl_filt_conv_utf8_wchar_flush }; const struct mbfl_convert_vtbl vtbl_wchar_utf8_kddi_a = { @@ -151,7 +152,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_kddi_b_wchar = { mbfl_filt_conv_common_ctor, mbfl_filt_conv_common_dtor, mbfl_filt_conv_utf8_mobile_wchar, - mbfl_filt_conv_common_flush + mbfl_filt_conv_utf8_wchar_flush }; const struct mbfl_convert_vtbl vtbl_wchar_utf8_kddi_b = { @@ -169,7 +170,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_sb_wchar = { mbfl_filt_conv_common_ctor, mbfl_filt_conv_common_dtor, mbfl_filt_conv_utf8_mobile_wchar, - mbfl_filt_conv_common_flush + mbfl_filt_conv_utf8_wchar_flush }; const struct mbfl_convert_vtbl vtbl_wchar_utf8_sb = { @@ -191,119 +192,97 @@ int mbfl_filt_conv_utf8_mobile_wchar(int c, mbfl_convert_filter *filter) int s, w = 0, flag = 0; int s1 = 0, c1 = 0, snd = 0; - if (c < 0x80) { - if (c >= 0) { +retry: + switch (filter->status & 0xff) { + case 0x00: + if (c < 0x80) { CK((*filter->output_function)(c, filter->data)); - } - filter->status = 0; - } else if (c < 0xc0) { - int status = filter->status & 0xff; - switch (status) { - case 0x10: /* 2byte code 2nd char: 0x80-0xbf */ - case 0x21: /* 3byte code 3rd char: 0x80-0xbf */ - case 0x32: /* 4byte code 4th char: 0x80-0xbf */ - filter->status = 0; - s = filter->cache | (c & 0x3f); - filter->cache = 0; - if ((status == 0x10 && s >= 0x80) || - (status == 0x21 && s >= 0x800 && (s < 0xd800 || s > 0xdfff)) || - (status == 0x32 && s >= 0x10000 && s < 0x110000)) { - - if (filter->from->no_encoding == mbfl_no_encoding_utf8_docomo && - mbfilter_conv_r_map_tbl(s, &s1, mbfl_docomo2uni_pua, 4) > 0) { - s = mbfilter_sjis_emoji_docomo2unicode(s1, &snd); - } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_a && - mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua, 7) > 0) { - s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd); - } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_b && - mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua_b, 8) > 0) { - s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd); - } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_sb && - mbfilter_conv_r_map_tbl(s, &s1, mbfl_sb2uni_pua, 6) > 0) { - s = mbfilter_sjis_emoji_sb2unicode(s1, &snd); - } - - if (snd > 0) { - CK((*filter->output_function)(snd, filter->data)); - } - CK((*filter->output_function)(s, filter->data)); - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */ - s = filter->cache | ((c & 0x3f) << 6); - c1 = (s >> 12) & 0xf; - if ((c1 == 0x0 && c >= 0xa0) || - (c1 == 0xd && c < 0xa0) || - (c1 > 0x0 && c1 != 0xd)) { - filter->cache = s; - filter->status++; - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - case 0x31: /* 4byte code 3rd char: 0x80-0xbf */ - filter->cache |= ((c & 0x3f) << 6); - filter->status++; - break; - case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */ - s = filter->cache | ((c & 0x3f) << 12); - c1 = (s >> 18) & 0x7; - if ((c1 == 0x0 && c >= 0x90) || - (c1 > 0x0 && c1 < 0x4) || - (c1 == 0x4 && c < 0x90)) { - filter->cache = s; - filter->status++; - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - default: - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - break; - } - } else if (c < 0xc2) { /* invalid: 0xc0,0xc1 */ - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } else if (c < 0xe0) { /* 2byte code first char: 0xc2-0xdf */ - if (filter->status == 0x0) { + } else if (c >= 0xc2 && c <= 0xdf) { /* 2byte code first char: 0xc2-0xdf */ filter->status = 0x10; - filter->cache = (c & 0x1f) << 6; - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - } else if (c < 0xf0) { /* 3byte code first char: 0xe0-0xef */ - if (filter->status == 0x0) { + filter->cache = c & 0x1f; + } else if (c >= 0xe0 && c <= 0xef) { /* 3byte code first char: 0xe0-0xef */ filter->status = 0x20; - filter->cache = (c & 0xf) << 12; - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - } else if (c < 0xf5) { /* 4byte code first char: 0xf0-0xf4 */ - if (filter->status == 0x0) { + filter->cache = c & 0xf; + } else if (c >= 0xf0 && c <= 0xf4) { /* 3byte code first char: 0xf0-0xf4 */ filter->status = 0x30; - filter->cache = (c & 0x7) << 18; + filter->cache = c & 0x7; } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; + mbfl_filt_put_invalid_char(c, filter); } - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - - if (flag) { - w |= MBFL_WCSGROUP_THROUGH; - CK((*filter->output_function)(w, filter->data)); + break; + case 0x10: /* 2byte code 2nd char: 0x80-0xbf */ + case 0x21: /* 3byte code 3rd char: 0x80-0xbf */ + case 0x32: /* 4byte code 4th char: 0x80-0xbf */ filter->status = 0; - filter->cache = 0; + if (c >= 0x80 && c <= 0xbf) { + s = (filter->cache<<6) | (c & 0x3f); + filter->cache = 0; + + if (filter->from->no_encoding == mbfl_no_encoding_utf8_docomo && + mbfilter_conv_r_map_tbl(s, &s1, mbfl_docomo2uni_pua, 4) > 0) { + s = mbfilter_sjis_emoji_docomo2unicode(s1, &snd); + } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_a && + mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua, 7) > 0) { + s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd); + } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_b && + mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua_b, 8) > 0) { + s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd); + } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_sb && + mbfilter_conv_r_map_tbl(s, &s1, mbfl_sb2uni_pua, 6) > 0) { + s = mbfilter_sjis_emoji_sb2unicode(s1, &snd); + } + + if (snd > 0) { + CK((*filter->output_function)(snd, filter->data)); + } + CK((*filter->output_function)(s, filter->data)); + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */ + s = (filter->cache<<6) | (c & 0x3f); + c1 = filter->cache & 0xf; + + if ((c >= 0x80 && c <= 0xbf) && + ((c1 == 0x0 && c >= 0xa0) || + (c1 == 0xd && c < 0xa0) || + (c1 > 0x0 && c1 != 0xd))) { + filter->cache = s; + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */ + s = (filter->cache<<6) | (c & 0x3f); + c1 = filter->cache & 0x7; + + if ((c >= 0x80 && c <= 0xbf) && + ((c1 == 0x0 && c >= 0x90) || + (c1 == 0x4 && c < 0x90) || + (c1 > 0x0 && c1 != 0x4))) { + filter->cache = s; + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x31: /* 4byte code 3rd char: 0x80-0xbf */ + if (c >= 0x80 && c <= 0xbf) { + filter->cache = (filter->cache<<6) | (c & 0x3f); + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + default: + filter->status = 0; + break; } return c; diff --git a/ext/mbstring/tests/illformed_utf_sequences.phpt b/ext/mbstring/tests/illformed_utf_sequences.phpt index b5b9d94db84..378b956d681 100644 --- a/ext/mbstring/tests/illformed_utf_sequences.phpt +++ b/ext/mbstring/tests/illformed_utf_sequences.phpt @@ -25,28 +25,28 @@ var_dump(chk_enc("\x31\x32\x33", 0)); var_dump(chk_enc("\x41\x42\x43", 0)); var_dump(chk_enc("\xc0\xb1\xc0\xb2\xc0\xb3", 6)); var_dump(chk_enc("\xc1\x81\xc1\x82\xc1\x83", 6)); -var_dump(chk_enc("\xe0\x80\xb1\xe0\x80\xb2\xe0\x80\xb3", 6)); -var_dump(chk_enc("\xe0\x81\x81\xe0\x81\x82\xe0\x81\x83", 6)); -var_dump(chk_enc("\xf0\x80\x80\xb1\xf0\x80\x80\xb2\xf0\x80\x80\xb3", 9)); -var_dump(chk_enc("\xf0\x80\x81\x81\xf0\x80\x81\x82\xf0\x81\x83", 8)); +var_dump(chk_enc("\xe0\x80\xb1\xe0\x80\xb2\xe0\x80\xb3", 9)); +var_dump(chk_enc("\xe0\x81\x81\xe0\x81\x82\xe0\x81\x83", 9)); +var_dump(chk_enc("\xf0\x80\x80\xb1\xf0\x80\x80\xb2\xf0\x80\x80\xb3", 12)); +var_dump(chk_enc("\xf0\x80\x81\x81\xf0\x80\x81\x82\xf0\x81\x83", 11)); var_dump(chk_enc("\xf8\x80\x80\x80\xb1\xf8\x80\x80\x80\xb2\xf8\x80\x80\x80\xb3", 15)); var_dump(chk_enc("\xf8\x80\x80\x81\x81\xf8\x80\x80\x81\x82\xf8\x80\x80\x81\x83", 15)); var_dump(chk_enc("\xfc\x80\x80\x80\x80\xb1\xfc\x80\x80\x80\x80\xb2\xfc\x80\x80\x80\x80\xb3", 18)); var_dump(chk_enc("\xfc\x80\x80\x80\x81\x81\xfc\x80\x80\x80\x81\x82\xfc\x80\x80\x80\x81\x83", 18)); var_dump(chk_enc("\xc2\xa2\xc2\xa3\xc2\xa5", 0)); -var_dump(chk_enc("\xe0\x82\xa2\xe0\x82\xa3\xe0\x82\xa5", 6)); -var_dump(chk_enc("\xf0\x80\x82\xa2\xf0\x80\x82\xa3\xf0\x80\x82\xa5", 9)); +var_dump(chk_enc("\xe0\x82\xa2\xe0\x82\xa3\xe0\x82\xa5", 9)); +var_dump(chk_enc("\xf0\x80\x82\xa2\xf0\x80\x82\xa3\xf0\x80\x82\xa5", 12)); var_dump(chk_enc("\xf8\x80\x80\x82\xa2\xf8\x80\x80\x82\xa3\xf8\x80\x80\x82\xa5", 15)); var_dump(chk_enc("\xfc\x80\x80\x80\x82\xa2\xfc\x80\x80\x80\x82\xa3\xfc\x80\x80\x80\x82\xa5", 18)); var_dump(chk_enc("\xc1\xbf", 2)); var_dump(chk_enc("\xc2\x80", 0)); var_dump(chk_enc("\xdf\xbf", 0)); -var_dump(chk_enc("\xe0\x9f\xff", 2)); +var_dump(chk_enc("\xe0\x9f\xff", 3)); var_dump(chk_enc("\xe0\xa0\x80", 2)); var_dump(chk_enc("\xef\xbf\xbf", 0)); -var_dump(chk_enc("\xf0\x8f\xbf\xbf", 3)); +var_dump(chk_enc("\xf0\x8f\xbf\xbf", 4)); var_dump(chk_enc("\xf0\x90\x80\x80", 0)); var_dump(chk_enc("\xf7\xbf\xbf\xbf", 4)); var_dump(chk_enc("\xf8\x87\xbf\xbf\xbf", 5)); @@ -61,7 +61,7 @@ echo "UTF-8 and surrogates area\n"; $out = ''; $cnt = 0; for ($i = 0xd7ff; $i <= 0xe000; ++$i) { - $s = chk_enc(pack('C3', 0xe0 | ($i >> 12), 0x80 | ($i >> 6) & 0x3f, 0x80 | $i & 0x3f), 2); + $s = chk_enc(pack('C3', 0xe0 | ($i >> 12), 0x80 | ($i >> 6) & 0x3f, 0x80 | $i & 0x3f), 3); if ($s === false) { $cnt++; } else { From 7da331501545c36088b535be0c53580a268ee5f4 Mon Sep 17 00:00:00 2001 From: Rui Hirokawa Date: Wed, 31 Jul 2013 08:18:39 +0900 Subject: [PATCH 4/9] added test script for bug65045. --- ext/mbstring/tests/bug65045.phpt | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 ext/mbstring/tests/bug65045.phpt diff --git a/ext/mbstring/tests/bug65045.phpt b/ext/mbstring/tests/bug65045.phpt new file mode 100644 index 00000000000..03a090ded2d --- /dev/null +++ b/ext/mbstring/tests/bug65045.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #65045: mb_convert_encoding breaks well-formed character +--SKIPIF-- + +--FILE-- + Date: Wed, 31 Jul 2013 03:22:34 +0400 Subject: [PATCH 5/9] Fixed php-5.2 support --- ext/opcache/zend_accelerator_blacklist.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ext/opcache/zend_accelerator_blacklist.c b/ext/opcache/zend_accelerator_blacklist.c index b11d41e1ecb..da83cfd3119 100644 --- a/ext/opcache/zend_accelerator_blacklist.c +++ b/ext/opcache/zend_accelerator_blacklist.c @@ -30,6 +30,10 @@ # include "main/php_regex.h" #endif +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO +# include "ext/standard/php_string.h" +#endif + #ifdef ZEND_WIN32 # define REGEX_MODE (REG_EXTENDED|REG_NOSUB|REG_ICASE) #else @@ -252,7 +256,11 @@ void zend_accel_blacklist_load(zend_blacklist *blacklist, char *filename) zend_accel_error(ACCEL_LOG_DEBUG,"Loading blacklist file: '%s'", filename); if (VCWD_REALPATH(filename, buf)) { +#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO + blacklist_path_length = php_dirname(buf, strlen(buf)); +#else blacklist_path_length = zend_dirname(buf, strlen(buf)); +#endif blacklist_path = zend_strndup(buf, blacklist_path_length); } From 0a974f14d13832838dcc7bae88b3271b7d035f46 Mon Sep 17 00:00:00 2001 From: Rui Hirokawa Date: Wed, 31 Jul 2013 08:46:54 +0900 Subject: [PATCH 6/9] MFH: fixed #65045: mb_convert_encoding breaks well-formed character. --- ext/mbstring/libmbfl/filters/mbfilter_utf8.c | 192 ++++++++--------- ext/mbstring/libmbfl/filters/mbfilter_utf8.h | 1 + .../libmbfl/filters/mbfilter_utf8_mobile.c | 199 ++++++++---------- ext/mbstring/tests/bug65045.phpt | 29 +++ .../tests/illformed_utf_sequences.phpt | 18 +- 5 files changed, 226 insertions(+), 213 deletions(-) create mode 100644 ext/mbstring/tests/bug65045.phpt diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c index fcee610533d..55397003437 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c @@ -79,7 +79,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_wchar = { mbfl_filt_conv_common_ctor, mbfl_filt_conv_common_dtor, mbfl_filt_conv_utf8_wchar, - mbfl_filt_conv_common_flush + mbfl_filt_conv_utf8_wchar_flush }; const struct mbfl_convert_vtbl vtbl_wchar_utf8 = { @@ -93,6 +93,17 @@ const struct mbfl_convert_vtbl vtbl_wchar_utf8 = { #define CK(statement) do { if ((statement) < 0) return (-1); } while (0) +int mbfl_filt_put_invalid_char(int c, mbfl_convert_filter *filter) +{ + int w; + w = c & MBFL_WCSGROUP_MASK; + w |= MBFL_WCSGROUP_THROUGH; + filter->status = 0; + filter->cache = 0; + CK((*filter->output_function)(w, filter->data)); +} + + /* * UTF-8 => wchar */ @@ -100,111 +111,104 @@ int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter) { int s, c1, w = 0, flag = 0; - if (c < 0x80) { - if (filter->status != 0) { - w = (filter->cache & MBFL_WCSGROUP_MASK) | MBFL_WCSGROUP_THROUGH; - CK((*filter->output_function)(w, filter->data)); - filter->status = 0; - filter->cache = 0; - } - if (c >= 0) { +retry: + switch (filter->status & 0xff) { + case 0x00: + if (c < 0x80) { CK((*filter->output_function)(c, filter->data)); - } - } else if (c < 0xc0) { - int status = filter->status & 0xff; - switch (status) { - case 0x10: /* 2byte code 2nd char: 0x80-0xbf */ - case 0x21: /* 3byte code 3rd char: 0x80-0xbf */ - case 0x32: /* 4byte code 4th char: 0x80-0xbf */ - filter->status = 0; - s = filter->cache | (c & 0x3f); - filter->cache = 0; - if ((status == 0x10 && s >= 0x80) || - (status == 0x21 && s >= 0x800 && (s < 0xd800 || s > 0xdfff)) || - (status == 0x32 && s >= 0x10000 && s < 0x110000)) { - CK((*filter->output_function)(s, filter->data)); - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */ - s = filter->cache | ((c & 0x3f) << 6); - c1 = (s >> 12) & 0xf; - if ((c1 == 0x0 && c >= 0xa0) || - (c1 == 0xd && c < 0xa0) || - (c1 > 0x0 && c1 != 0xd)) { - filter->cache = s; - filter->status++; - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - case 0x31: /* 4byte code 3rd char: 0x80-0xbf */ - filter->cache |= ((c & 0x3f) << 6); - filter->status++; - break; - case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */ - s = filter->cache | ((c & 0x3f) << 12); - c1 = (s >> 18) & 0x7; - if ((c1 == 0x0 && c >= 0x90) || - (c1 > 0x0 && c1 < 0x4) || - (c1 == 0x4 && c < 0x90)) { - filter->cache = s; - filter->status++; - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - default: - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - break; - } - } else if (c < 0xc2) { /* invalid: 0xc0,0xc1 */ - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } else if (c < 0xe0) { /* 2byte code first char: 0xc2-0xdf */ - if (filter->status == 0x0) { + } else if (c >= 0xc2 && c <= 0xdf) { /* 2byte code first char: 0xc2-0xdf */ filter->status = 0x10; - filter->cache = (c & 0x1f) << 6; - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - } else if (c < 0xf0) { /* 3byte code first char: 0xe0-0xef */ - if (filter->status == 0x0) { + filter->cache = c & 0x1f; + } else if (c >= 0xe0 && c <= 0xef) { /* 3byte code first char: 0xe0-0xef */ filter->status = 0x20; - filter->cache = (c & 0xf) << 12; - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - } else if (c < 0xf5) { /* 4byte code first char: 0xf0-0xf4 */ - if (filter->status == 0x0) { + filter->cache = c & 0xf; + } else if (c >= 0xf0 && c <= 0xf4) { /* 3byte code first char: 0xf0-0xf4 */ filter->status = 0x30; - filter->cache = (c & 0x7) << 18; + filter->cache = c & 0x7; } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; + mbfl_filt_put_invalid_char(c, filter); } - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - - if (flag) { - w |= MBFL_WCSGROUP_THROUGH; - CK((*filter->output_function)(w, filter->data)); + break; + case 0x10: /* 2byte code 2nd char: 0x80-0xbf */ + case 0x21: /* 3byte code 3rd char: 0x80-0xbf */ + case 0x32: /* 4byte code 4th char: 0x80-0xbf */ filter->status = 0; - filter->cache = 0; + if (c >= 0x80 && c <= 0xbf) { + s = (filter->cache<<6) | (c & 0x3f); + filter->cache = 0; + CK((*filter->output_function)(s, filter->data)); + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */ + s = (filter->cache<<6) | (c & 0x3f); + c1 = filter->cache & 0xf; + + if ((c >= 0x80 && c <= 0xbf) && + ((c1 == 0x0 && c >= 0xa0) || + (c1 == 0xd && c < 0xa0) || + (c1 > 0x0 && c1 != 0xd))) { + filter->cache = s; + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */ + s = (filter->cache<<6) | (c & 0x3f); + c1 = filter->cache & 0x7; + + if ((c >= 0x80 && c <= 0xbf) && + ((c1 == 0x0 && c >= 0x90) || + (c1 == 0x4 && c < 0x90) || + (c1 > 0x0 && c1 != 0x4))) { + filter->cache = s; + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x31: /* 4byte code 3rd char: 0x80-0xbf */ + if (c >= 0x80 && c <= 0xbf) { + filter->cache = (filter->cache<<6) | (c & 0x3f); + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + default: + filter->status = 0; + break; } return c; } +int mbfl_filt_conv_utf8_wchar_flush(mbfl_convert_filter *filter) +{ + int status, cache; + + status = filter->status; + cache = filter->cache; + + filter->status = 0; + filter->cache = 0; + + if (status != 0) { + mbfl_filt_put_invalid_char(cache, filter); + } + + if (filter->flush_function != NULL) { + (*filter->flush_function)(filter->data); + } + return 0; +} + /* * wchar => UTF-8 */ diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8.h b/ext/mbstring/libmbfl/filters/mbfilter_utf8.h index 07bf655022a..970ace6462a 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_utf8.h +++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8.h @@ -37,5 +37,6 @@ extern const struct mbfl_convert_vtbl vtbl_wchar_utf8; int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter); int mbfl_filt_conv_wchar_utf8(int c, mbfl_convert_filter *filter); +int mbfl_filt_conv_utf8_wchar_flush(mbfl_convert_filter *filter); #endif /* MBFL_MBFILTER_UTF8_H */ diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c b/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c index 62feca40b6f..f9b643c17de 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8_mobile.c @@ -37,6 +37,7 @@ #include "mbfilter_sjis_mobile.h" extern int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter); +extern int mbfl_filt_conv_utf8_wchar_flush(mbfl_convert_filter *filter); extern const unsigned char mblen_table_utf8[]; @@ -115,7 +116,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_docomo_wchar = { mbfl_filt_conv_common_ctor, mbfl_filt_conv_common_dtor, mbfl_filt_conv_utf8_mobile_wchar, - mbfl_filt_conv_common_flush + mbfl_filt_conv_utf8_wchar_flush }; const struct mbfl_convert_vtbl vtbl_wchar_utf8_docomo = { @@ -133,7 +134,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_kddi_a_wchar = { mbfl_filt_conv_common_ctor, mbfl_filt_conv_common_dtor, mbfl_filt_conv_utf8_mobile_wchar, - mbfl_filt_conv_common_flush + mbfl_filt_conv_utf8_wchar_flush }; const struct mbfl_convert_vtbl vtbl_wchar_utf8_kddi_a = { @@ -151,7 +152,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_kddi_b_wchar = { mbfl_filt_conv_common_ctor, mbfl_filt_conv_common_dtor, mbfl_filt_conv_utf8_mobile_wchar, - mbfl_filt_conv_common_flush + mbfl_filt_conv_utf8_wchar_flush }; const struct mbfl_convert_vtbl vtbl_wchar_utf8_kddi_b = { @@ -169,7 +170,7 @@ const struct mbfl_convert_vtbl vtbl_utf8_sb_wchar = { mbfl_filt_conv_common_ctor, mbfl_filt_conv_common_dtor, mbfl_filt_conv_utf8_mobile_wchar, - mbfl_filt_conv_common_flush + mbfl_filt_conv_utf8_wchar_flush }; const struct mbfl_convert_vtbl vtbl_wchar_utf8_sb = { @@ -191,119 +192,97 @@ int mbfl_filt_conv_utf8_mobile_wchar(int c, mbfl_convert_filter *filter) int s, w = 0, flag = 0; int s1 = 0, c1 = 0, snd = 0; - if (c < 0x80) { - if (c >= 0) { +retry: + switch (filter->status & 0xff) { + case 0x00: + if (c < 0x80) { CK((*filter->output_function)(c, filter->data)); - } - filter->status = 0; - } else if (c < 0xc0) { - int status = filter->status & 0xff; - switch (status) { - case 0x10: /* 2byte code 2nd char: 0x80-0xbf */ - case 0x21: /* 3byte code 3rd char: 0x80-0xbf */ - case 0x32: /* 4byte code 4th char: 0x80-0xbf */ - filter->status = 0; - s = filter->cache | (c & 0x3f); - filter->cache = 0; - if ((status == 0x10 && s >= 0x80) || - (status == 0x21 && s >= 0x800 && (s < 0xd800 || s > 0xdfff)) || - (status == 0x32 && s >= 0x10000 && s < 0x110000)) { - - if (filter->from->no_encoding == mbfl_no_encoding_utf8_docomo && - mbfilter_conv_r_map_tbl(s, &s1, mbfl_docomo2uni_pua, 4) > 0) { - s = mbfilter_sjis_emoji_docomo2unicode(s1, &snd); - } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_a && - mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua, 7) > 0) { - s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd); - } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_b && - mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua_b, 8) > 0) { - s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd); - } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_sb && - mbfilter_conv_r_map_tbl(s, &s1, mbfl_sb2uni_pua, 6) > 0) { - s = mbfilter_sjis_emoji_sb2unicode(s1, &snd); - } - - if (snd > 0) { - CK((*filter->output_function)(snd, filter->data)); - } - CK((*filter->output_function)(s, filter->data)); - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */ - s = filter->cache | ((c & 0x3f) << 6); - c1 = (s >> 12) & 0xf; - if ((c1 == 0x0 && c >= 0xa0) || - (c1 == 0xd && c < 0xa0) || - (c1 > 0x0 && c1 != 0xd)) { - filter->cache = s; - filter->status++; - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - case 0x31: /* 4byte code 3rd char: 0x80-0xbf */ - filter->cache |= ((c & 0x3f) << 6); - filter->status++; - break; - case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */ - s = filter->cache | ((c & 0x3f) << 12); - c1 = (s >> 18) & 0x7; - if ((c1 == 0x0 && c >= 0x90) || - (c1 > 0x0 && c1 < 0x4) || - (c1 == 0x4 && c < 0x90)) { - filter->cache = s; - filter->status++; - } else { - w = s & MBFL_WCSGROUP_MASK; - flag = 1; - } - break; - default: - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - break; - } - } else if (c < 0xc2) { /* invalid: 0xc0,0xc1 */ - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } else if (c < 0xe0) { /* 2byte code first char: 0xc2-0xdf */ - if (filter->status == 0x0) { + } else if (c >= 0xc2 && c <= 0xdf) { /* 2byte code first char: 0xc2-0xdf */ filter->status = 0x10; - filter->cache = (c & 0x1f) << 6; - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - } else if (c < 0xf0) { /* 3byte code first char: 0xe0-0xef */ - if (filter->status == 0x0) { + filter->cache = c & 0x1f; + } else if (c >= 0xe0 && c <= 0xef) { /* 3byte code first char: 0xe0-0xef */ filter->status = 0x20; - filter->cache = (c & 0xf) << 12; - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - } else if (c < 0xf5) { /* 4byte code first char: 0xf0-0xf4 */ - if (filter->status == 0x0) { + filter->cache = c & 0xf; + } else if (c >= 0xf0 && c <= 0xf4) { /* 3byte code first char: 0xf0-0xf4 */ filter->status = 0x30; - filter->cache = (c & 0x7) << 18; + filter->cache = c & 0x7; } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; + mbfl_filt_put_invalid_char(c, filter); } - } else { - w = c & MBFL_WCSGROUP_MASK; - flag = 1; - } - - if (flag) { - w |= MBFL_WCSGROUP_THROUGH; - CK((*filter->output_function)(w, filter->data)); + break; + case 0x10: /* 2byte code 2nd char: 0x80-0xbf */ + case 0x21: /* 3byte code 3rd char: 0x80-0xbf */ + case 0x32: /* 4byte code 4th char: 0x80-0xbf */ filter->status = 0; - filter->cache = 0; + if (c >= 0x80 && c <= 0xbf) { + s = (filter->cache<<6) | (c & 0x3f); + filter->cache = 0; + + if (filter->from->no_encoding == mbfl_no_encoding_utf8_docomo && + mbfilter_conv_r_map_tbl(s, &s1, mbfl_docomo2uni_pua, 4) > 0) { + s = mbfilter_sjis_emoji_docomo2unicode(s1, &snd); + } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_a && + mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua, 7) > 0) { + s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd); + } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_kddi_b && + mbfilter_conv_r_map_tbl(s, &s1, mbfl_kddi2uni_pua_b, 8) > 0) { + s = mbfilter_sjis_emoji_kddi2unicode(s1, &snd); + } else if (filter->from->no_encoding == mbfl_no_encoding_utf8_sb && + mbfilter_conv_r_map_tbl(s, &s1, mbfl_sb2uni_pua, 6) > 0) { + s = mbfilter_sjis_emoji_sb2unicode(s1, &snd); + } + + if (snd > 0) { + CK((*filter->output_function)(snd, filter->data)); + } + CK((*filter->output_function)(s, filter->data)); + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */ + s = (filter->cache<<6) | (c & 0x3f); + c1 = filter->cache & 0xf; + + if ((c >= 0x80 && c <= 0xbf) && + ((c1 == 0x0 && c >= 0xa0) || + (c1 == 0xd && c < 0xa0) || + (c1 > 0x0 && c1 != 0xd))) { + filter->cache = s; + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */ + s = (filter->cache<<6) | (c & 0x3f); + c1 = filter->cache & 0x7; + + if ((c >= 0x80 && c <= 0xbf) && + ((c1 == 0x0 && c >= 0x90) || + (c1 == 0x4 && c < 0x90) || + (c1 > 0x0 && c1 != 0x4))) { + filter->cache = s; + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + case 0x31: /* 4byte code 3rd char: 0x80-0xbf */ + if (c >= 0x80 && c <= 0xbf) { + filter->cache = (filter->cache<<6) | (c & 0x3f); + filter->status++; + } else { + mbfl_filt_put_invalid_char(filter->cache, filter); + goto retry; + } + break; + default: + filter->status = 0; + break; } return c; diff --git a/ext/mbstring/tests/bug65045.phpt b/ext/mbstring/tests/bug65045.phpt new file mode 100644 index 00000000000..03a090ded2d --- /dev/null +++ b/ext/mbstring/tests/bug65045.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #65045: mb_convert_encoding breaks well-formed character +--SKIPIF-- + +--FILE-- +> 12), 0x80 | ($i >> 6) & 0x3f, 0x80 | $i & 0x3f), 2); + $s = chk_enc(pack('C3', 0xe0 | ($i >> 12), 0x80 | ($i >> 6) & 0x3f, 0x80 | $i & 0x3f), 3); if ($s === false) { $cnt++; } else { From d69b3d8f5955a51ec688a52ceb925705d393821d Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 31 Jul 2013 14:20:56 +0400 Subject: [PATCH 7/9] Added opcache.restrict_api configuration directive that may limit usage of OPcahce API functions only to patricular script(s) --- NEWS | 2 ++ ext/opcache/README | 4 ++++ ext/opcache/ZendAccelerator.h | 1 + ext/opcache/zend_accelerator_module.c | 32 +++++++++++++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/NEWS b/NEWS index 60b2760b390..19e33d84ca4 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ PHP NEWS limited case). (Arpad) - OPcahce: + . Added opcache.restrict_api configuration directive that may limit + usage of OPcahce API functions only to patricular script(s). (Dmitry) . Added support for glob symbols in blacklist entries (?, *, **). (Terry Elison, Dmitry) . Fixed bug #65338 (Enabling both php_opcache and php_wincache AVs on diff --git a/ext/opcache/README b/ext/opcache/README index 311001224ad..6c3cc746e77 100644 --- a/ext/opcache/README +++ b/ext/opcache/README @@ -199,6 +199,10 @@ opcache.protect_memory (default "0") Protect the shared memory from unexpected writing during script execution. Useful for internal debugging only. +opcache.restrict_api (default "") + Allows calling OPcache API functions only from PHP scripts which path is + started from specified string. The default "" means no restriction. + opcache.mmap_base Mapping base of shared memory segments (for Windows only). All the PHP processes have to map shared memory into the same address space. This diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index 57e2e7a0c5d..361b60b08f1 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -232,6 +232,7 @@ typedef struct _zend_accel_directives { #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO long interned_strings_buffer; #endif + char *restrict_api; } zend_accel_directives; typedef struct _zend_accel_globals { diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index 2287d1353ce..f9ddaa98b8b 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -71,6 +71,21 @@ static zend_function_entry accel_functions[] = { { NULL, NULL, NULL, 0, 0 } }; +static int validate_api_restriction(TSRMLS_D) +{ + if (ZCG(accel_directives).restrict_api && *ZCG(accel_directives).restrict_api) { + int len = strlen(ZCG(accel_directives).restrict_api); + + if (!SG(request_info).path_translated || + strlen(SG(request_info).path_translated) < len || + memcmp(SG(request_info).path_translated, ZCG(accel_directives).restrict_api, len) != 0) { + zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME " API is restricted by \"restrict_api\" configuration directive"); + return 0; + } + } + return 1; +} + static ZEND_INI_MH(OnUpdateMemoryConsumption) { long *p; @@ -251,6 +266,7 @@ ZEND_INI_BEGIN() STD_PHP_INI_BOOLEAN("opcache.enable_file_override" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_override_enabled, zend_accel_globals, accel_globals) STD_PHP_INI_BOOLEAN("opcache.enable_cli" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.enable_cli, zend_accel_globals, accel_globals) STD_PHP_INI_ENTRY("opcache.error_log" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.error_log, zend_accel_globals, accel_globals) + STD_PHP_INI_ENTRY("opcache.restrict_api" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.restrict_api, zend_accel_globals, accel_globals) #ifdef ZEND_WIN32 STD_PHP_INI_ENTRY("opcache.mmap_base", NULL, PHP_INI_SYSTEM, OnUpdateString, accel_directives.mmap_base, zend_accel_globals, accel_globals) @@ -517,6 +533,10 @@ static ZEND_FUNCTION(opcache_get_status) return; } + if (!validate_api_restriction(TSRMLS_C)) { + RETURN_FALSE; + } + if (!accel_startup_ok) { RETURN_FALSE; } @@ -587,6 +607,10 @@ static ZEND_FUNCTION(opcache_get_configuration) } #endif + if (!validate_api_restriction(TSRMLS_C)) { + RETURN_FALSE; + } + array_init(return_value); /* directives */ @@ -651,6 +675,10 @@ static ZEND_FUNCTION(opcache_reset) } #endif + if (!validate_api_restriction(TSRMLS_C)) { + RETURN_FALSE; + } + if (!ZCG(enabled) || !accel_startup_ok || !ZCSG(accelerator_enabled)) { RETURN_FALSE; } @@ -671,6 +699,10 @@ static ZEND_FUNCTION(opcache_invalidate) return; } + if (!validate_api_restriction(TSRMLS_C)) { + RETURN_FALSE; + } + if (zend_accel_invalidate(script_name, script_name_len, force TSRMLS_CC) == SUCCESS) { RETURN_TRUE; } else { From fd8f45452032720d3239af2106434232c95249e2 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 31 Jul 2013 16:32:26 +0400 Subject: [PATCH 8/9] Fixed bug #65018 (SoapHeader problems with SoapServer) --- NEWS | 3 + ext/soap/soap.c | 93 ++++++++++++++++++------------- ext/soap/tests/bugs/bug65018.phpt | 28 ++++++++++ 3 files changed, 86 insertions(+), 38 deletions(-) create mode 100644 ext/soap/tests/bugs/bug65018.phpt diff --git a/NEWS b/NEWS index 97c25dfc04c..d480e3d669e 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,9 @@ PHP NEWS . Fixed bug #50308 (session id not appended properly for empty anchor tags). (Arpad) +- SOAP: + . Fixed bug #65018 (SoapHeader problems with SoapServer). (Dmitry) + - SPL: . Fixed bug #65328 (Segfault when getting SplStack object Value). (Laruence) diff --git a/ext/soap/soap.c b/ext/soap/soap.c index e08f8b60b0e..9371df6fb4f 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -3658,7 +3658,44 @@ ignore_header: return function; } -static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, char *function_name, char *uri, zval *ret, int version, int main TSRMLS_DC) +static void set_soap_header_attributes(xmlNodePtr h, HashTable *ht, int version) +{ + zval **tmp; + + if (zend_hash_find(ht, "mustUnderstand", sizeof("mustUnderstand"), (void**)&tmp) == SUCCESS && + Z_TYPE_PP(tmp) == IS_BOOL && Z_LVAL_PP(tmp)) { + if (version == SOAP_1_1) { + xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("1")); + } else { + xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("true")); + } + } + if (zend_hash_find(ht, "actor", sizeof("actor"), (void**)&tmp) == SUCCESS) { + if (Z_TYPE_PP(tmp) == IS_STRING) { + if (version == SOAP_1_1) { + xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(Z_STRVAL_PP(tmp))); + } else { + xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(Z_STRVAL_PP(tmp))); + } + } else if (Z_TYPE_PP(tmp) == IS_LONG) { + if (version == SOAP_1_1) { + if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) { + xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(SOAP_1_1_ACTOR_NEXT)); + } + } else { + if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) { + xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NEXT)); + } else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NONE) { + xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NONE)); + } else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_UNLIMATERECEIVER) { + xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_UNLIMATERECEIVER)); + } + } + } + } +} + +static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, char *function_name, char *uri, zval *ret, int version, int main, xmlNodePtr *node TSRMLS_DC) { xmlNodePtr method = NULL, param; sdlParamPtr parameter = NULL; @@ -3758,6 +3795,9 @@ static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, ch if (use == SOAP_ENCODED && version == SOAP_1_2 && method != NULL) { xmlSetNsProp(method, body->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE)); } + if (node) { + *node = method; + } return use; } @@ -3839,7 +3879,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function } if (headers->function) { - if (serialize_response_call2(head, headers->function, Z_STRVAL(headers->function_name), uri, hdr_ret, version, 0 TSRMLS_CC) == SOAP_ENCODED) { + if (serialize_response_call2(head, headers->function, Z_STRVAL(headers->function_name), uri, hdr_ret, version, 0, NULL TSRMLS_CC) == SOAP_ENCODED) { use = SOAP_ENCODED; } } else { @@ -4025,15 +4065,15 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function zval *hdr_ret = &h->retval; char *hdr_ns = h->hdr?h->hdr->ns:NULL; char *hdr_name = Z_STRVAL(h->function_name); - + HashTable *ht = NULL; if (Z_TYPE(h->retval) == IS_OBJECT && instanceof_function(Z_OBJCE(h->retval), soap_header_class_entry TSRMLS_CC)) { - HashTable* ht = Z_OBJPROP(h->retval); zval **tmp; sdlSoapBindingFunctionHeaderPtr *hdr; smart_str key = {0}; + ht = Z_OBJPROP(h->retval); if (zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) { smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); @@ -4064,9 +4104,14 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function } if (h->function) { - if (serialize_response_call2(head, h->function, Z_STRVAL(h->function_name), uri, hdr_ret, version, 0 TSRMLS_CC) == SOAP_ENCODED) { + xmlNodePtr xmlHdr = NULL; + + if (serialize_response_call2(head, h->function, Z_STRVAL(h->function_name), uri, hdr_ret, version, 0, &xmlHdr TSRMLS_CC) == SOAP_ENCODED) { use = SOAP_ENCODED; } + if (ht) { + set_soap_header_attributes(xmlHdr, ht, version); + } } else { xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head TSRMLS_CC); if (hdr_name) { @@ -4076,6 +4121,9 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function xmlNsPtr nsptr = encode_add_ns(xmlHdr,hdr_ns); xmlSetNs(xmlHdr, nsptr); } + if (ht) { + set_soap_header_attributes(xmlHdr, ht, version); + } } } h = h->next; @@ -4089,7 +4137,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL); - if (serialize_response_call2(body, function, function_name, uri, ret, version, 1 TSRMLS_CC) == SOAP_ENCODED) { + if (serialize_response_call2(body, function, function_name, uri, ret, version, 1, NULL TSRMLS_CC) == SOAP_ENCODED) { use = SOAP_ENCODED; } @@ -4281,38 +4329,7 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function } nsptr = encode_add_ns(h, Z_STRVAL_PP(ns)); xmlSetNs(h, nsptr); - - if (zend_hash_find(ht, "mustUnderstand", sizeof("mustUnderstand"), (void**)&tmp) == SUCCESS && - Z_TYPE_PP(tmp) == IS_BOOL && Z_LVAL_PP(tmp)) { - if (version == SOAP_1_1) { - xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("1")); - } else { - xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("true")); - } - } - if (zend_hash_find(ht, "actor", sizeof("actor"), (void**)&tmp) == SUCCESS) { - if (Z_TYPE_PP(tmp) == IS_STRING) { - if (version == SOAP_1_1) { - xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(Z_STRVAL_PP(tmp))); - } else { - xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(Z_STRVAL_PP(tmp))); - } - } else if (Z_TYPE_PP(tmp) == IS_LONG) { - if (version == SOAP_1_1) { - if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) { - xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(SOAP_1_1_ACTOR_NEXT)); - } - } else { - if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) { - xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NEXT)); - } else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NONE) { - xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NONE)); - } else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_UNLIMATERECEIVER) { - xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_UNLIMATERECEIVER)); - } - } - } - } + set_soap_header_attributes(h, ht, version); } zend_hash_move_forward(soap_headers); } diff --git a/ext/soap/tests/bugs/bug65018.phpt b/ext/soap/tests/bugs/bug65018.phpt new file mode 100644 index 00000000000..bbb9b5e42d3 --- /dev/null +++ b/ext/soap/tests/bugs/bug65018.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #65018 (SoapHeader problems with SoapServer) +--SKIPIF-- + +--FILE-- +'.PHP_EOL. + ''. + 'abc'. + ''; + + $soap = new SoapServer(null, array('uri' => '127.0.0.1')); + $soap->setClass('Tool'); + $soap->handle($input); +?> +--EXPECT-- + +abc From 4395f702074435edfbf44ddb5d82a7cd3ce82f01 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 31 Jul 2013 17:36:06 +0400 Subject: [PATCH 9/9] Improved fix for bug #44686 (SOAP-ERROR: Parsing WSDL) --- ext/soap/php_schema.c | 54 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/ext/soap/php_schema.c b/ext/soap/php_schema.c index 7d2e129746e..25bb1772736 100644 --- a/ext/soap/php_schema.c +++ b/ext/soap/php_schema.c @@ -1081,6 +1081,14 @@ static int schema_group(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr groupType, sdlTyp nsptr = xmlSearchNs(groupType->doc, groupType, BAD_CAST(ns)); if (nsptr != NULL) { smart_str_appends(&key, (char*)nsptr->href); + } else { + xmlAttrPtr ns = get_attribute(groupType->properties, "targetNamespace"); + if (ns == NULL) { + ns = tns; + } + if (ns) { + smart_str_appends(&key, (char*)ns->children->content); + } } smart_str_appendc(&key, ':'); smart_str_appends(&key, type); @@ -1509,6 +1517,14 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTyp if (nsptr != NULL) { smart_str_appends(&nscat, (char*)nsptr->href); newType->namens = estrdup((char*)nsptr->href); + } else { + xmlAttrPtr ns = get_attribute(attrs, "targetNamespace"); + if (ns == NULL) { + ns = tns; + } + if (ns) { + smart_str_appends(&nscat, (char*)ns->children->content); + } } smart_str_appendc(&nscat, ':'); smart_str_appends(&nscat, type); @@ -1735,6 +1751,14 @@ static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdl if (nsptr != NULL) { smart_str_appends(&key, (char*)nsptr->href); newAttr->namens = estrdup((char*)nsptr->href); + } else { + xmlAttrPtr ns = get_attribute(attrType->properties, "targetNamespace"); + if (ns == NULL) { + ns = tns; + } + if (ns) { + smart_str_appends(&key, (char*)ns->children->content); + } } smart_str_appendc(&key, ':'); smart_str_appends(&key, attr_name); @@ -2036,13 +2060,31 @@ static void copy_extra_attribute(void *attribute) } } +static void* schema_find_by_ref(HashTable *ht, char *ref) +{ + void **tmp; + + if (zend_hash_find(ht, ref, strlen(ref)+1, (void**)&tmp) == SUCCESS) { + return tmp; + } else { + ref = strrchr(ref, ':'); + if (ref) { + if (zend_hash_find(ht, ref, strlen(ref)+1, (void**)&tmp) == SUCCESS) { + return tmp; + } + } + } + return NULL; +} + static void schema_attribute_fixup(sdlCtx *ctx, sdlAttributePtr attr) { sdlAttributePtr *tmp; if (attr->ref != NULL) { if (ctx->attributes != NULL) { - if (zend_hash_find(ctx->attributes, attr->ref, strlen(attr->ref)+1, (void**)&tmp) == SUCCESS) { + tmp = (sdlAttributePtr*)schema_find_by_ref(ctx->attributes, attr->ref); + if (tmp) { schema_attribute_fixup(ctx, *tmp); if ((*tmp)->name != NULL && attr->name == NULL) { attr->name = estrdup((*tmp)->name); @@ -2092,7 +2134,8 @@ static void schema_attributegroup_fixup(sdlCtx *ctx, sdlAttributePtr attr, HashT if (attr->ref != NULL) { if (ctx->attributeGroups != NULL) { - if (zend_hash_find(ctx->attributeGroups, attr->ref, strlen(attr->ref)+1, (void**)&tmp) == SUCCESS) { + tmp = (sdlTypePtr*)schema_find_by_ref(ctx->attributeGroups, attr->ref); + if (tmp) { if ((*tmp)->attributes) { zend_hash_internal_pointer_reset((*tmp)->attributes); while (zend_hash_get_current_data((*tmp)->attributes,(void**)&tmp_attr) == SUCCESS) { @@ -2149,7 +2192,7 @@ static void schema_content_model_fixup(sdlCtx *ctx, sdlContentModelPtr model) model->kind = XSD_CONTENT_GROUP; model->u.group = (*tmp); } else { - soap_error0(E_ERROR, "Parsing Schema: unresolved group 'ref' attribute"); + soap_error1(E_ERROR, "Parsing Schema: unresolved group 'ref' attribute '%s'", model->u.group_ref); } break; } @@ -2193,7 +2236,8 @@ static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type) if (type->ref != NULL) { if (ctx->sdl->elements != NULL) { - if (zend_hash_find(ctx->sdl->elements, type->ref, strlen(type->ref)+1, (void**)&tmp) == SUCCESS) { + tmp = (sdlTypePtr*)schema_find_by_ref(ctx->sdl->elements, type->ref); + if (tmp) { type->kind = (*tmp)->kind; type->encode = (*tmp)->encode; if ((*tmp)->nillable) { @@ -2209,7 +2253,7 @@ static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type) } else if (strcmp(type->ref, SCHEMA_NAMESPACE ":schema") == 0) { type->encode = get_conversion(XSD_ANYXML); } else { - soap_error0(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute"); + soap_error1(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute '%s'", type->ref); } } efree(type->ref);