mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
ecpg: Fix out-of-bound writes due to processing of invalid bytea data
ECPG assumes that any bytea data it receives from a backend starts with '\x' as its first two bytes, but a check was missed to enforce that. A rogue server sending some garbage bytea data would be able to crash a client, resulting in a client-side DoS, in the most common cases. Reported-by: ylwangtju <ylwangtju@qq.com> Backpatch-through: 14 Security: CVE-2026-16241
This commit is contained in:
committed by
Noah Misch
parent
aff9dac1c1
commit
74c59d062a
@@ -529,6 +529,13 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
|
||||
src_size,
|
||||
dec_size;
|
||||
|
||||
if (size < 2 || pval[0] != '\\' || pval[1] != 'x')
|
||||
{
|
||||
ecpg_raise(lineno, ECPG_BYTEA_FORMAT,
|
||||
ECPG_SQLSTATE_DATATYPE_MISMATCH, pval);
|
||||
return false;
|
||||
}
|
||||
|
||||
dst_size = ecpg_hex_enc_len(varcharsize);
|
||||
src_size = size - 2; /* exclude backslash + 'x' */
|
||||
dec_size = src_size < dst_size ? src_size : dst_size;
|
||||
|
||||
@@ -130,6 +130,13 @@ ecpg_raise(int line, int code, const char *sqlstate, const char *str)
|
||||
ecpg_gettext("inserting an array of variables is not supported on line %d"), line);
|
||||
break;
|
||||
|
||||
case ECPG_BYTEA_FORMAT:
|
||||
snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
|
||||
/*------
|
||||
translator: this string will be truncated at 149 characters expanded. */
|
||||
ecpg_gettext("invalid input syntax for type bytea: \"%s\", on line %d"), str, line);
|
||||
break;
|
||||
|
||||
case ECPG_NO_CONN:
|
||||
snprintf(sqlca->sqlerrm.sqlerrmc, sizeof(sqlca->sqlerrm.sqlerrmc),
|
||||
/*------
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define ECPG_NO_ARRAY -214
|
||||
#define ECPG_DATA_NOT_ARRAY -215
|
||||
#define ECPG_ARRAY_INSERT -216
|
||||
#define ECPG_BYTEA_FORMAT -217
|
||||
|
||||
#define ECPG_NO_CONN -220
|
||||
#define ECPG_NOT_CONN -221
|
||||
|
||||
@@ -356,17 +356,36 @@ if (sqlca.sqlcode < 0) sqlprint();}
|
||||
if (sqlca.sqlcode < 0) sqlprint();}
|
||||
#line 115 "bytea.pgc"
|
||||
|
||||
{ ECPGtrans(__LINE__, NULL, "commit");
|
||||
#line 116 "bytea.pgc"
|
||||
|
||||
/* Test for invalid bytea format */
|
||||
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select '' :: text", ECPGt_EOIT,
|
||||
ECPGt_bytea,&(recv_buf[0]),(long)DATA_SIZE,(long)1,sizeof(struct bytea_2),
|
||||
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
|
||||
#line 118 "bytea.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint();}
|
||||
#line 116 "bytea.pgc"
|
||||
#line 118 "bytea.pgc"
|
||||
|
||||
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select '\\\\a1234' :: text", ECPGt_EOIT,
|
||||
ECPGt_bytea,&(recv_buf[0]),(long)DATA_SIZE,(long)1,sizeof(struct bytea_2),
|
||||
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
|
||||
#line 119 "bytea.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint();}
|
||||
#line 119 "bytea.pgc"
|
||||
|
||||
|
||||
{ ECPGtrans(__LINE__, NULL, "commit");
|
||||
#line 121 "bytea.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint();}
|
||||
#line 121 "bytea.pgc"
|
||||
|
||||
{ ECPGdisconnect(__LINE__, "CURRENT");
|
||||
#line 117 "bytea.pgc"
|
||||
#line 122 "bytea.pgc"
|
||||
|
||||
if (sqlca.sqlcode < 0) sqlprint();}
|
||||
#line 117 "bytea.pgc"
|
||||
#line 122 "bytea.pgc"
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -181,7 +181,29 @@ SQL error: invalid statement name "cursor1" on line 82
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_process_output on line 115: OK: DROP TABLE
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ECPGtrans on line 116: action "commit"; connection "ecpg1_regression"
|
||||
[NO_PID]: ecpg_execute on line 118: query: select '' :: text; with 0 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 118: using PQexec
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_process_output on line 118: correctly got 1 tuples with 1 fields
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_get_data on line 118: RESULT: offset: -1; array: no
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: raising sqlcode -217 on line 118: invalid input syntax for type bytea: "", on line 118
|
||||
[NO_PID]: sqlca: code: -217, state: 42804
|
||||
SQL error: invalid input syntax for type bytea: "", on line 118
|
||||
[NO_PID]: ecpg_execute on line 119: query: select '\\a1234' :: text; with 0 parameter(s) on connection ecpg1_regression
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_execute on line 119: using PQexec
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_process_output on line 119: correctly got 1 tuples with 1 fields
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: ecpg_get_data on line 119: RESULT: \\a1234 offset: -1; array: no
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: raising sqlcode -217 on line 119: invalid input syntax for type bytea: "\\a1234", on line 119
|
||||
[NO_PID]: sqlca: code: -217, state: 42804
|
||||
SQL error: invalid input syntax for type bytea: "\\a1234", on line 119
|
||||
[NO_PID]: ECPGtrans on line 121: action "commit"; connection "ecpg1_regression"
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
[NO_PID]: deallocate_one on line 0: name sel_stmt
|
||||
[NO_PID]: sqlca: code: 0, state: 00000
|
||||
|
||||
@@ -113,6 +113,11 @@ while (0)
|
||||
dump_binary(recv_short_buf.arr, recv_short_buf.len, ind[1]);
|
||||
|
||||
exec sql drop table test;
|
||||
|
||||
/* Test for invalid bytea format */
|
||||
exec sql select ''::text into :recv_buf[0];
|
||||
exec sql select '\\a1234'::text into :recv_buf[0];
|
||||
|
||||
exec sql commit;
|
||||
exec sql disconnect;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user