Common Weakness Enumeration

CWE-125

Allowed

Out-of-bounds Read

Abstraction: Base · Status: Draft

The product reads data past the end, or before the beginning, of the intended buffer.

11503 vulnerabilities reference this CWE, most recent first.

GHSA-6JW8-GWR2-HM7V

Vulnerability from github – Published: 2025-01-28 00:32 – Updated: 2025-11-03 21:32
VLAI
Details

A path handling issue was addressed with improved validation. This issue is fixed in macOS Ventura 13.7.3, macOS Sequoia 15.3, macOS Sonoma 14.7.3. An app may be able to read files outside of its sandbox.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-24115"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-125"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-01-27T22:15:16Z",
    "severity": "MODERATE"
  },
  "details": "A path handling issue was addressed with improved validation. This issue is fixed in macOS Ventura 13.7.3, macOS Sequoia 15.3, macOS Sonoma 14.7.3. An app may be able to read files outside of its sandbox.",
  "id": "GHSA-6jw8-gwr2-hm7v",
  "modified": "2025-11-03T21:32:24Z",
  "published": "2025-01-28T00:32:14Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-24115"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122068"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122069"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122070"
    },
    {
      "type": "WEB",
      "url": "http://seclists.org/fulldisclosure/2025/Jan/15"
    },
    {
      "type": "WEB",
      "url": "http://seclists.org/fulldisclosure/2025/Jan/16"
    },
    {
      "type": "WEB",
      "url": "http://seclists.org/fulldisclosure/2025/Jan/17"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-6JWR-HC2R-77JR

Vulnerability from github – Published: 2022-05-13 01:25 – Updated: 2022-05-13 01:25
VLAI
Details

An issue was discovered in Freeware Advanced Audio Decoder 2 (FAAD2) 2.8.1. There is a NULL pointer dereference in ifilter_bank() in libfaad/filtbank.c.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2018-19504"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-125"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2018-11-23T19:29:00Z",
    "severity": "HIGH"
  },
  "details": "An issue was discovered in Freeware Advanced Audio Decoder 2 (FAAD2) 2.8.1. There is a NULL pointer dereference in ifilter_bank() in libfaad/filtbank.c.",
  "id": "GHSA-6jwr-hc2r-77jr",
  "modified": "2022-05-13T01:25:48Z",
  "published": "2022-05-13T01:25:48Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-19504"
    },
    {
      "type": "WEB",
      "url": "https://github.com/TeamSeri0us/pocs/tree/master/faad"
    },
    {
      "type": "WEB",
      "url": "https://seclists.org/bugtraq/2019/Sep/28"
    },
    {
      "type": "WEB",
      "url": "https://security.gentoo.org/glsa/202006-17"
    },
    {
      "type": "WEB",
      "url": "https://sourceforge.net/p/faac/bugs/240"
    },
    {
      "type": "WEB",
      "url": "https://www.debian.org/security/2019/dsa-4522"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-6JWV-W5XF-7J27

Vulnerability from github – Published: 2026-04-06 21:31 – Updated: 2026-04-13 19:32
VLAI
Summary
Withdrawn Advisory: go.etcd.io/bbolt affected by index out-of-range vulnerability
Details

Withdrawn Advisory

This advisory has been withdrawn because its CVE Numbering Authority has determined this issue to be a false positive. This link is maintained to preserve external references.

Original Description

Index out-of-range when encountering a branch page with zero elements in go.etcd.io/bbolt

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "go.etcd.io/bbolt"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "1.4.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-33817"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-125"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-08T00:15:13Z",
    "nvd_published_at": "2026-04-06T19:16:27Z",
    "severity": "MODERATE"
  },
  "details": "### Withdrawn Advisory\nThis advisory has been withdrawn because its CVE Numbering Authority has determined this issue to be a false positive. This link is maintained to preserve external references.\n\n### Original Description\nIndex out-of-range when encountering a branch page with zero elements in go.etcd.io/bbolt",
  "id": "GHSA-6jwv-w5xf-7j27",
  "modified": "2026-04-13T19:32:09Z",
  "published": "2026-04-06T21:31:34Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33817"
    },
    {
      "type": "WEB",
      "url": "https://github.com/golang/vulndb/issues/4923"
    },
    {
      "type": "WEB",
      "url": "https://github.com/etcd-io/bbolt/pull/1171/changes/386d5b69785937d1aa20cb25c8439404cf398143"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/etcd-io/bbolt"
    },
    {
      "type": "WEB",
      "url": "https://pkg.go.dev/vuln/GO-2026-4923"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Withdrawn Advisory: go.etcd.io/bbolt affected by index out-of-range vulnerability",
  "withdrawn": "2026-04-13T19:32:09Z"
}

