Vyper is the Pythonic Programming Language for the Ethereum Virtual Machine. In versions up to and including 0.4.2rc1, the `slice()`…
GitHub_M·CWE-691·Published 2025-05-15
Vyper is the Pythonic Programming Language for the Ethereum Virtual Machine. In versions up to and including 0.4.2rc1, the `slice()` builtin can elide side effects when the output length is 0, and the source bytestring is a builtin (`msg.data` or `<address>.code`). The reason is that for these source locations, the check that `length >= 1` is skipped. The result is that a 0-length bytestring constructed with slice can be passed to `make_byte_array_copier`, which elides evaluation of its source argument when the max length is 0. The impact is that side effects in the `start` argument may be elided when the `length` argument is 0, e.g. `slice(msg.data, self.do_side_effect(), 0)`. The fix in pull request 4645 disallows any invocation of `slice()` with length 0, including for the ad hoc locations discussed in this advisory. The fix is expected to be part of version 0.4.2.
Vyper is the Pythonic Programming Language for the Ethereum Virtual Machine. In versions up to and including 0.4.2rc1, the `slice()` builtin can elide side effects when the output length is 0, and the source bytestring is a builtin (`msg.data` or `<address>.code`). The reason is that for these source locations, the check that `length >= 1` is skipped. The result is that a 0-length bytestring constructed with slice can be passed to `make_byte_array_copier`, which elides evaluation of its source argument when the max length is 0. The impact is that side effects in the `start` argument may be elided when the `length` argument is 0, e.g. `slice(msg.data, self.do_side_effect(), 0)`. The fix in pull request 4645 disallows any invocation of `slice()` with length 0, including for the ad hoc locations discussed in this advisory. The fix is expected to be part of version 0.4.2.
### Impact the `slice()` builtin can elide side effects when the output length is 0, and the source bytestring is a builtin (`msg.data` or `<address>.code`). the reason is that for these source locations, the check that `length >= 1` is skipped: https://github.com/vyperlang/vyper/blob/68b68c4b30c5ef2f312b4674676170b8a6eaa316/vyper/builtins/functions.py#L315-L319 the result is that a 0-length bytestring constructed with slice can be passed to `make_byte_array_copier`, which elides evaluation of its source argument when the max length is 0: https://github.com/vyperlang/vyper/blob/68b68c4b30c5ef2f312b4674676170b8a6eaa316/vyper/codegen/core.py#L189-L191 the impact is that side effects in the `start` argument may be elided when the `length` argument is 0, e.g. `slice(msg.data, self.do_side_effect(), 0)`. the following example illustrates how the issue would look in user code ```vyper counter: public(uint256) @external def test() -> Bytes[10]: b: Bytes[10] = slice(msg.data, self.side_effect(), 0) return b def side_effect() -> uint256: self.counter += 1 return 0 ``` the severity assigned is low, since this is not a very useful pattern and unlikely to be found in user code. ### Patches the fix is tracked in https://github.com/vyperlang/vyper/pull/4645, which disallows any invocation of `slice()` with length 0, including for the ad hoc locations discussed in this advisory. ### Workarounds _Is there a way for users to fix or remediate the vulnerability without upgrading?_ ### References _Are there any links users can visit to find out more?_
### Impact the `slice()` builtin can elide side effects when the output length is 0, and the source bytestring is a builtin (`msg.data` or `<address>.code`). the reason is that for these source locations, the check that `length >= 1` is skipped: https://github.com/vyperlang/vyper/blob/68b68c4b30c5ef2f312b4674676170b8a6eaa316/vyper/builtins/functions.py#L315-L319 the result is that a 0-length bytestring constructed with slice can be passed to `make_byte_array_copier`, which elides evaluation of its source argument when the max length is 0: https://github.com/vyperlang/vyper/blob/68b68c4b30c5ef2f312b4674676170b8a6eaa316/vyper/codegen/core.py#L189-L191 the impact is that side effects in the `start` argument may be elided when the `length` argument is 0, e.g. `slice(msg.data, self.do_side_effect(), 0)`. the following example illustrates how the issue would look in user code ```vyper counter: public(uint256) @external def test() -> Bytes[10]: b: Bytes[10] = slice(msg.data, self.side_effect(), 0) return b def side_effect() -> uint256: self.counter += 1 return 0 ``` the severity assigned is low, since this is not a very useful pattern and unlikely to be found in user code. ### Patches the fix is tracked in https://github.com/vyperlang/vyper/pull/4645, which disallows any invocation of `slice()` with length 0, including for the ad hoc locations discussed in this advisory. ### Workarounds _Is there a way for users to fix or remediate the vulnerability without upgrading?_ ### References _Are there any links users can visit to find out more?_
Vyper es el lenguaje de programación Pythonic para la Máquina Virtual de Ethereum. En versiones hasta la 0.4.2rc1 (incluida), la instrucción integrada `slice()` puede omitir efectos secundarios cuando la longitud de salida es 0 y la cadena de bytes de origen es una instrucción integrada (`msg.data` o `.code`). Esto se debe a que, para estas ubicaciones de origen, se omite la comprobación de que `length >= 1`. Como resultado, una cadena de bytes de longitud 0 construida con slice puede pasarse a `make_byte_array_copier`, que omite la evaluación de su argumento de origen cuando la longitud máxima es 0. Esto implica que los efectos secundarios del argumento `start` pueden omitirse cuando el argumento `length` es 0, por ejemplo, `slice(msg.data, self.do_side_effect(), 0)`. La corrección en la solicitud de incorporación de cambios 4645 impide la invocación de `slice()` con longitud 0, incluso para las ubicaciones ad hoc descritas en este aviso. Se espera que la solución sea parte de la versión 0.4.2.
| Version | Type | Source | Base | Exp | Impact | Vector |
|---|---|---|---|---|---|---|
| 4.0 | Primary | cve.org | 2.9 | — | — | CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:P |
| 4.0 | Primary | cve.org | 2.9 | — | — |
| CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:P |
| 4.0 | Secondary | NVD | 2.9 | — | — | CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X |
| 4.0 | Secondary | GHSA | 2.9 | — | — | CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:P |