Re: BUG #17406: Segmentation fault on GiST index after 14.2 upgrade
От | Tomas Vondra |
---|---|
Тема | Re: BUG #17406: Segmentation fault on GiST index after 14.2 upgrade |
Дата | |
Msg-id | 78098996-ca5e-a2ce-ae33-68ec8648ccc7@enterprisedb.com обсуждение исходный текст |
Ответ на | Re: BUG #17406: Segmentation fault on GiST index after 14.2 upgrade (Tomas Vondra <tomas.vondra@enterprisedb.com>) |
Список | pgsql-bugs |
On 2/17/22 13:26, Tomas Vondra wrote: > On 2/17/22 03:52, Peter Geoghegan wrote: >> On Wed, Feb 16, 2022 at 4:16 PM Tomas Vondra >> <tomas.vondra@enterprisedb.com> wrote: >>> test=# SELECT * FROM gist_page_items(get_raw_page('path_gist_idx', 0), >>> 'path_gist_idx'); >> >> Maybe this is obvious, but just in case: gist_page_items is *very* >> trusting here. It's necessary to use gist_page_items_bytea() if you're >> not 100% sure about the index definition for the index page you >> provide. The fact that you can display the contents of each tuple >> using the underlying type's own output function is very handy. But >> potentially hazardous. >> > > Sure, but I used this to inspect the index from example in our docs: > > https://www.postgresql.org/docs/14/ltree.html#id-1.11.7.30.8 > > I doubt we can be even more sure about the index definition. > > > I don't know what the root cause is yet, but the memory corruption > happens simply because ltree_out() sees entirely bogus data when > executed from gist_page_items. > > For example it gets 16B varlena, allocates 16B string for it, and starts > iterating over the ltree data. The it finds the first element is 60B > long and happily copies it "into" the 16B buffer. That can't end well, > obviously. > > Clearly, the ltree values are mangled somehow / somewhere. The funny > thing is the bytea always looks 8B longer and with bogus data. So for > example if you select this ltree from the table directly > > Top.Collections.Pictures.Astronomy.Astronauts > > then ltree_out sees it as 80B varlena, with 5 levels. But if ltree_out > gets called from gist_page_items, then it sees 88B with 1 level, which > is completely bogus. > > And funnily enough, if you do this at the beginning of ltree_out: > > in = (ltree *) ((char *) in + 8); > > then gist_page_items() starts working just fine. > > So, I guess gist_page_items() is broken/confused in some way. I'm not > sure if this is related to the crash reported by Victor or a separate, > independent issue. > I may be wrong, but it seems gist_page_items() is entirely oblivious to the fact that GiST does "compression", and fails to decompress the values before passing them to out function. So instead of "ltree" it extracts "ltree_gist" and passes that to "ltree_out". This is consistent with the 8B offset I mentioned before, because ltree_gist has 8B header and then stores the original ltree value. But I may be missing something - this seems like such an obvious gap that I don't know how this could have worked with anything but the most trivial cases without GiST compression. Furthermore, it seems more like a pageinspect issue, unrelated to the original issue reported by Victor. regards -- Tomas Vondra EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company
В списке pgsql-bugs по дате отправления: