Skip to content

Commit afa4e41

Browse files
author
Andrei Zmievski
committed
Implement JIT request decoding support for $_GET and $_POST.
1 parent 9708b01 commit afa4e41

22 files changed

+504
-1337
lines changed

Zend/zend.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -195,13 +195,17 @@ ZEND_INI_BEGIN()
195195
STD_ZEND_INI_ENTRY("unicode.fallback_encoding", NULL, ZEND_INI_ALL, OnUpdateEncoding, fallback_encoding_conv, zend_unicode_globals, unicode_globals)
196196
STD_ZEND_INI_ENTRY("unicode.runtime_encoding", NULL, ZEND_INI_ALL, OnUpdateEncoding, runtime_encoding_conv, zend_unicode_globals, unicode_globals)
197197
STD_ZEND_INI_ENTRY("unicode.script_encoding", NULL, ZEND_INI_ALL, OnUpdateEncoding, script_encoding_conv, zend_unicode_globals, unicode_globals)
198-
STD_ZEND_INI_ENTRY("unicode.http_input_encoding", NULL, ZEND_INI_ALL, OnUpdateEncoding, http_input_encoding_conv, zend_unicode_globals, unicode_globals)
199198
STD_ZEND_INI_ENTRY("unicode.filesystem_encoding", NULL, ZEND_INI_ALL, OnUpdateEncoding, filesystem_encoding_conv, zend_unicode_globals, unicode_globals)
200199
/*
201200
* This is used as a default for the stream contexts. It's not an actual
202201
* UConverter because each stream needs its own.
203202
*/
204203
STD_ZEND_INI_ENTRY("unicode.stream_encoding", "UTF-8", ZEND_INI_ALL, OnUpdateStringUnempty, stream_encoding, zend_unicode_globals, unicode_globals)
204+
/*
205+
* This is used as a default for the request encoding. It's not an actual
206+
* UConverter because the request encoding converter is reset on each request.
207+
*/
208+
STD_ZEND_INI_ENTRY("unicode.request_encoding_default", "UTF-8", ZEND_INI_ALL, OnUpdateStringUnempty, request_encoding_def, zend_unicode_globals, unicode_globals)
205209
ZEND_INI_END()
206210

207211

@@ -1008,8 +1012,8 @@ static void unicode_globals_ctor(zend_unicode_globals *unicode_globals TSRMLS_DC
10081012
unicode_globals->runtime_encoding_conv = NULL;
10091013
unicode_globals->output_encoding_conv = NULL;
10101014
unicode_globals->script_encoding_conv = NULL;
1011-
unicode_globals->http_input_encoding_conv = NULL;
10121015
unicode_globals->filesystem_encoding_conv = NULL;
1016+
unicode_globals->request_encoding_conv = NULL;
10131017
zend_set_converter_encoding(&unicode_globals->utf8_conv, "UTF-8");
10141018
zend_set_converter_error_mode(unicode_globals->utf8_conv, ZEND_TO_UNICODE, ZEND_CONV_ERROR_STOP);
10151019
zend_set_converter_encoding(&unicode_globals->ascii_conv, "US-ASCII");
@@ -1061,11 +1065,6 @@ static void unicode_globals_dtor(zend_unicode_globals *unicode_globals TSRMLS_DC
10611065
unicode_globals->script_encoding_conv != unicode_globals->ascii_conv) {
10621066
ucnv_close(unicode_globals->script_encoding_conv);
10631067
}
1064-
if (unicode_globals->http_input_encoding_conv &&
1065-
unicode_globals->http_input_encoding_conv != unicode_globals->utf8_conv &&
1066-
unicode_globals->http_input_encoding_conv != unicode_globals->ascii_conv) {
1067-
ucnv_close(unicode_globals->http_input_encoding_conv);
1068-
}
10691068
if (unicode_globals->utf8_conv) {
10701069
ucnv_close(unicode_globals->utf8_conv);
10711070
}
@@ -1385,12 +1384,24 @@ static void init_unicode_request_globals(TSRMLS_D) /* {{{ */
13851384
UG(default_locale) = safe_estrdup(uloc_getDefault());
13861385
UG(default_collator) = NULL;
13871386

1387+
if (strcmp(UG(request_encoding_def), "binary") != 0) {
1388+
if (zend_set_converter_encoding(&UG(request_encoding_conv), UG(request_encoding_def)) == FAILURE) {
1389+
zend_error(E_CORE_ERROR, "Unrecognized encoding '%s' used for request_encoding", UG(request_encoding_def));
1390+
return;
1391+
}
1392+
zend_set_converter_error_mode(UG(request_encoding_conv), ZEND_TO_UNICODE, ZEND_CONV_ERROR_STOP);
1393+
}
1394+
13881395
zend_reset_locale_deps(TSRMLS_C);
13891396
}
13901397
/* }}} */
13911398

13921399
static void shutdown_unicode_request_globals(TSRMLS_D) /* {{{ */
13931400
{
1401+
if (UG(request_encoding_conv)) {
1402+
ucnv_close(UG(request_encoding_conv));
1403+
UG(request_encoding_conv) = NULL;
1404+
}
13941405
zend_collator_destroy(UG(default_collator));
13951406
efree(UG(default_locale));
13961407
}

Zend/zend_compile.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,25 @@ static void build_runtime_defined_function_key(zval *result, zend_uchar type, co
104104
}
105105
/* }}} */
106106

107-
int zend_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
107+
ZEND_API int zend_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
108108
{
109109
auto_global->armed = (auto_global->auto_global_callback ? 1 : 0);
110110
return 0;
111111
}
112+
113+
ZEND_API int zend_auto_global_arm_by_name(const char *name, zend_uint name_len TSRMLS_DC) /* {{{ */
114+
{
115+
zend_auto_global *auto_global;
116+
117+
if (zend_hash_find(CG(auto_globals), name, name_len+1, (void **) &auto_global)==FAILURE) {
118+
return FAILURE;
119+
}
120+
121+
auto_global->armed = 1;
122+
CG(auto_globals_cache)[auto_global->index] = NULL;
123+
124+
return SUCCESS;
125+
}
112126
/* }}} */
113127

114128
int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC) /* {{{ */

Zend/zend_compile.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,8 @@ ZEND_API int zend_register_auto_global_ex(const char *name, uint name_len, zend_
625625
ZEND_API zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC);
626626
ZEND_API zend_bool zend_u_is_auto_global(zend_uchar type, zstr name, uint name_len TSRMLS_DC);
627627
ZEND_API zend_bool zend_u_is_auto_global_ex(zend_uchar type, zstr name, uint name_len, zend_bool runtime, zend_auto_global **ret TSRMLS_DC);
628+
ZEND_API int zend_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC);
629+
ZEND_API int zend_auto_global_arm_by_name(const char *name, zend_uint name_len TSRMLS_DC);
628630
ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC);
629631
ZEND_API size_t zend_dirname(char *path, size_t len);
630632
ZEND_API size_t zend_u_dirname(UChar *path, size_t len);

