luxms / rw_redis_fdw

Other
0 stars 3 forks source link

garbage in SELECT results when server is built with --enable-cassert #18

Open petrov9268 opened 1 week ago

petrov9268 commented 1 week ago

After removing Assert from #17, the server process no longer crashes, but there still seem to be problems when running on a server built with the --enable-cassert build flag.

For example, this works just fine without --enable-cassert:

psql (16.3, server 15.5)
Type "help" for help.

postgres=# CREATE FOREIGN TABLE rft_hash(
        key    TEXT,
        field  TEXT,
        value  TEXT,
        expiry INT
) SERVER localredis
  OPTIONS (tabletype 'hash', keyprefix 'rfth_', database '1');

INSERT INTO rft_hash (key, field, value, expiry) VALUES ('hkey', 'f1', 'v1', 10);
INSERT INTO rft_hash (key, field, value, expiry) VALUES ('hkey', 'f2', 'v2', 10);

SELECT * FROM rft_hash WHERE key = (SELECT 'hkey'::TEXT);
CREATE FOREIGN TABLE
INSERT 0 1
INSERT 0 1
 key  | field | value | expiry
------+-------+-------+--------
 hkey | f1    | v1    |     10
 hkey | f2    | v2    |     10
(2 rows)

However, if enabled:

psql (16.3, server 15.5)
Type "help" for help.

postgres=# CREATE FOREIGN TABLE rft_hash(
        key    TEXT,
        field  TEXT,
        value  TEXT,
        expiry INT
) SERVER localredis
  OPTIONS (tabletype 'hash', keyprefix 'rfth_', database '1');

INSERT INTO rft_hash (key, field, value, expiry) VALUES ('hkey', 'f1', 'v1', 10);
INSERT INTO rft_hash (key, field, value, expiry) VALUES ('hkey', 'f2', 'v2', 10);

SELECT * FROM rft_hash WHERE key = (SELECT 'hkey'::TEXT);
CREATE FOREIGN TABLE
INSERT 0 1
INSERT 0 1
                                                                                               key                                                                                                | field | value | expiry
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------+-------+--------
 hkey                                                                                                                                                                                             | f1    | v1    |     10
 \x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F\x7F | f2    | v2    |     10
(2 rows)

Server version seems to be irrelevant, result is the same on 15.8.

Not sure how Assert can affect SELECT result, or if this is relevant to empty SELECT on other custom built PostgreSQL server on different OS.

The above result is from Rocky Linux 9 running inside a Docker container.

petrov9268 commented 5 days ago

--enable-cassert also enables this.

HGETALL returns a virtual table, by querying data only on the first row scan and filling data for the latter ones with stored in context values. The problem seems to be in how the key (in the example above) is stored and in the query itself.

Basically, use after free.

This does not happen if data is queried with:

SELECT * FROM rft_hash WHERE key = 'hkey';

if this is relevant to empty SELECT on other custom built PostgreSQL server on different OS.

This issue is completely unrelated to this problem. The server in question is built without --enable-cassert, but returns nothing on any query, including those not affected by this issue.