Skip to content

Commit

Permalink
Fix AFL crashes in C++ demangler
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jart committed Nov 23, 2024
1 parent 7466600 commit ef00a7d
Showing 1 changed file with 22 additions and 12 deletions.
34 changes: 22 additions & 12 deletions libc/intrin/demangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,13 +380,16 @@ demangle_free(struct demangle_data *h, void *ptr)
}

static privileged returnspointerwithnoaliases returnsnonnull void *
demangle_malloc(struct demangle_data *h, int a, int n)
demangle_malloc(struct demangle_data *h, long a, long n)
{
int rem;
long rem;
uintptr_t ptr;
index_t next, next2;
index_t *link, *link2;
int b = sizeof(index_t);
long b = sizeof(index_t);

if (n < 0 || n >= 32768)
__builtin_longjmp(h->jmpbuf, 1);

/* Roundup size. */
n += a - 1;
Expand Down Expand Up @@ -2098,10 +2101,11 @@ demangle_read_tmpl_param(struct demangle_data *ddata)
/* T_ is first */
++nth;

while (*ddata->cur != '_')
while (*ddata->cur && *ddata->cur != '_')
++ddata->cur;

ASSERT(nth > 0);
if (nth <= 0)
return 0;

return demangle_get_tmpl_param(ddata, nth);
}
Expand Down Expand Up @@ -2752,7 +2756,7 @@ demangle_read_offset_number(struct demangle_data *ddata)
start = ddata->cur;
}

while (*ddata->cur != '_')
while (*ddata->cur && *ddata->cur != '_')
++ddata->cur;

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

len = demangle_strtol(ddata->cur, 10);
if (len < 0)
__builtin_longjmp(ddata->jmpbuf, 1);

while (ELFTC_ISDIGIT(*ddata->cur))
++ddata->cur;

ASSERT(len >= 0);
ASSERT(negative_factor == 1 || negative_factor == -1);

*rtn = len * negative_factor;

return 1;
Expand Down Expand Up @@ -3419,6 +3422,7 @@ demangle_read_pointer_to_member(struct demangle_data *ddata,
static privileged int
demangle_read_sname(struct demangle_data *ddata)
{
size_t lim;
long len;
int err;

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

lim = demangle_strlen(ddata->cur);
if (len > lim)
len = lim;
ddata->cur += len;

return 1;
Expand Down Expand Up @@ -3647,10 +3654,11 @@ demangle_read_subst(struct demangle_data *ddata)
/* first was '_', so increase one */
++nth;

while (*ddata->cur != '_')
while (*ddata->cur && *ddata->cur != '_')
++ddata->cur;

ASSERT(nth > 0);
if (nth <= 0)
return 0;

return demangle_get_subst(ddata, nth);
}
Expand Down Expand Up @@ -3881,7 +3889,7 @@ demangle_read_type(struct demangle_data *ddata, struct type_delimit *td)

case 'E':
/* unexpected end (except some things) */
if (ddata->is_guard_variable)
if (td && ddata->is_guard_variable)
td->paren = false;
if (ddata->is_guard_variable ||
(ddata->ref_qualifier && ddata->is_functype)) {
Expand Down Expand Up @@ -4102,6 +4110,8 @@ demangle_read_type(struct demangle_data *ddata, struct type_delimit *td)
if (!demangle_vector_str_push(ddata, &v.ext_name, ddata->cur,
len))
return 0;
if (len > demangle_strlen(ddata->cur))
len = demangle_strlen(ddata->cur);
ddata->cur += len;
if (!demangle_vector_type_qualifier_push(ddata, &v, TYPE_EXT))
return 0;
Expand Down

0 comments on commit ef00a7d

Please sign in to comment.