From 45cc0a0721bb8c5f8d486576b4c662a3eb185bdf Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sun, 16 Oct 2016 22:56:34 -0500 Subject: [PATCH] Prevent struct/union members from having incomplete type, except for flexible array member. ORCA/C previously allowed struct/union members to be declared with incomplete type. Because of this, it allowed C99-style flexible array members to be declared, albeit by accident rather than by design. In some basic testing, these seem to work correctly, except that they could be initialized and that would give rise to odd behavior. I have restricted it to allowing flexible array members only in the cases allowed by C99/C11, and otherwise disallowing members with incomplete type. I have also prohibited initializing flexible array members. --- Parser.pas | 13 ++++++++++++- Scanner.pas | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Parser.pas b/Parser.pas index 9837d81..537df7f 100644 --- a/Parser.pas +++ b/Parser.pas @@ -2298,7 +2298,8 @@ var count := tp^.size; ip := tp^.fieldList; bitCount := 0; - while (ip <> nil) and (token.kind <> rbracech) do begin + while (ip <> nil) and (ip^.itype^.size > 0) + and (token.kind <> rbracech) do begin if ip^.isForwardDeclared then ResolveForwardReference(ip); InitializeTerm(ip^.itype, ip^.bitsize, ip^.bitdisp, false); @@ -2449,6 +2450,7 @@ var lstorageClass: tokenEnum; {storage class of the declaration} maxDisp: longint; {for determining union sizes} variable: identPtr; {variable being defined} + didFlexibleArray: boolean; {have we seen a flexible array member?} begin {FieldList} ldoingParameters := doingParameters; {allow fields in K&R dec. area} @@ -2459,6 +2461,7 @@ var bitDisp := 0; {start allocation from byte 0} disp := 0; maxDisp := 0; + didFlexibleArray := false; fl := nil; {nothing in the field list, yet} {check for no declarations} if not (token.kind in [unsignedsy,signedsy,intsy,longsy,charsy,shortsy, @@ -2473,6 +2476,8 @@ var TypeSpecifier(true,false); {get the type specifier} if not skipDeclarator then repeat {declare the variables...} + if didFlexibleArray then + Error(118); variable := nil; if token.kind <> colonch then begin Declarator(typeSpec, variable, fieldListSpace, false); @@ -2535,6 +2540,12 @@ var disp := disp + variable^.itype^.size; if disp > maxDisp then maxDisp := disp; + if variable^.itype^.size = 0 then + if (variable^.itype^.kind = arrayType) + and (disp > 0) then {handle flexible array member} + didFlexibleArray := true + else + Error(117); end {if} else Error(116); diff --git a/Scanner.pas b/Scanner.pas index 4e2e117..40e6186 100644 --- a/Scanner.pas +++ b/Scanner.pas @@ -597,6 +597,8 @@ if list or (numErr <> 0) then begin 114: msg := @'a function call was made to a non-function'; 115: msg := @'illegal bit field declaration'; 116: msg := @'missing field name'; + 117: msg := @'field cannot have incomplete type'; + 118: msg := @'flexible array must be last member of structure'; otherwise: Error(57); end; {case} writeln(msg^);