Skip to content

Commit 6275a01

Browse files
authored
Merge pull request github#12708 from MathiasVP/dont-break-ir-cfg-on-vla
C++: Don't produce partial CFGs when using VLAs
2 parents aeaeade + 65c7a50 commit 6275a01

File tree

9 files changed

+363
-25
lines changed

9 files changed

+363
-25
lines changed

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,3 +1105,49 @@ class TranslatedAsmStmt extends TranslatedStmt {
11051105
)
11061106
}
11071107
}
1108+
1109+
class TranslatedVlaDimensionStmt extends TranslatedStmt {
1110+
override VlaDimensionStmt stmt;
1111+
1112+
override TranslatedExpr getChild(int id) {
1113+
id = 0 and
1114+
result = getTranslatedExpr(stmt.getDimensionExpr().getFullyConverted())
1115+
}
1116+
1117+
override Instruction getFirstInstruction() { result = this.getChild(0).getFirstInstruction() }
1118+
1119+
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
1120+
none()
1121+
}
1122+
1123+
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
1124+
1125+
override Instruction getChildSuccessor(TranslatedElement child) {
1126+
child = this.getChild(0) and
1127+
result = this.getParent().getChildSuccessor(this)
1128+
}
1129+
}
1130+
1131+
class TranslatedVlaDeclarationStmt extends TranslatedStmt {
1132+
override VlaDeclStmt stmt;
1133+
1134+
override TranslatedExpr getChild(int id) { none() }
1135+
1136+
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
1137+
1138+
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
1139+
// TODO: This needs a new kind of instruction that represents initialization of a VLA.
1140+
// For now we just emit a `NoOp` instruction so that the CFG isn't incomplete.
1141+
tag = OnlyInstructionTag() and
1142+
opcode instanceof Opcode::NoOp and
1143+
resultType = getVoidType()
1144+
}
1145+
1146+
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
1147+
tag = OnlyInstructionTag() and
1148+
result = this.getParent().getChildSuccessor(this) and
1149+
kind instanceof GotoEdge
1150+
}
1151+
1152+
override Instruction getChildSuccessor(TranslatedElement child) { none() }
1153+
}

cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,3 +1814,81 @@ ssa.cpp:
18141814

