Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions design/mvp/Binary.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@ Notes:
`none` case of an optional immediate.)
* 🔧 for fixed-sized lists the length of the list must be larger than 0 to pass
validation.
* Validation requires that, for every `defvaltype` `t`, `elem_size(t, 'i64')` is
less than 2<sup>28</sup>, as defined by the
[Canonical ABI](CanonicalABI.md#element-size).


## Canonical Definitions
Expand Down
7 changes: 6 additions & 1 deletion design/mvp/CanonicalABI.md
Original file line number Diff line number Diff line change
Expand Up @@ -2306,7 +2306,10 @@ byte size be a static property of the type instead of attempting to use a
variable-length element-encoding scheme both simplifies the implementation and
maps well to languages which represent `list`s as random-access arrays. Empty
types, such as records with no fields, are not permitted, to avoid
complications in source languages.
complications in source languages. To prevent integer overflow in obscure corner
cases, component validation rules require that for every value type `t` defined
by a component, `elem_size(t, 'i64')` is less than 2<sup>28</sup> (the same
upper bound as `MAX_LIST_BYTE_LENGTH`).
```python
def elem_size(t, ptr_type):
match despecialize(t):
Expand Down Expand Up @@ -3594,6 +3597,8 @@ performed for a component. These are defined as:
* `lift(T)`
* requires `realloc` if `T` contains a `list` or `string`

Value types used by `lift`/`lower` are already rejected at `defvaltype`
definition if they exceed the [Element Size](#element-size) bound.

### `canon lift`

Expand Down
5 changes: 5 additions & 0 deletions design/mvp/Explainer.md
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,11 @@ where bind-id(X) parses '(' sort <id>? Y ')' when X parses '(' sort Y ')'
Because there is nothing in this type grammar analogous to the [gc] proposal's
[`rectype`], none of these types are recursive.

To prevent integer overflow in obscure corner cases, as an extra validation
requirement, `defvaltype`s may not be equal or greater than 2<sup>28</sup> bytes
when serialized into linear memory according to the `i64` ABI definition of
[Element Size](CanonicalABI.md#element-size).

#### Fundamental value types

The value types in `valtype` can be broken into two categories: *fundamental*
Expand Down
1 change: 1 addition & 0 deletions test/nyi.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# See README.md
./validation/max-value-size.wast
./async/during-sync-call-may-block-if-other-ready-threads.wast
./async/during-sync-call-no-exclusive-resume.wast
./async/during-sync-call-no-sibling-resume.wast
65 changes: 65 additions & 0 deletions test/validation/max-value-size.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
;; Validation requires elem_size(t, i64) < 2^28 for every defvaltype t.
;; See CanonicalABI.md#element-size.

;; valid boundaries (single component)

(component
(type (list u8 268435455))
(type (list u64 33554431))
(type (list string 16777215))
(type (map u8 (list u8 4)))
(type (tuple (list u8 268435454) (list u8 1)))
(type (record
(field "a" (list u8 134217727))
(field "b" (list u8 134217728))))
(type (list (list u8 134217727) 2))
(type (map u8 (list u8 268435455)))
(type (option (map u8 (list u8 268435455))))
(type (record (field "m" (map u8 (list u8 268435455)))))
(type (stream (list u8 268435455)))
(type (future (list u8 268435455)))
)

;; single fixed list just over the limit

(assert_invalid
(component (type (list u8 268435456)))
"exceeds maximum byte size")

;; fixed list whose product exceeds MAX

(assert_invalid
(component (type (list u64 33554432)))
"exceeds maximum byte size")

;; u32 wrap class: real byte size is 2^32 but naive u32 multiply wraps to 0

(assert_invalid
(component (type (list u64 536870912)))
"exceeds maximum byte size")

;; compound sum exceeds MAX

(assert_invalid
(component
(type (tuple (list u8 268435455) (list u8 1))))
"exceeds maximum byte size")

(assert_invalid
(component
(type (record
(field "a" (list u8 134217728))
(field "b" (list u8 134217728)))))
"exceeds maximum byte size")

;; nested fixed list

(assert_invalid
(component (type (list (list u8 268435455) 2)))
"exceeds maximum byte size")

;; pointer-width-sensitive rejection (passes i32, fails i64)

(assert_invalid
(component (type (list string 16777216)))
"exceeds maximum byte size")
Loading