Skip to content

Commit ef00a7d

Browse files
committed
Fix AFL crashes in C++ demangler
American Fuzzy Lop didn't need to try very hard, to crash our privileged __demangle() implementation. This change helps ensure our barebones impl will fail rather than crash when given adversarial input data.
1 parent 7466600 commit ef00a7d

File tree

1 file changed

+22
-12
lines changed

1 file changed

+22
-12
lines changed

libc/intrin/demangle.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -380,13 +380,16 @@ demangle_free(struct demangle_data *h, void *ptr)
380380
}
381381

382382
static privileged returnspointerwithnoaliases returnsnonnull void *
383-
demangle_malloc(struct demangle_data *h, int a, int n)
383+
demangle_malloc(struct demangle_data *h, long a, long n)
384384
{
385-
int rem;
385+
long rem;
386386
uintptr_t ptr;
387387
index_t next, next2;
388388
index_t *link, *link2;
389-
int b = sizeof(index_t);
389+
long b = sizeof(index_t);
390+
391+
if (n < 0 || n >= 32768)
392+
__builtin_longjmp(h->jmpbuf, 1);
390393

391394
/* Roundup size. */
392395
n += a - 1;
@@ -2098,10 +2101,11 @@ demangle_read_tmpl_param(struct demangle_data *ddata)
20982101
/* T_ is first */
20992102
++nth;
21002103

2101-
while (*ddata->cur != '_')
2104+
while (*ddata->cur && *ddata->cur != '_')
21022105
++ddata->cur;
21032106

2104-
ASSERT(nth > 0);
2107+
if (nth <= 0)
2108+
return 0;
21052109

21062110
return demangle_get_tmpl_param(ddata, nth);
21072111
}
@@ -2752,7 +2756,7 @@ demangle_read_offset_number(struct demangle_data *ddata)
27522756
start = ddata->cur;
27532757
}
27542758

2755-
while (*ddata->cur != '_')
2759+
while (*ddata->cur && *ddata->cur != '_')
27562760
++ddata->cur;
27572761

27582762
if (negative && !DEM_PUSH_STR(ddata, "-"))
@@ -2859,13 +2863,12 @@ demangle_read_number(struct demangle_data *ddata, long *rtn)
28592863
return 0;
28602864

28612865
len = demangle_strtol(ddata->cur, 10);
2866+
if (len < 0)
2867+
__builtin_longjmp(ddata->jmpbuf, 1);
28622868

28632869
while (ELFTC_ISDIGIT(*ddata->cur))
28642870
++ddata->cur;
28652871

2866-
ASSERT(len >= 0);
2867-
ASSERT(negative_factor == 1 || negative_factor == -1);
2868-
28692872
*rtn = len * negative_factor;
28702873

28712874
return 1;
@@ -3419,6 +3422,7 @@ demangle_read_pointer_to_member(struct demangle_data *ddata,
34193422
static privileged int
34203423
demangle_read_sname(struct demangle_data *ddata)
34213424
{
3425+
size_t lim;
34223426
long len;
34233427
int err;
34243428

@@ -3438,6 +3442,9 @@ demangle_read_sname(struct demangle_data *ddata)
34383442
ddata->last_sname = VEC_STR(ddata, ddata->cur_output,
34393443
ddata->cur_output->size - 1);
34403444

3445+
lim = demangle_strlen(ddata->cur);
3446+
if (len > lim)
3447+
len = lim;
34413448
ddata->cur += len;
34423449

34433450
return 1;
@@ -3647,10 +3654,11 @@ demangle_read_subst(struct demangle_data *ddata)
36473654
/* first was '_', so increase one */
36483655
++nth;
36493656

3650-
while (*ddata->cur != '_')
3657+
while (*ddata->cur && *ddata->cur != '_')
36513658
++ddata->cur;
36523659

3653-
ASSERT(nth > 0);
3660+
if (nth <= 0)
3661+
return 0;
36543662

36553663
return demangle_get_subst(ddata, nth);
36563664
}
@@ -3881,7 +3889,7 @@ demangle_read_type(struct demangle_data *ddata, struct type_delimit *td)
38813889

38823890
case 'E':
38833891
/* unexpected end (except some things) */
3884-
if (ddata->is_guard_variable)
3892+
if (td && ddata->is_guard_variable)
38853893
td->paren = false;
38863894
if (ddata->is_guard_variable ||
38873895
(ddata->ref_qualifier && ddata->is_functype)) {
@@ -4102,6 +4110,8 @@ demangle_read_type(struct demangle_data *ddata, struct type_delimit *td)
41024110
if (!demangle_vector_str_push(ddata, &v.ext_name, ddata->cur,
41034111
len))
41044112
return 0;
4113+
if (len > demangle_strlen(ddata->cur))
4114+
len = demangle_strlen(ddata->cur);
41054115
ddata->cur += len;
41064116
if (!demangle_vector_type_qualifier_push(ddata, &v, TYPE_EXT))
41074117
return 0;

0 commit comments

Comments
 (0)