18151815
# 383| Block 5
18161816
# 383| v383_17(void) = Unreached :
1817+
1818+
# 401| void vla(int, int, int, bool)
1819+
# 401| Block 0
1820+
# 401| v401_1(void) = EnterFunction :
1821+
# 401| m401_2(unknown) = AliasedDefinition :
1822+
# 401| m401_3(unknown) = InitializeNonLocal :
1823+
# 401| m401_4(unknown) = Chi : total:m401_2, partial:m401_3
1824+
# 401| r401_5(glval<int>) = VariableAddress[n1] :
1825+
# 401| m401_6(int) = InitializeParameter[n1] : &:r401_5
1826+
# 401| r401_7(glval<int>) = VariableAddress[n2] :
1827+
# 401| m401_8(int) = InitializeParameter[n2] : &:r401_7
1828+
# 401| r401_9(glval<int>) = VariableAddress[n3] :
1829+
# 401| m401_10(int) = InitializeParameter[n3] : &:r401_9
1830+
# 401| r401_11(glval<bool>) = VariableAddress[b1] :
1831+
# 401| m401_12(bool) = InitializeParameter[b1] : &:r401_11
1832+
# 402| r402_1(glval<int[]>) = VariableAddress[b] :
1833+
# 402| m402_2(int[]) = Uninitialized[b] : &:r402_1
1834+
# 402| r402_3(glval<int>) = VariableAddress[n1] :
1835+
# 402| r402_4(int) = Load[n1] : &:r402_3, m401_6
1836+
# 402| v402_5(void) = NoOp :
1837+
# 403| r403_1(glval<int[][]>) = VariableAddress[c] :
1838+
# 403| m403_2(int[][]) = Uninitialized[c] : &:r403_1
1839+
# 403| m403_3(unknown) = Chi : total:m401_4, partial:m403_2
1840+
# 403| r403_4(glval<int>) = VariableAddress[n1] :
1841+
# 403| r403_5(int) = Load[n1] : &:r403_4, m401_6
1842+
# 403| r403_6(glval<int>) = VariableAddress[n2] :
1843+
# 403| r403_7(int) = Load[n2] : &:r403_6, m401_8
1844+
# 403| v403_8(void) = NoOp :
1845+
# 405| r405_1(int) = Constant[0] :
1846+
# 405| r405_2(glval<int[]>) = VariableAddress[b] :
1847+
# 405| r405_3(int *) = Convert : r405_2
1848+
# 405| r405_4(glval<int>) = CopyValue : r405_3
1849+
# 405| m405_5(int) = Store[?] : &:r405_4, r405_1
1850+
# 405| m405_6(int[]) = Chi : total:m402_2, partial:m405_5
1851+
# 406| r406_1(int) = Constant[1] :
1852+
# 406| r406_2(glval<int[]>) = VariableAddress[b] :
1853+
# 406| r406_3(int *) = Convert : r406_2
1854+
# 406| r406_4(int) = Constant[0] :
1855+
# 406| r406_5(glval<int>) = PointerAdd[4] : r406_3, r406_4
1856+
# 406| m406_6(int) = Store[?] : &:r406_5, r406_1
1857+
# 406| m406_7(int[]) = Chi : total:m405_6, partial:m406_6
1858+
# 408| r408_1(int) = Constant[0] :
1859+
# 408| r408_2(glval<int[][]>) = VariableAddress[c] :
1860+
# 408| r408_3(int(*)[]) = Convert : r408_2
1861+
# 408| r408_4(int) = Constant[1] :
1862+
# 408| r408_5(int(*)[]) = PointerAdd : r408_3, r408_4
1863+
# 408| r408_6(glval<int[]>) = CopyValue : r408_5
1864+
# 408| r408_7(int *) = Convert : r408_6
1865+
# 408| r408_8(glval<int>) = CopyValue : r408_7
1866+
# 408| m408_9(int) = Store[?] : &:r408_8, r408_1
1867+
# 408| m408_10(unknown) = Chi : total:m403_3, partial:m408_9
1868+
# 410| r410_1(glval<bool>) = VariableAddress[b1] :
1869+
# 410| r410_2(bool) = Load[b1] : &:r410_1, m401_12
1870+
# 410| v410_3(void) = ConditionalBranch : r410_2
1871+
#-----| False -> Block 2
1872+
#-----| True -> Block 1
1873+
1874+
# 411| Block 1
1875+
# 411| r411_1(glval<int[]>) = VariableAddress[b] :
1876+
# 411| m411_2(int[]) = Uninitialized[b] : &:r411_1
1877+
# 411| r411_3(glval<int>) = VariableAddress[n1] :
1878+
# 411| r411_4(int) = Load[n1] : &:r411_3, m401_6
1879+
# 411| v411_5(void) = NoOp :
1880+
#-----| Goto -> Block 3
1881+
1882+
# 413| Block 2
1883+
# 413| r413_1(glval<int[]>) = VariableAddress[b] :
1884+
# 413| m413_2(int[]) = Uninitialized[b] : &:r413_1
1885+
# 413| r413_3(glval<int>) = VariableAddress[n2] :
1886+
# 413| r413_4(int) = Load[n2] : &:r413_3, m401_8
1887+
# 413| v413_5(void) = NoOp :
1888+
#-----| Goto -> Block 3
1889+
1890+
# 415| Block 3
1891+
# 415| v415_1(void) = NoOp :
1892+
# 401| v401_13(void) = ReturnVoid :
1893+
# 401| v401_14(void) = AliasedUse : ~m408_10
1894+
# 401| v401_15(void) = ExitFunction :

cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1804,3 +1804,80 @@ ssa.cpp:
18041804

18051805
# 383| Block 5
18061806
# 383| v383_17(void) = Unreached :
1807+
1808+
# 401| void vla(int, int, int, bool)
1809+
# 401| Block 0
1810+
# 401| v401_1(void) = EnterFunction :
1811+
# 401| m401_2(unknown) = AliasedDefinition :
1812+
# 401| m401_3(unknown) = InitializeNonLocal :
1813+
# 401| m401_4(unknown) = Chi : total:m401_2, partial:m401_3
1814+
# 401| r401_5(glval<int>) = VariableAddress[n1] :
1815+
# 401| m401_6(int) = InitializeParameter[n1] : &:r401_5
1816+
# 401| r401_7(glval<int>) = VariableAddress[n2] :
1817+
# 401| m401_8(int) = InitializeParameter[n2] : &:r401_7
1818+
# 401| r401_9(glval<int>) = VariableAddress[n3] :
1819+
# 401| m401_10(int) = InitializeParameter[n3] : &:r401_9
1820+
# 401| r401_11(glval<bool>) = VariableAddress[b1] :
1821+
# 401| m401_12(bool) = InitializeParameter[b1] : &:r401_11
1822+
# 402| r402_1(glval<int[]>) = VariableAddress[b] :
1823+
# 402| m402_2(int[]) = Uninitialized[b] : &:r402_1
1824+
# 402| r402_3(glval<int>) = VariableAddress[n1] :
1825+
# 402| r402_4(int) = Load[n1] : &:r402_3, m401_6
1826+
# 402| v402_5(void) = NoOp :
1827+
# 403| r403_1(glval<int[][]>) = VariableAddress[c] :
1828+
# 403| m403_2(int[][]) = Uninitialized[c] : &:r403_1
1829+
# 403| r403_3(glval<int>) = VariableAddress[n1] :
1830+
# 403| r403_4(int) = Load[n1] : &:r403_3, m401_6
1831+
# 403| r403_5(glval<int>) = VariableAddress[n2] :
1832+
# 403| r403_6(int) = Load[n2] : &:r403_5, m401_8
1833+
# 403| v403_7(void) = NoOp :
1834+
# 405| r405_1(int) = Constant[0] :
1835+
# 405| r405_2(glval<int[]>) = VariableAddress[b] :
1836+
# 405| r405_3(int *) = Convert : r405_2
1837+
# 405| r405_4(glval<int>) = CopyValue : r405_3
1838+
# 405| m405_5(int) = Store[?] : &:r405_4, r405_1
1839+
# 405| m405_6(int[]) = Chi : total:m402_2, partial:m405_5
1840+
# 406| r406_1(int) = Constant[1] :
1841+
# 406| r406_2(glval<int[]>) = VariableAddress[b] :
1842+
# 406| r406_3(int *) = Convert : r406_2
1843+
# 406| r406_4(int) = Constant[0] :
1844+
# 406| r406_5(glval<int>) = PointerAdd[4] : r406_3, r406_4
1845+
# 406| m406_6(int) = Store[?] : &:r406_5, r406_1
1846+
# 406| m406_7(int[]) = Chi : total:m405_6, partial:m406_6
1847+
# 408| r408_1(int) = Constant[0] :
1848+
# 408| r408_2(glval<int[][]>) = VariableAddress[c] :
1849+
# 408| r408_3(int(*)[]) = Convert : r408_2
1850+
# 408| r408_4(int) = Constant[1] :
1851+
# 408| r408_5(int(*)[]) = PointerAdd : r408_3, r408_4
1852+
# 408| r408_6(glval<int[]>) = CopyValue : r408_5
1853+
# 408| r408_7(int *) = Convert : r408_6
1854+
# 408| r408_8(glval<int>) = CopyValue : r408_7
1855+
# 408| m408_9(int) = Store[?] : &:r408_8, r408_1
1856+
# 408| m408_10(unknown) = Chi : total:m401_4, partial:m408_9
1857+
# 410| r410_1(glval<bool>) = VariableAddress[b1] :
1858+
# 410| r410_2(bool) = Load[b1] : &:r410_1, m401_12
1859+
# 410| v410_3(void) = ConditionalBranch : r410_2
1860+
#-----| False -> Block 2
1861+
#-----| True -> Block 1
1862+
1863+
# 411| Block 1
1864+
# 411| r411_1(glval<int[]>) = VariableAddress[b] :
1865+
# 411| m411_2(int[]) = Uninitialized[b] : &:r411_1
1866+
# 411| r411_3(glval<int>) = VariableAddress[n1] :
1867+
# 411| r411_4(int) = Load[n1] : &:r411_3, m401_6
1868+
# 411| v411_5(void) = NoOp :
1869+
#-----| Goto -> Block 3
1870+
1871+
# 413| Block 2
1872+
# 413| r413_1(glval<int[]>) = VariableAddress[b] :
1873+
# 413| m413_2(int[]) = Uninitialized[b] : &:r413_1
1874+
# 413| r413_3(glval<int>) = VariableAddress[n2] :
1875+
# 413| r413_4(int) = Load[n2] : &:r413_3, m401_8
1876+
# 413| v413_5(void) = NoOp :
1877+
#-----| Goto -> Block 3
1878+
1879+
# 415| Block 3
1880+
# 415| v415_1(void) = NoOp :
1881+
# 401| v401_13(void) = ReturnVoid :
1882+
# 401| v401_14(void) = AliasedUse : ~m408_10
1883+
# 401| v401_15(void) = ExitFunction :

