From 2e8ed46599720113ce024f098e12652a1dfffe8e Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 14 Nov 2018 11:27:30 -0500 Subject: Second try at fixing numeric data passed through an ECPG SQLDA. In commit ecfd55795, I removed sqlda.c's checks for ndigits != 0 on the grounds that we should duplicate the state of the numeric value's digit buffer even when all the digits are zeroes. However, that still isn't quite right, because another possible state of the digit buffer is buf == digits == NULL (this occurs for a NaN). As the code now stands, it'll invoke memcpy with a NULL source address and zero bytecount, which we know a few platforms crash on. Hence, reinstate the no-copy short-circuit, but make it test specifically for buf != NULL rather than some other condition. In hindsight, the ndigits test (added by commit f2ae9f9c3) was almost certainly meant to fix the NaN case not the all-zeroes case as the associated thread alleged. As before, back-patch to all supported versions. Discussion: https://postgr.es/m/1803D792815FC24D871C00D17AE95905C71161@g01jpexmbkw24 --- src/interfaces/ecpg/ecpglib/sqlda.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'src/interfaces/ecpg/ecpglib/sqlda.c') diff --git a/src/interfaces/ecpg/ecpglib/sqlda.c b/src/interfaces/ecpg/ecpglib/sqlda.c index acca50f32b8..bb1f31d0b21 100644 --- a/src/interfaces/ecpg/ecpglib/sqlda.c +++ b/src/interfaces/ecpg/ecpglib/sqlda.c @@ -122,7 +122,8 @@ sqlda_common_total_size(const PGresult *res, int row, enum COMPAT_MODE compat, l num = PGTYPESnumeric_from_asc(val, NULL); if (!num) break; - ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset); + if (num->buf) + ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset); PGTYPESnumeric_free(num); } break; @@ -346,11 +347,14 @@ ecpg_set_compat_sqlda(int lineno, struct sqlda_compat **_sqlda, const PGresult * memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric)); - ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset); - memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits); + if (num->buf) + { + ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset); + memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits); - ((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset; - ((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf); + ((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset; + ((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf); + } PGTYPESnumeric_free(num); @@ -532,11 +536,14 @@ ecpg_set_native_sqlda(int lineno, struct sqlda_struct **_sqlda, const PGresult * memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric)); - ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset); - memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits); + if (num->buf) + { + ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset); + memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits); - ((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset; - ((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf); + ((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset; + ((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf); + } PGTYPESnumeric_free(num); -- cgit v1.2.3