Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wVSDa-001yI8-2S for pgsql-bugs@arkaria.postgresql.org; Fri, 05 Jun 2026 10:56:02 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wVSDZ-00BrKj-1e for pgsql-bugs@arkaria.postgresql.org; Fri, 05 Jun 2026 10:56:01 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wVSDZ-00BrKa-0h for pgsql-bugs@lists.postgresql.org; Fri, 05 Jun 2026 10:56:01 +0000 Received: from mail-yw1-x112e.google.com ([2607:f8b0:4864:20::112e]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wVSDX-00000001PAx-0loY for pgsql-bugs@lists.postgresql.org; Fri, 05 Jun 2026 10:56:00 +0000 Received: by mail-yw1-x112e.google.com with SMTP id 00721157ae682-7e8b45dfb3dso23385427b3.3 for ; Fri, 05 Jun 2026 03:55:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1780656957; cv=none; d=google.com; s=arc-20240605; b=IKSTme4YlqTQQVO9Adxi07GXgluIywUjGbISti7GYKLKqUYB+BYPgTT+eKqs5nqsEH pIj4iUKDx1CXBpdSlD05bUd1/jg6/fYCrljveNPGoYS2OZs0RsclyKAO7Bv05cavkzDx /+y33QWSnq/nU/LLQGJZvk5s8BxNvNTwl+bfGFdvMxSPZ5Fl02ovQYYuL6GyFE02pu4t zlNfPNG/3Ts5oGTEAFQMuhsTJI9qxzeuX0H0alQIsSyWCgB4z9BfJXvwJ32rxHQyIVZ7 Gg7L17POURx0inJoPwPaq0h/8VOrdPe6SkjADZqXGIeiR0WLjbhezTRvAnEdAF9INLMz GLBA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=FF1+/g7YbueLlSqA3tsXVR4lP7DcOKXpwjGazPtaVyw=; fh=q/Dog7X3ImCtpwWiTPXJaBMLV4ZgeqgpQEjvlGdUfTY=; b=VF56LP6SPXUP6hktAi2yDVLhr7rl7InkbD1SJR2H1dBleX2BBAcXspqY0bVfvI03o2 nBDkYCquNlOAOGdJFvP4Y5xcChjZjIetl9o1EM0kAqIZrbRpCmP9rIiPpYo8K1zgqEXC xtWyagVVd64+eeyF/8JAgMpA5luaRnMDT2lNjLdWTmwvHmJGgvvhGVTtzy0sU9AQzRPz rcRiqbc2ffg+HqfaHqc73hnmuG2W0XjKLL5ofLXBNhc/y+R7MoxszI9fRlW/lxonF/pC wtZDzBamzfOQFdtHF0bX0/Q3iIusb75nkPYgmzA7LdovFRvNeMYdgiEJO2z+yKMfJz2n rQsw==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780656957; x=1781261757; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=FF1+/g7YbueLlSqA3tsXVR4lP7DcOKXpwjGazPtaVyw=; b=AL4D0XgVzWULK3a/LoiagLvjPoNoXFNeA08mb/j0c5JCXVMSqI2iUcokwcmMoerl+y B+J01mYXUhFdPAN6cQ/5bioE0tmYF4r/8u03iAXa2wsHPaV/yA9dxbgq7bKDIzghTw6K tTsflPKMzjaOThJDUqezV+/hCOns/Z3jsCvpBUyMu7+fAKGTyAmkgLlymeeqlVZIMUjg 4Bbqt9RIrCYoi02kH104cPQcNH8CvVC6/qF4HEzr4iM0QrZa6iSPIFV9QUckH1wxCWtf zUPmWdzAvB9Xo87yVh2/uRLbhf+H6KG7qBLAipvive1c+tQlugoIcYPQO7XmbQYmiIi8 mDLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780656957; x=1781261757; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=FF1+/g7YbueLlSqA3tsXVR4lP7DcOKXpwjGazPtaVyw=; b=nU0LayYtKwnRjCfJvLUbbqyg617pCrxl+yCIbIA5P3/VGdY/tOtmGeu/mtE1fw2HYL tbt6beI7vwf/+fj7kffkqVZkNbx9itTHSF9j8kPimUEVBiUuLxACHV9eBdPR5YPnNdFN y820t2tfvqOs0e1Sz40UXvMq7tzu5Opc+MhsZm9INMLGH/3H2wVg545M03YrJGTvuWdW Wq/opHICttY21UPBXST9fO6UvEu7tkbxJjwzU+B+niz30+DoZNwGNX8c5e9GQmzk9Jfs rdVgV5H0zdCNHqRYdRnDlU1qMPTiAL6zWaxIPlddqh5p/u8D2LN/SurpF5bxTk+gfEI8 jfmQ== X-Gm-Message-State: AOJu0YzUSm/WqJZEReZ88zQKn2WGJHsIqlcSKMnDAPGLpe3vyOmAB4Rm 2hj/6Zhm4XgBDfb4jUXxq2FWCkMvOYT+2hZYBHfU0VbgXbZM53APw0Ql0379FSyHXj6XsxkooFX wYnIwdAwn7KqqNlyjH2s/FOech2UZkZQ= X-Gm-Gg: Acq92OG1GmRlEPGpiOLDCZYGSmRuJ+eFSPq6zpbhZmsHYxthqTrXV6ukDNs7bMSb9Kq 4ThLiC9utx5sRYxIKxBg/ItHJKNJTZdG+PrSY8rnja4ib6ho0ev047scJWBnOBLazDRfLvsUO9U l/90MP/+92lJpLIVhAg8mENrI76yuLBOjPtBNWyY0uxcBhAXUb+89nYhaalV5G1hQ6jTBKGuhZT mYPRTU3PNECCKmfrZAx6kj9e5BF6l5J847tGBGsOxN0XxjzKTiOurNI4PbwdCR2xOLxDtg+jGZO tYBBAfdgQaMw8lvNRA4= X-Received: by 2002:a05:690c:6d07:b0:7dd:b286:dfdc with SMTP id 00721157ae682-7ed0b680e78mr28860817b3.11.1780656957325; Fri, 05 Jun 2026 03:55:57 -0700 (PDT) MIME-Version: 1.0 References: <19511-f9f251767b658232@postgresql.org> In-Reply-To: From: Amjad Shahzad Date: Fri, 5 Jun 2026 15:55:39 +0500 X-Gm-Features: AVHnY4JIhsh-bZoE9wgf11MZ9aidAvNSjt74vM_bOaHjeM6fTUq6MTFvYP17YiI Message-ID: Subject: Re: BUG #19511: contrib/dblink: NULL dereference in dblink_get_notify() when called without a prior connection To: Fujii Masao Cc: pgsql-bugs@lists.postgresql.org Content-Type: multipart/alternative; boundary="0000000000006886c206537f8178" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000006886c206537f8178 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Fujii, You are correct. I checked the libpq source and both PQconsumeInput() and PQnotifies() have explicit NULL guards: /* fe-exec.c line 2003 */ if (!conn) return 0; /* fe-exec.c line 2688 */ if (!conn) return NULL; So no segmentation fault actually occurs. The function silently returns 0 rows when called without a prior connection instead of crashing. The real issue is a behavioral inconsistency: every other dblink function that uses the default connection explicitly checks for NULL and calls dblink_conn_not_avail() to give a clear error message. dblink_get_notify() is the only exception, it silently returns an empty result set, which could mislead callers into thinking no notifications exist when in fact no connection was established. Whether this inconsistency is worth fixing with a proper error message is up to the community's judgment. I apologize for incorrectly characterizing it as a crash. Regards, Amjad Shahzad On Fri, Jun 5, 2026 at 9:45=E2=80=AFAM Fujii Masao = wrote: > On Fri, Jun 5, 2026 at 10:20=E2=80=AFAM Amjad Shahzad > wrote: > >> I found a NULL pointer dereference in contrib/dblink/dblink.c in the > >> dblink_get_notify() function. Any user with EXECUTE on the function > >> can crash their backend process with a single call. Confirmed against > master > >> commit 0392fb900eb. > >> > >> WHAT IS THE ISSUE > >> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > >> dblink_get_notify() retrieves async notifications from a remote > connection. > >> When called with no arguments it uses the default > >> (unnamed) connection. If no default connection has been established > first, > >> pconn->conn is NULL. The code assigns this NULL to conn and > >> then passes it directly to PQconsumeInput() and PQnotifies(): > >> > >> /* line 1893 (master) */ > >> else > >> conn =3D pconn->conn; /* NULL =E2=80=94 no connection est= ablished */ > >> > >> InitMaterializedSRF(fcinfo, 0); > >> > >> PQconsumeInput(conn); /* passes NULL to libpq */ > >> while ((notify =3D PQnotifies(conn)) !=3D NULL) /* NULL dereferen= ce */ > >> > >> PQnotifies(NULL) dereferences a null pointer internally, causing a > backend > >> SIGSEGV. > > Can this segmentation fault actually happen? > > PQconsumeInput() and PQnotifies() both simply return immediately when > conn =3D=3D NULL. So even if dblink_get_notify() calls them with a NULL c= onn, > it doesn't seem like that would lead to a segmentation fault. > Am I missing something? > > Regards, > > -- > Fujii Masao > --0000000000006886c206537f8178 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Fujii,

You are correct. I checked the libpq sour= ce and both PQconsumeInput() and PQnotifies() have explicit NULL guards:
=C2=A0 =C2=A0 /* fe-exec.c line 2003 */
=C2=A0 =C2=A0 if (!conn)=C2=A0 =C2=A0 =C2=A0 =C2=A0 return 0;

=C2=A0 =C2=A0 /* fe-exec.c li= ne 2688 */
=C2=A0 =C2=A0 if (!conn)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 retur= n NULL;

So no segmentation fault actually occurs. The function silen= tly returns 0 rows when called without a prior connection instead of crashi= ng.

The real issue is a behavioral inconsistency: every other dblink= function that uses the default connection explicitly checks for NULL
an= d calls dblink_conn_not_avail() to give a clear error message.

= dblink_get_notify() is the only exception, it silently returns an empty res= ult set, which could mislead callers into thinking no
notifications exis= t when in fact no connection was established. Whether this inconsistency is= worth fixing with a proper error message
is up to the community's j= udgment. I apologize for incorrectly characterizing it as a crash.

R= egards,
Amjad Shahzad

On Fri, Jun 5, 2026 at = 9:45=E2=80=AFAM Fujii Masao <ma= sao.fujii@gmail.com> wrote:
On Fri, Jun 5, 2026 at 10:20=E2=80=AFAM Amjad Shahzad <amjadsh= ahzad2000@gmail.com> wrote:
>> I found a NULL pointer dereference in contrib/dblink/dblink.c in t= he
>> dblink_get_notify() function. Any user with EXECUTE on the functio= n
>> can crash their backend process with a single call. Confirmed agai= nst master
>> commit 0392fb900eb.
>>
>> WHAT IS THE ISSUE
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>> dblink_get_notify() retrieves async notifications from a remote co= nnection.
>> When called with no arguments it uses the default
>> (unnamed) connection. If no default connection has been establishe= d first,
>> pconn->conn is NULL. The code assigns this NULL to conn and
>> then passes it directly to PQconsumeInput() and PQnotifies():
>>
>>=C2=A0 =C2=A0 =C2=A0/* line 1893 (master) */
>>=C2=A0 =C2=A0 =C2=A0else
>>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0conn =3D pconn->conn;=C2=A0 = =C2=A0 =C2=A0 /* NULL =E2=80=94 no connection established */
>>
>>=C2=A0 =C2=A0 =C2=A0InitMaterializedSRF(fcinfo, 0);
>>
>>=C2=A0 =C2=A0 =C2=A0PQconsumeInput(conn);=C2=A0 =C2=A0 =C2=A0 =C2= =A0 /* passes NULL to libpq */
>>=C2=A0 =C2=A0 =C2=A0while ((notify =3D PQnotifies(conn)) !=3D NULL)= =C2=A0 /* NULL dereference */
>>
>> PQnotifies(NULL) dereferences a null pointer internally, causing a= backend
>> SIGSEGV.

Can this segmentation fault actually happen?

PQconsumeInput() and PQnotifies() both simply return immediately when
conn =3D=3D NULL. So even if dblink_get_notify() calls them with a NULL con= n,
it doesn't seem like that would lead to a segmentation fault.
Am I missing something?

Regards,

--
Fujii Masao
--0000000000006886c206537f8178--