ossc-db / pg_store_plans

Store execution plans like pg_stat_statements does for queries.
http://ossc-db.github.io/pg_store_plans/
Other
52 stars 26 forks source link

segmentation fault with strlen(0) on the different extension version. #34

Open harukat opened 1 week ago

harukat commented 1 week ago

A SEGV occurred in the code of pg_store_plan during operation. The pg_store_plans module used are source built from the latest code in the repository at this time, but EXTENTSION haven't be updated from version 1.5.

A stack trace of the core dump is shown below.

In the pg_store_plans_internal() function, the value of char* pstr was obtained, which could be NULL, but the value was passed to the pgsp_json_textize() function and init_json_lex_context() function without NULL checking, and finally strlen(0) was executed, causing the crash.

It is considered better to add a NULL check somewhere (with a warning log message if necessary) and simply abort processing on the data.

Core was generated by `postgres: postgres postgres [local] SELECT'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f1a370d4cd5 in __strlen_avx2 () from /lib64/libc.so.6
Missing separate debuginfos, use: yum debuginfo-install audit-libs-3.0-0.13.20190507gitf58ec40.el8.x86_64 cyrus-sasl-lib-2.1.27-1.el8.x86_64 glibc-2.28-72.el8.x86_64 keyutils-libs-1.5.10-6.el8.x86_64 krb5-libs-1.17-9.el8.x86_64 libblkid-2.32.1-17.el8.x86_64 libcap-2.26-1.el8.x86_64 libcap-ng-0.7.9-4.el8.x86_64 libcom_err-1.44.6-3.el8.x86_64 libgcc-8.3.1-4.5.el8.x86_64 libgcrypt-1.8.3-4.el8.x86_64 libgpg-error-1.31-1.el8.x86_64 libicu-60.3-1.el8.x86_64 libmount-2.32.1-17.el8.x86_64 libselinux-2.9-2.1.el8.x86_64 libstdc++-8.3.1-4.5.el8.x86_64 libuuid-2.32.1-17.el8.x86_64 libxcrypt-4.1.1-4.el8.x86_64 libxml2-2.9.7-5.el8.x86_64 lz4-libs-1.8.1.2-4.el8.x86_64 openldap-2.4.46-10.el8.x86_64 openssl-libs-1.1.1c-2.el8.x86_64 pam-1.3.1-4.el8.x86_64 pcre2-10.32-1.el8.x86_64 pg_dbms_stats13-1.5.0-1.el8.x86_64 pg_hint_plan13-1.3.7-1.el8.x86_64 pg_statsinfo-13.0-1.pg13.rhel8.x86_64 pgaudit15_13-1.5.0-1.rhel8.x86_64 sssd-client-2.2.0-19.el8.x86_64 systemd-libs-239-18.el8.x86_64 xz-libs-5.2.4-3.el8.x86_64 zlib-1.2.11-10.el8.x86_64
(gdb) bt
#0  0x00007f1a370d4cd5 in __strlen_avx2 () from /lib64/libc.so.6
#1  0x00007f1a30db5282 in init_json_lex_context (lex=lex@entry=0x7ffecf8f0d50, json=json@entry=0x0) at pgsp_json.c:1349
#2  0x00007f1a30db890b in pgsp_json_textize (json=json@entry=0x0) at pgsp_json_text.c:1037
#3  0x00007f1a30db190d in pg_store_plans_internal (fcinfo=<optimized out>, api_version=api_version@entry=PGSP_V1_5)
    at pg_store_plans.c:1585
#4  0x00007f1a30db39bf in pg_store_plans (fcinfo=<optimized out>) at pg_store_plans.c:1422
#5  0x0000000000646315 in ExecMakeTableFunctionResult (setexpr=0x2eb8ff8, econtext=0x2eb8f18, 
    argContext=<optimized out>, expectedDesc=0x2ec1fb8, randomAccess=false) at execSRF.c:234
#6  0x000000000065747f in FunctionNext (node=node@entry=0x2eb84b8) at nodeFunctionscan.c:94
#7  0x0000000000646f4a in ExecScanFetch (recheckMtd=0x657150 <FunctionRecheck>, accessMtd=0x657180 <FunctionNext>, 
    node=0x2eb84b8) at execScan.c:133
#8  ExecScan (node=0x2eb84b8, accessMtd=0x657180 <FunctionNext>, recheckMtd=0x657150 <FunctionRecheck>)
    at execScan.c:182
harukat commented 1 week ago

I also found the reproduce steps in V1.8.

db1(5432)=# \dx
                                            List of installed extensions
        Name        | Version |   Schema   |                              Description
--------------------+---------+------------+------------------------------------------------------------------------
 pg_stat_statements | 1.8     | public     | track planning and execution statistics of all SQL statements executed
 pg_store_plans     | 1.8     | public     | track plan statistics of all SQL statements executed
 plpgsql            | 1.0     | pg_catalog | PL/pgSQL procedural language
(3 rows)

db1(5432)=# SELECT pg_store_plans_reset();
 pg_store_plans_reset
----------------------

(1 row)

db1(5432)=# SELECT plan FROM pg_stat_statements s JOIN pg_store_plans p USING (queryid) ORDER BY mean_time DESC LIMIT 10;
                   plan
------------------------------------------
 Result  (cost=0.00..0.01 rows=1 width=4)
(1 row)

db1(5432)=# \q
[postgres@host1]$ unlink $PGDATA/pg_stat_tmp/pgsp_plan_texts.stat
[postgres@host1]$ psql db1
psql (13.15)
Type "help" for help.

db1(5432)=# SELECT plan FROM pg_stat_statements s JOIN pg_store_plans p USING (queryid) ORDER BY mean_time DESC LIMIT 10;
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
harukat commented 1 week ago

Above reproduce steps on the patched version:

db1(5432)=# SELECT pg_store_plans_reset();
 pg_store_plans_reset
----------------------

(1 row)

db1(5432)=# SELECT plan FROM pg_stat_statements s JOIN pg_store_plans p USING (queryid) ORDER BY mean_time DESC LIMIT 10;
                   plan
------------------------------------------
 Result  (cost=0.00..0.01 rows=1 width=4)
(1 row)

db1(5432)=# \q

[postgres@host1]$ unlink $PGDATA/pg_stat_tmp/pgsp_plan_texts.stat
[postgres@host1]$ psql db1
psql (13.15)
Type "help" for help.

db1(5432)=# SELECT plan FROM pg_stat_statements s JOIN pg_store_plans p USING (queryid) ORDER BY mean_time DESC LIMIT 10;
      plan
----------------
 <invalid plan>
 <invalid plan>
(2 rows)