Overview
While fuzzing pg_store_plans using AFL++ and AddressSanitizer, I discovered a memory problem in pgsp_json.c caused by the overlapping memory area when calling memcpy.This could corrupt memory regions and trigger undefined behaviors.
Environment
OS: Ubuntu 22.04.5 LTS (x64)
PostgreSQL: 18.0 (./configure --enable-cassert --enable-debug CFLAGS="-fsanitize=address -fno-omit-frame-pointer -g -O1 -fsanitize-recover=address" LDFLAGS="-fsanitize=address" CC=gcc-11 CXX=g++-11)
Extension pg_store_plans: df94f66
Extension compilation: CC=afl-clang-fast COPT=-g -O2 -fgnu89-inline -fgnu89-inline -fsanitize=address -fno-omit-frame-pointer
AFL++ version: https://github.com/aflplusplus/aflplusplus bf2eac470804df48a1bca6a78d4dd6c71968a556
PostgreSQL setup:
- compile, install
- initdb -D xxx
- install the extension
- createdb
test
- create extension pg_store_plans (on the
test database)
- fuzzing started, feed sqls
- e.g., SELECT public.pg_store_plans_hash_query('# nM?z');
- ...
Affected Code
pgsp_json.c#551
548 if (lasttok == IDENT)
549 {
550 /* Identifiers are copied in case-sensitive manner. */
551 memcpy(wp, expr + i, i2 - i);
552 wp += i2 - i;
553 }
Possible SQLs that Trigger the Problem
SELECT public.pg_store_plans_hash_query('# nM?z');
SELECT public.pg_store_plans_hash_query(' @$ucxm');
SELECT public.pg_store_plans_hash_query('@;GXZ');
SELECT public.pg_store_plans_hash_query(';)Ic');
SELECT public.pg_store_plans_hash_query('D#G-lTF');
SELECT public.pg_store_plans_hash_query(';EX0{Y');
SELECT public.pg_store_plans_hash_query('I;W5');
SELECT public.pg_store_plans_hash_query(';lu');
SELECT public.pg_store_plans_hash_query(':XF ,FU');
SELECT public.pg_store_plans_hash_query(' aY[&:P');
...
Fix Suggestions
Use memmove instead of using memcpy in line 551@pgsp_json.c.
ASan trace
=================================================================
==999986==ERROR: AddressSanitizer: memcpy-param-overlap: memory ranges [0x52500004621c,0x52500004621e) and [0x52500004621d, 0x52500004621f) overlap
#0 0x7b86e54b2f51 in __asan_memcpy ../../../../src/libsanitizer/asan/asan_interceptors_memintrinsics.cpp:22
#1 0x7b86d5427906 in normalize_expr /pg_store_plans/pgsp_json.c:490
#2 0x7b86d54221a7 in hash_query /pg_store_plans/pg_store_plans.c:840
#3 0x7b86d54221a7 in pg_store_plans_hash_query /pg_store_plans/pg_store_plans.c:2137
#4 0x575722103c1e in ExecInterpExpr /postgresql-18.0/src/backend/executor/execExprInterp.c:977
#5 0x5757220ef9af in ExecInterpExprStillValid /postgresql-18.0/src/backend/executor/execExprInterp.c:2299
#6 0x5757221e3126 in ExecEvalExprNoReturn ../../../src/include/executor/executor.h:419
#7 0x5757221e3126 in ExecEvalExprNoReturnSwitchContext ../../../src/include/executor/executor.h:460
#8 0x5757221e3126 in ExecProject ../../../src/include/executor/executor.h:492
#9 0x5757221e3126 in ExecResult /postgresql-18.0/src/backend/executor/nodeResult.c:135
#10 0x575722132f50 in ExecProcNodeFirst /postgresql-18.0/src/backend/executor/execProcnode.c:469
#11 0x575722115cd8 in ExecProcNode ../../../src/include/executor/executor.h:315
#12 0x575722115cd8 in ExecutePlan /postgresql-18.0/src/backend/executor/execMain.c:1697
#13 0x575722115cd8 in standard_ExecutorRun /postgresql-18.0/src/backend/executor/execMain.c:366
#14 0x575722116020 in ExecutorRun /postgresql-18.0/src/backend/executor/execMain.c:303
#15 0x57572274cfce in PortalRunSelect /postgresql-18.0/src/backend/tcop/pquery.c:921
#16 0x575722751747 in PortalRun /postgresql-18.0/src/backend/tcop/pquery.c:765
#17 0x575722746100 in exec_simple_query /postgresql-18.0/src/backend/tcop/postgres.c:1273
#18 0x575722747fde in PostgresMain /postgresql-18.0/src/backend/tcop/postgres.c:4766
#19 0x57572273b75c in BackendMain /postgresql-18.0/src/backend/tcop/backend_startup.c:124
#20 0x575722523e48 in postmaster_child_launch /postgresql-18.0/src/backend/postmaster/launch_backend.c:290
#21 0x57572252c916 in BackendStartup /postgresql-18.0/src/backend/postmaster/postmaster.c:3587
#22 0x57572252c916 in ServerLoop /postgresql-18.0/src/backend/postmaster/postmaster.c:1702
#23 0x57572252f9d4 in PostmasterMain /postgresql-18.0/src/backend/postmaster/postmaster.c:1400
#24 0x5757222568e4 in main /postgresql-18.0/src/backend/main/main.c:227
#25 0x7b86e482a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#26 0x7b86e482a28a in __libc_start_main_impl ../csu/libc-start.c:360
#27 0x575721ac0b94 in _start (/pgserver/bin/postgres+0x41eb94)
0x52500004621c is located 284 bytes inside of 8192-byte region [0x525000046100,0x525000048100)
allocated by thread T0 here:
#0 0x7b86e54b3ec7 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x575722b7d4f1 in AllocSetContextCreateInternal /postgresql-18.0/src/backend/utils/mmgr/aset.c:444
#2 0x57572214b354 in CreateExprContextInternal /postgresql-18.0/src/backend/executor/execUtils.c:259
#3 0x57572214c697 in CreateExprContext /postgresql-18.0/src/backend/executor/execUtils.c:309
#4 0x57572214ce31 in ExecAssignExprContext /postgresql-18.0/src/backend/executor/execUtils.c:487
#5 0x5757221e372c in ExecInitResult /postgresql-18.0/src/backend/executor/nodeResult.c:204
#6 0x575722133286 in ExecInitNode /postgresql-18.0/src/backend/executor/execProcnode.c:167
#7 0x575722118a42 in InitPlan /postgresql-18.0/src/backend/executor/execMain.c:987
#8 0x575722118a42 in standard_ExecutorStart /postgresql-18.0/src/backend/executor/execMain.c:261
#9 0x575722118d32 in ExecutorStart /postgresql-18.0/src/backend/executor/execMain.c:137
#10 0x57572274f762 in PortalStart /postgresql-18.0/src/backend/tcop/pquery.c:518
#11 0x57572274600f in exec_simple_query /postgresql-18.0/src/backend/tcop/postgres.c:1234
#12 0x575722747fde in PostgresMain /postgresql-18.0/src/backend/tcop/postgres.c:4766
#13 0x57572273b75c in BackendMain /postgresql-18.0/src/backend/tcop/backend_startup.c:124
#14 0x575722523e48 in postmaster_child_launch /postgresql-18.0/src/backend/postmaster/launch_backend.c:290
#15 0x57572252c916 in BackendStartup /postgresql-18.0/src/backend/postmaster/postmaster.c:3587
#16 0x57572252c916 in ServerLoop /postgresql-18.0/src/backend/postmaster/postmaster.c:1702
#17 0x57572252f9d4 in PostmasterMain /postgresql-18.0/src/backend/postmaster/postmaster.c:1400
#18 0x5757222568e4 in main /postgresql-18.0/src/backend/main/main.c:227
#19 0x7b86e482a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#20 0x7b86e482a28a in __libc_start_main_impl ../csu/libc-start.c:360
#21 0x575721ac0b94 in _start (/pgserver/bin/postgres+0x41eb94)
0x52500004621d is located 285 bytes inside of 8192-byte region [0x525000046100,0x525000048100)
allocated by thread T0 here:
#0 0x7b86e54b3ec7 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x575722b7d4f1 in AllocSetContextCreateInternal /postgresql-18.0/src/backend/utils/mmgr/aset.c:444
#2 0x57572214b354 in CreateExprContextInternal /postgresql-18.0/src/backend/executor/execUtils.c:259
#3 0x57572214c697 in CreateExprContext /postgresql-18.0/src/backend/executor/execUtils.c:309
#4 0x57572214ce31 in ExecAssignExprContext /postgresql-18.0/src/backend/executor/execUtils.c:487
#5 0x5757221e372c in ExecInitResult /postgresql-18.0/src/backend/executor/nodeResult.c:204
#6 0x575722133286 in ExecInitNode /postgresql-18.0/src/backend/executor/execProcnode.c:167
#7 0x575722118a42 in InitPlan /postgresql-18.0/src/backend/executor/execMain.c:987
#8 0x575722118a42 in standard_ExecutorStart /postgresql-18.0/src/backend/executor/execMain.c:261
#9 0x575722118d32 in ExecutorStart /postgresql-18.0/src/backend/executor/execMain.c:137
#10 0x57572274f762 in PortalStart /postgresql-18.0/src/backend/tcop/pquery.c:518
#11 0x57572274600f in exec_simple_query /postgresql-18.0/src/backend/tcop/postgres.c:1234
#12 0x575722747fde in PostgresMain /postgresql-18.0/src/backend/tcop/postgres.c:4766
#13 0x57572273b75c in BackendMain /postgresql-18.0/src/backend/tcop/backend_startup.c:124
#14 0x575722523e48 in postmaster_child_launch /postgresql-18.0/src/backend/postmaster/launch_backend.c:290
#15 0x57572252c916 in BackendStartup /postgresql-18.0/src/backend/postmaster/postmaster.c:3587
#16 0x57572252c916 in ServerLoop /postgresql-18.0/src/backend/postmaster/postmaster.c:1702
#17 0x57572252f9d4 in PostmasterMain /postgresql-18.0/src/backend/postmaster/postmaster.c:1400
#18 0x5757222568e4 in main /postgresql-18.0/src/backend/main/main.c:227
#19 0x7b86e482a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#20 0x7b86e482a28a in __libc_start_main_impl ../csu/libc-start.c:360
#21 0x575721ac0b94 in _start (/pgserver/bin/postgres+0x41eb94)
SUMMARY: AddressSanitizer: memcpy-param-overlap ../../../../src/libsanitizer/asan/asan_interceptors_memintrinsics.cpp:22 in __asan_memcpy
Expanded C source file
A preprocessed and macro-expanded version of the code can be found https://github.com/gaoxiangliu/fuzzing-dbms-extensions-logs/blob/main/postgresql/pg_store_plans/df94f6pg18/pgsp_json.c
Overview
While fuzzing
pg_store_plansusing AFL++ and AddressSanitizer, I discovered a memory problem in pgsp_json.c caused by the overlapping memory area when callingmemcpy.This could corrupt memory regions and trigger undefined behaviors.Environment
OS: Ubuntu 22.04.5 LTS (x64)
PostgreSQL: 18.0 (./configure --enable-cassert --enable-debug CFLAGS="-fsanitize=address -fno-omit-frame-pointer -g -O1 -fsanitize-recover=address" LDFLAGS="-fsanitize=address" CC=gcc-11 CXX=g++-11)
Extension pg_store_plans: df94f66
Extension compilation: CC=afl-clang-fast COPT=-g -O2 -fgnu89-inline -fgnu89-inline -fsanitize=address -fno-omit-frame-pointer
AFL++ version: https://github.com/aflplusplus/aflplusplus bf2eac470804df48a1bca6a78d4dd6c71968a556
PostgreSQL setup:
testtestdatabase)Affected Code
pgsp_json.c#551
Possible SQLs that Trigger the Problem
Fix Suggestions
Use
memmoveinstead of usingmemcpyin line 551@pgsp_json.c.ASan trace
Expanded C source file
A preprocessed and macro-expanded version of the code can be found https://github.com/gaoxiangliu/fuzzing-dbms-extensions-logs/blob/main/postgresql/pg_store_plans/df94f6pg18/pgsp_json.c