The following CVE has been assigned to this issue: CVE-2026-6042
> On 2 Apr 2026, at 22.27, Jens Jarl Nestén Hansen-Nord <[email protected]> wrote: > > ========================================== > libc musl Security Advisory: April 2, 2026 > ========================================== > Description: > The GB18030 4-byte decoder in musl libc's iconv() implementation contains a > gap-skipping loop that performs a full linear scan of the gb18030126 lookup > table (23,940 entries) on each iteration of an outer loop whose iteration > count is input-dependent. For 4-byte sequences whose linear index falls just > below the dense CJK Unified Ideographs range, the outer loop executes > approximately 20,905 times, resulting in approximately 500 million > comparisons per input character. > Classification: > Inefficient Algorithmic Complexity (CWE-407) > Impact: > This allows a remote attacker to cause denial of service via CPU exhaustion > by sending a crafted GB18030 payload to any network service that uses musl's > iconv() for character encoding conversion. Measured on musl 1.2.6 and 1.2.5: > a single 4-byte input character (bytes 0x82 0x35 0x8F 0x33) takes > approximately 260ms to decode, compared to approximately 13 microseconds for > a benign character — a 19,000x slowdown. A payload of 40kB will take ~43 > minutes to decode. > > Versions affected: > musl 0.8.0 to 1.2.6 > > Status: > The issue has been confirmed and fixed by maintainer, Rich Felker. > A CVE has been requested and is pending assignment. > > Reported by: > Jens Jarl Nestén Hansen-Nord > > Upstream fix: > Iconv-gb18030-fix.diff > > diff --git a/src/locale/iconv.c b/src/locale/iconv.c > index 52178950..e559aa4c 100644 > --- a/src/locale/iconv.c > +++ b/src/locale/iconv.c > @@ -74,6 +74,10 @@ static const unsigned short gb18030[126][190] = { > #include "gb18030.h" > }; > > +static const unsigned short gb18030utf[][2] = { > +#include "gb18030utf.h" > +}; > + > static const unsigned short big5[89][157] = { > #include "big5.h" > }; > @@ -224,6 +228,8 @@ static unsigned uni_to_jis(unsigned c) > } > } > > +#define countof(a) (sizeof (a) / sizeof *(a)) > + > size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char > **restrict out, size_t *restrict outb) > { > size_t x=0; > @@ -430,16 +436,14 @@ size_t iconv(iconv_t cd, char **restrict in, size_t > *restrict inb, char **restri > d = *((unsigned char *)*in + 3); > if (d-'0'>9) goto ilseq; > c += d-'0'; > - c += 128; > - for (d=0; d<=c; ) { > - k = 0; > - for (int i=0; i<126; i++) > - for (int j=0; j<190; j++) > - if (gb18030[i][j]-d <= c-d) > - k++; > - d = c+1; > - c += k; > + for (int i=0; i<countof(gb18030utf); i++) { > + if (c<gb18030utf[i][1]) { > + c += gb18030utf[i][0]; > + break; > + } > + c -= gb18030utf[i][1]; > } > + c += 0x10000; > break; > } > d -= 0x40; > > > >
