Skip to content

Commit 75876b6

Browse files
committed
bugfix: ngx.req.get_uri_args and ngx.req.get_post_args now only parse up to 100 arguments by default. but one can specify the optional argument to these two methods to specify a custom maximum number of args. thanks Tzury Bar Yochay for reporting this.
1 parent 2b18629 commit 75876b6

File tree

4 files changed

+289
-10
lines changed

4 files changed

+289
-10
lines changed

src/ngx_http_lua_args.c

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99

1010
static int ngx_http_lua_parse_args(ngx_http_request_t *r, lua_State *L,
11-
u_char *buf, u_char *last);
11+
u_char *buf, u_char *last, int max);
1212
static int ngx_http_lua_ngx_req_set_uri_args(lua_State *L);
1313
static int ngx_http_lua_ngx_req_get_uri_args(lua_State *L);
1414
static int ngx_http_lua_ngx_req_get_post_args(lua_State *L);
@@ -80,10 +80,21 @@ ngx_http_lua_ngx_req_get_uri_args(lua_State *L) {
8080
u_char *buf;
8181
u_char *last;
8282
int retval;
83+
int n;
84+
int max;
8385

84-
if (lua_gettop(L) != 0) {
85-
return luaL_error(L, "expecting 0 arguments but seen %d",
86-
lua_gettop(L));
86+
n = lua_gettop(L);
87+
88+
if (n != 0 && n != 1) {
89+
return luaL_error(L, "expecting 0 or 1 arguments but seen %d", n);
90+
}
91+
92+
if (n == 1) {
93+
max = luaL_checkinteger(L, 1);
94+
lua_pop(L, 1);
95+
96+
} else {
97+
max = NGX_HTTP_LUA_MAX_ARGS;
8798
}
8899

89100
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
@@ -108,7 +119,7 @@ ngx_http_lua_ngx_req_get_uri_args(lua_State *L) {
108119

109120
last = buf + r->args.len;
110121

111-
retval = ngx_http_lua_parse_args(r, L, buf, last);
122+
retval = ngx_http_lua_parse_args(r, L, buf, last, max);
112123

113124
ngx_pfree(r->pool, buf);
114125

@@ -126,10 +137,21 @@ ngx_http_lua_ngx_req_get_post_args(lua_State *L)
126137
ngx_chain_t *cl;
127138
u_char *p;
128139
u_char *last;
140+
int n;
141+
int max;
129142

130-
if (lua_gettop(L) != 0) {
131-
return luaL_error(L, "expecting 0 arguments but seen %d",
132-
lua_gettop(L));
143+
n = lua_gettop(L);
144+
145+
if (n != 0 && n != 1) {
146+
return luaL_error(L, "expecting 0 or 1 arguments but seen %d", n);
147+
}
148+
149+
if (n == 1) {
150+
max = luaL_checkinteger(L, 1);
151+
lua_pop(L, 1);
152+
153+
} else {
154+
max = NGX_HTTP_LUA_MAX_ARGS;
133155
}
134156

135157
lua_getglobal(L, GLOBALS_SYMBOL_REQUEST);
@@ -184,7 +206,7 @@ ngx_http_lua_ngx_req_get_post_args(lua_State *L)
184206

185207
last = buf + len;
186208

187-
retval = ngx_http_lua_parse_args(r, L, buf, last);
209+
retval = ngx_http_lua_parse_args(r, L, buf, last, max);
188210

189211
ngx_pfree(r->pool, buf);
190212

@@ -194,12 +216,13 @@ ngx_http_lua_ngx_req_get_post_args(lua_State *L)
194216

195217
static int
196218
ngx_http_lua_parse_args(ngx_http_request_t *r, lua_State *L, u_char *buf,
197-
u_char *last)
219+
u_char *last, int max)
198220
{
199221
u_char *p, *q;
200222
u_char *src, *dst;
201223
unsigned parsing_value;
202224
size_t len;
225+
int count = 0;
203226

204227
p = buf;
205228

@@ -267,6 +290,13 @@ ngx_http_lua_parse_args(ngx_http_request_t *r, lua_State *L, u_char *buf,
267290
ngx_http_lua_set_multi_value_table(L, 1);
268291
}
269292

293+
if (max > 0 && ++count == max) {
294+
dd("gettop: %d", lua_gettop(L));
295+
dd("type: %s", lua_typename(L, lua_type(L, 1)));
296+
297+
return 1;
298+
}
299+
270300
} else {
271301
p++;
272302
}
@@ -302,6 +332,7 @@ ngx_http_lua_parse_args(ngx_http_request_t *r, lua_State *L, u_char *buf,
302332

303333
dd("gettop: %d", lua_gettop(L));
304334
dd("type: %s", lua_typename(L, lua_type(L, 1)));
335+
305336
if (lua_gettop(L) != 1) {
306337
return luaL_error(L, "internal error: stack in bad state");
307338
}

src/ngx_http_lua_common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ typedef struct {
5858
#endif
5959

6060

61+
#ifndef NGX_HTTP_LUA_MAX_ARGS
62+
#define NGX_HTTP_LUA_MAX_ARGS 100
63+
#endif
64+
65+
6166
typedef struct {
6267
lua_State *lua;
6368

t/030-uri-args.t

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,3 +763,121 @@ GET /lua
763763
--- response_body
764764
rc: false, err: bad argument #1 to '?' (table expected, got boolean)
765765

766+
767+
768+
=== TEST 35: max args (limited after normal key=value)
769+
--- config
770+
location /lua {
771+
content_by_lua '
772+
local args = ngx.req.get_uri_args(2)
773+
local keys = {}
774+
for key, val in pairs(args) do
775+
table.insert(keys, key)
776+
end
777+
778+
table.sort(keys)
779+
for i, key in ipairs(keys) do
780+
ngx.say(key, " = ", args[key])
781+
end
782+
';
783+
}
784+
--- request
785+
GET /lua?foo=3&bar=4&baz=2
786+
--- response_body
787+
bar = 4
788+
foo = 3
789+
790+
791+
792+
=== TEST 36: max args (limited after an orphan key)
793+
--- config
794+
location /lua {
795+
content_by_lua '
796+
local args = ngx.req.get_uri_args(2)
797+
local keys = {}
798+
for key, val in pairs(args) do
799+
table.insert(keys, key)
800+
end
801+
802+
table.sort(keys)
803+
for i, key in ipairs(keys) do
804+
ngx.say(key, " = ", args[key])
805+
end
806+
';
807+
}
808+
--- request
809+
GET /lua?foo=3&bar&baz=2
810+
--- response_body
811+
bar = true
812+
foo = 3
813+
814+
815+
816+
=== TEST 37: max args (limited after an empty key, but non-emtpy values)
817+
--- config
818+
location /lua {
819+
content_by_lua '
820+
local args = ngx.req.get_uri_args(2)
821+
local keys = {}
822+
for key, val in pairs(args) do
823+
table.insert(keys, key)
824+
end
825+
826+
table.sort(keys)
827+
for i, key in ipairs(keys) do
828+
ngx.say(key, " = ", args[key])
829+
end
830+
831+
ngx.say("done")
832+
';
833+
}
834+
--- request
835+
GET /lua?foo=3&=hello&=world
836+
--- response_body
837+
foo = 3
838+
done
839+
840+
841+
842+
=== TEST 38: default max 100 args
843+
--- config
844+
location /lua {
845+
content_by_lua '
846+
local args = ngx.req.get_uri_args()
847+
local keys = {}
848+
for key, val in pairs(args) do
849+
table.insert(keys, key)
850+
end
851+
852+
table.sort(keys)
853+
for i, key in ipairs(keys) do
854+
ngx.say(key, " = ", args[key])
855+
end
856+
';
857+
}
858+
--- request eval
859+
my $s = "GET /lua?";
860+
my $i = 1;
861+
while ($i <= 102) {
862+
if ($i != 1) {
863+
$s .= '&';
864+
}
865+
$s .= "a$i=$i";
866+
$i++;
867+
}
868+
$s
869+
--- response_body eval
870+
my @k;
871+
my $i = 1;
872+
while ($i <= 100) {
873+
push @k, "a$i";
874+
$i++;
875+
}
876+
@k = sort @k;
877+
for my $k (@k) {
878+
if ($k =~ /\d+/) {
879+
$k .= " = $&\n";
880+
}
881+
}
882+
CORE::join("", @k);
883+

t/031-post-args.t

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,128 @@ a=3&b=4&c
9696
POST /lua
9797
--- response_body
9898

99+
100+
101+
=== TEST 4: max args (limited after normal key=value)
102+
--- config
103+
location /lua {
104+
content_by_lua '
105+
ngx.req.read_body();
106+
local args = ngx.req.get_post_args(2)
107+
local keys = {}
108+
for key, val in pairs(args) do
109+
table.insert(keys, key)
110+
end
111+
112+
table.sort(keys)
113+
for i, key in ipairs(keys) do
114+
ngx.say(key, " = ", args[key])
115+
end
116+
';
117+
}
118+
--- request
119+
POST /lua
120+
foo=3&bar=4&baz=2
121+
--- response_body
122+
bar = 4
123+
foo = 3
124+
125+
126+
127+
=== TEST 5: max args (limited after an orphan key)
128+
--- config
129+
location /lua {
130+
content_by_lua '
131+
ngx.req.read_body();
132+
local args = ngx.req.get_post_args(2)
133+
local keys = {}
134+
for key, val in pairs(args) do
135+
table.insert(keys, key)
136+
end
137+
138+
table.sort(keys)
139+
for i, key in ipairs(keys) do
140+
ngx.say(key, " = ", args[key])
141+
end
142+
';
143+
}
144+
--- request
145+
POST /lua
146+
foo=3&bar&baz=2
147+
--- response_body
148+
bar = true
149+
foo = 3
150+
151+
152+
153+
=== TEST 6: max args (limited after an empty key, but non-emtpy values)
154+
--- config
155+
location /lua {
156+
content_by_lua '
157+
ngx.req.read_body();
158+
local args = ngx.req.get_post_args(2)
159+
local keys = {}
160+
for key, val in pairs(args) do
161+
table.insert(keys, key)
162+
end
163+
164+
table.sort(keys)
165+
for i, key in ipairs(keys) do
166+
ngx.say(key, " = ", args[key])
167+
end
168+
169+
ngx.say("done")
170+
';
171+
}
172+
--- request
173+
POST /lua
174+
foo=3&=hello&=world
175+
--- response_body
176+
foo = 3
177+
done
178+
179+
180+
181+
=== TEST 7: default max 100 args
182+
--- config
183+
location /lua {
184+
content_by_lua '
185+
ngx.req.read_body();
186+
local args = ngx.req.get_post_args()
187+
local keys = {}
188+
for key, val in pairs(args) do
189+
table.insert(keys, key)
190+
end
191+
192+
table.sort(keys)
193+
for i, key in ipairs(keys) do
194+
ngx.say(key, " = ", args[key])
195+
end
196+
';
197+
}
198+
--- request eval
199+
my $s = "POST /lua\n";
200+
my $i = 1;
201+
while ($i <= 102) {
202+
if ($i != 1) {
203+
$s .= '&';
204+
}
205+
$s .= "a$i=$i";
206+
$i++;
207+
}
208+
$s
209+
--- response_body eval
210+
my @k;
211+
my $i = 1;
212+
while ($i <= 100) {
213+
push @k, "a$i";
214+
$i++;
215+
}
216+
@k = sort @k;
217+
for my $k (@k) {
218+
if ($k =~ /\d+/) {
219+
$k .= " = $&\n";
220+
}
221+
}
222+
CORE::join("", @k);
223+

0 commit comments

Comments
 (0)