Last active
November 22, 2023 20:03
-
-
Save larskanis/5546a20365b0ca64e294a32b138f441e to your computer and use it in GitHub Desktop.
postgresql-bug #18210 reproducer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Run this program in a Kerberos capable environment and it should fail like so: | |
* $ gcc -I /usr/include/postgresql bug-gssapi-caller.c -o bug-gssapi-caller -l pq | |
* $ ./bug-gssapi-caller | |
* PQputCopyData text2 command failed: GSSAPI caller failed to retransmit all data needing to be retried | |
*/ | |
#ifdef WIN32 | |
#include <windows.h> | |
#endif | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <sys/select.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <libpq-fe.h> | |
static void | |
exit_nicely(PGconn *conn) | |
{ | |
PQfinish(conn); | |
exit(1); | |
} | |
static void | |
wait_socket(PGconn *conn) | |
{ | |
/* Quit after four notifies are received. */ | |
while (PQisBusy(conn)) { | |
int sock; | |
fd_set input_mask; | |
PQflush(conn); | |
sock = PQsocket(conn); | |
if (sock < 0) | |
break; /* shouldn't happen */ | |
FD_ZERO(&input_mask); | |
FD_SET(sock, &input_mask); | |
if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0) | |
{ | |
fprintf(stderr, "select() failed: %s\n", strerror(errno)); | |
exit_nicely(conn); | |
} | |
/* Now check for input */ | |
PQconsumeInput(conn); | |
} | |
} | |
int | |
main(int argc, char **argv) | |
{ | |
PGconn *conn; | |
PGresult *res; | |
PGnotify *notify; | |
int nnotifies; | |
/* Make a connection to the database | |
* With gssencmode=disable the program finishes. | |
* With gssencmode=require it fails after some loops. | |
*/ | |
conn = PQconnectdb("host=comdb2 dbname=Entwicklung gssencmode=require"); | |
/* Check to see that the backend connection was successfully made */ | |
if (PQstatus(conn) != CONNECTION_OK) { | |
fprintf(stderr, "%s", PQerrorMessage(conn)); | |
exit_nicely(conn); | |
} | |
res = PQexec(conn, | |
"CREATE TEMP TABLE mycopy (id SERIAL PRIMARY KEY, data TEXT)"); | |
if (PQresultStatus(res) != PGRES_COMMAND_OK) { | |
fprintf(stderr, "CREATE TABLE failed: %s", PQerrorMessage(conn)); | |
PQclear(res); | |
exit_nicely(conn); | |
} | |
PQclear(res); | |
if(PQsetnonblocking(conn, 1) == -1) { | |
fprintf(stderr, "PQsetnonblocking failed: %s", PQerrorMessage(conn)); | |
PQclear(res); | |
exit_nicely(conn); | |
} | |
PQsendQuery(conn, "COPY mycopy (data) FROM STDIN"); | |
/* wait_socket is called for completeness only. | |
* Otherwise PQgetResult() just blocks even in nonblocking mode. */ | |
wait_socket(conn); | |
res = PQgetResult(conn); | |
if (PQresultStatus(res) != PGRES_COPY_IN) { | |
fprintf(stderr, "COPY command failed: %s", PQerrorMessage(conn)); | |
PQclear(res); | |
exit_nicely(conn); | |
} | |
PQclear(res); | |
char *text1 = malloc(27000); | |
char *text2 = malloc(180); | |
for(int i = 0; i < 100000; i++) { | |
if( PQputCopyData(conn, text1, 27000) != 1) { | |
fprintf(stderr, "PQputCopyData text1 command failed: %s", PQerrorMessage(conn)); | |
exit_nicely(conn); | |
} | |
if( PQputCopyData(conn, text2, 180) != 1) { | |
fprintf(stderr, "PQputCopyData text2 command failed: %s", PQerrorMessage(conn)); | |
exit_nicely(conn); | |
} | |
} | |
fprintf(stderr, "Done.\n"); | |
/* close the connection to the database and cleanup */ | |
PQfinish(conn); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment