diff --git a/src/ngx_http_lua_util.c b/src/ngx_http_lua_util.c index e9d40fc0e3..9e263841de 100644 --- a/src/ngx_http_lua_util.c +++ b/src/ngx_http_lua_util.c @@ -1843,6 +1843,26 @@ ngx_http_lua_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; + + /* not ALPHA, DIGIT, "-", ".", "_", "~" */ + + static uint32_t uri_component[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0xfc00987d, /* 1111 1100 0000 0000 1001 1000 0111 1101 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x78000001, /* 0111 1000 0000 0000 0000 0000 0000 0001 */ + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ @@ -1912,8 +1932,7 @@ ngx_http_lua_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) /* mail_auth is the same as memcached */ static uint32_t *map[] = - { uri, args, html, refresh, memcached, memcached }; - + { uri, args, uri_component, html, refresh, memcached, memcached }; escape = map[type]; @@ -2320,7 +2339,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, key = (u_char *) lua_tolstring(L, -2, &key_len); key_escape = 2 * ngx_http_lua_escape_uri(NULL, key, key_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT); total_escape += key_escape; switch (lua_type(L, -1)) { @@ -2329,7 +2348,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, value = (u_char *) lua_tolstring(L, -1, &value_len); total_escape += 2 * ngx_http_lua_escape_uri(NULL, value, value_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT); len += key_len + value_len + (sizeof("=") - 1); n++; @@ -2370,7 +2389,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, total_escape += 2 * ngx_http_lua_escape_uri(NULL, value, value_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT); len += key_len + value_len + (sizeof("=") - 1); } @@ -2427,7 +2446,8 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, if (total_escape) { p = (u_char *) ngx_http_lua_escape_uri(p, key, key_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT + ); } else { dd("shortcut: no escape required"); @@ -2441,7 +2461,8 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, if (total_escape) { p = (u_char *) ngx_http_lua_escape_uri(p, value, value_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT + ); } else { p = ngx_copy(p, value, value_len); @@ -2460,7 +2481,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, if (lua_toboolean(L, -1)) { if (total_escape) { p = (u_char *) ngx_http_lua_escape_uri(p, key, key_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT); } else { dd("shortcut: no escape required"); @@ -2488,7 +2509,7 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, if (total_escape) { p = (u_char *) ngx_http_lua_escape_uri(p, key, key_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT); } else { dd("shortcut: no escape required"); @@ -2507,7 +2528,8 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, p = (u_char *) ngx_http_lua_escape_uri(p, key, key_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT + ); } else { dd("shortcut: no escape required"); @@ -2523,7 +2545,8 @@ ngx_http_lua_process_args_option(ngx_http_request_t *r, lua_State *L, p = (u_char *) ngx_http_lua_escape_uri(p, value, value_len, - NGX_ESCAPE_URI); + NGX_ESCAPE_URI_COMPONENT + ); } else { p = ngx_copy(p, value, value_len); diff --git a/t/030-uri-args.t b/t/030-uri-args.t index 2f18ba7a8a..e0835d41dd 100644 --- a/t/030-uri-args.t +++ b/t/030-uri-args.t @@ -9,7 +9,7 @@ log_level('warn'); repeat_each(2); #repeat_each(1); -plan tests => repeat_each() * (blocks() * 2 + 17); +plan tests => repeat_each() * (blocks() * 2 + 18); no_root_location(); @@ -749,7 +749,21 @@ args: -=== TEST 33: ngx.encode_args (bad arg) +=== TEST 33: ngx.encode_args (escaping) +--- config + location /lua { + content_by_lua ' + local t = {bar = "-_.!~*\'()", foo = ",$@|`"} + ngx.say("args: ", ngx.encode_args(t)) + '; + } +--- request +GET /lua +--- response_body +args: foo=%2C%24%40%7C%60&bar=-_.!~*'() + + +=== TEST 34: ngx.encode_args (bad arg) --- config location /lua { content_by_lua ' @@ -764,7 +778,7 @@ rc: false, err: bad argument #1 to '?' (table expected, got boolean) -=== TEST 34: max args (limited after normal key=value) +=== TEST 35: max args (limited after normal key=value) --- config location /lua { content_by_lua ' @@ -791,7 +805,7 @@ lua hit query args limit 2 -=== TEST 35: max args (limited after an orphan key) +=== TEST 36: max args (limited after an orphan key) --- config location /lua { content_by_lua ' @@ -818,7 +832,7 @@ lua hit query args limit 2 -=== TEST 36: max args (limited after an empty key, but non-emtpy values) +=== TEST 37: max args (limited after an empty key, but non-emtpy values) --- config location /lua { content_by_lua ' @@ -847,7 +861,7 @@ lua hit query args limit 2 -=== TEST 37: default max 100 args +=== TEST 38: default max 100 args --- config location /lua { content_by_lua ' @@ -895,7 +909,7 @@ lua hit query args limit 100 -=== TEST 38: custom max 102 args +=== TEST 39: custom max 102 args --- config location /lua { content_by_lua ' @@ -943,7 +957,7 @@ lua hit query args limit 102 -=== TEST 39: custom unlimited args +=== TEST 40: custom unlimited args --- config location /lua { content_by_lua ' @@ -988,7 +1002,7 @@ CORE::join("", @k); -=== TEST 40: rewrite uri and args (multi-value args) +=== TEST 41: rewrite uri and args (multi-value args) --- config location /bar { echo $server_protocol $query_string; @@ -1008,7 +1022,7 @@ HTTP/1.0 a=3&b=5&b=6 -=== TEST 41: ngx.decode_args (sanity) +=== TEST 42: ngx.decode_args (sanity) --- config location /lua { content_by_lua ' @@ -1026,7 +1040,7 @@ b = foo -=== TEST 42: ngx.decode_args (multi-value) +=== TEST 43: ngx.decode_args (multi-value) --- config location /lua { content_by_lua ' @@ -1044,7 +1058,7 @@ b = foo -=== TEST 43: ngx.decode_args (empty string) +=== TEST 44: ngx.decode_args (empty string) --- config location /lua { content_by_lua ' @@ -1060,7 +1074,7 @@ n = 0 -=== TEST 44: ngx.decode_args (boolean args) +=== TEST 45: ngx.decode_args (boolean args) --- config location /lua { content_by_lua ' @@ -1078,7 +1092,7 @@ b = true -=== TEST 45: ngx.decode_args (empty value args) +=== TEST 46: ngx.decode_args (empty value args) --- config location /lua { content_by_lua ' @@ -1096,7 +1110,7 @@ b = -=== TEST 46: ngx.decode_args (max_args = 1) +=== TEST 47: ngx.decode_args (max_args = 1) --- config location /lua { content_by_lua ' @@ -1114,7 +1128,7 @@ b = nil -=== TEST 47: ngx.decode_args (max_args = -1) +=== TEST 48: ngx.decode_args (max_args = -1) --- config location /lua { content_by_lua ' @@ -1132,7 +1146,7 @@ b = foo -=== TEST 48: ngx.decode_args should not modify lua strings in place +=== TEST 49: ngx.decode_args should not modify lua strings in place --- config location /lua { content_by_lua ' @@ -1160,7 +1174,7 @@ s = f+f=bar&B=foo -=== TEST 49: ngx.decode_args should not modify lua strings in place (sample from Xu Jian) +=== TEST 50: ngx.decode_args should not modify lua strings in place (sample from Xu Jian) --- config lua_need_request_body on; location /t { @@ -1220,7 +1234,7 @@ method: zadd -=== TEST 50: recursive rewrite +=== TEST 51: recursive rewrite --- config rewrite_by_lua ' local args = ngx.var.args @@ -1252,7 +1266,7 @@ rewrite or internal redirection cycle while processing "/jump" -=== TEST 51: boolean values in ngx.encode_args (trailing arg) +=== TEST 52: boolean values in ngx.encode_args (trailing arg) --- config location /lua { set_by_lua $args_str ' @@ -1276,7 +1290,7 @@ GET /lua -=== TEST 52: false boolean values in ngx.encode_args +=== TEST 53: false boolean values in ngx.encode_args --- config location /lua { set_by_lua $args_str ' @@ -1299,7 +1313,7 @@ GET /lua -=== TEST 53: false boolean values in ngx.encode_args (escaping) +=== TEST 54: false boolean values in ngx.encode_args (escaping) --- config location /lua { set_by_lua $args_str ' @@ -1322,7 +1336,7 @@ GET /lua -=== TEST 54: true boolean values in ngx.encode_args (escaping) +=== TEST 55: true boolean values in ngx.encode_args (escaping) --- config location /lua { set_by_lua $args_str ' @@ -1346,7 +1360,7 @@ GET /lua -=== TEST 55: rewrite uri and args (boolean in multi-value args) +=== TEST 56: rewrite uri and args (boolean in multi-value args) --- config location /bar { echo $server_protocol $query_string; @@ -1372,7 +1386,7 @@ GET /lua -=== TEST 56: rewrite uri and args (boolean value) +=== TEST 57: rewrite uri and args (boolean value) --- config location /bar { echo $server_protocol $query_string;