From: Simon Marchi <simark@simark.ca>
To: Joel Brobecker <brobecker@adacore.com>, gdb-patches@sourceware.org
Subject: Re: [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values
Date: Mon, 30 Nov 2020 10:56:11 -0500 [thread overview]
Message-ID: <ff6e02e4-57fd-095f-ca84-241b142e20e3@simark.ca> (raw)
In-Reply-To: <1606664757-144138-3-git-send-email-brobecker@adacore.com>
On 2020-11-29 10:45 a.m., Joel Brobecker wrote:
> The gdb_mpz class currently provides a couple of methods which
> essentially export an mpz_t value into either a buffer, or an integral
> type. The export is based on using the mpz_export function which
> we discovered can be a bit treacherous if used without caution.
>
> In particular, the initial motivation for this patch was to catch
> situations where the mpz_t value was so large that it would not fit
> in the destination area. mpz_export does not know the size of
> the buffer, and therefore can happily write past the end of our buffer.
>
> While designing a solution to the above problem, I also discovered
> that we also needed to be careful when exporting signed numbers.
> In particular, numbers which are larger than the maximum value
> for a given signed type size, but no so large as to fit in the
> *unsigned* version with the same size, would end up being exported
> incorrectly. This is related to the fact that mpz_export ignores
> the sign of the value being exportd, and assumes an unsigned export.
> Thus, for such large values, the appears as if mpz_export is able
> to fit our value into our buffer, but in fact, it does not.
>
> Also, I noticed that gdb_mpz::write wasn't taking its unsigned_p
> parameter, which was a hole.
>
> For all these reasons, a new low-level private method called
> "safe_export" has been added to class gdb_mpz, whose goal is
> to perform all necessary checks and manipulations for a safe
> and correct export. As a bonus, this method allows us to factorize
> the handling of negative value exports.
>
> The gdb_mpz::as_integer and gdb_mpz::write methods are then simplified
> to take advantage of this new safe_export method.
>
> gdb/ChangeLog:
>
> * gmp-utils.h (gdb_mpz::safe_export): New private method.
> (gdb_mpz::as_integer): Reimplement using gdb_mpz::safe_export.
> * gmp-utils.c (gdb_mpz::write): Rewrite using gdb_mpz::safe_export.
> (gdb_mpz::safe_export): New method.
> * unittests/gmp-utils-selftests .c (gdb_mpz_as_integer):
> Update function description.
> (check_as_integer_raises_out_of_range_error): New function.
> (gdb_mpz_as_integer_out_of_range): New function.
> (_initialize_gmp_utils_selftests): Register
> gdb_mpz_as_integer_out_of_range as a selftest.
> ---
> gdb/gmp-utils.c | 79 ++++++++++++++++++++++++++++++++++---
> gdb/gmp-utils.h | 44 ++++++++++++---------
> gdb/unittests/gmp-utils-selftests.c | 71 +++++++++++++++++++++++++++++++--
> 3 files changed, 167 insertions(+), 27 deletions(-)
>
> diff --git a/gdb/gmp-utils.c b/gdb/gmp-utils.c
> index e3a3333..f94bdc5 100644
> --- a/gdb/gmp-utils.c
> +++ b/gdb/gmp-utils.c
> @@ -68,9 +68,62 @@ void
> gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
> bool unsigned_p) const
> {
> + this->safe_export
> + (buf, byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */, 0 /* nails */,
> + unsigned_p);
> +}
> +
> +/* See gmp-utils.h. */
> +
> +void
> +gdb_mpz::safe_export (gdb::array_view<gdb_byte> buf,
> + int endian, size_t nails, bool unsigned_p) const
Just wondering if you'll ever need to pass a non-zero value for nails.
If not, I think you could simplify the code by just removing it.
> +{
> + gdb_assert (buf.size () > 0);
> +
> + if (mpz_sgn (val) == 0)
> + {
> + /* Our value is zero, so no need to call mpz_export to do the work,
> + especially since mpz_export's documentation explicitly says
> + that the function is a noop in this case. Just write zero to
> + BUF ourselves. */
> + memset (buf.data (), 0, buf.size ());
> + return;
> + }
> +
> + /* Determine the maximum range of values that our buffer can hold,
> + and verify that VAL is within that range. */
> +
> + gdb_mpz lo, hi;
> + const size_t max_usable_bits = buf.size () * HOST_CHAR_BIT - nails;
> + if (unsigned_p)
> + {
> + lo = 0;
> +
> + mpz_ui_pow_ui (hi.val, 2, max_usable_bits);
> + mpz_sub_ui (hi.val, hi.val, 1);
> + }
> + else
> + {
> + mpz_ui_pow_ui (lo.val, 2, max_usable_bits - 1);
> + mpz_neg (lo.val, lo.val);
> +
> + mpz_ui_pow_ui (hi.val, 2, max_usable_bits - 1);
> + mpz_sub_ui (hi.val, hi.val, 1);
> + }
> +
> + if (mpz_cmp (val, lo.val) < 0 || mpz_cmp (val, hi.val) > 0)
> + error (_("Cannot export value %s as %zubits %s integer"
> + " (must be between %s and %s)"),
You might be missing a space before "bits", or maybe it's on purpose.
> + this->str ().c_str (),
> + max_usable_bits,
> + unsigned_p ? _("unsigned") : _("signed"),
> + lo.str ().c_str (),
> + hi.str ().c_str ());
> +
> gdb_mpz exported_val (val);
>
> - if (mpz_cmp_ui (val, 0) < 0)
> + if (mpz_cmp_ui (exported_val.val, 0) < 0)
> {
> /* mpz_export does not handle signed values, so create a positive
> value whose bit representation as an unsigned of the same length
> @@ -81,13 +134,27 @@ gdb_mpz::write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order,
> mpz_add (exported_val.val, exported_val.val, neg_offset.val);
> }
>
> + /* Do the export into a buffer allocated by GMP itself; that way,
> + we can detect cases where BUF is not large enough to export
> + our value, and thus avoid a buffer overlow. Normally, this should
> + never happen, since we verified earlier that the buffer is large
> + enough to accomodate our value, but doing this allows us to be
> + extra safe with the export.
> +
> + After verification that the export behaved as expected, we will
> + copy the data over to BUF. */
> +
> + size_t word_countp;
> + gdb::unique_xmalloc_ptr<void> exported
I'd prefer if we didn't use heap allocation unnecessarily. If we get
things right, that isn't necessary. And if we can still assert after
the call that we did indeed get it right, then we'll catch any case
where we didn't.
> + (mpz_export (NULL, &word_countp, -1 /* order */, buf.size () /* size */,
> + endian, nails, exported_val.val));
> +
> + gdb_assert (word_countp == 1);
> +
> /* Start by clearing the buffer, as mpz_export only writes as many
> - bytes as it needs (including none, if the value to export is zero. */
> + bytes as it needs. */
> memset (buf.data (), 0, buf.size ());
> - mpz_export (buf.data (), NULL /* count */, -1 /* order */,
> - buf.size () /* size */,
> - byte_order == BFD_ENDIAN_BIG ? 1 : -1 /* endian */,
> - 0 /* nails */, exported_val.val);
> + memcpy (buf.data (), exported.get (), buf.size ());
The memset just before the memcpy of the same size is useless, as all
the bytes will get overwritten by the memcpy.
> @@ -258,26 +278,14 @@ template<typename T>
> T
> gdb_mpz::as_integer () const
> {
> - /* Initialize RESULT, because mpz_export only write the minimum
> - number of bytes, including none if our value is zero! */
> - T result = 0;
> + T result;
>
> - gdb_mpz exported_val (val);
> - if (std::is_signed<T>::value && mpz_cmp_ui (val, 0) < 0)
> - {
> - /* We want to use mpz_export to set the return value, but
> - this function does not handle the sign. So give exported_val
> - a value which is at the same time positive, and has the same
> - bit representation as our negative value. */
> - gdb_mpz neg_offset;
> + this->safe_export (gdb::make_array_view ((gdb_byte *) &result,
> + sizeof (result)),
I'd suggest using
{(gdb_byte *) &result, sizeof (result)}
to make the array view, as suggested by Pedro earlier.
Simon
next prev parent reply other threads:[~2020-11-30 15:56 UTC|newest]
Thread overview: 140+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-08 6:30 RFA: Add support for DWARF-based fixed point types Joel Brobecker
2020-11-08 6:30 ` [PATCH 1/9] gdb/configure: Add --with-libgmp-prefix option Joel Brobecker
2020-11-08 6:30 ` [PATCH 2/9] gdb: Make GMP a required dependency for building GDB Joel Brobecker
2020-12-15 6:55 ` Sebastian Huber
2020-12-15 8:57 ` Joel Brobecker
2020-11-08 6:30 ` [PATCH 3/9] gmp-utils: New API to simply use of GMP's integer/rational/float objects Joel Brobecker
2020-11-10 20:15 ` Simon Marchi
2020-11-13 8:12 ` Joel Brobecker
2020-11-13 15:04 ` Tom Tromey
2020-11-13 15:06 ` Simon Marchi
2020-11-16 16:18 ` Tom Tromey
2020-11-16 16:34 ` Luis Machado via Gdb-patches
2020-11-18 3:52 ` Joel Brobecker
2020-11-08 6:30 ` [PATCH 4/9] Move uinteger_pow gdb/valarith.c to gdb/utils.c and make it public Joel Brobecker
2020-11-08 6:30 ` [PATCH 5/9] Add support for printing value of DWARF-based fixed-point type objects Joel Brobecker
2020-11-10 21:06 ` Simon Marchi
2020-11-14 10:48 ` Joel Brobecker
2020-11-14 13:20 ` Simon Marchi
2020-11-14 11:30 ` Joel Brobecker
2020-11-14 16:14 ` Simon Marchi
2020-11-15 5:30 ` Joel Brobecker
2020-11-15 6:33 ` Joel Brobecker
2020-11-16 0:13 ` Simon Marchi
2020-11-08 6:30 ` [PATCH 6/9] fix printing of DWARF fixed-point type objects with format modifier Joel Brobecker
2020-11-10 22:50 ` Simon Marchi
2020-11-08 6:30 ` [PATCH 7/9] Add ptype support for DWARF-based fixed-point types Joel Brobecker
2020-11-10 23:00 ` Simon Marchi
2020-11-15 6:57 ` Joel Brobecker
2020-11-15 7:09 ` Joel Brobecker
2020-11-16 0:16 ` Simon Marchi
2020-11-16 4:03 ` Joel Brobecker
2020-11-08 6:30 ` [PATCH 8/9] Add support for fixed-point type arithmetic Joel Brobecker
2020-11-10 23:18 ` Simon Marchi
2020-11-08 6:30 ` [PATCH 9/9] Add support for fixed-point type comparison operators Joel Brobecker
2020-11-10 23:21 ` RFA: Add support for DWARF-based fixed point types Simon Marchi
2020-11-11 4:53 ` Joel Brobecker
2020-11-15 8:35 ` pushed: " Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 1/9] gdb/configure: Add --with-libgmp-prefix option Joel Brobecker
2020-11-15 15:52 ` Bernd Edlinger
2020-11-16 3:45 ` Joel Brobecker
2020-11-16 14:20 ` Bernd Edlinger
2020-11-17 7:41 ` [PATCH] Enable GDB build with in-tree GMP and MPFR Bernd Edlinger
2020-11-18 3:44 ` Joel Brobecker
2020-11-18 8:14 ` Bernd Edlinger
2020-12-01 19:29 ` Bernd Edlinger
2020-12-01 19:32 ` Simon Marchi
2020-12-01 19:38 ` Bernd Edlinger
2020-12-01 20:29 ` Bernd Edlinger
2020-12-01 20:30 ` Simon Marchi
2020-12-02 3:21 ` Joel Brobecker
2020-12-08 20:39 ` [PING] " Bernd Edlinger
2020-12-14 17:40 ` [PATCH v2] " Bernd Edlinger
2020-12-14 18:47 ` Simon Marchi
2020-12-14 21:35 ` Tom Tromey
2020-12-14 22:17 ` Simon Marchi
2020-12-15 2:33 ` Joel Brobecker
2020-12-15 14:39 ` Simon Marchi via Gdb-patches
2020-12-15 16:24 ` Bernd Edlinger
2020-12-16 7:33 ` Joel Brobecker
2020-12-16 18:16 ` Bernd Edlinger
2020-12-25 12:05 ` Bernd Edlinger
2020-12-27 22:01 ` Simon Marchi via Gdb-patches
2020-12-29 8:36 ` Bernd Edlinger
2020-12-29 14:50 ` Simon Marchi via Gdb-patches
2021-01-10 14:12 ` Bernd Edlinger
2021-01-10 15:32 ` Simon Marchi via Gdb-patches
2021-01-11 3:22 ` Joel Brobecker
2021-01-16 18:01 ` Bernd Edlinger
2020-12-15 15:33 ` Bernd Edlinger
2020-12-15 15:10 ` Bernd Edlinger
2020-11-15 8:35 ` [pushed/v2 2/9] gdb: Make GMP a required dependency for building GDB Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 3/9] gmp-utils: New API to simply use of GMP's integer/rational/float objects Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 4/9] Move uinteger_pow gdb/valarith.c to gdb/utils.c and make it public Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 5/9] Add support for printing value of DWARF-based fixed-point type objects Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 6/9] fix printing of DWARF fixed-point type objects with format modifier Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 7/9] Add ptype support for DWARF-based fixed-point types Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 8/9] Add support for fixed-point type arithmetic Joel Brobecker
2020-11-15 8:35 ` [pushed/v2 9/9] Add support for fixed-point type comparison operators Joel Brobecker
2020-11-16 23:48 ` pushed: Add support for DWARF-based fixed point types Pedro Alves
2020-11-17 14:25 ` Simon Marchi
2020-11-18 3:47 ` Joel Brobecker
2020-11-22 13:12 ` [RFA] Add TYPE_CODE_FIXED_POINT handling in print_type_scalar Joel Brobecker
2020-11-22 14:35 ` Simon Marchi
2020-11-24 3:04 ` Joel Brobecker
2020-11-22 14:00 ` pushed: Add support for DWARF-based fixed point types Joel Brobecker
2020-11-22 20:11 ` Simon Marchi
2020-11-23 4:27 ` Joel Brobecker
2020-11-23 16:12 ` Simon Marchi
2020-11-24 2:39 ` Joel Brobecker
2020-11-29 15:45 ` RFA: wrap mpz_export into gdb_mpz::safe_export Joel Brobecker
2020-11-29 15:45 ` [RFA 1/2] Fix TARGET_CHAR_BIT/HOST_CHAR_BIT confusion in gmp-utils.c Joel Brobecker
2020-11-30 15:42 ` Simon Marchi
2020-12-05 8:05 ` Joel Brobecker
2020-11-29 15:45 ` [RFA 2/2] gmp-utils: protect gdb_mpz exports against out-of-range values Joel Brobecker
2020-11-30 15:56 ` Simon Marchi [this message]
2020-12-01 3:37 ` Joel Brobecker
2020-12-01 4:02 ` Simon Marchi
2020-12-01 7:11 ` Joel Brobecker
2020-12-05 8:10 ` [RFAv2 " Joel Brobecker
2020-12-05 23:26 ` Simon Marchi
2020-12-06 4:58 ` Joel Brobecker
2020-11-30 12:44 ` RFA: wrap mpz_export into gdb_mpz::safe_export Christian Biesinger via Gdb-patches
2020-11-20 14:08 ` pushed: Add support for DWARF-based fixed point types Pedro Alves
2020-11-20 14:14 ` Joel Brobecker
2020-11-22 11:56 ` RFA/doco: Various changes related to GMP and fixed point type support Joel Brobecker
2020-11-22 11:56 ` [RFA/doco 1/4] gdb/NEWS: Document that building GDB now requires GMP Joel Brobecker
2020-11-22 15:31 ` Eli Zaretskii via Gdb-patches
2020-11-24 3:11 ` Joel Brobecker
2020-11-22 11:56 ` [RFA/doco 2/4] gdb/NEWS: Document that GDB now supports DWARF-based fixed point types Joel Brobecker
2020-11-22 15:33 ` Eli Zaretskii via Gdb-patches
2020-11-24 3:12 ` Joel Brobecker
2020-11-22 11:56 ` [RFA/doco 3/4] gdb/README: Document the --with-libgmp-prefix configure option Joel Brobecker
2020-11-22 15:32 ` Eli Zaretskii via Gdb-patches
2020-11-24 3:11 ` Joel Brobecker
2020-11-22 11:56 ` [RFA/doco 4/4] gdb/README: Fix the URL of the MPFR website (now https) Joel Brobecker
2020-11-22 15:33 ` Eli Zaretskii via Gdb-patches
2020-11-24 3:11 ` Joel Brobecker
2020-11-15 8:49 ` RFA: Various enhancements to the fixed-point support implementation Joel Brobecker
2020-11-15 8:49 ` [RFA 1/6] change gmp_string_asprintf to return an std::string Joel Brobecker
2020-11-16 0:41 ` Simon Marchi
2020-11-16 3:55 ` Joel Brobecker
2020-11-16 20:10 ` Simon Marchi
2020-11-15 8:49 ` [RFA 2/6] gmp-utils: Convert the read/write methods to using gdb::array_view Joel Brobecker
2020-11-16 0:52 ` Simon Marchi
2020-11-16 23:05 ` Pedro Alves
2020-11-17 14:32 ` Simon Marchi
2020-11-15 8:49 ` [RFA 3/6] gdbtypes.h: Get rid of the TYPE_FIXED_POINT_INFO macro Joel Brobecker
2020-11-15 8:49 ` [RFA 4/6] Make fixed_point_type_base_type a method of struct type Joel Brobecker
2020-11-15 8:49 ` [RFA 5/6] Make function fixed_point_scaling_factor " Joel Brobecker
2020-11-15 8:49 ` [RFA 6/6] valarith.c: Replace INIT_VAL_WITH_FIXED_POINT_VAL macro by lambda Joel Brobecker
2020-11-16 1:01 ` RFA: Various enhancements to the fixed-point support implementation Simon Marchi
2020-11-22 11:14 ` RFA v2: " Joel Brobecker
2020-11-22 11:14 ` [RFA v2 1/6] change and rename gmp_string_asprintf to return an std::string Joel Brobecker
2020-11-22 11:14 ` [RFA v2 2/6] gmp-utils: Convert the read/write methods to using gdb::array_view Joel Brobecker
2020-11-22 11:14 ` [RFA v2 3/6] gdbtypes.h: Get rid of the TYPE_FIXED_POINT_INFO macro Joel Brobecker
2020-11-22 11:14 ` [RFA v2 4/6] Make fixed_point_type_base_type a method of struct type Joel Brobecker
2020-11-22 11:14 ` [RFA v2 5/6] Make function fixed_point_scaling_factor " Joel Brobecker
2020-11-22 11:14 ` [RFA v2 6/6] valarith.c: Replace INIT_VAL_WITH_FIXED_POINT_VAL macro by lambda Joel Brobecker
2020-11-23 16:46 ` RFA v2: Various enhancements to the fixed-point support implementation Simon Marchi
2020-11-24 2:56 ` Joel Brobecker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ff6e02e4-57fd-095f-ca84-241b142e20e3@simark.ca \
--to=simark@simark.ca \
--cc=brobecker@adacore.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox