https://gcc.gnu.org/bugzilla/show_bug.cgi?id=28277

--- Comment #21 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Andrew Pinski from comment #20)
> here is the current list as far as I can tell:
> config/locale/dragonfly/codecvt_members.cc
> config/locale/gnu/codecvt_members.cc
> config/locale/gnu/messages_members.cc

See above.

> include/bits/fstream.tcc

This is potentially unbounded. A malicious user could use filebuf::setbuf to
give the filebuf a huge buffer, and imbue a custom codecvt facet with a large
do_max_length(). Then the alloca would use buflen * maxlen. That could even
overflow. In practice the maximum size will be BUFSZ*4 or so.

> include/bits/locale_facets.tcc (some there are ok as the values are actually
> constant)

maximum alloca for the formatted integer is sizeof(wchar_t) * 5 * sizeof(long
long) + 1
but then we allocate io.width() * sizeof(wchar_t) which could be set to
something huge by a silly user. We also do three alloca calls in the same
function.

For a formatted float it's numeric_limits<long double>::digits10 * 3 for the
first alloca, but we use alloca several times, and the max depends on
io.precision() and io.width() so we might need a large buffer.

These need some sanity checks, and use the heap as a fallback. See PR 87228 for
that.

> include/bits/locale_facets_nonio.tcc

These are all fixed size and small.

> include/ext/codecvt_specializations.h (BOM case)

Depends on the size of the input being converted, which could be large. This is
unsafe (but I don't think anybody uses this extension).

> include/ext/string_conversions.h

The worst case is std::to_wstring(long double) which uses:

sizeof(wchar_t) * (__numeric_traits<long double>::__max_exponent10 + 20)

So maximum 4 * (4932 + 20) == 19808
That's too big.

> include/std/format (non-char type formating and localization)

Tightly bounded to 2 * ndigits * sizeof(wchar_t) + prefix_len
The worst case is something like std::format("{:#0b}", LLONG_MIN) where the
alloca will be for 2 * 64 * 4 + 3 which is only 515 bytes.

> src/c++11/functexcept.cc (__throw_out_of_range_fmt)

strlen(fmt) + 512, where fmt is ~40 bytes. Users could call that function
themselves, but then that's their problem. It's an internal impl detail, and
our uses are safe.

> src/c++11/snprintf_lite.cc (__throw_insufficient_space)

Another internal impl detail, but this one is not even visible to users. No
declaration in headers, not exported from the shared lib. This one uses alloca
for the same size as __throw_out_of_range_fmt + 104 bytes, but we've already
done the first alloca, so it's (strlen(fmt) + 512) * 2 + 104.

Reply via email to