From 10ea91133e3bfb05b04c3dc14f836d9fa9931184 Mon Sep 17 00:00:00 2001 From: Al Snow <43523+jasnow@users.noreply.github.com> Date: Tue, 7 Apr 2026 09:24:52 -0400 Subject: [PATCH] GHSA/SYNC: 1 brand new advisory --- gems/rdiscount/CVE-2026-35201.yml | 125 ++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 gems/rdiscount/CVE-2026-35201.yml diff --git a/gems/rdiscount/CVE-2026-35201.yml b/gems/rdiscount/CVE-2026-35201.yml new file mode 100644 index 0000000000..d767ca6cf8 --- /dev/null +++ b/gems/rdiscount/CVE-2026-35201.yml @@ -0,0 +1,125 @@ +--- +gem: rdiscount +cve: 2026-35201 +ghsa: 6r34-94wq-jhrc +url: https://github.com/davidfstr/rdiscount/security/advisories/GHSA-6r34-94wq-jhrc +title: rdiscount has an Out-of-bounds Read +date: 2026-04-06 +description: | + ### Summary + + A signed length truncation bug causes an out-of-bounds read in the + default Markdown parse path. Inputs larger than `INT_MAX` are truncated + to a signed `int` before entering the native parser, allowing the + parser to read past the end of the supplied buffer and crash the process. + + ### Details + + In both public entry points: + + - `ext/rdiscount.c:97` + - `ext/rdiscount.c:136` + + `RSTRING_LEN(text)` is passed directly into `mkd_string()`: + + ```c + MMIOT *doc = mkd_string(RSTRING_PTR(text), + RSTRING_LEN(text), flags); + ``` + + `mkd_string()` accepts `int len`: + + - `ext/mkdio.c:174` + + ```c + Document + * mkd_string(const char *buf, int len, mkd_flag_t flags) + { + struct string_stream about; + + about.data = buf; + about.size = len; + + return populate((getc_func)__mkd_io_strget, &about, flags & INPUT_MASK); + } + ``` + + The parser stores the remaining input length in a signed `int`: + + - `ext/markdown.h:205` + + ```c + struct string_stream { + const + char *data; + int size; + }; + ``` + + The read loop stops only when `size == 0`: + + - `ext/mkdio.c:161` + + ```c + int __mkd_io_strget(struct string_stream *in) + { + if ( !in->size ) return EOF; + + --(in->size); + + return *(in->data)++; + } + ``` + + If the Ruby string length exceeds `INT_MAX`, the value can truncate + to a negative `int`. In that state, the parser continues incrementing + `data` and reading past the end of the original Ruby string, causing + an out-of-bounds read and native crash. + + Affected APIs: + + - `RDiscount.new(input).to_html` + - `RDiscount.new(input).toc_content` + + ### Impact + + This is an out-of-bounds read with the main issue being reliable + denial-of-service. Impacted is limited to deployments parses + attacker-controlled Markdown and permits multi-GB inputs. + + ### Fix + + just add a checked length guard before the `mkd_string()` + call in both public entry points: + + - `ext/rdiscount.c:97` + - `ext/rdiscount.c:136` + ex: + + ```c + VALUE text = rb_funcall(self, rb_intern(\"text\"), 0); + long text_len = RSTRING_LEN(text); + VALUE buf = rb_str_buf_new(1024); + Check_Type(text, T_STRING); + + if (text_len > INT_MAX) { + rb_raise(rb_eArgError, \"markdown input too large\"); + } + + MMIOT *doc = mkd_string(RSTRING_PTR(text), (int)text_len, flags); + ``` + + The same guard should be applied in `rb_rdiscount_toc_content()` + before its `mkd_string()` call. +cvss_v3: 5.9 +unaffected_versions: + - "< 1.3.1.1" +patched_versions: + - ">= 2.2.7.4" +related: + url: + - https://nvd.nist.gov/vuln/detail/CVE-2026-35201 + - https://github.com/davidfstr/rdiscount/security/advisories/GHSA-6r34-94wq-jhrc + - http://github.com/davidfstr/rdiscount/releases/tag/2.2.7.4 + - https://github.com/davidfstr/rdiscount/commit/b1a16445e92e0d12c07594dedcdc56f80b317761 + - https://github.com/advisories/GHSA-6r34-94wq-jhrc