[Tarantool-patches] [PATCH v4 02/16] sql: fix possible undefined behavior during cast

Mergen Imeev imeevma at tarantool.org
Tue Oct 5 12:00:40 MSK 2021


Thank you for the review! My answers below.

On Mon, Oct 04, 2021 at 11:52:18PM +0200, Vladislav Shpilevoy wrote:
> Thanks for the fixes!
> 
> On 01.10.2021 14:48, imeevma at tarantool.org wrote:
> > This patch fixes possible undefined behavior during the implicit cast of
> > INTEGER to DOUBLE. The problem is, if the INTEGER is close enough to
> > 2^64, it will be cast to 2^64 when it is cast to DOUBLE. Since we have a
> > check for loss of precision, this will cause this DOUBLE to be cast to
> > an INTEGER, which will result in undefined behavior since this DOUBLE is
> > outside the range of INTEGER.
> > ---
> >  src/box/sql/mem.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
> > index 24d6d7dbf..079083fa1 100644
> > --- a/src/box/sql/mem.c
> > +++ b/src/box/sql/mem.c
> > @@ -682,7 +682,7 @@ uint_to_double_precise(struct Mem *mem)
> >  	assert(mem->type == MEM_TYPE_UINT);
> >  	double d;
> >  	d = (double)mem->u.u;
> > -	if (mem->u.u != (uint64_t)d)
> > +	if (d == (double)UINT64_MAX || mem->u.u != (uint64_t)d)
> 
> What if uint really was UINT64_MAX? Then you treat its conversion
> into UINT64_MAX double as an error?
> 
The UINT64_MAX value is 2^64-1, which will change to 2^64 when INTEGER is cast
to DOUBLE. Since the cast is not exact, an error will be thrown anyway. The
question is what we will get when DOUBLE 2^64 is cast to INTEGER? Since it is
not defined, I decided to avoid this by adding a new restriction.

> Maybe we could simply refuse to convert all ints > 2^53 and <-2^53
> (or whatever is the precise int limit in double). All ints above
> these values will convert 'from time to time' depending on exact
> values, which does not look reliable anyway.
I don't think we should be doing this. One reason is that in this case
we must decide what to do with casts from DOUBLE to INTEGER, DOUBLE to
DECIMAL, DECIMAL to DOUBLE, and DECIMAL to INTEGER. I don't see simple
enough rules to give us an easy way to determine when we should allow
these casts and when we shouldn't. The current rule of "allow when cast
is exact" seems easier to understand and implement.


More information about the Tarantool-patches mailing list