Zend/zend_globals.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,15 +292,16 @@ struct _zend_unicode_globals {
292292
UConverter *fallback_encoding_conv; /* converter for default encoding for IS_STRING type */
293293
UConverter *runtime_encoding_conv; /* runtime encoding converter */
294294
UConverter *output_encoding_conv; /* output layer converter */
295+
UConverter *request_encoding_conv; /* http request encoding converter */
295296
UConverter *script_encoding_conv; /* default script encoding converter */
296-
UConverter *http_input_encoding_conv;/* http input encoding converter */
297297
UConverter *filesystem_encoding_conv;/* default filesystem converter (entries, not contents) */
298298
UConverter *utf8_conv; /* all-purpose UTF-8 converter */
299299
UConverter *ascii_conv; /* all-purpose ASCII converter */
300300

301301
char *stream_encoding; /* default stream encoding (contents, not FS entries)
302302
Uses name of encoding rather than a real converter
303303
because each stream needs its own instance */
304+
char *request_encoding_def; /* the default http request encoding */
304305

305306
uint16_t from_error_mode;
306307
UChar from_subst_char[3];

ext/filter/filter.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ zend_module_entry filter_module_entry = {
139139
filter_functions,
140140
PHP_MINIT(filter),
141141
PHP_MSHUTDOWN(filter),
142-
NULL,
142+
PHP_RINIT(filter),
143143
PHP_RSHUTDOWN(filter),
144144
PHP_MINFO(filter),
145145
"0.11.0",
@@ -287,6 +287,20 @@ PHP_MSHUTDOWN_FUNCTION(filter)
287287
}
288288
/* }}} */
289289

290+
/* {{{ PHP_RINIT_FUNCTION
291+
*/
292+
PHP_RINIT_FUNCTION(filter)
293+
{
294+
IF_G(get_array) = NULL;
295+
IF_G(post_array) = NULL;
296+
IF_G(cookie_array) = NULL;
297+
IF_G(server_array) = NULL;
298+
IF_G(env_array) = NULL;
299+
IF_G(session_array) = NULL;
300+
return SUCCESS;
301+
}
302+
/* }}} */
303+
290304
/* {{{ PHP_RSHUTDOWN_FUNCTION
291305
*/
292306
#define VAR_ARRAY_COPY_DTOR(a) \

ext/mbstring/mb_gpc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ enum mbfl_no_encoding _php_mb_encoding_handler_ex(const php_mb_encoding_handler_
326326
val = estrndup(val, val_len);
327327
if (sapi_module.input_filter(info->data_type, var, &val, val_len, &new_val_len TSRMLS_CC)) {
328328
/* add variable to symbol table */
329-
php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
329+
php_register_variable_safe(IS_STRING, ZSTR(var), ZSTR(val), new_val_len, array_ptr TSRMLS_CC);
330330
}
331331
efree(val);
332332

ext/pcre/php_pcre.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,7 @@ static int preg_do_eval(char *eval_str, int eval_str_len, char *subject,
996996
match = subject + offsets[backref<<1];
997997
match_len = offsets[(backref<<1)+1] - offsets[backref<<1];
998998
if (match_len) {
999-
esc_match = php_addslashes_ex(match, match_len, &esc_match_len, 0, 1 TSRMLS_CC);
999+
esc_match = php_addslashes_ex(match, match_len, &esc_match_len, 0 TSRMLS_CC);
10001000
} else {
10011001
esc_match = match;
10021002
esc_match_len = 0;

ext/standard/basic_functions.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,13 @@ ZEND_END_ARG_INFO()
861861
ZEND_BEGIN_ARG_INFO(arginfo_sys_getloadavg, 0)
862862
ZEND_END_ARG_INFO()
863863
#endif
864+
865+
ZEND_BEGIN_ARG_INFO(arginfo_request_set_encoding, 0)
866+
ZEND_ARG_INFO(0, encoding)
867+
ZEND_END_ARG_INFO()
868+
869+
ZEND_BEGIN_ARG_INFO(arginfo_request_had_errors, 0)
870+
ZEND_END_ARG_INFO()
864871
/* }}} */
865872
/* {{{ assert.c */
866873
ZEND_BEGIN_ARG_INFO(arginfo_assert, 0)
@@ -3364,6 +3371,9 @@ const zend_function_entry basic_functions[] = { /* {{{ */
33643371

33653372
PHP_FE(sys_get_temp_dir, arginfo_sys_get_temp_dir)
33663373

3374+
PHP_FE(request_set_encoding, arginfo_request_set_encoding)
3375+
PHP_FE(request_had_errors, arginfo_request_had_errors)
3376+
33673377
{NULL, NULL, NULL}
33683378
};
33693379
/* }}} */
@@ -6213,6 +6223,55 @@ PHP_FUNCTION(sys_getloadavg)
62136223
/* }}} */
62146224
#endif
62156225

6226+
PHP_FUNCTION(request_set_encoding)
6227+
{
6228+
char *req_enc;
6229+
int req_enc_len;
6230+
6231+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &req_enc, &req_enc_len) == FAILURE) {
6232+
return;
6233+
}
6234+
6235+
if (req_enc_len == 0 || strcmp(req_enc, "binary") == 0) {
6236+
/* converter is already unset, no need to re-arm, just return */
6237+
if (UG(request_encoding_conv) == NULL)
6238+
return;
6239+
ucnv_close(UG(request_encoding_conv));
6240+
UG(request_encoding_conv) = NULL;
6241+
} else {
6242+
/* if the converter is the same as the requested one, no need to re-arm, just
6243+
* return */
6244+
if (UG(request_encoding_conv)) {
6245+
UErrorCode status = U_ZERO_ERROR;
6246+
const char *current = ucnv_getName(UG(request_encoding_conv), &status);
6247+
if (!ucnv_compareNames(current, req_enc)) {
6248+
return;
6249+
}
6250+
}
6251+
if (zend_set_converter_encoding(&UG(request_encoding_conv), req_enc) == FAILURE) {
6252+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unrecognized encoding '%s'", req_enc);
6253+
RETURN_FALSE;
6254+
}
6255+
zend_set_converter_error_mode(UG(request_encoding_conv), ZEND_TO_UNICODE, ZEND_CONV_ERROR_STOP);
6256+
}
6257+
6258+
zend_auto_global_arm_by_name(ZEND_STRL("_GET") TSRMLS_CC);
6259+
zend_auto_global_arm_by_name(ZEND_STRL("_POST") TSRMLS_CC);
6260+
zend_auto_global_arm_by_name(ZEND_STRL("_FILES") TSRMLS_CC);
6261+
zend_auto_global_arm_by_name(ZEND_STRL("_REQUEST") TSRMLS_CC);
6262+
6263+
RETURN_TRUE;
6264+
}
6265+
6266+
PHP_FUNCTION(request_had_errors)
6267+
{
6268+
if (zend_parse_parameters_none() == FAILURE) {
6269+
return;
6270+
}
6271+
6272+
RETURN_BOOL(PG(request_decoding_error));
6273+
}
6274+
62166275
/*
62176276
* Local variables:
62186277
* tab-width: 4

ext/standard/basic_functions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ PHP_FUNCTION(stream_bucket_new);
141141
PHP_MINIT_FUNCTION(user_filters);
142142
PHP_RSHUTDOWN_FUNCTION(user_filters);
143143

144+
/* Unicode-related */
145+
PHP_FUNCTION(request_set_encoding);
146+
PHP_FUNCTION(request_had_errors);
147+
144148
PHPAPI int _php_error_log(int opt_err, char *message, char *opt, char *headers TSRMLS_DC);
145149
PHPAPI char *php_get_current_user(void);
146150
PHPAPI int php_prefix_varname(zval *result, zval *prefix, zstr var_name, int var_name_len, int var_name_type, zend_bool add_underscore TSRMLS_DC);

ext/standard/php_string.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,9 @@ PHPAPI UChar *php_u_strtoupper(UChar *s, int *len, const char *locale);
129129
PHPAPI UChar *php_u_strtolower(UChar *s, int *len, const char *locale);
130130
PHPAPI char *php_strtr(char *str, int len, char *str_from, char *str_to, int trlen);
131131
PHPAPI UChar *php_u_addslashes(UChar *str, int length, int *new_length, int freeit TSRMLS_DC);
132-
PHPAPI UChar *php_u_addslashes_ex(UChar *str, int length, int *new_length, int freeit, int ignore_sybase TSRMLS_DC);
132+
PHPAPI UChar *php_u_addslashes_ex(UChar *str, int length, int *new_length, int freeit TSRMLS_DC);
133133
PHPAPI char *php_addslashes(char *str, int length, int *new_length, int freeit TSRMLS_DC);
134-
PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int freeit, int ignore_sybase TSRMLS_DC);
134+
PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int freeit TSRMLS_DC);
135135
PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int freeit, char *what, int wlength TSRMLS_DC);
136136
PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC);
137137
PHPAPI void php_u_stripslashes(UChar *str, int *len TSRMLS_DC);