GHSA-6JX5-MJMQ-JPMV

Vulnerability from github – Published: 2022-05-24 17:46 – Updated: 2022-05-24 17:46
VLAI
Details

An out-of-bounds read was addressed with improved input validation. This issue is fixed in macOS Big Sur 11.0.1, tvOS 14.0, macOS Big Sur 11.1, Security Update 2020-001 Catalina, Security Update 2020-007 Mojave, watchOS 7.0, iOS 14.0 and iPadOS 14.0. Processing a maliciously crafted font file may lead to arbitrary code execution.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-9956"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-125"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-04-02T18:15:00Z",
    "severity": "HIGH"
  },
  "details": "An out-of-bounds read was addressed with improved input validation. This issue is fixed in macOS Big Sur 11.0.1, tvOS 14.0, macOS Big Sur 11.1, Security Update 2020-001 Catalina, Security Update 2020-007 Mojave, watchOS 7.0, iOS 14.0 and iPadOS 14.0. Processing a maliciously crafted font file may lead to arbitrary code execution.",
  "id": "GHSA-6jx5-mjmq-jpmv",
  "modified": "2022-05-24T17:46:14Z",
  "published": "2022-05-24T17:46:14Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-9956"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/HT211843"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/HT211844"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/HT211850"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/HT211931"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/HT212011"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-6M2W-GR82-X4XQ

Vulnerability from github – Published: 2022-12-13 18:30 – Updated: 2022-12-15 06:30
VLAI
Details

In toLanguageTag of LocaleListCache.cpp, there is a possible out of bounds read due to an incorrect bounds check. This could lead to remote code execution with no additional execution privileges needed. User interaction is not needed for exploitation.Product: AndroidVersions: Android-10 Android-11 Android-12 Android-12L Android-13Android ID: A-239267173

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-20473"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-125"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-12-13T16:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "In toLanguageTag of LocaleListCache.cpp, there is a possible out of bounds read due to an incorrect bounds check. This could lead to remote code execution with no additional execution privileges needed. User interaction is not needed for exploitation.Product: AndroidVersions: Android-10 Android-11 Android-12 Android-12L Android-13Android ID: A-239267173",
  "id": "GHSA-6m2w-gr82-x4xq",
  "modified": "2022-12-15T06:30:30Z",
  "published": "2022-12-13T18:30:33Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-20473"
    },
    {
      "type": "WEB",
      "url": "https://source.android.com/security/bulletin/2022-12-01"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-6M34-XWQ2-MRCH

Vulnerability from github – Published: 2024-10-21 21:30 – Updated: 2024-10-31 15:30
VLAI
Details

In the Linux kernel, the following vulnerability has been resolved:

ipv4: Handle attempt to delete multipath route when fib_info contains an nh reference

Gwangun Jung reported a slab-out-of-bounds access in fib_nh_match: fib_nh_match+0xf98/0x1130 linux-6.0-rc7/net/ipv4/fib_semantics.c:961 fib_table_delete+0x5f3/0xa40 linux-6.0-rc7/net/ipv4/fib_trie.c:1753 inet_rtm_delroute+0x2b3/0x380 linux-6.0-rc7/net/ipv4/fib_frontend.c:874

Separate nexthop objects are mutually exclusive with the legacy multipath spec. Fix fib_nh_match to return if the config for the to be deleted route contains a multipath spec while the fib_info is using a nexthop object.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-48999"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-125"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-10-21T20:15:11Z",
    "severity": "HIGH"
  },
  "details": "In the Linux kernel, the following vulnerability has been resolved:\n\nipv4: Handle attempt to delete multipath route when fib_info contains an nh reference\n\nGwangun Jung reported a slab-out-of-bounds access in fib_nh_match:\n    fib_nh_match+0xf98/0x1130 linux-6.0-rc7/net/ipv4/fib_semantics.c:961\n    fib_table_delete+0x5f3/0xa40 linux-6.0-rc7/net/ipv4/fib_trie.c:1753\n    inet_rtm_delroute+0x2b3/0x380 linux-6.0-rc7/net/ipv4/fib_frontend.c:874\n\nSeparate nexthop objects are mutually exclusive with the legacy\nmultipath spec. Fix fib_nh_match to return if the config for the\nto be deleted route contains a multipath spec while the fib_info\nis using a nexthop object.",
  "id": "GHSA-6m34-xwq2-mrch",
  "modified": "2024-10-31T15:30:58Z",
  "published": "2024-10-21T21:30:52Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-48999"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/0b5394229ebae09afc07aabccb5ffd705ffd250e"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/25174d91e4a32a24204060d283bd5fa6d0ddf133"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/61b91eb33a69c3be11b259c5ea484505cd79f883"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/bb20a2ae241be846bc3c11ea4b3a3c69e41d51f2"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/cc3cd130ecfb8b0ae52e235e487bae3f16a24a32"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-6M57-8R3P-PQX6

