-
-
Notifications
You must be signed in to change notification settings - Fork 231
Expand file tree
/
Copy pathCVE-2026-35201.yml
More file actions
125 lines (94 loc) · 3.03 KB
/
CVE-2026-35201.yml
File metadata and controls
125 lines (94 loc) · 3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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