From 222c34a38563c033e61ea1fb6d70e73bc30b9851 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Mon, 11 Oct 2021 19:55:09 -0500 Subject: [PATCH] Fix bug in initialization using string literals with embedded nulls. When using such a string literal to initialize an array with automatic storage duration, the bytes after the first null would be set to 0, rather than the values from the string literal. Here is an example program showing the problem: #include int main(void) { char s[] = "a\0b"; puts(s+2); } --- Parser.pas | 45 ++++++++++++++++++++++++++++++--------------- cc.notes | 2 ++ 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/Parser.pas b/Parser.pas index d7a8b27..f159617 100644 --- a/Parser.pas +++ b/Parser.pas @@ -4351,21 +4351,36 @@ var arrayType: begin elements := itype^.elements; if elements = 0 then goto 1; {don't init flexible array member} - if itype^.aType^.kind = scalarType then - if itype^.aType^.baseType in [cgByte,cgUByte] then - if iPtr^.iTree^.token.kind = stringConst then begin - GenLdcLong(itype^.elements); - Gen0t(pc_stk, cgULong); - GenS(pc_lca, iPtr^.iTree^.token.sval); - Gen0t(pc_stk, cgULong); - Gen0t(pc_bno, cgULong); - LoadAddress; - Gen0t(pc_stk, cgULong); - Gen0t(pc_bno, cgULong); - Gen1tName(pc_cup, 0, cgVoid, @'strncpy'); - iPtr := iPtr^.next; - goto 1; - end; {if} + if iPtr^.iTree^.token.kind = stringConst then begin + size := iPtr^.iTree^.token.sval^.length+1; + if size >= elements then + size := ord(elements) + else + size := size-1; + if size <> 0 then begin + GenLdcLong(size); + Gen0t(pc_stk, cgULong); + GenS(pc_lca, iPtr^.iTree^.token.sval); + Gen0t(pc_stk, cgULong); + Gen0t(pc_bno, cgULong); + LoadAddress; + Gen0t(pc_stk, cgULong); + Gen0t(pc_bno, cgULong); + Gen1tName(pc_cup, 0, cgVoid, @'memcpy'); + end; {if} + if size < elements then begin + elements := elements - size; + disp := disp + size; + LoadAddress; + Gen0t(pc_stk, cgULong); + Gen1t(pc_ldc, ord(elements), cgWord); + Gen0t(pc_stk, cgWord); + Gen0t(pc_bno, cgULong); + Gen1tName(pc_cup, 0, cgVoid, @'~ZERO'); + end; {if} + iPtr := iPtr^.next; + goto 1; + end; {if} itype := itype^.atype; if ZeroFill(elements, itype, count, iPtr) then begin if itype^.kind = enumType then diff --git a/cc.notes b/cc.notes index baf13cc..2cd0983 100644 --- a/cc.notes +++ b/cc.notes @@ -1357,6 +1357,8 @@ int foo(int[42]); 166. The fields of structures and unions should be accessible from any expression of structure or union type, including assignments and function calls. For example, if x and y have type "struct S {int i;}", then (x=y).i is a legal expression that performs an assignment and then gets the value of the i field. Similarly, f().i is a legal expression if the function call f() has a return type of struct S. These expressions were not being accepted, but now they are. +167. If an array with automatic storage duration was initialized from a string literal containing an embedded null byte (e.g. char s[] = "a\0b"), characters after the null byte would not be properly initialized. + -- Bugs from C 2.1.0 that have been fixed ----------------------------------- 1. In some situations, fread() reread the first 1K or so of the file.