Skip to content

Commit ba0be2f

Browse files
committed
C++: Better discriminate for unions.
1 parent 4ba5059 commit ba0be2f

File tree

1 file changed

+25
-7
lines changed

1 file changed

+25
-7
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,18 +1616,35 @@ predicate localExprFlow(Expr e1, Expr e2) {
16161616
localExprFlowPlus(e1, e2)
16171617
}
16181618

1619+
bindingset[f]
1620+
pragma[inline_late]
1621+
private int getFieldSize(Field f) { result = f.getType().getSize() }
1622+
1623+
/**
1624+
* Gets a field in the union `u` whose size
1625+
* is `bytes` number of bytes.
1626+
*/
1627+
private Field getAFieldWithSize(Union u, int bytes) {
1628+
result = u.getAField() and
1629+
bytes = getFieldSize(result)
1630+
}
1631+
16191632
cached
16201633
private newtype TContent =
16211634
TFieldContent(Field f, int indirectionIndex) {
16221635
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(f.getUnspecifiedType())] and
16231636
// Reads and writes of union fields are tracked using `UnionContent`.
16241637
not f.getDeclaringType() instanceof Union
16251638
} or
1626-
TUnionContent(Union u, int indirectionIndex) {
1627-
// We key `UnionContent` by the union instead of its fields since a write to one
1628-
// field can be read by any read of the union's fields.
1629-
indirectionIndex =
1630-
[1 .. max(Ssa::getMaxIndirectionsForType(u.getAField().getUnspecifiedType()))]
1639+
TUnionContent(Union u, int bytes, int indirectionIndex) {
1640+
exists(Field f |
1641+
f = u.getAField() and
1642+
bytes = getFieldSize(f) and
1643+
// We key `UnionContent` by the union instead of its fields since a write to one
1644+
// field can be read by any read of the union's fields.
1645+
indirectionIndex =
1646+
[1 .. max(Ssa::getMaxIndirectionsForType(getAFieldWithSize(u, bytes).getUnspecifiedType()))]
1647+
)
16311648
}
16321649

16331650
/**
@@ -1669,8 +1686,9 @@ class FieldContent extends Content, TFieldContent {
16691686
class UnionContent extends Content, TUnionContent {
16701687
Union u;
16711688
int indirectionIndex;
1689+
int bytes;
16721690

1673-
UnionContent() { this = TUnionContent(u, indirectionIndex) }
1691+
UnionContent() { this = TUnionContent(u, bytes, indirectionIndex) }
16741692

16751693
override string toString() {
16761694
indirectionIndex = 1 and result = u.toString()
@@ -1679,7 +1697,7 @@ class UnionContent extends Content, TUnionContent {
16791697
}
16801698

16811699
/** Gets a field of the underlying union of this `UnionContent`, if any. */
1682-
Field getAField() { result = u.getAField() }
1700+
Field getAField() { result = u.getAField() and getFieldSize(result) = bytes }
16831701

16841702
/** Gets the underlying union of this `UnionContent`. */
16851703
Union getUnion() { result = u }

0 commit comments

Comments
 (0)