ext/standard/string.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4874,13 +4874,13 @@ PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int should_
48744874
*/
48754875
PHPAPI UChar *php_u_addslashes(UChar *str, int length, int *new_length, int should_free TSRMLS_DC)
48764876
{
4877-
return php_u_addslashes_ex(str, length, new_length, should_free, 0 TSRMLS_CC);
4877+
return php_u_addslashes_ex(str, length, new_length, should_free TSRMLS_CC);
48784878
}
48794879
/* }}} */
48804880

48814881
/* {{{ php_u_addslashes_ex
48824882
*/
4883-
PHPAPI UChar *php_u_addslashes_ex(UChar *str, int length, int *new_length, int should_free, int ignore_sybase TSRMLS_DC)
4883+
PHPAPI UChar *php_u_addslashes_ex(UChar *str, int length, int *new_length, int should_free TSRMLS_DC)
48844884
{
48854885
UChar *buf;
48864886
int32_t buf_len = 0, i = 0;
@@ -4929,13 +4929,13 @@ PHPAPI UChar *php_u_addslashes_ex(UChar *str, int length, int *new_length, int s
49294929
*/
49304930
PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_free TSRMLS_DC)
49314931
{
4932-
return php_addslashes_ex(str, length, new_length, should_free, 0 TSRMLS_CC);
4932+
return php_addslashes_ex(str, length, new_length, should_free TSRMLS_CC);
49334933
}
49344934
/* }}} */
49354935

49364936
/* {{{ php_addslashes_ex
49374937
*/
4938-
PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int should_free, int ignore_sybase TSRMLS_DC)
4938+
PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int should_free TSRMLS_DC)
49394939
{
49404940
/* maximum string length, worst case situation */
49414941
char *new_str;

main/SAPI.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,22 @@ SAPI_API void sapi_free_header(sapi_header_struct *sapi_header)
118118
SAPI_API void sapi_handle_post(void *arg TSRMLS_DC)
119119
{
120120
if (SG(request_info).post_entry && SG(request_info).content_type_dup) {
121+
/*
122+
* We need to re-populate post_data from the stored raw POST data in case we had
123+
* any before, so that the handler can get to it.
124+
*/
125+
if (SG(request_info).post_data == NULL && SG(request_info).raw_post_data != NULL) {
126+
SG(request_info).post_data = estrndup(SG(request_info).raw_post_data, SG(request_info).raw_post_data_length);
127+
}
121128
SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg TSRMLS_CC);
122129
if (SG(request_info).post_data) {
123130
efree(SG(request_info).post_data);
124131
SG(request_info).post_data = NULL;
125132
}
133+
#if 0 /* UTODO see if this works */
126134
efree(SG(request_info).content_type_dup);
127135
SG(request_info).content_type_dup = NULL;
136+
#endif
128137
}
129138
}
130139

