You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Following batch generates script with arbitrary level of nesting BEGIN..END statements within single EB:
@echo off
setlocal enabledelayedexpansion enableextensions
cls
set fq=%1
if .%fq%.==.. set fq=3
set sql=%~n0.tmp
del %sql% 2>nul
echo show version;>>%sql%
echo recreate exception ex_test 'Hi from Mariana Trench, depth=@1, time=@2';>>%sql%
echo recreate sequence g;>>%sql%
echo commit;>>%sql%
echo set list on;>>%sql%
echo select current_timestamp as dts_start from rdb$database;>>%sql%
echo set term ^^;>>%sql%
echo execute block as>>%sql%
echo declare n int = 0;>>%sql%
echo begin>>%sql%
for /l %%i in (1, 1, %fq%) do (
echo begin -- level = %%i>>%sql%
echo n = gen_id(g, 1^);>>%sql%
)
for /l %%i in (%fq%, -1, 1) do (
if .%%i.==.%fq%. echo exception ex_test using( n, cast('now' as timestamp^) ^);>>%sql%
echo end -- level = %%i>>%sql%
)
echo end^^>>%sql%
echo set term ;^^>>%sql%
echo select current_timestamp as dts_finish from rdb$database;>>%sql%
echo commit;>>%sql%
When running this batch w/o arguments nesting level will be 3 (default) and resulting script will be like this:
show version;
recreate exception ex_test 'Hi from Mariana Trench, depth=@1, time=@2';
recreate sequence g;
commit;
set list on;
select current_timestamp as dts_start from rdb$database;
set term ^;
execute block as
declare n int = 0;
begin
begin -- level = 1
n = gen_id(g, 1);
begin -- level = 2
n = gen_id(g, 1);
begin -- level = 3
n = gen_id(g, 1);
exception ex_test using( n, cast('now' as timestamp) );
end -- level = 3
end -- level = 2
end -- level = 1
end^
set term ;^
select current_timestamp as dts_finish from rdb$database;
commit;
FB can handle w/o any problem script with nesting level up to 10'000, though it is absolutely unreal in practice to use such things.
When this script containing ~12000 nested begin..end's on Windows one may to obtain:
Statement failed, SQLSTATE = HY001
Stack overflow. The resource requirements of the runtime stack have exceeded the memory available to it.
-- and that final, of course, is explainable.
But when this batch is used for generating scripts with enormous level, say ~15-20 thousands, FB crashes (on Linux) or hangs without ability to stop script or server (on Windows).
For my Linux environment I got two crashes, one with BugCheckAbort=1 and second w/o thi option in config.
The problem is that I can not wait till stacktrace building will finish: gdb creates text file with huge size and does this infinitely.
I've interrupted process of stacktrace creation and both these files can be see in attach.
It will be nice if parser will bound limit of nesting up to 255 (like contexts number in SQL statements), because greater values obviously illustrates that something wrong in PSQL code.
summary: Crash on pasring of script containing `execute block` with lot of nested begin..end statements => Crash on parsing of script containing `execute block` with lot of nested begin..end statements
Submitted by: @pavel-zotov
Attachments:
gdb-huge-number-of-nested-begin-ends.rar
Following batch generates script with arbitrary level of nesting BEGIN..END statements within single EB:
@echo off
setlocal enabledelayedexpansion enableextensions
cls
set fq=%1
if .%fq%.==.. set fq=3
set sql=%~n0.tmp
del %sql% 2>nul
echo show version;>>%sql%
echo recreate exception ex_test 'Hi from Mariana Trench, depth=@1, time=@2';>>%sql%
echo recreate sequence g;>>%sql%
echo commit;>>%sql%
echo set list on;>>%sql%
echo select current_timestamp as dts_start from rdb$database;>>%sql%
echo set term ^^;>>%sql%
echo execute block as>>%sql%
echo declare n int = 0;>>%sql%
echo begin>>%sql%
for /l %%i in (1, 1, %fq%) do (
echo begin -- level = %%i>>%sql%
echo n = gen_id(g, 1^);>>%sql%
)
for /l %%i in (%fq%, -1, 1) do (
if .%%i.==.%fq%. echo exception ex_test using( n, cast('now' as timestamp^) ^);>>%sql%
echo end -- level = %%i>>%sql%
)
echo end^^>>%sql%
echo set term ;^^>>%sql%
echo select current_timestamp as dts_finish from rdb$database;>>%sql%
echo commit;>>%sql%
When running this batch w/o arguments nesting level will be 3 (default) and resulting script will be like this:
show version;
recreate exception ex_test 'Hi from Mariana Trench, depth=@1, time=@2';
recreate sequence g;
commit;
set list on;
select current_timestamp as dts_start from rdb$database;
set term ^;
execute block as
declare n int = 0;
begin
begin -- level = 1
n = gen_id(g, 1);
begin -- level = 2
n = gen_id(g, 1);
begin -- level = 3
n = gen_id(g, 1);
exception ex_test using( n, cast('now' as timestamp) );
end -- level = 3
end -- level = 2
end -- level = 1
end^
set term ;^
select current_timestamp as dts_finish from rdb$database;
commit;
FB can handle w/o any problem script with nesting level up to 10'000, though it is absolutely unreal in practice to use such things.
When this script containing ~12000 nested begin..end's on Windows one may to obtain:
Statement failed, SQLSTATE = HY001
Stack overflow. The resource requirements of the runtime stack have exceeded the memory available to it.
-- and that final, of course, is explainable.
But when this batch is used for generating scripts with enormous level, say ~15-20 thousands, FB crashes (on Linux) or hangs without ability to stop script or server (on Windows).
For my Linux environment I got two crashes, one with BugCheckAbort=1 and second w/o thi option in config.
The problem is that I can not wait till stacktrace building will finish: gdb creates text file with huge size and does this infinitely.
I've interrupted process of stacktrace creation and both these files can be see in attach.
It will be nice if parser will bound limit of nesting up to 255 (like contexts number in SQL statements), because greater values obviously illustrates that something wrong in PSQL code.
Commits: 9a2a88b FirebirdSQL/fbt-repository@ee43ce9 FirebirdSQL/fbt-repository@3d5d7fd
The text was updated successfully, but these errors were encountered: