From b85a780dc1db240cbfc89131617dd926dd9ca121 Mon Sep 17 00:00:00 2001 From: coderJeff Date: Sat, 27 Jul 2019 20:58:37 -0400 Subject: [PATCH] fbc: SELECT CASE AS CONST jump table size - check for ranges that would produce unreasonably large jump tables (greater than 8192 entries) --- changelog.txt | 1 + src/compiler/parser-compound-select-const.bas | 29 +++++++++++++++++-- tests/compound/select-const-large-range-1.bas | 6 ++++ tests/compound/select-const-large-range-2.bas | 8 +++++ 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 tests/compound/select-const-large-range-1.bas create mode 100644 tests/compound/select-const-large-range-2.bas diff --git a/changelog.txt b/changelog.txt index 7c05614967..178a6fbdd5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -49,6 +49,7 @@ Version 1.07.0 - sf.net #893: 'Suffixes are only valid in -lang' error message showing incorrect -lang options allowed - fbc uses '-march=armv8-a' instead of invalid option '-march=aarch64' when passing options to gcc/LLVM (czsgaba) - rtlib: sys/io.h incorrectly included on systems that do not provide it. It is used only for x86, x86_64 and is unnecessary for all other linux targets (armhf ,arm64, mips ....) +- SELECT CASE AS CONST checks for ranges that would produce unreasonably large jump tables (greater than 8192 entries) Version 1.06.0 diff --git a/src/compiler/parser-compound-select-const.bas b/src/compiler/parser-compound-select-const.bas index 094030b145..b15eb3662e 100644 --- a/src/compiler/parser-compound-select-const.bas +++ b/src/compiler/parser-compound-select-const.bas @@ -223,6 +223,17 @@ sub cSelConstStmtNext( byval stk as FB_CMPSTMTSTK ptr ) '' first case? if( swtbase = ctx.base ) then + '' we initially set the bias to the first value minus + '' FB_MAXJUMPTBSLOTS. This allows us to compare range values + '' (fromvalue <= tovalue ) and check if ranges are too + '' large. Later, in cSelConstStmtEnd() we will adjust the + '' bias to the lowest valid range value seen. + + '' In terms of values used by the user: + '' minimum := bias + '' initial := bias + FB_MAXJUMPTBSLOTS + '' maximum := bias + FB_MAXJUMPTBSLOTS*2 + stk->select.const_.bias = value - FB_MAXJUMPTBSLOTS end if @@ -253,10 +264,17 @@ sub cSelConstStmtNext( byval stk as FB_CMPSTMTSTK ptr ) continue do end if - assert( value <= (FB_MAXJUMPTBSLOTS*2) ) - assert( tovalue <= (FB_MAXJUMPTBSLOTS*2) ) assert( tovalue >= value ) + '' check if emitted jump table would be too large. Even without this check, + '' emitter can still build a valid jump table, as it will fill in gaps + '' between ranges, however we limit the size here, as it might end up + '' unreasonably large. + if( (value >= FB_MAXJUMPTBSLOTS*2) or (tovalue >= FB_MAXJUMPTBSLOTS*2) ) then + errReport( FB_ERRMSG_RANGETOOLARGE ) + continue do + end if + '' Add Case values in range do if( hSelConstAddCase( swtbase, value, label ) = FALSE ) then @@ -323,6 +341,13 @@ sub cSelConstStmtEnd( byval stk as FB_CMPSTMTSTK ptr ) stk->select.const_.bias += adjust_bias end if + '' Jump table too large? We haven't overflowed any internal structures + '' and the emitter will produce valid code, but to be consistent with + '' limits and documentation, report an error. + if( span >= FB_MAXJUMPTBSLOTS ) then + errReport( FB_ERRMSG_TOOMANYLABELS ) + end if + astAdd( astBuildJMPTB( stk->select.sym, _ @ctx.casevalues(stk->select.const_.base), _ @ctx.caselabels(stk->select.const_.base), _ diff --git a/tests/compound/select-const-large-range-1.bas b/tests/compound/select-const-large-range-1.bas new file mode 100644 index 0000000000..b584478570 --- /dev/null +++ b/tests/compound/select-const-large-range-1.bas @@ -0,0 +1,6 @@ +' TEST_MODE : COMPILE_ONLY_FAIL + +dim x as integer +select case as const x +case 1 to 8193 +end select diff --git a/tests/compound/select-const-large-range-2.bas b/tests/compound/select-const-large-range-2.bas new file mode 100644 index 0000000000..e35184de58 --- /dev/null +++ b/tests/compound/select-const-large-range-2.bas @@ -0,0 +1,8 @@ +' TEST_MODE : COMPILE_ONLY_FAIL + +dim x as integer +select case as const x +case 8192 +case 8193 +case 1 +end select