ghsa-2p94-8669-xg86
Vulnerability from github
Published
2025-02-21 22:43
Modified
2025-02-21 22:43
Summary
Vyper's sqrt doesn't define rounding behavior
Details

Vyper's sqrt() builtin uses the babylonian method to calculate square roots of decimals. Unfortunately, improper handling of the oscillating final states may lead to sqrt incorrectly returning rounded up results.

the fix is tracked in https://github.com/vyperlang/vyper/pull/4486

Vulnerability Details

Vyper injects the following code to handle calculation of decimal sqrt. x is the input provided by user. ```python assert x >= 0.0 z: decimal = 0.0

if x == 0.0: z = 0.0 else: z = x / 2.0 + 0.5 y: decimal = x

for i: uint256 in range(256):
    if z == y:
        break
    y = z
    z = (x / z + z) / 2.0

`` Notably, the terminal condition of the algorithm is eitherz_cur == z_prev`, or the algorithm runs for 256 rounds.

However, for certain inputs, z might actually oscillate between N and N + epsilon, where N ** 2 <= x < (N + epsilon) ** 2. This means that the current behavior does not define whether it will round up or down to the nearest epsilon.

The example snippet here returns 0.9999999999, the rounded up result for sqrt(0.9999999998). This is due to the oscillation ending in N + epsilon instead of N. vyper @external def test(): d: decimal = 0.9999999998 r: decimal = sqrt(d) #this will be 0.9999999999

Note that sqrt() diverges from isqrt() here -- isqrt() consistently rounds down, so it is not subject to the same issue.

Impact Details

Since sqrt() can be used for determining boundary conditions, rounding down is preferred. However, since sqrt() is used very rarely in the wild, this advisory has been assigned an impact of low.

Show details on source website


{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.4.0"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "vyper"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.4.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-26622"
  ],
  "database_specific": {
    "cwe_ids": [],
    "github_reviewed": true,
    "github_reviewed_at": "2025-02-21T22:43:30Z",
    "nvd_published_at": null,
    "severity": "LOW"
  },
  "details": "Vyper\u0027s `sqrt()` builtin uses the babylonian method to calculate square roots of decimals. Unfortunately, improper handling of the oscillating final states may lead to sqrt incorrectly returning rounded up results.\n\nthe fix is tracked in https://github.com/vyperlang/vyper/pull/4486\n\n### Vulnerability Details\n\nVyper injects the following code to handle calculation of decimal sqrt. x is the input provided by user.\n```python\nassert x \u003e= 0.0\nz: decimal = 0.0\n\nif x == 0.0:\n    z = 0.0\nelse:\n    z = x / 2.0 + 0.5\n    y: decimal = x\n\n    for i: uint256 in range(256):\n        if z == y:\n            break\n        y = z\n        z = (x / z + z) / 2.0\n```\nNotably, the terminal condition of the algorithm is either `z_cur == z_prev`, or the algorithm runs for 256 rounds.\n\nHowever, for certain inputs, `z` might actually oscillate between `N` and `N + epsilon`, where `N ** 2 \u003c= x \u003c (N + epsilon) ** 2`. This means that the current behavior does not define whether it will round up or down to the nearest epsilon.\n\nThe example snippet here returns 0.9999999999, the rounded up result for sqrt(0.9999999998). This is due to the oscillation ending in N + epsilon instead of N.\n```vyper\n@external\ndef test():\n    d: decimal = 0.9999999998\n    r: decimal = sqrt(d)    #this will be 0.9999999999\n```\n\nNote that `sqrt()` diverges from `isqrt()` here -- `isqrt()` consistently rounds down, so it is not subject to the same issue.\n\n### Impact Details\n\nSince `sqrt()` can be used for determining boundary conditions, rounding down is preferred. However, since `sqrt()` is used very rarely in the wild, this advisory has been assigned an impact of `low`.",
  "id": "GHSA-2p94-8669-xg86",
  "modified": "2025-02-21T22:43:30Z",
  "published": "2025-02-21T22:43:30Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/vyperlang/vyper/security/advisories/GHSA-2p94-8669-xg86"
    },
    {
      "type": "WEB",
      "url": "https://github.com/vyperlang/vyper/pull/4486"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/vyperlang/vyper"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [],
  "summary": "Vyper\u0027s sqrt doesn\u0027t define rounding behavior"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.