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 <stdio.h>
int main(void) {
        char s[] = "a\0b";
        puts(s+2);
}
This commit is contained in:
Stephen Heumann 2021-10-11 19:55:09 -05:00
parent b076f85149
commit 222c34a385
2 changed files with 32 additions and 15 deletions

View File

@ -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

View File

@ -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.