Skip to content

Commit f9e25ba

Browse files
committed
Second try at fixing numeric data passed through an ECPG SQLDA.
In commit ecfd557, 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 f2ae9f9) 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
1 parent 0d472b1 commit f9e25ba

File tree

5 files changed

+23
-16
lines changed

5 files changed

+23
-16
lines changed

src/interfaces/ecpg/ecpglib/sqlda.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ sqlda_common_total_size(const PGresult *res, int row, enum COMPAT_MODE compat, l
122122
num = PGTYPESnumeric_from_asc(val, NULL);
123123
if (!num)
124124
break;
125-
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
125+
if (num->buf)
126+
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
126127
PGTYPESnumeric_free(num);
127128
}
128129
break;
@@ -346,11 +347,14 @@ ecpg_set_compat_sqlda(int lineno, struct sqlda_compat ** _sqlda, const PGresult
346347

347348
memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
348349

349-
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
350-
memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
350+
if (num->buf)
351+
{
352+
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
353+
memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
351354

352-
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
353-
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
355+
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
356+
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
357+
}
354358

355359
PGTYPESnumeric_free(num);
356360

@@ -532,11 +536,14 @@ ecpg_set_native_sqlda(int lineno, struct sqlda_struct ** _sqlda, const PGresult
532536

533537
memcpy(sqlda->sqlvar[i].sqldata, num, sizeof(numeric));
534538

535-
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
536-
memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
539+
if (num->buf)
540+
{
541+
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->digits - num->buf + num->ndigits, &offset, &next_offset);
542+
memcpy((char *) sqlda + offset, num->buf, num->digits - num->buf + num->ndigits);
537543

538-
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
539-
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
544+
((numeric *) sqlda->sqlvar[i].sqldata)->buf = (NumericDigit *) sqlda + offset;
545+
((numeric *) sqlda->sqlvar[i].sqldata)->digits = (NumericDigit *) sqlda + offset + (num->digits - num->buf);
546+
}
540547

541548
PGTYPESnumeric_free(num);
542549

src/interfaces/ecpg/test/expected/sql-sqlda.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ if (sqlca.sqlcode < 0) exit (1);}
228228

229229

230230
strcpy(msg, "insert");
231-
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into t1 values ( 1 , 'a' , 1.0 , 1 , 'a' , 1111111111111111111 ) , ( 2 , null , null , null , null , null ) , ( 3 , 'c' , 0.0 , 3 , 'c' , 3333333333333333333 ) , ( 4 , 'd' , 4.0 , 4 , 'd' , 4444444444444444444 ) , ( 5 , 'e' , 0.001234 , 5 , 'e' , 5555555555555555555 )", ECPGt_EOIT, ECPGt_EORT);
231+
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into t1 values ( 1 , 'a' , 1.0 , 1 , 'a' , 1111111111111111111 ) , ( 2 , null , null , null , null , null ) , ( 3 , 'c' , 0.0 , 3 , 'c' , 3333333333333333333 ) , ( 4 , 'd' , 'NaN' , 4 , 'd' , 4444444444444444444 ) , ( 5 , 'e' , 0.001234 , 5 , 'e' , 5555555555555555555 )", ECPGt_EOIT, ECPGt_EORT);
232232
#line 99 "sqlda.pgc"
233233

234234
if (sqlca.sqlcode < 0) exit (1);}