@@ -384,6 +393,8 @@ SAPI_API void sapi_activate(TSRMLS_D)
384393
SG(request_info).headers_only = 0;
385394
}
386395
SG(rfc1867_uploaded_files) = NULL;
396+
SG(rfc1867_vars) = NULL;
397+
SG(rfc1867_vars) = NULL;
387398

388399
/* handle request mehtod */
389400
if (SG(server_context)) {
@@ -468,6 +479,14 @@ SAPI_API void sapi_deactivate(TSRMLS_D)
468479
if (SG(rfc1867_uploaded_files)) {
469480
destroy_uploaded_files_hash(TSRMLS_C);
470481
}
482+
if (SG(rfc1867_vars)) {
483+
zend_hash_destroy(SG(rfc1867_vars));
484+
FREE_HASHTABLE(SG(rfc1867_vars));
485+
}
486+
if (SG(rfc1867_files_vars)) {
487+
zend_hash_destroy(SG(rfc1867_files_vars));
488+
FREE_HASHTABLE(SG(rfc1867_files_vars));
489+
}
471490
if (SG(sapi_headers).mimetype) {
472491
efree(SG(sapi_headers).mimetype);
473492
SG(sapi_headers).mimetype = NULL;

main/SAPI.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ typedef struct _sapi_globals_struct {
131131
zend_bool sapi_started;
132132
time_t global_request_time;
133133
HashTable known_post_content_types;
134+
135+
/* raw POST and FILES variables from RFC1867 handler */
136+
HashTable *rfc1867_vars;
137+
HashTable *rfc1867_files_vars;
134138
} sapi_globals_struct;
135139

136140

main/php_globals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ struct _php_core_globals {
154154

155155
zend_bool mail_x_header;
156156
char *mail_log;
157+
158+
zend_bool request_decoding_error;
157159
};
158160

159161

0 commit comments

Comments
 (0)