summaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/ecpglib/data.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2023-04-18 11:20:51 +0900
committerMichael Paquier <michael@paquier.xyz>2023-04-18 11:20:51 +0900
commite9e457d22d264308bd709ac034b23a6c5716432a (patch)
treed9eb45bf546908b2bdeda7f06f0c03615c7b2bd0 /src/interfaces/ecpg/ecpglib/data.c
parent86874a6dfc8b1878bede18437b1709fbe485a911 (diff)
ecpg: Fix handling of strings in ORACLE compat code with SQLDA
When compiled with -C ORACLE, ecpg_get_data() had a one-off issue where it would incorrectly store the null terminator byte to str[-1] when varcharsize is 0, which is something that can happen when using SQLDA. This would eat 1 byte from the previous field stored, corrupting the results generated. All the callers of ecpg_get_data() estimate and allocate enough storage for the data received, and the fix of this commit relies on this assumption. Note that this maps to the case where no padding or truncation is required. This issue has been introduced by 3b7ab43 with the Oracle compatibility option, so backpatch down to v11. Author: Kyotaro Horiguchi Discussion: https://postgr.es/m/20230410.173500.440060475837236886.horikyota.ntt@gmail.com Backpatch-through: 11
Diffstat (limited to 'src/interfaces/ecpg/ecpglib/data.c')
-rw-r--r--src/interfaces/ecpg/ecpglib/data.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/src/interfaces/ecpg/ecpglib/data.c b/src/interfaces/ecpg/ecpglib/data.c
index 6bc91ef7eb6..c94907bcc5f 100644
--- a/src/interfaces/ecpg/ecpglib/data.c
+++ b/src/interfaces/ecpg/ecpglib/data.c
@@ -582,7 +582,7 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
if (varcharsize == 0 && offset == sizeof(char *))
str = *(char **) str;
- if (varcharsize == 0 || varcharsize > size)
+ if (varcharsize > size)
{
/*
* compatibility mode, blank pad and null
@@ -642,16 +642,25 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
}
else
{
- strncpy(str, pval, varcharsize);
+ int charsize = varcharsize;
+
+ /*
+ * assume that the caller provided storage exactly
+ * fit when varcharsize is zero.
+ */
+ if (varcharsize == 0)
+ charsize = size + 1;
+
+ strncpy(str, pval, charsize);
/* compatibility mode, null terminate char array */
- if (ORACLE_MODE(compat) && (varcharsize - 1) < size)
+ if (ORACLE_MODE(compat) && (charsize - 1) < size)
{
if (type == ECPGt_char || type == ECPGt_unsigned_char)
- str[varcharsize - 1] = '\0';
+ str[charsize - 1] = '\0';
}
- if (varcharsize < size || (ORACLE_MODE(compat) && (varcharsize - 1) < size))
+ if (charsize < size || (ORACLE_MODE(compat) && (charsize - 1) < size))
{
/* truncation */
switch (ind_type)