Skip to content

Commit 1f6a9ff

Browse files
committed
sf.net #910: cast(string, variable) can cause fbc to segfault
- due to (infinite recursion), and misplaced const & non-const casting handling (cherry picked from commit be95dec)
1 parent f2a27ad commit 1f6a9ff

File tree

12 files changed

+188
-5
lines changed

12 files changed

+188
-5
lines changed

changelog.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ Version 1.07.1
1414

1515
[fixed]
1616
- makefile: under MSYS2 (and friends), TARGET_ARCH is now identified from shell's default target architecture instead of shell's host architecture
17-
- gcc backend: pass '-Wno-format' to prevent format string errors in gcc 9.x (enabled by default with -Wall)
17+
- sf.net #904; gcc backend: pass '-Wno-format' to prevent format string errors in gcc 9.x (enabled by default with -Wall)
18+
- sf.net #910: cast(string, variable) can cause fbc to segfault (infinite recursion), due to misplaced const & non-const casting
1819

1920

2021
Version 1.07.0

src/compiler/ast-node-arg.bas

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,14 @@ private sub hCheckByrefParam _
290290
dim as ASTNODE ptr t = any
291291

292292
'' skip any casting if they won't do any conversion
293-
t = astSkipNoConvCAST( n->l )
293+
'' TODO: astSkipConstCASTs() will skip over any CONST conversions
294+
'' This is OK when generating the final AST, as we probably no longer care
295+
'' about CONST. However, if we ever get here and we expect PARSER/AST to
296+
'' return an error, or preserve the CONST conversion as part of the
297+
'' translation, this may introduce undesired behaviour. Need to verify.
298+
'' Specifically, using astSkipConstCASTs() instead of astSkipNoConvCAST()
299+
'' allows us to fix the fbc crash as reported in sf.net bug #910
300+
t = astSkipConstCASTs( n->l )
294301

295302
'' If it's a CALL returning a STRING, it actually returns a pointer,
296303
'' which can be passed to the BYREF param as-is

src/compiler/ast-node-conv.bas

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,15 @@ function astLoadCONV _
724724

725725
end function
726726

727+
function astSkipConstCASTs( byval n as ASTNODE ptr ) as ASTNODE ptr
728+
function = n
729+
if( n->class = AST_NODECLASS_CONV ) then
730+
if( n->cast.doconv = FALSE ) then
731+
function = n->l
732+
end if
733+
end if
734+
end function
735+
727736
function astSkipNoConvCAST( byval n as ASTNODE ptr ) as ASTNODE ptr
728737
function = n
729738
if( n->class = AST_NODECLASS_CONV ) then

src/compiler/ast.bi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ declare sub astUpdateCONVFD2FS _
561561
byval is_expr as integer _
562562
)
563563

564+
declare function astSkipConstCASTs( byval n as ASTNODE ptr ) as ASTNODE ptr
564565
declare function astSkipNoConvCAST( byval n as ASTNODE ptr ) as ASTNODE ptr
565566
declare function astRemoveNoConvCAST( byval n as ASTNODE ptr ) as ASTNODE ptr
566567
declare function astSkipCASTs( byval n as ASTNODE ptr ) as ASTNODE ptr

src/compiler/parser-expr-unary.bas

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,13 @@ private function hVarPtrBody _
488488
end if
489489

490490
'' skip any casting if they won't do any conversion
491-
dim as ASTNODE ptr t = astSkipNoConvCAST( expr )
491+
'' TODO: replace astSkipNoConvCast() with astSkipConstCASTs()
492+
'' where applicable. Need to verify. On one hand, we
493+
'' probably don't care about CONST anymore, on the other
494+
'' hand, we need to make sure we don't prematurely optimize
495+
'' the CONST specifier away in the event that it is needed
496+
'' to be known with AST type checking later.
497+
dim as ASTNODE ptr t = astSkipConstCASTs( expr )
492498

493499
select case as const astGetClass( t )
494500
case AST_NODECLASS_VAR, AST_NODECLASS_IDX, AST_NODECLASS_DEREF, _

src/compiler/rtl-string.bas

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,8 +2539,8 @@ function rtlStrAssign _
25392539
'' always calc len before pushing the param
25402540
lgt = rtlCalcStrLen( src, sdtype )
25412541

2542-
'' src as any
2543-
if( astNewARG( proc, src, astGetDataType( src ) ) = NULL ) then
2542+
'' src as const any
2543+
if( astNewARG( proc, src ) = NULL ) then
25442544
exit function
25452545
end if
25462546