src/interfaces/ecpg/test/expected/sql-sqlda.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
[NO_PID]: sqlca: code: 0, state: 00000
1515
[NO_PID]: ecpg_process_output on line 84: OK: CREATE TABLE
1616
[NO_PID]: sqlca: code: 0, state: 00000
17-
[NO_PID]: ecpg_execute on line 94: query: insert into t1 values ( 1 , 'a' , 1.0 , 1 , 'a' , 1111111111111111111 ) , ( 2 , null , null , null , null , null ) , ( 3 , 'c' , 0.0 , 3 , 'c' , 3333333333333333333 ) , ( 4 , 'd' , 4.0 , 4 , 'd' , 4444444444444444444 ) , ( 5 , 'e' , 0.001234 , 5 , 'e' , 5555555555555555555 ); with 0 parameter(s) on connection regress1
17+
[NO_PID]: ecpg_execute on line 94: query: insert into t1 values ( 1 , 'a' , 1.0 , 1 , 'a' , 1111111111111111111 ) , ( 2 , null , null , null , null , null ) , ( 3 , 'c' , 0.0 , 3 , 'c' , 3333333333333333333 ) , ( 4 , 'd' , 'NaN' , 4 , 'd' , 4444444444444444444 ) , ( 5 , 'e' , 0.001234 , 5 , 'e' , 5555555555555555555 ); with 0 parameter(s) on connection regress1
1818
[NO_PID]: sqlca: code: 0, state: 00000
1919
[NO_PID]: ecpg_execute on line 94: using PQexec
2020
[NO_PID]: sqlca: code: 0, state: 00000

src/interfaces/ecpg/test/expected/sql-sqlda.stdout

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ name sqlda descriptor: 'big' value 3333333333333333333
2222
FETCH RECORD 4
2323
name sqlda descriptor: 'id' value 4
2424
name sqlda descriptor: 't' value 'd'
25-
name sqlda descriptor: 'd1' value NUMERIC '4.0'
25+
name sqlda descriptor: 'd1' value NUMERIC 'NaN'
2626
name sqlda descriptor: 'd2' value 4.000000
2727
name sqlda descriptor: 'c' value 'd '
2828
name sqlda descriptor: 'big' value 4444444444444444444
@@ -57,7 +57,7 @@ name sqlda descriptor: 'big' value 3333333333333333333
5757
FETCH RECORD 4
5858
name sqlda descriptor: 'id' value 4
5959
name sqlda descriptor: 't' value 'd'
60-
name sqlda descriptor: 'd1' value NUMERIC '4.0'
60+
name sqlda descriptor: 'd1' value NUMERIC 'NaN'
6161
name sqlda descriptor: 'd2' value 4.000000
6262
name sqlda descriptor: 'c' value 'd '
6363
name sqlda descriptor: 'big' value 4444444444444444444
@@ -71,14 +71,14 @@ name sqlda descriptor: 'big' value 5555555555555555555
7171
EXECUTE RECORD 4
7272
name sqlda descriptor: 'id' value 4
7373
name sqlda descriptor: 't' value 'd'
74-
name sqlda descriptor: 'd1' value NUMERIC '4.0'
74+
name sqlda descriptor: 'd1' value NUMERIC 'NaN'
7575
name sqlda descriptor: 'd2' value 4.000000
7676
name sqlda descriptor: 'c' value 'd '
7777
name sqlda descriptor: 'big' value 4444444444444444444
7878
EXECUTE RECORD 4
7979
name sqlda descriptor: 'id' value 4
8080
name sqlda descriptor: 't' value 'd'
81-
name sqlda descriptor: 'd1' value NUMERIC '4.0'
81+
name sqlda descriptor: 'd1' value NUMERIC 'NaN'
8282
name sqlda descriptor: 'd2' value 4.000000
8383
name sqlda descriptor: 'c' value 'd '
8484
name sqlda descriptor: 'big' value 4444444444444444444

src/interfaces/ecpg/test/sql/sqlda.pgc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ exec sql end declare section;
9595
(1, 'a', 1.0, 1, 'a',1111111111111111111),
9696
(2, null, null, null, null,null),
9797
(3, 'c', 0.0, 3, 'c',3333333333333333333),
98-
(4, 'd', 4.0, 4, 'd',4444444444444444444),
98+
(4, 'd', 'NaN', 4, 'd',4444444444444444444),
9999
(5, 'e', 0.001234, 5, 'e',5555555555555555555);
100100

101101
strcpy(msg, "commit");

0 commit comments

Comments
 (0)