Skip to content

Commit 3875a33

Browse files
committed
bugfix: ngx.re.gsub() might throw out the "attempt to call a string value" exception when the "replace" argument is a Lua function and the subject string is large. thanks Zhu Maohai for reporting this issue.
1 parent 7ee528b commit 3875a33

File tree

2 files changed

+113
-3
lines changed

2 files changed

+113
-3
lines changed

src/ngx_http_lua_regex.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,7 +1492,7 @@ ngx_http_lua_ngx_re_sub_helper(lua_State *L, unsigned global)
14921492
}
14931493

14941494
if (func) {
1495-
lua_pushvalue(L, -1);
1495+
lua_pushvalue(L, 3);
14961496

14971497
lua_createtable(L, rc - 1 /* narr */, 1 /* nrec */);
14981498

@@ -1529,12 +1529,14 @@ ngx_http_lua_ngx_re_sub_helper(lua_State *L, unsigned global)
15291529
return luaL_argerror(L, 3, msg);
15301530
}
15311531

1532+
lua_insert(L, 1);
1533+
15321534
luaL_addlstring(&luabuf, (char *) &subj.data[cp_offset],
15331535
cap[0] - cp_offset);
15341536

15351537
luaL_addlstring(&luabuf, (char *) tpl.data, tpl.len);
15361538

1537-
lua_pop(L, 1);
1539+
lua_remove(L, 1);
15381540

15391541
cp_offset = cap[1];
15401542
offset = cp_offset;

t/037-gsub.t

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ log_level('warn');
99

1010
repeat_each(2);
1111

12-
plan tests => repeat_each() * (blocks() * 2 + 4);
12+
plan tests => repeat_each() * (blocks() * 2 + 8);
1313

1414
#no_diff();
1515
no_long_string();
@@ -255,3 +255,111 @@ n: 1
255255
--- no_error_log
256256
[error]
257257

258+
259+
260+
=== TEST 14: big subject string exceeding the luabuf chunk size (with trailing unmatched data, func repl)
261+
--- config
262+
location /re {
263+
content_by_lua '
264+
local subj = string.rep("a", 8000)
265+
.. string.rep("b", 1000)
266+
.. string.rep("a", 8000)
267+
.. string.rep("b", 1000)
268+
.. "aaa"
269+
270+
local function repl(m)
271+
return string.rep("c", string.len(m[0]))
272+
end
273+
274+
local s, n = ngx.re.gsub(subj, "b+", repl)
275+
ngx.say(s)
276+
ngx.say(n)
277+
';
278+
}
279+
--- request
280+
GET /re
281+
--- response_body eval
282+
("a" x 8000) . ("c" x 1000) . ("a" x 8000) . ("c" x 1000)
283+
. "aaa
284+
2
285+
"
286+
--- no_error_log
287+
[error]
288+
289+
290+
291+
=== TEST 15: big subject string exceeding the luabuf chunk size (without trailing unmatched data, func repl)
292+
--- config
293+
location /re {
294+
content_by_lua '
295+
local subj = string.rep("a", 8000)
296+
.. string.rep("b", 1000)
297+
.. string.rep("a", 8000)
298+
.. string.rep("b", 1000)
299+
300+
local function repl(m)
301+
return string.rep("c", string.len(m[0]))
302+
end
303+
304+
local s, n = ngx.re.gsub(subj, "b+", repl)
305+
ngx.say(s)
306+
ngx.say(n)
307+
';
308+
}
309+
--- request
310+
GET /re
311+
--- response_body eval
312+
("a" x 8000) . ("c" x 1000) . ("a" x 8000) . ("c" x 1000)
313+
. "\n2\n"
314+
--- no_error_log
315+
[error]
316+
317+
318+
319+
=== TEST 16: big subject string exceeding the luabuf chunk size (with trailing unmatched data, str repl)
320+
--- config
321+
location /re {
322+
content_by_lua '
323+
local subj = string.rep("a", 8000)
324+
.. string.rep("b", 1000)
325+
.. string.rep("a", 8000)
326+
.. string.rep("b", 1000)
327+
.. "aaa"
328+
329+
local s, n = ngx.re.gsub(subj, "b(b+)(b)", "$1 $2")
330+
ngx.say(s)
331+
ngx.say(n)
332+
';
333+
}
334+
--- request
335+
GET /re
336+
--- response_body eval
337+
("a" x 8000) . ("b" x 998) . " b" . ("a" x 8000) . ("b" x 998) . " baaa
338+
2
339+
"
340+
--- no_error_log
341+
[error]
342+
343+
344+
345+
=== TEST 17: big subject string exceeding the luabuf chunk size (without trailing unmatched data, str repl)
346+
--- config
347+
location /re {
348+
content_by_lua '
349+
local subj = string.rep("a", 8000)
350+
.. string.rep("b", 1000)
351+
.. string.rep("a", 8000)
352+
.. string.rep("b", 1000)
353+
354+
local s, n = ngx.re.gsub(subj, "b(b+)(b)", "$1 $2")
355+
ngx.say(s)
356+
ngx.say(n)
357+
';
358+
}
359+
--- request
360+
GET /re
361+
--- response_body eval
362+
("a" x 8000) . ("b" x 998) . " b" . ("a" x 8000) . ("b" x 998) . " b\n2\n"
363+
--- no_error_log
364+
[error]
365+

0 commit comments

Comments
 (0)