Обсуждение: BUG #12664: numeric_recv does not accept large values

Поиск
Список
Период
Сортировка

BUG #12664: numeric_recv does not accept large values

От
emil.lenngren@gmail.com
Дата:
The following bug has been logged on the website:

Bug reference:      12664
Logged by:          Emil Lenngren
Email address:      emil.lenngren@gmail.com
PostgreSQL version: 9.4.0
Operating system:   N/A
Description:

According to the documentation for data type "numeric" at
http://www.postgresql.org/docs/9.4/static/datatype-numeric.html:
"up to 131072 digits before the decimal point; up to 16383 digits after the
decimal point"
"Note: The maximum allowed precision when explicitly specified in the type
declaration is 1000; NUMERIC without a specified precision is subject to the
limits described in Table 8-2."

In the binary representation, digits are grouped into groups of 4. The
number of such groups is checked in numeric_recv:

    len = (uint16) pq_getmsgint(buf, sizeof(uint16));
    if (len < 0 || len > NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                 errmsg("invalid length in external \"numeric\" value")));

but NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE is 3000 which means a
limit of only 12000 digits. numeric_in has no such limit.

The guard should check something like (len > ceil((131072+16383)/4))
instead, or not at all, since the function make_result also checks the
length. Checking for len < 0 also seems a bit needless since len already
contains an unsigned 16-bit value.

Re: BUG #12664: numeric_recv does not accept large values

От
Tom Lane
Дата:
emil.lenngren@gmail.com writes:
> According to the documentation for data type "numeric" at
> http://www.postgresql.org/docs/9.4/static/datatype-numeric.html:
> "up to 131072 digits before the decimal point; up to 16383 digits after the
> decimal point"
> "Note: The maximum allowed precision when explicitly specified in the type
> declaration is 1000; NUMERIC without a specified precision is subject to the
> limits described in Table 8-2."

Note that that's not saying anything about how many significant digits
you can write.

> In the binary representation, digits are grouped into groups of 4. The
> number of such groups is checked in numeric_recv:

>     len = (uint16) pq_getmsgint(buf, sizeof(uint16));
>     if (len < 0 || len > NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE)
>         ereport(ERROR,
>                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
>                  errmsg("invalid length in external \"numeric\" value")));

> but NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE is 3000 which means a
> limit of only 12000 digits. numeric_in has no such limit.

It's true that numeric_in and numeric_recv aren't too consistent about
the limits they enforce.  I doubt that "remove the limits" is the right
answer for that, though.  In particular, allowing hundreds of thousands
of digits would be a good way to lock a backend up for very long times
in simple arithmetic operations ...

            regards, tom lane