Vulnerability from github – Published: 2026-05-29 19:05 – Updated: 2026-06-12 19:31
VLAI
Summary
unbounded-spsc: Sender::send pointer-as-value transmute causes OOB read and fake-Arc drop under TX/RX race
Details

Summary

Sender::send in src/lib.rs contains an unsafe block in the DISCONNECTED arm that transmutes a raw pointer (*mut Producer<T>) into the bytes of a value-level Consumer<T>. The author's intent, visible in the surrounding comment at lines 386-390, was a value transmute. The shipped code is one level of indirection off.

The resulting Consumer<T> has its internal Arc::ptr set to the address of the producer field on the Sender, not the real ArcInner<Buffer<T>>. Every subsequent consumer.try_pop() walks Buffer<T> fields at offsets that lie inside the Sender<T> struct (over send_new, inner) and adjacent memory, an out-of-bounds read. When the fake Consumer<T> is dropped at the end of the unsafe block, its Drop calls Arc::drop_in_place on a non-ArcInner address: it decrements bytes that the type system treats as strong_count: AtomicUsize but that are actually the real Arc::ptr value of the Sender, and at zero count it calls dealloc(Layout::for_value(...)) on an address the allocator never returned.

Reachable from 100% safe Rust through the canonical channel pattern: a tx.send(msg) that races with rx.drop(). This is consistent with the SIGSEGV that issue #3 reports in your own test suite.

Affected code (0.2.0, master at 23a9ce7)

