public inbox for [email protected]
help / color / mirror / Atom feedFrom: Shruthi Gowda <[email protected]>
To: Nishant Sharma <[email protected]>
Cc: Mahendra Singh Thalor <[email protected]>
Cc: Fujii Masao <[email protected]>
Cc: Tom Lane <[email protected]>
Cc: PostgreSQL Development <[email protected]>
Subject: Re: [BUG] CRASH: ECPGprepared_statement() and ECPGdeallocate_all() when connection is NULL
Date: Wed, 15 Apr 2026 15:26:27 +0530
Message-ID: <CAASxf_PtXCsmu5oCvZH4BmLdojG+0XJUH8foHFZv+2vmsSbNwA@mail.gmail.com> (raw)
In-Reply-To: <CADrsxdbPw1ZYcuqH1-DTNhAvRN=tRTTY+_dFy8wU2g4DQb67Bg@mail.gmail.com>
References: <CAASxf_P1F75Ck+0qyb10auT+BORupOM4yigXBnm7aWRNx1LYcA@mail.gmail.com>
<[email protected]>
<CAASxf_P5f=Frf8S7rN9BzphtCLoeN9vFuh-V7ukotOQZU54g+w@mail.gmail.com>
<CAHGQGwHAPXexiGaHMkDDRF7cPBr_3fgCNdT4n2+1UjaEU++BAQ@mail.gmail.com>
<CAASxf_OGWD7PA5TMEh2MdF2YxN8V3ByLhnFJ=uw0hKr33sgqAw@mail.gmail.com>
<CAKYtNAqjJbzV+ZJDqA-s0fHSLen6msc=A0SfrTS1ub1KKH9haQ@mail.gmail.com>
<CADrsxdbb2fn1LACQShrQT0bNqSCQ3hSzEojb2tODhD0PmewDiA@mail.gmail.com>
<CAASxf_OdsJRi17EZ_ZMyQgOwUzn357YyMqJ2Z2qiExPaLRW_Lg@mail.gmail.com>
<CADrsxdbPw1ZYcuqH1-DTNhAvRN=tRTTY+_dFy8wU2g4DQb67Bg@mail.gmail.com>
On Mon, Apr 13, 2026 at 4:00 PM Nishant Sharma <
[email protected]> wrote:
> Thanks Shruthi, for the new patches!
>
>
> Here are some review comments:-
> 1. I think we should rename "test_null_connection.pgc" to "test6.pgc", and
> make other required changes appropriately. We can see existing test files
> uses test1.pgc, test2.pgc ..., test5.pgc as naming convention, and has test
> description inside the file.
> 2. No need to add test_null_connection.c as commit file in
> src/interfaces/ecpg/test/connect/ folder, we don't see such C src files for
> other existing test files like test1.c, test2.c ..., test5.c. It is part of
> src/interfaces/ecpg/test/connect/.gitignore. So, need to add test6.c and
> its executable test6 like others in
> src/interfaces/ecpg/test/connect/.gitignore
> 3. After doing #2 above make sure to create the test9.c C src file as
> src/interfaces/ecpg/test/expected/connect-test6.c, I can see other existing
> connect tests C src files in src/interfaces/ecpg/test/expected/ folder.
> 3. Not able to run "make -j 8 installcheck" on my setup, fails due to #3.
> 4. Extra space at the end (don't see that in other tested cases prints) :
> printf("Test 1: Try to get descriptor on a disconnected connection \n");
> 5. char *query = "SELECT 1" -- unused in new test file added.
> 6. "if (stmt.connection == NULL)" --> "if (!stmt.connection)"?
> 7. Should we return -1 in else of new fix added in
> ecpg_freeStmtCacheEntry()? If 'con' is NULL, why clean up the cache? Is
> returning -1 more defensive than cleaning the cache?
> 8. Do we need to clean up "stmt.oldlocale = ecpg_strdup(...)" and undo
> setlocale() before returning from the newly added fix in ECPGget_desc()?
>
>
> Regards,
> Nishant Sharma,
> EDB, Pune.
> https://www.enterprisedb.com/
>
> On Thu, Apr 9, 2026 at 4:14 PM Shruthi Gowda <[email protected]> wrote:
>
>>
>>
>> On Tue, Mar 24, 2026 at 11:29 AM Nishant Sharma <
>> [email protected]> wrote:
>>
>>> Here are some review comments on v3 patch:-
>>>
>>> 1.
>>>
>>> Change in descriptor.c file - In my opinion, we can use `if(conn)`
>>> with ecpg_raise, like other occurrence of ecpg_get_connection() call check
>>> in this file, and not using ecpg_init(). Three reasons: a) Consistency in
>>> checking conn after ecpg_get_connection() call in this file with if check.
>>> b) We don't need to remove 'ecpg_init_sqlca(sqlca);' line due to call to
>>> ecpg_init(). c) #2 comment below.
>>> 2.
>>>
>>> If you agree with #1, then I see many other reasons for which
>>> ECPGget_desc() returns and we can avoid ecpg_get_connection() call at top
>>> of that function for those reasons and keep the check at the required
>>> location only instead of moving at top of the function.
>>> 3.
>>>
>>> I see there is one more location of ecpg_get_connection() call where
>>> there is no check of NULL conn. In function ecpg_freeStmtCacheEntry() of
>>> file prepare.c? I understand it's not required for a call in
>>> ecpg_auto_prepare(), as the caller already validated that connection
>>> string. But I think, conn in ecpg_freeStmtCacheEntry() is different from
>>> the one that was validated.
>>> 4.
>>>
>>> +1 to Mahindra, new test cases specific to the crash required for
>>> this change?
>>>
>>>
>>>
>>> Regards,
>>> Nishant Sharma,
>>> EDB, Pune.
>>> https://www.enterprisedb.com/
>>>
>>
>> Thanks, Nishant, for the review. I agree with points 1 and 2 and have
>> revised the patch accordingly. Regarding point 3, you are correct; the
>> conn in ecpg_freeStmtCacheEntry() differs from the one validated in the
>> caller. I have now added the necessary validation in the latest version.
>>
>> I have also included a test case patch covering all execution paths
>> except for the ecpg_freeStmtCacheEntry() flow. I was unable to trigger
>> that specific flow, and it appears none of the existing test cases cover
>> that line either.
>>
>> Thanks & Regards,
>>
>> Shruthi K C
>>
>> EnterpriseDB: http://www.enterprisedb.com
>>
>
Thanks for the review Nishant. I have updated the test case patch to
address comments 1–5. Regarding points 6–8, please see my detailed
responses below:
6. "if (stmt.connection == NULL)" --> "if (!stmt.connection)"?
--> Both formats are used interchangeably in the ecpg code. I’d prefer
to stick with the explicit null check here
7. Should we return -1 in else of new fix added in
ecpg_freeStmtCacheEntry()? If 'con' is NULL, why clean up the cache? Is
returning -1 more defensive than cleaning the cache?
--> The cache entry cleanup must happen regardless of whether the
connection exists, because:
- The cache slot is being reclaimed for a new statement
- Memory must be freed to avoid leaks
- A disconnected connection means the entry is stale and must be cleaned
The NULL check protects against crashes while still performing necessary
cleanup.
8. Do we need to clean up "stmt.oldlocale = ecpg_strdup(...)" and undo
setlocale() before returning from the newly added fix in ECPGget_desc()?
Great point! To avoid this cleanup complexity, I moved the connection
check before the locale setup so the early return happens before any
resources are allocated.
Thanks & Regards,
Shruthi K C
EnterpriseDB: http://www.enterprisedb.com
Attachments:
[application/octet-stream] v5-0001-Add-missing-connection-validation-in-ECPG.patch (3.5K, 3-v5-0001-Add-missing-connection-validation-in-ECPG.patch)
download | inline diff:
From 858e2bc8ecde70b704173d28993a977410136dab Mon Sep 17 00:00:00 2001
From: shruthi gowda <[email protected]>
Date: Wed, 15 Apr 2026 08:34:18 +0000
Subject: [PATCH v5] Add missing connection validation in ECPG
ECPGdeallocate_all(), ECPGprepared_statement(), ECPGget_desc(), and
ecpg_freeStmtCacheEntry() could crash or misbehave when operating on
NULL or invalid connections. Add proper connection validation to
prevent dereferencing NULL pointers.
---
src/interfaces/ecpg/ecpglib/descriptor.c | 12 ++++++++++--
src/interfaces/ecpg/ecpglib/prepare.c | 25 ++++++++++++++++--------
2 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/src/interfaces/ecpg/ecpglib/descriptor.c b/src/interfaces/ecpg/ecpglib/descriptor.c
index 39cd5130ec9..1ad5f2d88cc 100644
--- a/src/interfaces/ecpg/ecpglib/descriptor.c
+++ b/src/interfaces/ecpg/ecpglib/descriptor.c
@@ -476,6 +476,16 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
memset(&stmt, 0, sizeof stmt);
stmt.lineno = lineno;
+ /* desperate try to guess something sensible */
+ stmt.connection = ecpg_get_connection(NULL);
+ if (stmt.connection == NULL)
+ {
+ ecpg_raise(lineno, ECPG_NO_CONN, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST,
+ ecpg_gettext("NULL"));
+ va_end(args);
+ return false;
+ }
+
/* Make sure we do NOT honor the locale for numeric input */
/* since the database gives the standard decimal point */
/* (see comments in execute.c) */
@@ -505,8 +515,6 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
setlocale(LC_NUMERIC, "C");
#endif
- /* desperate try to guess something sensible */
- stmt.connection = ecpg_get_connection(NULL);
ecpg_store_result(ECPGresult, index, &stmt, &data_var);
#ifdef HAVE_USELOCALE
diff --git a/src/interfaces/ecpg/ecpglib/prepare.c b/src/interfaces/ecpg/ecpglib/prepare.c
index 5c7c5397535..f9489044724 100644
--- a/src/interfaces/ecpg/ecpglib/prepare.c
+++ b/src/interfaces/ecpg/ecpglib/prepare.c
@@ -381,8 +381,12 @@ ecpg_deallocate_all_conn(int lineno, enum COMPAT_MODE c, struct connection *con)
bool
ECPGdeallocate_all(int lineno, int compat, const char *connection_name)
{
- return ecpg_deallocate_all_conn(lineno, compat,
- ecpg_get_connection(connection_name));
+ struct connection *con = ecpg_get_connection(connection_name);
+
+ if (!ecpg_init(con, connection_name, lineno))
+ return false;
+
+ return ecpg_deallocate_all_conn(lineno, compat, con);
}
char *
@@ -395,13 +399,15 @@ ecpg_prepared(const char *name, struct connection *con)
}
/* return the prepared statement */
-/* lineno is not used here, but kept in to not break API */
char *
ECPGprepared_statement(const char *connection_name, const char *name, int lineno)
{
- (void) lineno; /* keep the compiler quiet */
+ struct connection *con = ecpg_get_connection(connection_name);
+
+ if (!ecpg_init(con, connection_name, lineno))
+ return NULL;
- return ecpg_prepared(name, ecpg_get_connection(connection_name));
+ return ecpg_prepared(name, con);
}
/*
@@ -499,9 +505,12 @@ ecpg_freeStmtCacheEntry(int lineno, int compat,
con = ecpg_get_connection(entry->connection);
/* free the 'prepared_statement' list entry */
- this = ecpg_find_prepared_statement(entry->stmtID, con, &prev);
- if (this && !deallocate_one(lineno, compat, con, prev, this))
- return -1;
+ if (con)
+ {
+ this = ecpg_find_prepared_statement(entry->stmtID, con, &prev);
+ if (this && !deallocate_one(lineno, compat, con, prev, this))
+ return -1;
+ }
entry->stmtID[0] = '\0';
--
2.43.0
[application/octet-stream] v2_test-0001-Tests-for-NULL-connection-validation.patch (12.7K, 4-v2_test-0001-Tests-for-NULL-connection-validation.patch)
download | inline diff:
From b6714c710e66d17bed41dfb165b8048d52d3c396 Mon Sep 17 00:00:00 2001
From: shruthi gowda <[email protected]>
Date: Wed, 15 Apr 2026 08:58:09 +0000
Subject: [PATCH v2_test] Tests for NULL connection validation
---
src/interfaces/ecpg/test/connect/.gitignore | 2 +
src/interfaces/ecpg/test/connect/Makefile | 3 +-
src/interfaces/ecpg/test/connect/meson.build | 1 +
src/interfaces/ecpg/test/connect/test6.pgc | 68 ++++++++
src/interfaces/ecpg/test/ecpg_schedule | 1 +
.../ecpg/test/expected/connect-test6.c | 146 ++++++++++++++++++
.../ecpg/test/expected/connect-test6.stderr | 50 ++++++
.../ecpg/test/expected/connect-test6.stdout | 8 +
8 files changed, 278 insertions(+), 1 deletion(-)
create mode 100644 src/interfaces/ecpg/test/connect/test6.pgc
create mode 100644 src/interfaces/ecpg/test/expected/connect-test6.c
create mode 100644 src/interfaces/ecpg/test/expected/connect-test6.stderr
create mode 100644 src/interfaces/ecpg/test/expected/connect-test6.stdout
diff --git a/src/interfaces/ecpg/test/connect/.gitignore b/src/interfaces/ecpg/test/connect/.gitignore
index e0639f3c8d1..02236847444 100644
--- a/src/interfaces/ecpg/test/connect/.gitignore
+++ b/src/interfaces/ecpg/test/connect/.gitignore
@@ -8,3 +8,5 @@
/test4.c
/test5
/test5.c
+/test6
+/test6.c
diff --git a/src/interfaces/ecpg/test/connect/Makefile b/src/interfaces/ecpg/test/connect/Makefile
index 2602d5d286f..17fa2667bf7 100644
--- a/src/interfaces/ecpg/test/connect/Makefile
+++ b/src/interfaces/ecpg/test/connect/Makefile
@@ -7,6 +7,7 @@ TESTS = test1 test1.c \
test2 test2.c \
test3 test3.c \
test4 test4.c \
- test5 test5.c
+ test5 test5.c \
+ test6 test6.c
all: $(TESTS)
diff --git a/src/interfaces/ecpg/test/connect/meson.build b/src/interfaces/ecpg/test/connect/meson.build
index 591e04bc422..1cc0a928309 100644
--- a/src/interfaces/ecpg/test/connect/meson.build
+++ b/src/interfaces/ecpg/test/connect/meson.build
@@ -6,6 +6,7 @@ pgc_files = [
'test3',
'test4',
'test5',
+ 'test6',
]
foreach pgc_file : pgc_files
diff --git a/src/interfaces/ecpg/test/connect/test6.pgc b/src/interfaces/ecpg/test/connect/test6.pgc
new file mode 100644
index 00000000000..da30a37d885
--- /dev/null
+++ b/src/interfaces/ecpg/test/connect/test6.pgc
@@ -0,0 +1,68 @@
+/*
+ * This test verifies that ecpg functions properly handle NULL connections
+ * (i.e., when a connection name doesn't exist or has been disconnected).
+ * Before the fix, these operations would cause a segmentation fault.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+exec sql include ../regression;
+
+int
+main(void)
+{
+exec sql begin declare section;
+ int val1output = 2;
+ int val1 = 1;
+ char val2[5] = "data1";
+ char *stmt1 = "SELECT * from test1 where a = $1 and b = $2";
+exec sql end declare section;
+
+ ECPGdebug(1, stderr);
+
+ /* Connect to the database */
+ exec sql connect to REGRESSDB1 as myconn;
+
+ /* Test 1: Try to get descriptor on a disconnected connection */
+ printf("Test 1: Try to get descriptor on a disconnected connection\n");
+ exec sql create table test1 (a int, b text);
+ exec sql insert into test1 (a,b) values (1, 'data1');
+
+ exec sql allocate descriptor indesc;
+ exec sql allocate descriptor outdesc;
+
+ exec sql prepare foo2 from :stmt1;
+
+ exec sql set descriptor indesc value 1 DATA = :val1;
+ exec sql set descriptor indesc value 2 DATA = :val2;
+
+ exec sql execute foo2 using sql descriptor indesc into sql descriptor outdesc;
+
+ exec sql disconnect;
+ exec sql get descriptor outdesc value 1 :val1output = DATA;
+ printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+ /* Test 2: Try to deallocate all on a non-existent connection */
+ printf("Test 2: deallocate all with non-existent connection\n");
+ exec sql at nonexistent deallocate all;
+ printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+ /* Test 3: deallocate on disconnected connection */
+ printf("Test 3: deallocate all on disconnected connection\n");
+ exec sql deallocate all;
+ printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+ /* Test 4: Use prepared statement from non-existent connection */
+ printf("Test 4: Use prepared statement from non-existent connection\n");
+ exec sql at nonexistent prepare stmt1 FROM "SELECT 1";
+ exec sql at nonexistent declare cur1 cursor for stmt1;
+ exec sql at nonexistent open cur1;
+
+ printf("All tests completed !\n");
+
+ exec sql disconnect;
+
+ return 0;
+}
diff --git a/src/interfaces/ecpg/test/ecpg_schedule b/src/interfaces/ecpg/test/ecpg_schedule
index b75e16fde1e..d1f5d9452b7 100644
--- a/src/interfaces/ecpg/test/ecpg_schedule
+++ b/src/interfaces/ecpg/test/ecpg_schedule
@@ -13,6 +13,7 @@ test: connect/test2
test: connect/test3
test: connect/test4
test: connect/test5
+test: connect/test6
test: pgtypeslib/dt_test
test: pgtypeslib/dt_test2
test: pgtypeslib/num_test
diff --git a/src/interfaces/ecpg/test/expected/connect-test6.c b/src/interfaces/ecpg/test/expected/connect-test6.c
new file mode 100644
index 00000000000..29cf70a2e9b
--- /dev/null
+++ b/src/interfaces/ecpg/test/expected/connect-test6.c
@@ -0,0 +1,146 @@
+/* Processed by ecpg (regression mode) */
+/* These include files are added by the preprocessor */
+#include <ecpglib.h>
+#include <ecpgerrno.h>
+#include <sqlca.h>
+/* End of automatic include section */
+#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
+
+#line 1 "test6.pgc"
+/*
+ * This test verifies that ecpg functions properly handle NULL connections
+ * (i.e., when a connection name doesn't exist or has been disconnected).
+ * Before the fix, these operations would cause a segmentation fault.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+
+#line 1 "regression.h"
+
+
+
+
+
+
+#line 11 "test6.pgc"
+
+
+int
+main(void)
+{
+/* exec sql begin declare section */
+
+
+
+
+
+#line 17 "test6.pgc"
+ int val1output = 2 ;
+
+#line 18 "test6.pgc"
+ int val1 = 1 ;
+
+#line 19 "test6.pgc"
+ char val2 [ 5 ] = "data1" ;
+
+#line 20 "test6.pgc"
+ char * stmt1 = "SELECT * from test1 where a = $1 and b = $2" ;
+/* exec sql end declare section */
+#line 21 "test6.pgc"
+
+
+ ECPGdebug(1, stderr);
+
+ /* Connect to the database */
+ { ECPGconnect(__LINE__, 0, "ecpg1_regression" , NULL, NULL , "myconn", 0); }
+#line 26 "test6.pgc"
+
+
+ /* Test 1: Try to get descriptor on a disconnected connection */
+ printf("Test 1: Try to get descriptor on a disconnected connection\n");
+ { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table test1 ( a int , b text )", ECPGt_EOIT, ECPGt_EORT);}
+#line 30 "test6.pgc"
+
+ { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into test1 ( a , b ) values ( 1 , 'data1' )", ECPGt_EOIT, ECPGt_EORT);}
+#line 31 "test6.pgc"
+
+
+ ECPGallocate_desc(__LINE__, "indesc");
+#line 33 "test6.pgc"
+
+ ECPGallocate_desc(__LINE__, "outdesc");
+#line 34 "test6.pgc"
+
+
+ { ECPGprepare(__LINE__, NULL, 0, "foo2", stmt1);}
+#line 36 "test6.pgc"
+
+
+ { ECPGset_desc(__LINE__, "indesc", 1,ECPGd_data,
+ ECPGt_int,&(val1),(long)1,(long)1,sizeof(int), ECPGd_EODT);
+}
+#line 38 "test6.pgc"
+
+ { ECPGset_desc(__LINE__, "indesc", 2,ECPGd_data,
+ ECPGt_char,(val2),(long)5,(long)1,(5)*sizeof(char), ECPGd_EODT);
+}
+#line 39 "test6.pgc"
+
+
+ { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_execute, "foo2",
+ ECPGt_descriptor, "indesc", 1L, 1L, 1L,
+ ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+ ECPGt_descriptor, "outdesc", 1L, 1L, 1L,
+ ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
+#line 41 "test6.pgc"
+
+
+ { ECPGdisconnect(__LINE__, "CURRENT");}
+#line 43 "test6.pgc"
+
+ { ECPGget_desc(__LINE__, "outdesc", 1,ECPGd_data,
+ ECPGt_int,&(val1output),(long)1,(long)1,sizeof(int), ECPGd_EODT);
+}
+#line 44 "test6.pgc"
+
+ printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+ /* Test 2: Try to deallocate all on a non-existent connection */
+ printf("Test 2: deallocate all with non-existent connection\n");
+ { ECPGdeallocate_all(__LINE__, 0, "nonexistent");}
+#line 49 "test6.pgc"
+
+ printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+ /* Test 3: deallocate on disconnected connection */
+ printf("Test 3: deallocate all on disconnected connection\n");
+ { ECPGdeallocate_all(__LINE__, 0, NULL);}
+#line 54 "test6.pgc"
+
+ printf("sqlca.sqlcode = %ld\n", sqlca.sqlcode);
+
+ /* Test 4: Use prepared statement from non-existent connection */
+ printf("Test 4: Use prepared statement from non-existent connection\n");
+ { ECPGprepare(__LINE__, "nonexistent", 0, "stmt1", "SELECT 1");}
+#line 59 "test6.pgc"
+
+ /* declare cur1 cursor for $1 */
+#line 60 "test6.pgc"
+
+ { ECPGdo(__LINE__, 0, 1, "nonexistent", 0, ECPGst_normal, "declare cur1 cursor for $1",
+ ECPGt_char_variable,(ECPGprepared_statement("nonexistent", "stmt1", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
+ ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
+#line 61 "test6.pgc"
+
+
+ printf("All tests completed !\n");
+
+ { ECPGdisconnect(__LINE__, "CURRENT");}
+#line 65 "test6.pgc"
+
+
+ return 0;
+}
diff --git a/src/interfaces/ecpg/test/expected/connect-test6.stderr b/src/interfaces/ecpg/test/expected/connect-test6.stderr
new file mode 100644
index 00000000000..fba91a8f257
--- /dev/null
+++ b/src/interfaces/ecpg/test/expected/connect-test6.stderr
@@ -0,0 +1,50 @@
+[NO_PID]: ECPGdebug: set to 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ECPGconnect: opening database ecpg1_regression on <DEFAULT> port <DEFAULT>
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 30: query: create table test1 ( a int , b text ); with 0 parameter(s) on connection myconn
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 30: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 30: OK: CREATE TABLE
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: query: insert into test1 ( a , b ) values ( 1 , 'data1' ); with 0 parameter(s) on connection myconn
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 31: using PQexec
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 31: OK: INSERT 0 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: prepare_common on line 36: name foo2; query: "SELECT * from test1 where a = $1 and b = $2"
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 41: query: SELECT * from test1 where a = $1 and b = $2; with 2 parameter(s) on connection myconn
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_execute on line 41: using PQexecPrepared for "SELECT * from test1 where a = $1 and b = $2"
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_free_params on line 41: parameter 1 = 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_free_params on line 41: parameter 2 = data1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 41: correctly got 1 tuples with 2 fields
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_process_output on line 41: putting result (1 tuples) into descriptor outdesc
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: deallocate_one on line 0: name foo2
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ecpg_finish: connection myconn closed
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: ECPGget_desc: reading items for tuple 1
+[NO_PID]: sqlca: code: 0, state: 00000
+[NO_PID]: raising sqlcode -220 on line 44: connection "NULL" does not exist on line 44
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 49: connection "nonexistent" does not exist on line 49
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 54: connection "NULL" does not exist on line 54
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 59: connection "nonexistent" does not exist on line 59
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 62: connection "nonexistent" does not exist on line 62
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 61: connection "nonexistent" does not exist on line 61
+[NO_PID]: sqlca: code: -220, state: 08003
+[NO_PID]: raising sqlcode -220 on line 65: connection "CURRENT" does not exist on line 65
+[NO_PID]: sqlca: code: -220, state: 08003
diff --git a/src/interfaces/ecpg/test/expected/connect-test6.stdout b/src/interfaces/ecpg/test/expected/connect-test6.stdout
new file mode 100644
index 00000000000..c83136c77e0
--- /dev/null
+++ b/src/interfaces/ecpg/test/expected/connect-test6.stdout
@@ -0,0 +1,8 @@
+Test 1: Try to get descriptor on a disconnected connection
+sqlca.sqlcode = -220
+Test 2: deallocate all with non-existent connection
+sqlca.sqlcode = -220
+Test 3: deallocate all on disconnected connection
+sqlca.sqlcode = -220
+Test 4: Use prepared statement from non-existent connection
+All tests completed !
--
2.43.0
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected], [email protected]
Subject: Re: [BUG] CRASH: ECPGprepared_statement() and ECPGdeallocate_all() when connection is NULL
In-Reply-To: <CAASxf_PtXCsmu5oCvZH4BmLdojG+0XJUH8foHFZv+2vmsSbNwA@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox