aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2026-03-18 23:10:25 +0100
committerlemon <lsof@mailbox.org>2026-03-18 23:10:25 +0100
commit1b782f049fa96d7ebccf93ad2b05fc30b938c870 (patch)
treed4048328308d676f05a9312af63e55e09459da8e /src
parent626c927bb70519e630402093ff4fba432d2ac8c5 (diff)
c: fix edge cases with zero sized bitfields and static initializers
Diffstat (limited to 'src')
-rw-r--r--src/c.c13
-rw-r--r--src/c_eval.c8
2 files changed, 12 insertions, 9 deletions
diff --git a/src/c.c b/src/c.c
index 8c43f5f..0877b56 100644
--- a/src/c.c
+++ b/src/c.c
@@ -1461,6 +1461,7 @@ iniwrite(CComp *cm, InitParser *ip, uint off, uint bitsiz, uint bitoff, Type ty,
if (nerror) return;
if (ip->dyn) {
if (ip->ddat.n < off + siz) {
+ /* extending ddata, can only happen for unknown-size arrays */
uint old = ip->ddat.n;
vresize(&ip->ddat, off + siz);
memset(ip->ddat.p + old, 0, ip->ddat.n - old);
@@ -1702,7 +1703,7 @@ designators(InitParser *ip, CComp *cm)
bool some = 0;
for (;;) {
- uint off, bitsiz, bitoff;
+ uint off, bitsiz, bitoff;
uvlong idx = ~0ull;
if (match(cm, &tk, '[')) {
Expr ex = commaexpr(cm);
@@ -1879,8 +1880,9 @@ initializer(CComp *cm, Type *ty, enum evalmode ev, bool globl,
if (!nerror) {
off = objnewdat(sym, sec, globl, siz = typesize(*ty), align = typealign(*ty));
p = sec == Srodata ? objout.rodata.p : objout.data.p;
+ assert(ip->ddat.n <= siz);
memcpy(p + off, ip->ddat.p, ip->ddat.n);
- memset(p + off + ip->ddat.n, 0, typesize(*ty) - ip->ddat.n);
+ memset(p + off + ip->ddat.n, 0, siz - ip->ddat.n);
for (InitReloc *rel = ip->drel; rel; rel = rel->link) {
objreloc(rel->sym, targ_64bit ? REL_ABS64 : REL_ABS32, sec, off + rel->off, rel->addend);
}
@@ -2028,11 +2030,8 @@ buildagg(CComp *cm, enum typetag tt, internstr name, int id)
} else {
bitsiz = ex.i;
if (bitsiz == 0) {
- if (bitftypesiz) {
- bitfbyteoff += bitftypesiz;
- bitfbyteoff = alignup(bitfbyteoff, typealign(decl.ty));
- }
- bitoff = 0;
+ bitsiz = bitftypesiz - bitoff;
+ continue;
} else if (bitftypesiz && bitftypesiz < tysize) {
/* end of previous bitfield */
bitoff = 0;
diff --git a/src/c_eval.c b/src/c_eval.c
index eff7e94..dce1457 100644
--- a/src/c_eval.c
+++ b/src/c_eval.c
@@ -139,7 +139,7 @@ truthy(const Expr *ex)
static bool
unop(Expr *ex, enum evalmode mode)
{
- Expr *sub = ex->sub;
+ Expr *sub = ex->sub, ex2;
if (mode >= EVSTATICINI && ex->t == EDEREF) {
uvlong off;
@@ -175,10 +175,14 @@ unop(Expr *ex, enum evalmode mode)
p = sub->sub[1].s.p, len = sub->sub[1].s.n;
csiz = typesize(typechild(sub->sub[1].ty));
goto StrRead;
+ } else if (ex->ty.t == TYARRAY && eval(sub, mode)) {
+ sub->ty = ex->ty;
+ *ex = *sub;
+ return 1;
} else return 0;
} else if (ex->t == EADDROF) {
assert(ex->ty.t == TYPTR);
- Expr ex2 = staticaddrof(ex->sub, mode);
+ ex2 = staticaddrof(ex->sub, mode);
if (!ex2.t) return 0;
ex2.span = ex->span;
ex2.ty = ex->ty;