```rust // src/lib.rs:384-401 DISCONNECTED => { self.inner.counter.store (DISCONNECTED, Ordering::SeqCst); // We want to guarantee if a message was not received that we get it // back; since spsc::{Producer,Consumer} have the same // internal representation (as a singleton struct containing Arc // >), we can safely transmute the producer in order to // pop the message back if it was orphaned. unsafe { let consumer : spsc::Consumer = std::mem::transmute (self.producer.get()); // <-- POINTER, not value let first = consumer.try_pop(); let second = consumer.try_pop(); assert!(second.is_none()); // <-- line 396; smoking-gun assert if let Some(t) = first { return Err (SendError (t)) } } }, self.producer is UnsafeCell> (line 29). UnsafeCell::::get(&self) returns mut X, a raw pointer, 8 bytes on 64-bit. The signature of transmute is transmute::(src: Src) -> Dst, so the call expands to transmute::<mut spsc::Producer, spsc::Consumer>(self.producer.get()). 8 bytes of pointer are reinterpreted as the bytes of a Consumer.

In bounded-spsc-queue-0.4.0, both Producer and Consumer are newtypes around Arc>, one pointer wide. The destination value therefore has Arc::ptr == &mut Producer as *const ArcInner>. To be a valid Arc>, that pointer must point to ArcInner { strong: AtomicUsize, weak: AtomicUsize, data: Buffer }, but it actually points to the start of Sender (the producer field). The first 8 bytes there hold the real Arc::ptr. The fake Arc reads those bytes as strong_count. The fake try_pop() then reads Buffer head/tail/data slots starting at offset 16 inside the Sender, that is, inside the send_new and inner fields.

The author's intent (per the comment at lines 386-390) was a value-level transmute:

let producer_val: spsc::Producer = std::ptr::read(self.producer.get()); let consumer : spsc::Consumer = std::mem::transmute(producer_val); which is layout-sound iff Producer and Consumer have identical layouts (they do, both are single-Arc newtypes). The shipped code is one indirection off.

Reachability The branch is not reachable single-threaded. Receiver::drop (line 332) stores connected = false before setting counter = DISCONNECTED; Sender::send (line 359) early-returns on connected == false. The trigger is a TOCTOU race:

Sender's self.inner.connected.load(SeqCst) reads true. Receiver-drop runs: stores connected = false and counter.compare_exchange(_, DISCONNECTED, SeqCst, SeqCst). Sender's self.inner.counter.fetch_add(1, SeqCst) (line 379) sees DISCONNECTED and enters the unsafe block. Under heavy contention this reproduces ~3/10 trials in release mode.

Proof of concept (race shape) // Cargo.toml: unbounded-spsc = "0.2" use std::thread; use unbounded_spsc::channel;

fn main() { for trial in 0..500 { let (tx, rx) = channel::>(); let started = std::sync::Arc::new( std::sync::atomic::AtomicBool::new(false)); let s = started.clone(); let h = thread::spawn(move || { s.store(true, std::sync::atomic::Ordering::SeqCst); for _ in 0..10_000 { let _ = tx.send(Box::new(0xDEAD_BEEF)); } }); while !started.load(std::sync::atomic::Ordering::SeqCst) { std::hint::spin_loop(); } drop(rx); let _ = h.join(); eprintln!("trial {trial} ok"); } } Observed:

Release-mode (no sanitizer): Segmentation fault (core dumped) reliably within a few trials. The non-segfaulting trials are masked by the separate send_new.send(new_consumer).unwrap() panic, see Secondary defect below. -Zsanitizer=address -Zbuild-std (nightly): ASan reports stack-buffer-overflow / stack-use-after-scope from the fake-Consumer's try_pop walking off the Sender frame. This matches the SIGSEGV reported in your own issue #3.

Smoking-gun upstream evidence src/lib.rs:975 in the project's test suite carries a TODO:

// TODO: failures // - failed with assertion on line 394 in send fn // assert!(second.is_none()) That is the assertion site of the transmute block (line 396 in 0.2.0 / master). You have observed try_pop() returning a non-None value where logically there should be none, which is exactly what reading random bytes from the Sender's send_new / inner fields produces, and the symptom has been marked as a flaky test rather than recognised as UB.

Impact Reachable from 100% safe Rust. Concrete UB primitives:

OOB read of bytes adjacent to the Sender struct via fake Consumer::try_pop(). The popped T is returned through Err(SendError(t)) to safe-code, an allocator-layout-controlled leak of process memory. OOB write via fake Arc::drop AtomicUsize::fetch_sub on bytes that are actually the real Arc::ptr value of the Sender. Allocator corruption via fake Arc::drop calling dealloc(Layout::for_value(...)) on a non-allocated address. The Sender struct holds the real Arc immediately after the producer field; the deallocator call therefore uses a layout the allocator never allocated, which on glibc is a confirmed double-free / arbitrary-bucket-poisoning primitive, and on hardened allocators (jemalloc-secure, mimalloc-secure) is an immediate abort. Secondary defect (same call path, bonus) Sender::send line 369:

self.send_new.send(new_consumer).unwrap(); When the Sender's message queue is full, a fresh bounded_spsc_queue::Channel is allocated and the new Consumer is shipped over an std::sync::mpsc side-channel to the Receiver. If the Receiver has already been dropped, receive_new is gone and this unwrap() panics. The panic surfaces in your own test suite, issue #2 (tests::port_gone_concurrent panicked at src/lib.rs:369) and the in-source TODO at lines 365-368 already note the question "Are we sure that this is safe to unwrap or should we handle the result explicitly ?".

The fix is to return Err(SendError(t)) instead of unwrapping, same shape as the channel-closed result the function already returns on the connected-false path. This is not a memory-safety defect, only a panic, but it lives on the same TX/RX-race code path and a single coordinated patch can address both. Filing it here so we cover the full call site in one cycle.

Suggested patch (primary defect) Replace the pointer-as-value transmute with a value-level read and a ManuallyDrop to suppress the alias's Producer::drop on subsequent exit:

unsafe { use core::mem::ManuallyDrop;

// Sound value-level transmute: Producer<T> and Consumer<T> are both
// newtypes around Arc<Buffer<T>>, so the value layouts match.
// ptr::read takes ownership of the Producer's bytes without running
// Producer's Drop.
let producer_val: spsc::Producer<T> = std::ptr::read(self.producer.get());
let consumer    : spsc::Consumer<T> = std::mem::transmute(producer_val);

let first  = consumer.try_pop();
let second = consumer.try_pop();
assert!(second.is_none());
if let Some(t) = first {
    return Err(SendError(t));
}

// consumer drops here; the same memory backs `producer`, so suppress
// the double Producer drop:
let _ = ManuallyDrop::new(consumer);

} Cleaner: restructure Sender to hold producer and consumer in a private enum Endpoint so no transmute is required, or use the bounded_spsc_queue::Producer::reclaim() escape hatch if available.

Suggested patch (secondary defect) if let Err(std::sync::mpsc::SendError(_)) = self.send_new.send(new_consumer) { // Receiver has been dropped: take the message back as the public // SendError, the same way the connected==false early-return does. return Err(SendError(t)); } Regression test (release-mode, race shape)

[test]

fn race_disconnect_does_not_corrupt_sender_or_abort() { for _ in 0..200 { let (tx, rx) = unbounded_spsc::channel::>(); let h = std::thread::spawn(move || { for _ in 0..10_000 { let _ = tx.send(Box::new(0xDEAD_BEEF)); } }); drop(rx); h.join().unwrap(); } } Reverse dependencies Two crates on crates.io depend on unbounded-spsc, both owned by you: apis (process-calculus framework) and gooey-rs (tile-UI library, unbounded-spsc gated behind opengl/fmod features). The OpenGL/FMOD callback-mailbox use is a natural rx-drop-during-tx-send scenario at scene-graph teardown. A single coordinated bump cycle is feasible.

Researcher Berkant Koc me@berkoc.com PGP: 0C588DFD76204987284213EA0AC529C41F8AA5D6

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "unbounded-spsc"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "0.2.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-46690"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-125",
      "CWE-415",
      "CWE-704",
      "CWE-787"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-29T19:05:21Z",
    "nvd_published_at": "2026-06-12T16:16:29Z",
    "severity": "MODERATE"
  },
  "details": "## Summary\n\n`Sender::send` in `src/lib.rs` contains an `unsafe` block in the `DISCONNECTED` arm that transmutes a **raw pointer** (`*mut Producer\u003cT\u003e`) into the bytes of a **value-level** `Consumer\u003cT\u003e`. The author\u0027s intent, visible in the surrounding comment at lines 386-390, was a value transmute. The shipped code is one level of indirection off.\n\nThe resulting `Consumer\u003cT\u003e` has its internal `Arc::ptr` set to the address of the `producer` field on the `Sender`, not the real `ArcInner\u003cBuffer\u003cT\u003e\u003e`. Every subsequent `consumer.try_pop()` walks `Buffer\u003cT\u003e` fields at offsets that lie inside the `Sender\u003cT\u003e` struct (over `send_new`, `inner`) and adjacent memory, an out-of-bounds read. When the fake `Consumer\u003cT\u003e` is dropped at the end of the `unsafe` block, its `Drop` calls `Arc::drop_in_place` on a non-`ArcInner` address: it decrements bytes that the type system treats as `strong_count: AtomicUsize` but that are actually the real `Arc::ptr` value of the `Sender`, and at zero count it calls `dealloc(Layout::for_value(...))` on an address the allocator never returned.\n\nReachable from 100% safe Rust through the canonical channel pattern: a `tx.send(msg)` that races with `rx.drop()`. This is consistent with the SIGSEGV that issue #3 reports in your own test suite.\n\n## Affected code (0.2.0, master at `23a9ce7`)\n\n```rust\n// src/lib.rs:384-401\nDISCONNECTED =\u003e {\n    self.inner.counter.store (DISCONNECTED, Ordering::SeqCst);\n    // We want to guarantee if a message was not received that we get it\n    // back; since spsc::{Producer,Consumer} have the same\n    // internal representation (as a singleton struct containing Arc\n    // \u003cBuffer \u003cT\u003e\u003e), we can safely transmute the producer in order to\n    // pop the message back if it was orphaned.\n    unsafe {\n      let consumer : spsc::Consumer \u003cT\u003e\n        = std::mem::transmute (self.producer.get());     // \u003c-- POINTER, not value\n      let first    = consumer.try_pop();\n      let second   = consumer.try_pop();\n      assert!(second.is_none());                          // \u003c-- line 396; smoking-gun assert\n      if let Some(t) = first {\n        return Err (SendError (t))\n      }\n    }\n},\nself.producer is UnsafeCell\u003cspsc::Producer\u003cT\u003e\u003e (line 29). UnsafeCell::\u003cX\u003e::get(\u0026self) returns *mut X, a raw pointer, 8 bytes on 64-bit. The signature of transmute is transmute::\u003cSrc, Dst\u003e(src: Src) -\u003e Dst, so the call expands to transmute::\u003c*mut spsc::Producer\u003cT\u003e, spsc::Consumer\u003cT\u003e\u003e(self.producer.get()). 8 bytes of pointer are reinterpreted as the bytes of a Consumer\u003cT\u003e.\n\nIn bounded-spsc-queue-0.4.0, both Producer\u003cT\u003e and Consumer\u003cT\u003e are newtypes around Arc\u003cBuffer\u003cT\u003e\u003e, one pointer wide. The destination value therefore has Arc::ptr == \u0026mut Producer\u003cT\u003e as *const ArcInner\u003cBuffer\u003cT\u003e\u003e. To be a valid Arc\u003cBuffer\u003cT\u003e\u003e, that pointer must point to ArcInner { strong: AtomicUsize, weak: AtomicUsize, data: Buffer\u003cT\u003e }, but it actually points to the start of Sender\u003cT\u003e (the producer field). The first 8 bytes there hold the real Arc::ptr. The fake Arc reads those bytes as strong_count. The fake try_pop() then reads Buffer\u003cT\u003e head/tail/data slots starting at offset 16 inside the Sender\u003cT\u003e, that is, inside the send_new and inner fields.\n\nThe author\u0027s intent (per the comment at lines 386-390) was a value-level transmute:\n\nlet producer_val: spsc::Producer\u003cT\u003e = std::ptr::read(self.producer.get());\nlet consumer    : spsc::Consumer\u003cT\u003e = std::mem::transmute(producer_val);\nwhich is layout-sound iff Producer\u003cT\u003e and Consumer\u003cT\u003e have identical layouts (they do, both are single-Arc newtypes). The shipped code is one indirection off.\n\nReachability\nThe branch is not reachable single-threaded. Receiver::drop (line 332) stores connected = false before setting counter = DISCONNECTED; Sender::send (line 359) early-returns on connected == false. The trigger is a TOCTOU race:\n\nSender\u0027s self.inner.connected.load(SeqCst) reads true.\nReceiver-drop runs: stores connected = false and counter.compare_exchange(_, DISCONNECTED, SeqCst, SeqCst).\nSender\u0027s self.inner.counter.fetch_add(1, SeqCst) (line 379) sees DISCONNECTED and enters the unsafe block.\nUnder heavy contention this reproduces ~3/10 trials in release mode.\n\nProof of concept (race shape)\n// Cargo.toml: unbounded-spsc = \"0.2\"\nuse std::thread;\nuse unbounded_spsc::channel;\n\nfn main() {\n    for trial in 0..500 {\n        let (tx, rx) = channel::\u003cBox\u003cu64\u003e\u003e();\n        let started = std::sync::Arc::new(\n            std::sync::atomic::AtomicBool::new(false));\n        let s = started.clone();\n        let h = thread::spawn(move || {\n            s.store(true, std::sync::atomic::Ordering::SeqCst);\n            for _ in 0..10_000 {\n                let _ = tx.send(Box::new(0xDEAD_BEEF));\n            }\n        });\n        while !started.load(std::sync::atomic::Ordering::SeqCst) {\n            std::hint::spin_loop();\n        }\n        drop(rx);\n        let _ = h.join();\n        eprintln!(\"trial {trial} ok\");\n    }\n}\nObserved:\n\nRelease-mode (no sanitizer): Segmentation fault (core dumped) reliably within a few trials. The non-segfaulting trials are masked by the separate send_new.send(new_consumer).unwrap() panic, see Secondary defect below.\n-Zsanitizer=address -Zbuild-std (nightly): ASan reports stack-buffer-overflow / stack-use-after-scope from the fake-Consumer\u0027s try_pop walking off the Sender frame.\nThis matches the SIGSEGV reported in your own issue #3.\n\nSmoking-gun upstream evidence\nsrc/lib.rs:975 in the project\u0027s test suite carries a TODO:\n\n// TODO: failures\n// - failed with assertion on line 394 in send fn\n//   assert!(second.is_none())\nThat is the assertion site of the transmute block (line 396 in 0.2.0 / master). You have observed try_pop() returning a non-None value where logically there should be none, which is exactly what reading random bytes from the Sender\u0027s send_new / inner fields produces, and the symptom has been marked as a flaky test rather than recognised as UB.\n\nImpact\nReachable from 100% safe Rust. Concrete UB primitives:\n\nOOB read of bytes adjacent to the Sender\u003cT\u003e struct via fake Consumer\u003cT\u003e::try_pop(). The popped T is returned through Err(SendError(t)) to safe-code, an allocator-layout-controlled leak of process memory.\nOOB write via fake Arc::drop AtomicUsize::fetch_sub on bytes that are actually the real Arc::ptr value of the Sender.\nAllocator corruption via fake Arc::drop calling dealloc(Layout::for_value(...)) on a non-allocated address. The Sender struct holds the real Arc\u003cInner\u003e immediately after the producer field; the deallocator call therefore uses a layout the allocator never allocated, which on glibc is a confirmed double-free / arbitrary-bucket-poisoning primitive, and on hardened allocators (jemalloc-secure, mimalloc-secure) is an immediate abort.\nSecondary defect (same call path, bonus)\nSender::send line 369:\n\nself.send_new.send(new_consumer).unwrap();\nWhen the Sender\u0027s message queue is full, a fresh bounded_spsc_queue::Channel is allocated and the new Consumer\u003cT\u003e is shipped over an std::sync::mpsc side-channel to the Receiver. If the Receiver has already been dropped, receive_new is gone and this unwrap() panics. The panic surfaces in your own test suite, issue #2 (tests::port_gone_concurrent panicked at src/lib.rs:369) and the in-source TODO at lines 365-368 already note the question \"Are we sure that this is safe to unwrap or should we handle the result explicitly ?\".\n\nThe fix is to return Err(SendError(t)) instead of unwrapping, same shape as the channel-closed result the function already returns on the connected-false path. This is not a memory-safety defect, only a panic, but it lives on the same TX/RX-race code path and a single coordinated patch can address both. Filing it here so we cover the full call site in one cycle.\n\nSuggested patch (primary defect)\nReplace the pointer-as-value transmute with a value-level read and a ManuallyDrop to suppress the alias\u0027s Producer::drop on subsequent exit:\n\nunsafe {\n    use core::mem::ManuallyDrop;\n\n    // Sound value-level transmute: Producer\u003cT\u003e and Consumer\u003cT\u003e are both\n    // newtypes around Arc\u003cBuffer\u003cT\u003e\u003e, so the value layouts match.\n    // ptr::read takes ownership of the Producer\u0027s bytes without running\n    // Producer\u0027s Drop.\n    let producer_val: spsc::Producer\u003cT\u003e = std::ptr::read(self.producer.get());\n    let consumer    : spsc::Consumer\u003cT\u003e = std::mem::transmute(producer_val);\n\n    let first  = consumer.try_pop();\n    let second = consumer.try_pop();\n    assert!(second.is_none());\n    if let Some(t) = first {\n        return Err(SendError(t));\n    }\n\n    // consumer drops here; the same memory backs `producer`, so suppress\n    // the double Producer drop:\n    let _ = ManuallyDrop::new(consumer);\n}\nCleaner: restructure Sender\u003cT\u003e to hold producer and consumer in a private enum Endpoint\u003cT\u003e so no transmute is required, or use the bounded_spsc_queue::Producer\u003cT\u003e::reclaim() escape hatch if available.\n\nSuggested patch (secondary defect)\nif let Err(std::sync::mpsc::SendError(_)) = self.send_new.send(new_consumer) {\n    // Receiver has been dropped: take the message back as the public\n    // SendError, the same way the connected==false early-return does.\n    return Err(SendError(t));\n}\nRegression test (release-mode, race shape)\n#[test]\nfn race_disconnect_does_not_corrupt_sender_or_abort() {\n    for _ in 0..200 {\n        let (tx, rx) = unbounded_spsc::channel::\u003cBox\u003cu64\u003e\u003e();\n        let h = std::thread::spawn(move || {\n            for _ in 0..10_000 {\n                let _ = tx.send(Box::new(0xDEAD_BEEF));\n            }\n        });\n        drop(rx);\n        h.join().unwrap();\n    }\n}\nReverse dependencies\nTwo crates on crates.io depend on unbounded-spsc, both owned by you: apis (process-calculus framework) and gooey-rs (tile-UI library, unbounded-spsc gated behind opengl/fmod features). The OpenGL/FMOD callback-mailbox use is a natural rx-drop-during-tx-send scenario at scene-graph teardown. A single coordinated bump cycle is feasible.\n\nResearcher\nBerkant Koc me@berkoc.com\nPGP: 0C588DFD76204987284213EA0AC529C41F8AA5D6",
  "id": "GHSA-6m57-8r3p-pqx6",
  "modified": "2026-06-12T19:31:16Z",
  "published": "2026-05-29T19:05:21Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/spearman/unbounded-spsc/security/advisories/GHSA-6m57-8r3p-pqx6"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-46690"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/spearman/unbounded-spsc"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "unbounded-spsc: Sender::send pointer-as-value transmute causes OOB read and fake-Arc drop under TX/RX race"
}