tests/warnings/const-discard.bas

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,3 +1040,72 @@ sub const_udt_array( byref s as const shape )
10401040
WARN(0)
10411041
print s.points(0).x
10421042
end sub
1043+
1044+
'' --------------------------------------------------------
1045+
1046+
'' from https://www.freebasic.net/forum/viewtopic.php?f=17&t=27692
1047+
'' and https://sourceforge.net/p/fbc/bugs/910/
1048+
1049+
#print "---- Regression Checks"
1050+
1051+
sub const_cast_string1( byval s as string )
1052+
end sub
1053+
sub const_cast_string2( byref s as const string )
1054+
WARN(1)
1055+
const_cast_string1( cast(string, s) )
1056+
end sub
1057+
1058+
scope
1059+
dim x as const string = "test"
1060+
dim y as string
1061+
WARN(1)
1062+
y = cast(string, x )
1063+
WARN(0)
1064+
y = cast(const string, x )
1065+
end scope
1066+
1067+
type T_integer
1068+
__ as integer
1069+
end type
1070+
1071+
sub const_cast_proc1i( byval i as integer ptr )
1072+
end sub
1073+
sub const_cast_proc2i( byval i as const integer ptr )
1074+
end sub
1075+
1076+
sub const_cast_proc1t( byval x as T_integer ptr )
1077+
end sub
1078+
sub const_cast_proc2t( byval x as const T_integer ptr )
1079+
end sub
1080+
1081+
scope
1082+
dim i as const integer = 1
1083+
WARN(1)
1084+
const_cast_proc1i( @cast(integer, i) )
1085+
WARN(0)
1086+
const_cast_proc2i( @cast(const integer, i) )
1087+
end scope
1088+
1089+
scope
1090+
dim i as integer = 1
1091+
WARN(1)
1092+
const_cast_proc2i( @cast(const integer, i) )
1093+
WARN(0)
1094+
const_cast_proc2i( @cast(integer, i) )
1095+
end scope
1096+
1097+
scope
1098+
dim x as const T_integer = ( 1 )
1099+
WARN(1)
1100+
const_cast_proc1t( @cast(T_integer, x) )
1101+
WARN(0)
1102+
const_cast_proc2t( @cast(const T_integer, x) )
1103+
end scope
1104+
1105+
scope
1106+
dim x as T_integer = ( 1 )
1107+
WARN(1)
1108+
const_cast_proc2t( @cast(const T_integer,x) )
1109+
WARN(0)
1110+
const_cast_proc2t( @cast(T_integer,x) )
1111+
end scope

tests/warnings/r/dos/const-discard.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,3 +420,21 @@ none expected
420420
none expected
421421
none expected
422422
none expected
423+
---- Regression Checks
424+
warning expected
425+
CONST qualifier discarded
426+
warning expected
427+
CONST qualifier discarded
428+
none expected
429+
warning expected
430+
CONST qualifier discarded
431+
none expected
432+
warning expected
433+
CONST qualifier discarded
434+
none expected
435+
warning expected
436+
CONST qualifier discarded
437+
none expected
438+
warning expected
439+
CONST qualifier discarded
440+
none expected

tests/warnings/r/linux-x86/const-discard.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,3 +420,21 @@ none expected
420420
none expected
421421
none expected
422422
none expected
423+
---- Regression Checks
424+
warning expected
425+
CONST qualifier discarded
426+
warning expected
427+
CONST qualifier discarded
428+
none expected
429+
warning expected
430+
CONST qualifier discarded
431+
none expected
432+
warning expected
433+
CONST qualifier discarded
434+
none expected
435+
warning expected
436+
CONST qualifier discarded
437+
none expected
438+
warning expected
439+
CONST qualifier discarded
440+
none expected

tests/warnings/r/linux-x86_64/const-discard.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,3 +420,21 @@ none expected
420420
none expected
421421
none expected
422422
none expected
423+
---- Regression Checks
424+
warning expected
425+
CONST qualifier discarded
426+
warning expected
427+
CONST qualifier discarded
428+
none expected
429+
warning expected
430+
CONST qualifier discarded
431+
none expected
432+
warning expected
433+
CONST qualifier discarded
434+
none expected
435+
warning expected
436+
CONST qualifier discarded
437+
none expected
438+
warning expected
439+
CONST qualifier discarded
440+
none expected

0 commit comments

Comments
 (0)