cpp/ql/test/library-tests/ir/ssa/ssa.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,4 +396,20 @@ int FusedBlockPhiOperand(int x, int y, int z, bool b1) {
396396
}
397397

398398
return ret;
399+
}
400+
401+
void vla(int n1, int n2, int n3, bool b1) {
402+
int b[n1];
403+
int c[n1][n2];
404+
405+
*b = 0;
406+
b[0] = 1;
407+
408+
**(c + 1) = 0;
409+
410+
if(b1) {
411+
int b[n1];
412+
} else {
413+
int b[n2];
414+
}
399415
}

cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,3 +1695,76 @@ ssa.cpp:
16951695
# 383| v383_13(void) = ReturnValue : &:r383_12, m398_5
16961696
# 383| v383_14(void) = AliasedUse : ~m?
16971697
# 383| v383_15(void) = ExitFunction :
1698+
1699+
# 401| void vla(int, int, int, bool)
1700+
# 401| Block 0
1701+
# 401| v401_1(void) = EnterFunction :
1702+
# 401| mu401_2(unknown) = AliasedDefinition :
1703+
# 401| mu401_3(unknown) = InitializeNonLocal :
1704+
# 401| r401_4(glval<int>) = VariableAddress[n1] :
1705+
# 401| m401_5(int) = InitializeParameter[n1] : &:r401_4
1706+
# 401| r401_6(glval<int>) = VariableAddress[n2] :
1707+
# 401| m401_7(int) = InitializeParameter[n2] : &:r401_6
1708+
# 401| r401_8(glval<int>) = VariableAddress[n3] :
1709+
# 401| m401_9(int) = InitializeParameter[n3] : &:r401_8
1710+
# 401| r401_10(glval<bool>) = VariableAddress[b1] :
1711+
# 401| m401_11(bool) = InitializeParameter[b1] : &:r401_10
1712+
# 402| r402_1(glval<int[]>) = VariableAddress[b] :
1713+
# 402| mu402_2(int[]) = Uninitialized[b] : &:r402_1
1714+
# 402| r402_3(glval<int>) = VariableAddress[n1] :
1715+
# 402| r402_4(int) = Load[n1] : &:r402_3, m401_5
1716+
# 402| v402_5(void) = NoOp :
1717+
# 403| r403_1(glval<int[][]>) = VariableAddress[c] :
1718+
# 403| mu403_2(int[][]) = Uninitialized[c] : &:r403_1
1719+
# 403| r403_3(glval<int>) = VariableAddress[n1] :
1720+
# 403| r403_4(int) = Load[n1] : &:r403_3, m401_5
1721+
# 403| r403_5(glval<int>) = VariableAddress[n2] :
1722+
# 403| r403_6(int) = Load[n2] : &:r403_5, m401_7
1723+
# 403| v403_7(void) = NoOp :
1724+
# 405| r405_1(int) = Constant[0] :
1725+
# 405| r405_2(glval<int[]>) = VariableAddress[b] :
1726+
# 405| r405_3(int *) = Convert : r405_2
1727+
# 405| r405_4(glval<int>) = CopyValue : r405_3
1728+
# 405| mu405_5(int) = Store[?] : &:r405_4, r405_1
1729+
# 406| r406_1(int) = Constant[1] :
1730+
# 406| r406_2(glval<int[]>) = VariableAddress[b] :
1731+
# 406| r406_3(int *) = Convert : r406_2
1732+
# 406| r406_4(int) = Constant[0] :
1733+
# 406| r406_5(glval<int>) = PointerAdd[4] : r406_3, r406_4
1734+
# 406| mu406_6(int) = Store[?] : &:r406_5, r406_1
1735+
# 408| r408_1(int) = Constant[0] :
1736+
# 408| r408_2(glval<int[][]>) = VariableAddress[c] :
1737+
# 408| r408_3(int(*)[]) = Convert : r408_2
1738+
# 408| r408_4(int) = Constant[1] :
1739+
# 408| r408_5(int(*)[]) = PointerAdd : r408_3, r408_4
1740+
# 408| r408_6(glval<int[]>) = CopyValue : r408_5
1741+
# 408| r408_7(int *) = Convert : r408_6
1742+
# 408| r408_8(glval<int>) = CopyValue : r408_7
1743+
# 408| mu408_9(int) = Store[?] : &:r408_8, r408_1
1744+
# 410| r410_1(glval<bool>) = VariableAddress[b1] :
1745+
# 410| r410_2(bool) = Load[b1] : &:r410_1, m401_11
1746+
# 410| v410_3(void) = ConditionalBranch : r410_2
1747+
#-----| False -> Block 2
1748+
#-----| True -> Block 1
1749+
1750+
# 411| Block 1
1751+
# 411| r411_1(glval<int[]>) = VariableAddress[b] :
1752+
# 411| m411_2(int[]) = Uninitialized[b] : &:r411_1
1753+
# 411| r411_3(glval<int>) = VariableAddress[n1] :
1754+
# 411| r411_4(int) = Load[n1] : &:r411_3, m401_5
1755+
# 411| v411_5(void) = NoOp :
1756+
#-----| Goto -> Block 3
1757+
1758+
# 413| Block 2
1759+
# 413| r413_1(glval<int[]>) = VariableAddress[b] :
1760+
# 413| m413_2(int[]) = Uninitialized[b] : &:r413_1
1761+
# 413| r413_3(glval<int>) = VariableAddress[n2] :
1762+
# 413| r413_4(int) = Load[n2] : &:r413_3, m401_7
1763+
# 413| v413_5(void) = NoOp :
1764+
#-----| Goto -> Block 3
1765+
1766+
# 415| Block 3
1767+
# 415| v415_1(void) = NoOp :
1768+
# 401| v401_12(void) = ReturnVoid :
1769+
# 401| v401_13(void) = AliasedUse : ~m?
1770+
# 401| v401_14(void) = ExitFunction :

0 commit comments

Comments
 (0)