GHSA-6M6F-RWF2-GHVG

Vulnerability from github – Published: 2025-05-14 21:31 – Updated: 2025-05-19 18:30
VLAI
Details

An issue was discovered in Samsung Mobile Processor and Wearable Processor Exynos 9820, 9825, 980, 990, 850, 1080, 2100, 1280, 2200, 1330, 1380, 1480, 2400, 9110, W920, W930, W1000, Modem 5123, Modem 5300, and Modem 5400. The lack of a length check leads to out-of-bounds access via malformed RRC packets to the target.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-56427"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-125"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-05-14T21:15:58Z",
    "severity": "MODERATE"
  },
  "details": "An issue was discovered in Samsung Mobile Processor and Wearable Processor Exynos 9820, 9825, 980, 990, 850, 1080, 2100, 1280, 2200, 1330, 1380, 1480, 2400, 9110, W920, W930, W1000, Modem 5123, Modem 5300, and Modem 5400. The lack of a length check leads to out-of-bounds access via malformed RRC packets to the target.",
  "id": "GHSA-6m6f-rwf2-ghvg",
  "modified": "2025-05-19T18:30:41Z",
  "published": "2025-05-14T21:31:20Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-56427"
    },
    {
      "type": "WEB",
      "url": "https://semiconductor.samsung.com/support/quality-support/product-security-updates"
    },
    {
      "type": "WEB",
      "url": "https://semiconductor.samsung.com/support/quality-support/product-security-updates/cve-2024-56427"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-6M86-HGFJ-MFMR

Vulnerability from github – Published: 2024-09-18 15:30 – Updated: 2024-09-20 21:31
VLAI
Details

Out-of-bounds Read vulnerability in Open Networking Foundation (ONF) libfluid (libfluid_msg module). This vulnerability is associated with program routine fluid_msg::of10::StatsReplyPort::unpack.

This issue affects libfluid: 0.1.0.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-31171"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-125"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-09-18T14:15:14Z",
    "severity": "MODERATE"
  },
  "details": "Out-of-bounds Read vulnerability in Open Networking Foundation (ONF) libfluid (libfluid_msg module). This vulnerability is associated with program routine\u00a0fluid_msg::of10::StatsReplyPort::unpack.\n\nThis issue affects libfluid: 0.1.0.",
  "id": "GHSA-6m86-hgfj-mfmr",
  "modified": "2024-09-20T21:31:38Z",
  "published": "2024-09-18T15:30:51Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-31171"
    },
    {
      "type": "WEB",
      "url": "https://www.nozominetworks.com/labs/vulnerability-advisories-cve-2024-31171"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-6M8H-J94Q-8VFV

Vulnerability from github – Published: 2023-01-26 21:30 – Updated: 2024-11-27 21:32
VLAI
Details

This vulnerability allows remote attackers to disclose sensitive information on affected installations of PDF-XChange Editor. User interaction is required to exploit this vulnerability in that the target must visit a malicious page or open a malicious file. The specific flaw exists within the parsing of U3D files. Crafted data in a U3D file can trigger a read past the end of an allocated buffer. An attacker can leverage this in conjunction with other vulnerabilities to execute arbitrary code in the context of the current process. Was ZDI-CAN-18529.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-42376"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-125"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-01-26T18:59:00Z",
    "severity": "MODERATE"
  },
  "details": "This vulnerability allows remote attackers to disclose sensitive information on affected installations of PDF-XChange Editor. User interaction is required to exploit this vulnerability in that the target must visit a malicious page or open a malicious file. The specific flaw exists within the parsing of U3D files. Crafted data in a U3D file can trigger a read past the end of an allocated buffer. An attacker can leverage this in conjunction with other vulnerabilities to execute arbitrary code in the context of the current process. Was ZDI-CAN-18529.",
  "id": "GHSA-6m8h-j94q-8vfv",
  "modified": "2024-11-27T21:32:37Z",
  "published": "2023-01-26T21:30:23Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-42376"
    },
    {
      "type": "WEB",
      "url": "https://www.tracker-software.com/product/pdf-xchange-editor/history"
    },
    {
      "type": "WEB",
      "url": "https://www.zerodayinitiative.com/advisories/ZDI-22-1363"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

Mitigation MIT-5
Implementation

Strategy: Input Validation

  • Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use a list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does.
  • When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid because it only contains alphanumeric characters, but it is not valid if the input is only expected to contain colors such as "red" or "blue."
  • Do not rely exclusively on looking for malicious or malformed inputs. This is likely to miss at least one undesirable input, especially if the code's environment changes. This can give attackers enough room to bypass the intended validation. However, denylists can be useful for detecting potential attacks or determining which inputs are so malformed that they should be rejected outright.
  • To reduce the likelihood of introducing an out-of-bounds read, ensure that you validate and ensure correct calculations for any length argument, buffer size calculation, or offset. Be especially careful of relying on a sentinel (i.e. special character such as NUL) in untrusted inputs.
Mitigation
Architecture and Design

Strategy: Language Selection

Use a language that provides appropriate memory abstractions.

CAPEC-540: Overread Buffers

An adversary attacks a target by providing input that causes an application to read beyond the boundary of a defined buffer. This typically occurs when a value influencing where to start or stop reading is set to reflect positions outside of the valid memory location of the buffer. This type of attack may result in exposure of sensitive information, a system crash, or arbitrary code execution.