Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: postgresql-cfbot/postgresql
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: cf/5251~1
Choose a base ref
...
head repository: postgresql-cfbot/postgresql
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: cf/5251
Choose a head ref
  • 3 commits
  • 5 files changed
  • 2 contributors

Commits on Aug 9, 2025

  1. libpq: Extend "read pending" check from SSL to GSS

    An extra check for pending bytes in the SSL layer has been part of
    pqReadReady() for a very long time (79ff2e9). But when GSS transport
    encryption was added, it didn't receive the same treatment. (As
    79ff2e9 notes, "The bug that I fixed in this patch is exceptionally
    hard to reproduce reliably.")
    
    Without that check, it's possible to hit a hang in gssencmode, if the
    server splits a large libpq message such that the final message in a
    streamed response is part of the same wrapped token as the split
    message:
    
        DataRowDataRowDataRowDataRowDataRowData
        -- token boundary --
        RowDataRowCommandCompleteReadyForQuery
    
    If the split message takes up enough memory to nearly fill libpq's
    receive buffer, libpq may return from pqReadData() before the later
    messages are pulled out of the PqGSSRecvBuffer. Without additional
    socket activity from the server, pqReadReady() (via pqSocketCheck())
    will never again return true, hanging the connection.
    
    Pull the pending-bytes check into the pqsecure API layer, where both SSL
    and GSS now implement it.
    
    Note that this does not fix the root problem! Third party clients of
    libpq have no way to call pqsecure_read_is_pending() in their own
    polling. This just brings the GSS implementation up to par with the
    existing SSL workaround; a broader fix is left to a subsequent commit.
    (However, pgtls_read_pending() is renamed to pgtls_read_is_pending(), to
    avoid conflation with the forthcoming pgtls_drain_pending().)
    
    Discussion: https://postgr.es/m/CAOYmi%2BmpymrgZ76Jre2dx_PwRniS9YZojwH0rZnTuiGHCsj0rA%40mail.gmail.com
    jchampio authored and Commitfest Bot committed Aug 9, 2025
    Configuration menu
    Copy the full SHA
    25f41f9 View commit details
    Browse the repository at this point in the history
  2. libpq: Drain all pending bytes from SSL/GSS during pqReadData()

    The previous commit strengthened a workaround for a hang when large
    messages are split across TLS records/GSS tokens. Because that
    workaround is implemented in libpq internals, it can only help us when
    libpq itself is polling on the socket. In nonblocking situations, where
    the client above libpq is expected to poll, the same bugs can show up.
    
    As a contrived example, consider a large protocol-2.0 error coming back
    from a server during PQconnectPoll(), split in an odd way across two
    records:
    
        -- TLS record (8192-byte payload) --
        EEEE[...repeated a total of 8192 times]
        -- TLS record (8193-byte payload) --
        EEEE[...repeated a total of 8192 times]\0
    
    The first record will fill the first half of the libpq receive buffer,
    which is 16k long by default. The second record completely fills the
    last half with its first 8192 bytes, leaving the terminating NULL in the
    OpenSSL buffer. Since we still haven't seen the terminator at our level,
    PQconnectPoll() will return PGRES_POLLING_READING, expecting to come
    back when the server has sent "the rest" of the data.  But there is
    nothing left to read from the socket; OpenSSL had to pull all of the
    data in the 8193-byte record off of the wire to decrypt it.
    
    (A real server would probably not split up the records this way, nor
    keep the connection open after sending a fatal connection error. But
    servers that regularly use larger TLS records can get the libpq receive
    buffer into the same state if DataRows are big enough, as reported on
    the list.)
    
    This is a layering violation. libpq makes decisions based on data in the
    application buffer, above the transport buffer (whether SSL or GSS), but
    clients are polling the socket, below the transport buffer. One way to
    fix this in a backportable way, without changing APIs too much, is to
    ensure data never stays in the transport buffer. Then pqReadData's
    postconditions will look similar for both raw sockets and SSL/GSS: any
    available data is either in the application buffer, or still on the
    socket.
    
    Building on the prior commit, add a function to the pqsecure API layer
    which drains all pending data from the transport layer into
    conn->inBuffer, expanding the buffer as necessary. pqReadData() calls
    this function before returning when pending data exists. This is not
    particularly efficient from an architectural perspective (the
    pqsecure_read() implementations take care to fit their packets into the
    current buffer, and that effort is now completely discarded), but it's
    hopefully easier to reason about than a full rewrite would be for the
    back branches.
    
    Reported-by: Lars Kanis <[email protected]>
    Discussion: https://postgr.es/m/2039ac58-d3e0-434b-ac1a-2a987f3b4cb1%40greiz-reinsdorf.de
    Backpatch-through: 13
    jchampio authored and Commitfest Bot committed Aug 9, 2025
    Configuration menu
    Copy the full SHA
    dc9a16a View commit details
    Browse the repository at this point in the history
  3. [CF 5251] v2 - libpq: Fix processing of SSL records >8kB on async API

    This branch was automatically generated by a robot using patches from an
    email thread registered at:
    
    https://commitfest.postgresql.org/patch/5251
    
    The branch will be overwritten each time a new patch version is posted to
    the thread, and also periodically to check for bitrot caused by changes
    on the master branch.
    
    Patch(es): https://www.postgresql.org/message-id/CAOYmi+=YJ2J_sQ6yS8y1o9AX1Xgz35_r0hApV8QRWwi1K8gC0g@mail.gmail.com
    Author(s): Jacob Champion, Lars Kanis
    Commitfest Bot committed Aug 9, 2025
    Configuration menu
    Copy the full SHA
    44dfb70 View commit details
    Browse the repository at this point in the history
Loading