Skip to content

Memory Problem in pgsp_json.c (memcpy-param-overlap) #57

Description

@gaoxiangliu

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions