rustsec-2026-0217
Vulnerability from osv_rustsec
Published
2026-06-18 12:00
Modified
2026-07-28 18:34
Summary
Integer overflow in tract-nnef NNEF tensor parser leads to out-of-bounds read on model load
Details

tract_nnef::tensors::read_tensor builds a tensor shape from attacker-controlled 32-bit dimensions and computes both the element count product(shape) and the byte allocation product(shape) * size_of(dt) with unchecked usize arithmetic. In release builds (no overflow-checks) both products wrap modulo 2^64.

A crafted NNEF .dat tensor can choose dimensions whose wrapped products collapse to a small value that satisfies the header size-consistency check, while the true element count stays astronomically large. read_tensor then returns a Tensor whose reported len (e.g. 2^61 + 7) far exceeds its backing heap allocation (e.g. 56 bytes). The unchecked accessor as_slice_unchecked (slice::from_raw_parts(ptr, self.len())) subsequently yields a slice spanning ~18 EiB over the small buffer.

The out-of-bounds read fires automatically during model build (no inference required), reachable through the default DatLoader resource loader via the public tract_nnef::nnef().model_for_path / model_for_read API when the const-folding as_uniform fast-path materializes the over-long constant. The always-on primitive is a bounded adjacent-heap over-read (information disclosure); access further past the mapped region SIGSEGVs (denial of service). No out-of-bounds write or code execution was demonstrated.

Affected: every release line prior to the backported fixes — < 0.21.16, 0.22.00.22.1, and 0.23.0. The block-quant path had already received an analogous blob-size guard; the dense DatLoader path was missed.

Mitigation

Upgrade to 0.21.16, 0.22.2, or 0.23.1. The fix computes the shape product and byte size with checked_mul and rejects the tensor on overflow (commit 34c7df2).


{
  "affected": [
    {
      "database_specific": {
        "categories": [
          "memory-exposure",
          "denial-of-service"
        ],
        "cvss": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:H",
        "informational": null
      },
      "ecosystem_specific": {
        "affected_functions": null,
        "affects": {
          "arch": [],
          "functions": [
            "tract_nnef::tensors::read_tensor"
          ],
          "os": []
        }
      },
      "package": {
        "ecosystem": "crates.io",
        "name": "tract-nnef",
        "purl": "pkg:cargo/tract-nnef"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.0.0-0"
            },
            {
              "fixed": "0.21.16"
            },
            {
              "introduced": "0.22.0"
            },
            {
              "fixed": "0.22.2"
            },
            {
              "introduced": "0.23.0"
            },
            {
              "fixed": "0.23.1"
            }
          ],
          "type": "SEMVER"
        }
      ],
      "versions": []
    }
  ],
  "aliases": [
    "CVE-2026-55093",
    "GHSA-x5mv-8wgw-29hg"
  ],
  "database_specific": {
    "license": "CC0-1.0"
  },
  "details": "`tract_nnef::tensors::read_tensor` builds a tensor shape from attacker-controlled\n32-bit dimensions and computes both the element count `product(shape)` and the\nbyte allocation `product(shape) * size_of(dt)` with **unchecked `usize`\narithmetic**. In release builds (no `overflow-checks`) both products wrap modulo\n2^64.\n\nA crafted NNEF `.dat` tensor can choose dimensions whose wrapped products\ncollapse to a small value that satisfies the header size-consistency check, while\nthe true element count stays astronomically large. `read_tensor` then returns a\n`Tensor` whose reported `len` (e.g. `2^61 + 7`) far exceeds its backing heap\nallocation (e.g. 56 bytes). The unchecked accessor `as_slice_unchecked`\n(`slice::from_raw_parts(ptr, self.len())`) subsequently yields a slice spanning\n~18 EiB over the small buffer.\n\nThe out-of-bounds read fires automatically during model build (no inference\nrequired), reachable through the default `DatLoader` resource loader via the\npublic `tract_nnef::nnef().model_for_path` / `model_for_read` API when the\nconst-folding `as_uniform` fast-path materializes the over-long constant. The\nalways-on primitive is a bounded adjacent-heap over-read (information\ndisclosure); access further past the mapped region SIGSEGVs (denial of service).\nNo out-of-bounds write or code execution was demonstrated.\n\nAffected: every release line prior to the backported fixes \u2014 `\u003c 0.21.16`,\n`0.22.0`\u2013`0.22.1`, and `0.23.0`. The block-quant path had already received an\nanalogous blob-size guard; the dense `DatLoader` path was missed.\n\n## Mitigation\n\nUpgrade to `0.21.16`, `0.22.2`, or `0.23.1`. The fix computes the shape product\nand byte size with `checked_mul` and rejects the tensor on overflow\n(commit [`34c7df2`](https://github.com/sonos/tract/commit/34c7df2c9bd2a36583e09b52f3e6319bf23102e8)).",
  "id": "RUSTSEC-2026-0217",
  "modified": "2026-07-28T18:34:53Z",
  "published": "2026-06-18T12:00:00Z",
  "references": [
    {
      "type": "PACKAGE",
      "url": "https://crates.io/crates/tract-nnef"
    },
    {
      "type": "ADVISORY",
      "url": "https://rustsec.org/advisories/RUSTSEC-2026-0217.html"
    },
    {
      "type": "ADVISORY",
      "url": "https://github.com/sonos/tract/security/advisories/GHSA-x5mv-8wgw-29hg"
    },
    {
      "type": "WEB",
      "url": "https://github.com/sonos/tract/commit/34c7df2c9bd2a36583e09b52f3e6319bf23102e8"
    }
  ],
  "related": [],
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Integer overflow in tract-nnef NNEF tensor parser leads to out-of-bounds read on model load"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Loading…