Skip to content

Commit 8b85d5d

Browse files
authored
Directize: Handle overflows and out of bounds (#6255)
1 parent 9361edf commit 8b85d5d

File tree

2 files changed

+182
-1
lines changed

2 files changed

+182
-1
lines changed

src/ir/table-utils.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "ir/element-utils.h"
2121
#include "ir/literal-utils.h"
2222
#include "ir/module-utils.h"
23+
#include "support/stdckdint.h"
2324
#include "wasm-traversal.h"
2425
#include "wasm.h"
2526

@@ -40,7 +41,13 @@ struct FlatTable {
4041
return;
4142
}
4243
Index start = offset->cast<Const>()->value.geti32();
43-
Index end = start + segment->data.size();
44+
Index size = segment->data.size();
45+
Index end;
46+
if (std::ckd_add(&end, start, size) || end > table.initial) {
47+
// Overflow.
48+
valid = false;
49+
return;
50+
}
4451
if (end > names.size()) {
4552
names.resize(end);
4653
}

test/lit/passes/directize_all-features.wast

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1586,3 +1586,177 @@
15861586
)
15871587
)
15881588
)
1589+
1590+
;; The elem's offset is way out of bounds, which we should not error on, and do
1591+
;; nothing otherwise.
1592+
(module
1593+
;; CHECK: (type $v (func))
1594+
;; IMMUT: (type $v (func))
1595+
(type $v (func))
1596+
1597+
(table 10 10 funcref)
1598+
1599+
(elem (i32.const -1) $0)
1600+
1601+
;; CHECK: (table $0 10 10 funcref)
1602+
1603+
;; CHECK: (elem $0 (i32.const -1) $0)
1604+
1605+
;; CHECK: (func $0 (type $v)
1606+
;; CHECK-NEXT: (call_indirect $0 (type $v)
1607+
;; CHECK-NEXT: (i32.const -1)
1608+
;; CHECK-NEXT: )
1609+
;; CHECK-NEXT: )
1610+
;; IMMUT: (table $0 10 10 funcref)
1611+
1612+
;; IMMUT: (elem $0 (i32.const -1) $0)
1613+
1614+
;; IMMUT: (func $0 (type $v)
1615+
;; IMMUT-NEXT: (call_indirect $0 (type $v)
1616+
;; IMMUT-NEXT: (i32.const -1)
1617+
;; IMMUT-NEXT: )
1618+
;; IMMUT-NEXT: )
1619+
(func $0
1620+
(call_indirect (type $v)
1621+
(i32.const -1)
1622+
)
1623+
)
1624+
)
1625+
1626+
;; Another elem offset that is way out of bounds.
1627+
(module
1628+
;; CHECK: (type $v (func))
1629+
;; IMMUT: (type $v (func))
1630+
(type $v (func))
1631+
1632+
(table 10 10 funcref)
1633+
1634+
(elem (i32.const -2) $0)
1635+
1636+
;; CHECK: (table $0 10 10 funcref)
1637+
1638+
;; CHECK: (elem $0 (i32.const -2) $0)
1639+
1640+
;; CHECK: (func $0 (type $v)
1641+
;; CHECK-NEXT: (call_indirect $0 (type $v)
1642+
;; CHECK-NEXT: (i32.const -2)
1643+
;; CHECK-NEXT: )
1644+
;; CHECK-NEXT: )
1645+
;; IMMUT: (table $0 10 10 funcref)
1646+
1647+
;; IMMUT: (elem $0 (i32.const -2) $0)
1648+
1649+
;; IMMUT: (func $0 (type $v)
1650+
;; IMMUT-NEXT: (call_indirect $0 (type $v)
1651+
;; IMMUT-NEXT: (i32.const -2)
1652+
;; IMMUT-NEXT: )
1653+
;; IMMUT-NEXT: )
1654+
(func $0
1655+
(call_indirect (type $v)
1656+
(i32.const -2)
1657+
)
1658+
)
1659+
)
1660+
1661+
;; The elem is just out of bounds due to its offset.
1662+
(module
1663+
;; CHECK: (type $v (func))
1664+
;; IMMUT: (type $v (func))
1665+
(type $v (func))
1666+
1667+
(table 10 10 funcref)
1668+
1669+
(elem (i32.const 10) $0)
1670+
1671+
;; CHECK: (table $0 10 10 funcref)
1672+
1673+
;; CHECK: (elem $0 (i32.const 10) $0)
1674+
1675+
;; CHECK: (func $0 (type $v)
1676+
;; CHECK-NEXT: (call_indirect $0 (type $v)
1677+
;; CHECK-NEXT: (i32.const 10)
1678+
;; CHECK-NEXT: )
1679+
;; CHECK-NEXT: )
1680+
;; IMMUT: (table $0 10 10 funcref)
1681+
1682+
;; IMMUT: (elem $0 (i32.const 10) $0)
1683+
1684+
;; IMMUT: (func $0 (type $v)
1685+
;; IMMUT-NEXT: (call_indirect $0 (type $v)
1686+
;; IMMUT-NEXT: (i32.const 10)
1687+
;; IMMUT-NEXT: )
1688+
;; IMMUT-NEXT: )
1689+
(func $0
1690+
(call_indirect (type $v)
1691+
(i32.const 10)
1692+
)
1693+
)
1694+
)
1695+
1696+
;; The elem is just out of bounds due to its length.
1697+
(module
1698+
;; CHECK: (type $v (func))
1699+
;; IMMUT: (type $v (func))
1700+
(type $v (func))
1701+
1702+
(table 10 10 funcref)
1703+
1704+
(elem (i32.const 9) $0 $0)
1705+
1706+
;; CHECK: (table $0 10 10 funcref)
1707+
1708+
;; CHECK: (elem $0 (i32.const 9) $0 $0)
1709+
1710+
;; CHECK: (func $0 (type $v)
1711+
;; CHECK-NEXT: (call_indirect $0 (type $v)
1712+
;; CHECK-NEXT: (i32.const 9)
1713+
;; CHECK-NEXT: )
1714+
;; CHECK-NEXT: )
1715+
;; IMMUT: (table $0 10 10 funcref)
1716+
1717+
;; IMMUT: (elem $0 (i32.const 9) $0 $0)
1718+
1719+
;; IMMUT: (func $0 (type $v)
1720+
;; IMMUT-NEXT: (call_indirect $0 (type $v)
1721+
;; IMMUT-NEXT: (i32.const 9)
1722+
;; IMMUT-NEXT: )
1723+
;; IMMUT-NEXT: )
1724+
(func $0
1725+
(call_indirect (type $v)
1726+
;; We could in theory optimize this, as the out of bounds part is after us,
1727+
;; but the wasm traps anyhow, so leave it alone.
1728+
(i32.const 9)
1729+
)
1730+
)
1731+
)
1732+
1733+
;; The elem is ok, and we can optimize.
1734+
(module
1735+
;; CHECK: (type $v (func))
1736+
;; IMMUT: (type $v (func))
1737+
(type $v (func))
1738+
1739+
(table 10 10 funcref)
1740+
1741+
(elem (i32.const 9) $0)
1742+
1743+
;; CHECK: (table $0 10 10 funcref)
1744+
1745+
;; CHECK: (elem $0 (i32.const 9) $0)
1746+
1747+
;; CHECK: (func $0 (type $v)
1748+
;; CHECK-NEXT: (call $0)
1749+
;; CHECK-NEXT: )
1750+
;; IMMUT: (table $0 10 10 funcref)
1751+
1752+
;; IMMUT: (elem $0 (i32.const 9) $0)
1753+
1754+
;; IMMUT: (func $0 (type $v)
1755+
;; IMMUT-NEXT: (call $0)
1756+
;; IMMUT-NEXT: )
1757+
(func $0
1758+
(call_indirect (type $v)
1759+
(i32.const 9)
1760+
)
1761+
)
1762+
)

0 commit comments

Comments
 (0)