* bug#13827: faulty range check in bytevector accessor
@ 2013-02-27 2:02 Ian Price
2013-02-27 2:30 ` Mark H Weaver
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Ian Price @ 2013-02-27 2:02 UTC (permalink / raw)
To: 13827
Branch: master
Commit: 9b977c836bf147d386944c401113aba32776fa68
System: 32 bit x86 Fedora 16
(use-modules (rnrs bytevectors))
(define not-32-bit (expt 2 32))
(define bv (make-bytevector 4))
(bytevector-u32-set! bv 0 not-32-bit (endianness big))
(pk bv)
Running this gives me a core dump. It happens for a wide range of values
that don't fit in 32 bits.
After some talk on #guile, Mark and I believe it comes down to the range
check in INTEGER_ACCESSOR_PROLOGUE in bytevectors.c
--
Ian Price -- shift-reset.com
"Programming is like pinball. The reward for doing it well is
the opportunity to do it again" - from "The Wizardy Compiled"
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#13827: faulty range check in bytevector accessor
2013-02-27 2:02 bug#13827: faulty range check in bytevector accessor Ian Price
@ 2013-02-27 2:30 ` Mark H Weaver
2013-02-27 11:42 ` Ludovic Courtès
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Mark H Weaver @ 2013-02-27 2:30 UTC (permalink / raw)
To: Ian Price; +Cc: 13827
Ian Price <ianprice90@googlemail.com> writes:
> After some talk on #guile, Mark and I believe it comes down to the range
> check in INTEGER_ACCESSOR_PROLOGUE in bytevectors.c
Going a bit further: INTEGER_ACCESSOR_PROLOGUE uses 'scm_to_uint', which
I believe should fail for 2^32 on a 32-bit machine. According to
numbers.h:430, 'scm_to_uint' should be an alias for 'scm_to_uint32',
which is defined in numbers.c:9277 and conv-uinteger.i.c:27.
It seems to me that it ought to be getting to conv-uinteger.i.c:50,
which calls 'mpz_fits_ulong_p'. So maybe it's a bug in the version of
libgmp on Ian's machine, or perhaps I'm missing something.
I don't know whether it's possible to step through the code in
'conv-uinteger.i.c' using gdb. If so, I'd like to see what happens. If
not, I suspect the next step is to write some test programs in C and try
them on Ian's machine: first test 'scm_to_uint32', which should raise an
exception for 2^32. If it doesn't then try testing 'mpz_fits_ulong_p'
directly and see if it's broken.
Thanks,
Mark
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#13827: faulty range check in bytevector accessor
2013-02-27 2:02 bug#13827: faulty range check in bytevector accessor Ian Price
2013-02-27 2:30 ` Mark H Weaver
@ 2013-02-27 11:42 ` Ludovic Courtès
2013-02-28 1:38 ` Mark H Weaver
2013-02-28 20:20 ` Ian Price
2013-03-13 12:55 ` Andy Wingo
2014-07-28 14:35 ` Ben Rocer
3 siblings, 2 replies; 9+ messages in thread
From: Ludovic Courtès @ 2013-02-27 11:42 UTC (permalink / raw)
To: Ian Price; +Cc: 13827
Ian Price <ianprice90@googlemail.com> skribis:
> Branch: master
> Commit: 9b977c836bf147d386944c401113aba32776fa68
> System: 32 bit x86 Fedora 16
>
> (use-modules (rnrs bytevectors))
> (define not-32-bit (expt 2 32))
> (define bv (make-bytevector 4))
> (bytevector-u32-set! bv 0 not-32-bit (endianness big))
> (pk bv)
FWIW, with 2.0.7+ on x86_64-linux-gnu, with GMP 5.1.0:
--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> (use-modules (rnrs bytevectors))
scheme@(guile-user)> (define not-32-bit (expt 2 32))
scheme@(guile-user)> (define bv (make-bytevector 4))
scheme@(guile-user)> (bytevector-u32-set! bv 0 not-32-bit (endianness big))
<unnamed port>:4:0: In procedure #<procedure 1b1bf00 at <current input>:4:0 ()>:
<unnamed port>:4:0: In procedure bytevector-u32-set!: Value out of range: 4294967296
Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.
--8<---------------cut here---------------end--------------->8---
As Mark pointed out, it could be due to the GMP version you’re using.
Could you check that?
TIA,
Ludo’.
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#13827: faulty range check in bytevector accessor
2013-02-27 11:42 ` Ludovic Courtès
@ 2013-02-28 1:38 ` Mark H Weaver
2013-02-28 20:20 ` Ian Price
1 sibling, 0 replies; 9+ messages in thread
From: Mark H Weaver @ 2013-02-28 1:38 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: Ian Price, 13827
ludo@gnu.org (Ludovic Courtès) writes:
> Ian Price <ianprice90@googlemail.com> skribis:
>
>> Branch: master
>> Commit: 9b977c836bf147d386944c401113aba32776fa68
>> System: 32 bit x86 Fedora 16
>>
>> (use-modules (rnrs bytevectors))
>> (define not-32-bit (expt 2 32))
>> (define bv (make-bytevector 4))
>> (bytevector-u32-set! bv 0 not-32-bit (endianness big))
>> (pk bv)
>
> FWIW, with 2.0.7+ on x86_64-linux-gnu, with GMP 5.1.0:
>
> scheme@(guile-user)> (use-modules (rnrs bytevectors))
> scheme@(guile-user)> (define not-32-bit (expt 2 32))
> scheme@(guile-user)> (define bv (make-bytevector 4))
> scheme@(guile-user)> (bytevector-u32-set! bv 0 not-32-bit (endianness big))
> <unnamed port>:4:0: In procedure #<procedure 1b1bf00 at <current input>:4:0 ()>:
> <unnamed port>:4:0: In procedure bytevector-u32-set!: Value out of range: 4294967296
That's because you're on a 64-bit system, where 2^32 is no difficulty.
Mark
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#13827: faulty range check in bytevector accessor
2013-02-27 11:42 ` Ludovic Courtès
2013-02-28 1:38 ` Mark H Weaver
@ 2013-02-28 20:20 ` Ian Price
1 sibling, 0 replies; 9+ messages in thread
From: Ian Price @ 2013-02-28 20:20 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: 13827
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=iso-2022-jp-2, Size: 550 bytes --]
ludo@gnu.org (Ludovic Court^[$(D+2^[(Bs) writes:
> As Mark pointed out, it could be due to the GMP version you^[$B!G^[(Bre using.
>
> Could you check that?
Well, I wouldn't rule it out until I've had a proper look. I believe I
am running 4.3.2, but do you have a specific test in mind?
I'm going away for the weekend, though, so I won't really be able to
debug this properly till Monday.
--
Ian Price -- shift-reset.com
"Programming is like pinball. The reward for doing it well is
the opportunity to do it again" - from "The Wizardy Compiled"
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#13827: faulty range check in bytevector accessor
2013-02-27 2:02 bug#13827: faulty range check in bytevector accessor Ian Price
2013-02-27 2:30 ` Mark H Weaver
2013-02-27 11:42 ` Ludovic Courtès
@ 2013-03-13 12:55 ` Andy Wingo
2013-03-13 14:37 ` Andy Wingo
2014-07-28 14:35 ` Ben Rocer
3 siblings, 1 reply; 9+ messages in thread
From: Andy Wingo @ 2013-03-13 12:55 UTC (permalink / raw)
To: Ian Price; +Cc: 13827
On Wed 27 Feb 2013 03:02, Ian Price <ianprice90@googlemail.com> writes:
> Branch: master
> Commit: 9b977c836bf147d386944c401113aba32776fa68
> System: 32 bit x86 Fedora 16
>
> (use-modules (rnrs bytevectors))
> (define not-32-bit (expt 2 32))
> (define bv (make-bytevector 4))
> (bytevector-u32-set! bv 0 not-32-bit (endianness big))
> (pk bv)
>
> Running this gives me a core dump. It happens for a wide range of values
> that don't fit in 32 bits.
>
> After some talk on #guile, Mark and I believe it comes down to the range
> check in INTEGER_ACCESSOR_PROLOGUE in bytevectors.c
Something like this look right to you?
--- a/libguile/bytevectors.c
+++ b/libguile/bytevectors.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+/* Copyright (C) 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -82,12 +82,12 @@
_sign char *c_bv; \
\
SCM_VALIDATE_BYTEVECTOR (1, bv); \
- c_index = scm_to_uint (index); \
+ c_index = scm_to_size_t (index); \
\
c_len = SCM_BYTEVECTOR_LENGTH (bv); \
c_bv = (_sign char *) SCM_BYTEVECTOR_CONTENTS (bv); \
\
- if (SCM_UNLIKELY (c_index + ((_len) >> 3UL) - 1 >= c_len)) \
+ if (SCM_UNLIKELY (c_index >= c_len)) \
scm_out_of_range (FUNC_NAME, index);
/* Template for fixed-size integer access (only 8, 16 or 32-bit). */
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#13827: faulty range check in bytevector accessor
2013-03-13 12:55 ` Andy Wingo
@ 2013-03-13 14:37 ` Andy Wingo
0 siblings, 0 replies; 9+ messages in thread
From: Andy Wingo @ 2013-03-13 14:37 UTC (permalink / raw)
To: Ian Price; +Cc: 13827
On Wed 13 Mar 2013 13:55, Andy Wingo <wingo@pobox.com> writes:
> - if (SCM_UNLIKELY (c_index + ((_len) >> 3UL) - 1 >= c_len)) \
> + if (SCM_UNLIKELY (c_index >= c_len)) \
> scm_out_of_range (FUNC_NAME, index);
I see the intention was to take into account the size of the access
(e.g. 32 bits). Confusing with len, _len, and c_len...
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#13827: faulty range check in bytevector accessor
2013-02-27 2:02 bug#13827: faulty range check in bytevector accessor Ian Price
` (2 preceding siblings ...)
2013-03-13 12:55 ` Andy Wingo
@ 2014-07-28 14:35 ` Ben Rocer
2016-06-20 15:16 ` Andy Wingo
3 siblings, 1 reply; 9+ messages in thread
From: Ben Rocer @ 2014-07-28 14:35 UTC (permalink / raw)
To: 13827
[resubmitting to bug-guile@gnu.org as debbugs seems to have eaten my
first mail]
When I tried to reproduce this bug on a 32-bit x86 system, I got an
abort in the function bytevector_large_set(); I think this is also
where the bug is.
Specifically, there are two bugs in these two consecutive lines in
bytevector_large_set():
value_size = (mpz_sizeinbase (c_mpz, 2) + (8 * c_size)) / (8 * c_size);
if (SCM_UNLIKELY (value_size > c_size))
In the first line, there is an off-by-one error in the calculation of
value_size; it gives the wrong answer if mpz_sizeinbase() is a
multiple of (8 * c_size) (see
https://gmplib.org/manual/Integer-Import-and-Export.html).
Secondly, this calculation gives the number of (c_size-byte) *words*
required to hold c_mpz, not the number of bytes. So the check in the
next line should be (c_size * value_size > c_size), or equivalently
(value_size > 1).
Since bytevector-u64-set! also calls bytevector_large_set, it
may be possible to reproduce this bug on 64 bit systems too; e.g
(bytevector-u64-set! (make-bytevector 8) 0 (expt 2 64) (endianness big))
[untested]
--- a/libguile/bytevectors.c
+++ b/libguile/bytevectors.c
@@ -867,10 +867,10 @@ bytevector_large_set (char *c_bv, size_t c_size, int signed_p,
memset (c_bv, 0, c_size);
else
{
- size_t word_count, value_size;
+ size_t word_count, value_words;
- value_size = (mpz_sizeinbase (c_mpz, 2) + (8 * c_size)) / (8 * c_size);
- if (SCM_UNLIKELY (value_size > c_size))
+ value_words = (mpz_sizeinbase (c_mpz, 2) + (8 * c_size) - 1) / (8 * c_size);
+ if (SCM_UNLIKELY (value_words > 1))
{
err = -2;
goto finish;
^ permalink raw reply [flat|nested] 9+ messages in thread
* bug#13827: faulty range check in bytevector accessor
2014-07-28 14:35 ` Ben Rocer
@ 2016-06-20 15:16 ` Andy Wingo
0 siblings, 0 replies; 9+ messages in thread
From: Andy Wingo @ 2016-06-20 15:16 UTC (permalink / raw)
To: Ben Rocer; +Cc: 13827-done
Hi!
Thank you very much for the bug report and fix! Applied to master, will
be part of 2.1.4.
Cheers,
Andy
On Mon 28 Jul 2014 16:35, "Ben Rocer" <fleabyte@mail.com> writes:
> [resubmitting to bug-guile@gnu.org as debbugs seems to have eaten my
> first mail]
>
> When I tried to reproduce this bug on a 32-bit x86 system, I got an
> abort in the function bytevector_large_set(); I think this is also
> where the bug is.
>
> Specifically, there are two bugs in these two consecutive lines in
> bytevector_large_set():
>
> value_size = (mpz_sizeinbase (c_mpz, 2) + (8 * c_size)) / (8 * c_size);
> if (SCM_UNLIKELY (value_size > c_size))
>
> In the first line, there is an off-by-one error in the calculation of
> value_size; it gives the wrong answer if mpz_sizeinbase() is a
> multiple of (8 * c_size) (see
> https://gmplib.org/manual/Integer-Import-and-Export.html).
>
> Secondly, this calculation gives the number of (c_size-byte) *words*
> required to hold c_mpz, not the number of bytes. So the check in the
> next line should be (c_size * value_size > c_size), or equivalently
> (value_size > 1).
>
> Since bytevector-u64-set! also calls bytevector_large_set, it
> may be possible to reproduce this bug on 64 bit systems too; e.g
> (bytevector-u64-set! (make-bytevector 8) 0 (expt 2 64) (endianness big))
> [untested]
>
>
> --- a/libguile/bytevectors.c
> +++ b/libguile/bytevectors.c
> @@ -867,10 +867,10 @@ bytevector_large_set (char *c_bv, size_t c_size, int signed_p,
> memset (c_bv, 0, c_size);
> else
> {
> - size_t word_count, value_size;
> + size_t word_count, value_words;
>
> - value_size = (mpz_sizeinbase (c_mpz, 2) + (8 * c_size)) / (8 * c_size);
> - if (SCM_UNLIKELY (value_size > c_size))
> + value_words = (mpz_sizeinbase (c_mpz, 2) + (8 * c_size) - 1) / (8 * c_size);
> + if (SCM_UNLIKELY (value_words > 1))
> {
> err = -2;
> goto finish;
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2016-06-20 15:16 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-02-27 2:02 bug#13827: faulty range check in bytevector accessor Ian Price
2013-02-27 2:30 ` Mark H Weaver
2013-02-27 11:42 ` Ludovic Courtès
2013-02-28 1:38 ` Mark H Weaver
2013-02-28 20:20 ` Ian Price
2013-03-13 12:55 ` Andy Wingo
2013-03-13 14:37 ` Andy Wingo
2014-07-28 14:35 ` Ben Rocer
2016-06-20 15:16 ` Andy Wingo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).