Server may segfault when using slices on int2vector
Hello.
While building a query on the pg_index relation, I came accross a bug which
simplest form is manifested as this:
select
a.indkey[1:3],
a.indkey[1:2]
from pg_index as a
This can result either in a segfault, a failed memory allocation or gibberish
results.
For example, this is a backtrace I could produce while running the above
query.
It turns out that the int2vector->dim1 member has a dummy value.
#0 int2vectorout (fcinfo=<optimized out>) at int.c:192
#1 0x000000000071b445 in FunctionCall1Coll (flinfo=flinfo@entry=0x1ec1360,
collation=collation@entry=0, arg1=arg1@entry=32251408) at fmgr.c:1297
#2 0x000000000071c58e in OutputFunctionCall (flinfo=0x1ec1360, val=32251408)
at fmgr.c:1950
#3 0x000000000046977d in printtup (slot=0x1ec0300, self=0x1e34c28) at
printtup.c:359
#4 0x000000000057eae2 in ExecutePlan (dest=0x1e34c28, direction=<optimized
out>, numberTuples=0, sendTuples=1 '\001', operation=CMD_SELECT,
planstate=0x1ebff10, estate=0x1ebfe00) at execMain.c:1499
#5 standard_ExecutorRun (queryDesc=0x1e96320, direction=<optimized out>,
count=0) at execMain.c:308
#6 0x0000000000652fc8 in PortalRunSelect (portal=portal@entry=0x1ee2680,
forward=forward@entry=1 '\001', count=0, count@entry=9223372036854775807,
dest=dest@entry=0x1e34c28) at pquery.c:946
#7 0x000000000065432f in PortalRun (portal=portal@entry=0x1ee2680,
count=count@entry=9223372036854775807, isTopLevel=isTopLevel@entry=1 '\001',
dest=dest@entry=0x1e34c28, altdest=altdest@entry=0x1e34c28,
completionTag=completionTag@entry=0x7fff90242090 "") at pquery.c:790
#8 0x00000000006520e5 in exec_simple_query (query_string=0x1e7cfa0 "select \n
a.indkey[1:3],\n a.indkey[1:2]\nfrom pg_index as a;") at postgres.c:1048
#9 PostgresMain (argc=<optimized out>, argv=argv@entry=0x1e1b8e8,
dbname=0x1e1b798 "postgres", username=<optimized out>) at postgres.c:3992
#10 0x000000000046607d in BackendRun (port=0x1e39b30) at postmaster.c:4085
#11 BackendStartup (port=0x1e39b30) at postmaster.c:3774
#12 ServerLoop () at postmaster.c:1585
#13 0x00000000006123b1 in PostmasterMain (argc=argc@entry=3,
argv=argv@entry=0x1e19550) at postmaster.c:1240
#14 0x00000000004669f5 in main (argc=3, argv=0x1e19550) at main.c:196
--
Ronan Dunklau
http://dalibo.com - http://dalibo.org
--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs
On 19.11.2013 16:24, Ronan Dunklau wrote:
Hello.
While building a query on the pg_index relation, I came accross a bug which
simplest form is manifested as this:select
a.indkey[1:3],
a.indkey[1:2]
from pg_index as aThis can result either in a segfault, a failed memory allocation or gibberish
results.
Hmm. int2vectorout expects the int2vector to have a single dimension,
but array_get_slice() returns a zero-dimension array if the result is empty.
I don't think it's safe to allow slicing int2vectors (nor oidvectors).
It seems all too likely that the result violates the limitations of
int2vector. In addition to that segfault, the array returned is 1-based,
not 0-based as we assume for int2vectors. One consequence of that is
that if you COPY the value out in binary format and try to read it back,
you'll get an error.
So I think we should just not allow slicing oidvectors, and throw an
error. You can cast from int2vector to int2[], and slice and dice that
as much as you want, so it's not a big loss in functionality. Another
solution would to provide a specialized slice-function for int2vector
and oidvector, but it's probably not worth the effort.
Thanks for the report!
- Heikki
--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs
Le mercredi 20 novembre 2013 13:43:48 Heikki Linnakangas a écrit :
On 19.11.2013 16:24, Ronan Dunklau wrote:
Hello.
While building a query on the pg_index relation, I came accross a bug
which
simplest form is manifested as this:select
a.indkey[1:3],
a.indkey[1:2]from pg_index as a
This can result either in a segfault, a failed memory allocation or
gibberish results.Hmm. int2vectorout expects the int2vector to have a single dimension,
but array_get_slice() returns a zero-dimension array if the result is empty.I don't think it's safe to allow slicing int2vectors (nor oidvectors).
It seems all too likely that the result violates the limitations of
int2vector. In addition to that segfault, the array returned is 1-based,
not 0-based as we assume for int2vectors. One consequence of that is
that if you COPY the value out in binary format and try to read it back,
you'll get an error.So I think we should just not allow slicing oidvectors, and throw an
error. You can cast from int2vector to int2[], and slice and dice that
as much as you want, so it's not a big loss in functionality. Another
solution would to provide a specialized slice-function for int2vector
and oidvector, but it's probably not worth the effort.Thanks for the report!
- Heikki
Are the differences between int2vector and a regular array documented somewhere
? What is the purpose of using this datatype instead of int2[] ?
On a sidenote, I would probably never have stumbled upon this bug if it was
clear that an int2vector was 0 indexed.
--
Ronan Dunklau
http://dalibo.com - http://dalibo.org
Heikki Linnakangas <hlinnakangas@vmware.com> writes:
On 19.11.2013 16:24, Ronan Dunklau wrote:
[ this crashes: ]
select
a.indkey[1:3],
a.indkey[1:2]
from pg_index as a
I don't think it's safe to allow slicing int2vectors (nor oidvectors).
It seems all too likely that the result violates the limitations of
int2vector. In addition to that segfault, the array returned is 1-based,
not 0-based as we assume for int2vectors. One consequence of that is
that if you COPY the value out in binary format and try to read it back,
you'll get an error.
So I think we should just not allow slicing oidvectors, and throw an
error. You can cast from int2vector to int2[], and slice and dice that
as much as you want, so it's not a big loss in functionality.
I think more useful is to automatically cast up to int2[], rather than
make the user write something as ugly as "(a.indkey::int2[])[1:3]".
This case is really pretty similar to what we have to do when handling
domains over arrays; int2vector could be thought of as a domain over
int2[] that constrains the allowed subscripting. And what we do for
those is automatically cast up.
With that thought in mind, I tried tweaking transformArrayType() to
auto-cast int2vector and oidvector to int2[] and oid[]. That resolves
this crash without throwing an error. On the other hand, it causes
assignment to an element or slice of these types to throw an error, which
strikes me as a Good Thing because otherwise such an assignment could
likewise result in a value violating the subscript constraints of these
types. We could if we liked fix that by providing a cast from int2[] to
int2vector that checks the subscript constraints, but like you I'm not
thinking it's worth the trouble. There are certainly no cases in the
system catalogs where we want to support such manual assignments.
While testing that I discovered an independent bug in
transformAssignmentSubscripts: the "probably shouldn't fail" error
reporting code doesn't work because "result" has already been set to NULL.
We should fix that as per attached whether or not we choose to resolve
Ronan's bug this way.
The attached patch is just a quick draft for testing; it needs more work
on the nearby comments, and the OIDs of int2[] and oid[] should be named
by #define's in pg_type.h not by literal constants. If there are no
objections, I'll clean it up and commit.
regards, tom lane
Attachments:
fix-int2vector-subscripting.patchtext/x-diff; charset=us-ascii; name=fix-int2vector-subscripting.patchDownload+17-4
Le samedi 23 novembre 2013 15:39:39 Tom Lane a écrit :
Heikki Linnakangas <hlinnakangas@vmware.com> writes:
On 19.11.2013 16:24, Ronan Dunklau wrote:
[ this crashes: ]
select
a.indkey[1:3],
a.indkey[1:2]
from pg_index as aI don't think it's safe to allow slicing int2vectors (nor oidvectors).
It seems all too likely that the result violates the limitations of
int2vector. In addition to that segfault, the array returned is 1-based,
not 0-based as we assume for int2vectors. One consequence of that is
that if you COPY the value out in binary format and try to read it back,
you'll get an error.So I think we should just not allow slicing oidvectors, and throw an
error. You can cast from int2vector to int2[], and slice and dice that
as much as you want, so it's not a big loss in functionality.I think more useful is to automatically cast up to int2[], rather than
make the user write something as ugly as "(a.indkey::int2[])[1:3]".
This case is really pretty similar to what we have to do when handling
domains over arrays; int2vector could be thought of as a domain over
int2[] that constrains the allowed subscripting. And what we do for
those is automatically cast up.With that thought in mind, I tried tweaking transformArrayType() to
auto-cast int2vector and oidvector to int2[] and oid[]. That resolves
this crash without throwing an error. On the other hand, it causes
assignment to an element or slice of these types to throw an error, which
strikes me as a Good Thing because otherwise such an assignment could
likewise result in a value violating the subscript constraints of these
types. We could if we liked fix that by providing a cast from int2[] to
int2vector that checks the subscript constraints, but like you I'm not
thinking it's worth the trouble. There are certainly no cases in the
system catalogs where we want to support such manual assignments.While testing that I discovered an independent bug in
transformAssignmentSubscripts: the "probably shouldn't fail" error
reporting code doesn't work because "result" has already been set to NULL.
We should fix that as per attached whether or not we choose to resolve
Ronan's bug this way.The attached patch is just a quick draft for testing; it needs more work
on the nearby comments, and the OIDs of int2[] and oid[] should be named
by #define's in pg_type.h not by literal constants. If there are no
objections, I'll clean it up and commit.regards, tom lane
Thank you for the match, I saw it got commited.
I have some more questions, however not directly related to this bug.
Casting from int2vector to int2[] returns a zero-indexed array, but slicing an
int2vector returns a one-indexed array. This behavior is consistent with
slicing in general, which always returns 1 indexed arrays, but I found it
surprising, especially when writing a query like this:
select ('1 2'::int2vector)[0:1] = ('1 2'::int2vector)::int2[];
I would have expected to return true, but it actually isn't because one array
is zero-indexed and the other one is not.
Is there a more convenient way to change the lower bound of an array than to
slice it ?
Thank you very much.
--
Ronan Dunklau
http://dalibo.com - http://dalibo.org
--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs