is it really needed? str_replace can easily do that… it just looks like this "unidentified problem" is not specific to json
On 11/29/07, Sara Golemon <[EMAIL PROTECTED]> wrote: > While it's technically "safe" to include user supplied data in > json_encode() serialized values. The fact that characters such as <>&' > remain as is means there room for some as-yet unidentified problem > either in the browser's rendering or (more likely) elsewhere in one's > codebase for this data to get into the wrong context and be executed. > > To that end, the attached patch allows the caller to be paranoid about > their data and stipulate that <>&' should be encoded to hex references > instead. This doesn't stop a web developer from dropping that content > into an innerHTML of course, but it's one more rope holding the ship > together. > > Obviously, since this adds five characters per pedantically escaped > character, it's not something you'd want on by default, so the normal > behavior would be to leave them alone. > > echo json_encode("<foo>"); > "<foo>" > > echo json_encode("<foo>", JSON_HEX_TAG); > "\u003Cfoo\u003E" > > echo json_encode("<foo bar='baz'>", JSON_HEX_TAG | JSON_HEX_APOS); > "\u003Cfoo bar=\u0027baz\u0027\u003E" > > If noone objects, I'll commit this in a week along with an MFH for 5.3 > > -Sara > > > > Index: json.c > =================================================================== > RCS file: /repository/pecl/json/json.c,v > retrieving revision 1.31 > diff -u -p -r1.31 json.c > --- json.c 1 Oct 2007 15:25:01 -0000 1.31 > +++ json.c 29 Nov 2007 19:01:34 -0000 > @@ -32,6 +32,10 @@ > > static const char digits[] = "0123456789abcdef"; > > +#define PHP_JSON_HEX_TAG (1<<0) > +#define PHP_JSON_HEX_AMP (1<<1) > +#define PHP_JSON_HEX_APOS (1<<2) > + > /* {{{ json_functions[] > * > * Every user visible function must have an entry in json_functions[]. > @@ -43,6 +47,18 @@ const function_entry json_functions[] = > }; > /* }}} */ > > +/* {{{ MINIT */ > +static PHP_MINIT_FUNCTION(json) > +{ > + REGISTER_LONG_CONSTANT("JSON_HEX_TAG", PHP_JSON_HEX_TAG, CONST_CS | > CONST_PERSISTENT); > + REGISTER_LONG_CONSTANT("JSON_HEX_AMP", PHP_JSON_HEX_AMP, CONST_CS | > CONST_PERSISTENT); > + REGISTER_LONG_CONSTANT("JSON_HEX_APOS", PHP_JSON_HEX_APOS, CONST_CS | > CONST_PERSISTENT); > + > + return SUCCESS; > +} > +/* }}} */ > + > + > /* {{{ json_module_entry > */ > zend_module_entry json_module_entry = { > @@ -51,7 +67,7 @@ zend_module_entry json_module_entry = { > #endif > "json", > json_functions, > - NULL, > + PHP_MINIT(json), > NULL, > NULL, > NULL, > @@ -78,8 +94,8 @@ PHP_MINFO_FUNCTION(json) > } > /* }}} */ > > -static void json_encode_r(smart_str *buf, zval *val TSRMLS_DC); > -static void json_escape_string(smart_str *buf, zstr s, int len, > zend_uchar type); > +static void json_encode_r(smart_str *buf, zval *val, int options > TSRMLS_DC); > +static void json_escape_string(smart_str *buf, zstr s, int len, > zend_uchar type, int options); > > static int json_determine_array_type(zval **val TSRMLS_DC) /* {{{ */ > { > @@ -115,7 +131,7 @@ static int json_determine_array_type(zva > } > /* }}} */ > > -static void json_encode_array(smart_str *buf, zval **val TSRMLS_DC) /* > {{{ */ > +static void json_encode_array(smart_str *buf, zval **val, int options > TSRMLS_DC) /* {{{ */ > { > int i, r; > HashTable *myht; > @@ -172,7 +188,7 @@ static void json_encode_array(smart_str > need_comma = 1; > } > > - json_encode_r(buf, *data TSRMLS_CC); > + json_encode_r(buf, *data, options > TSRMLS_CC); > } else if (r == 1) { > if (i == HASH_KEY_IS_STRING || > i == HASH_KEY_IS_UNICODE) { > @@ -187,10 +203,10 @@ static void json_encode_array(smart_str > need_comma = 1; > } > > - json_escape_string(buf, key, > key_len - 1, > (i==HASH_KEY_IS_UNICODE)?IS_UNICODE:IS_STRING); > + json_escape_string(buf, key, > key_len - 1, > (i==HASH_KEY_IS_UNICODE)?IS_UNICODE:IS_STRING, options); > smart_str_appendc(buf, ':'); > > - json_encode_r(buf, *data > TSRMLS_CC); > + json_encode_r(buf, *data, > options TSRMLS_CC); > } else { > if (need_comma) { > > smart_str_appendc(buf, ','); > @@ -203,7 +219,7 @@ static void json_encode_array(smart_str > smart_str_appendc(buf, '"'); > smart_str_appendc(buf, ':'); > > - json_encode_r(buf, *data > TSRMLS_CC); > + json_encode_r(buf, *data, > options TSRMLS_CC); > } > } > > @@ -227,7 +243,7 @@ static void json_encode_array(smart_str > > #define REVERSE16(us) (((us & 0xf) << 12) | (((us >> 4) & 0xf) << 8) | > (((us >> 8) & 0xf) << 4) | ((us >> 12) & 0xf)) > > -static void json_escape_string(smart_str *buf, zstr s, int len, > zend_uchar type) /* {{{ */ > +static void json_escape_string(smart_str *buf, zstr s, int len, > zend_uchar type, int options) /* {{{ */ > { > int pos = 0; > unsigned short us; > @@ -305,6 +321,42 @@ static void json_escape_string(smart_str > smart_str_appendl(buf, "\\t", 2); > } > break; > + case '<': > + { > + if (options & PHP_JSON_HEX_TAG) { > + smart_str_appendl(buf, > "\\u003C", 6); > + } else { > + smary_str_appendc(buf, '<'); > + } > + } > + break; > + case '>': > + { > + if (options & PHP_JSON_HEX_TAG) { > + smart_str_appendl(buf, > "\\u003E", 6); > + } else { > + smary_str_appendc(buf, '>'); > + } > + } > + break; > + case '&': > + { > + if (options & PHP_JSON_HEX_AMP) { > + smart_str_appendl(buf, > "\\u0026", 6); > + } else { > + smary_str_appendc(buf, '&'); > + } > + } > + break; > + case '\'': > + { > + if (options & PHP_JSON_HEX_APOS) { > + smart_str_appendl(buf, > "\\u0027", 6); > + } else { > + smary_str_appendc(buf, '\''); > + } > + } > + break; > default: > { > if (us >= ' ' && (us & 127) == us) > @@ -337,7 +389,7 @@ static void json_escape_string(smart_str > } > /* }}} */ > > -static void json_encode_r(smart_str *buf, zval *val TSRMLS_DC) /* {{{ */ > +static void json_encode_r(smart_str *buf, zval *val, int options > TSRMLS_DC) /* {{{ */ > { > switch (Z_TYPE_P(val)) { > case IS_NULL: > @@ -374,11 +426,11 @@ static void json_encode_r(smart_str *buf > break; > case IS_STRING: > case IS_UNICODE: > - json_escape_string(buf, Z_UNIVAL_P(val), > Z_UNILEN_P(val), > Z_TYPE_P(val)); > + json_escape_string(buf, Z_UNIVAL_P(val), > Z_UNILEN_P(val), > Z_TYPE_P(val), options); > break; > case IS_ARRAY: > case IS_OBJECT: > - json_encode_array(buf, &val TSRMLS_CC); > + json_encode_array(buf, &val, options TSRMLS_CC); > break; > default: > zend_error(E_WARNING, "[json] (json_encode_r) type is > unsupported, > encoded as null."); > @@ -396,12 +448,13 @@ PHP_FUNCTION(json_encode) > { > zval *parameter; > smart_str buf = {0}; > + long options = 0; > > - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) > == FAILURE) { > + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", > ¶meter, &options) == FAILURE) { > return; > } > > - json_encode_r(&buf, parameter TSRMLS_CC); > + json_encode_r(&buf, parameter, options TSRMLS_CC); > > /* > * Return as binary string, since the result is 99% likely to be just > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > -- Alexey Zakhlestin http://blog.milkfarmsoft.com/