Hi,

2011-11-17 14:53 keltezéssel, Michael Meskes írta:
> On Mon, Nov 14, 2011 at 09:06:30AM +0100, Boszormenyi Zoltan wrote:
>> Yes, you are right. For timestamp and interval, the safe alignment is int64.
>> Patch is attached.
> Applied, thanks.
>
> Michael

thanks.

Hopefully last turn in this topic. For NUMERIC types, the safe minimum
alignment is a pointer because there are 5 int members followed by
two pointer members in this struct. I got a crash from this with a lucky
query and dataset. The DECIMAL struct is safe because the digits[] array
is embedded there.

After fixing this, I got another one at an innocent looking memcpy():

    memcpy((char *) sqlda + offset, num->buf, num->ndigits + 1);

It turned out that when the server sends "0.00", PGTYPESnumeric_from_asc()
constructs a numeric structure with:
    ndigits == 0
    buf == NULL
    digits == NULL.
This makes memcpy() crash and burn. Let's also fix this case.

Best regards,
Zoltán Böszörményi

-- 
----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
Gröhrmühlgasse 26
A-2700 Wiener Neustadt, Austria
Web: http://www.postgresql-support.de
     http://www.postgresql.at/

--- postgresql-9.1.1/src/interfaces/ecpg/ecpglib/sqlda.c.orig   2011-11-19 
21:13:25.699169076 +0100
+++ postgresql-9.1.1/src/interfaces/ecpg/ecpglib/sqlda.c        2011-11-19 
22:50:13.895653223 +0100
@@ -110,7 +110,7 @@
                                 * int Unfortunately we need to do double work 
here to compute
                                 * the size of the space needed for the numeric 
structure.
                                 */
-                               ecpg_sqlda_align_add_size(offset, sizeof(int), 
sizeof(numeric), &offset, &next_offset);
+                               ecpg_sqlda_align_add_size(offset, 
sizeof(NumericDigit *), sizeof(numeric), &offset, &next_offset);
                                if (!PQgetisnull(res, row, i))
                                {
                                        char       *val = PQgetvalue(res, row, 
i);
@@ -119,7 +119,8 @@
                                        num = PGTYPESnumeric_from_asc(val, 
NULL);
                                        if (!num)
                                                break;
-                                       ecpg_sqlda_align_add_size(next_offset, 
sizeof(int), num->ndigits + 1, &offset, &next_offset);
+                                       if (num->ndigits)
+                                               
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->ndigits + 1, &offset, 
&next_offset);
                                        PGTYPESnumeric_free(num);
                                }
                                break;
@@ -323,7 +324,7 @@
 
                                        set_data = false;
 
-                                       ecpg_sqlda_align_add_size(offset, 
sizeof(int), sizeof(numeric), &offset, &next_offset);
+                                       ecpg_sqlda_align_add_size(offset, 
sizeof(NumericDigit *), sizeof(numeric), &offset, &next_offset);
                                        sqlda->sqlvar[i].sqldata = (char *) 
sqlda + offset;
                                        sqlda->sqlvar[i].sqllen = 
sizeof(numeric);
 
@@ -343,11 +344,14 @@
 
                                        memcpy(sqlda->sqlvar[i].sqldata, num, 
sizeof(numeric));
 
-                                       ecpg_sqlda_align_add_size(next_offset, 
sizeof(int), num->ndigits + 1, &offset, &next_offset);
-                                       memcpy((char *) sqlda + offset, 
num->buf, num->ndigits + 1);
+                                       if (num->ndigits)
+                                       {
+                                               
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->ndigits + 1, &offset, 
&next_offset);
+                                               memcpy((char *) sqlda + offset, 
num->buf, num->ndigits + 1);
 
-                                       ((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);
 
@@ -509,7 +513,7 @@
 
                                        set_data = false;
 
-                                       ecpg_sqlda_align_add_size(offset, 
sizeof(int), sizeof(numeric), &offset, &next_offset);
+                                       ecpg_sqlda_align_add_size(offset, 
sizeof(NumericDigit *), sizeof(numeric), &offset, &next_offset);
                                        sqlda->sqlvar[i].sqldata = (char *) 
sqlda + offset;
                                        sqlda->sqlvar[i].sqllen = 
sizeof(numeric);
 
@@ -529,11 +533,14 @@
 
                                        memcpy(sqlda->sqlvar[i].sqldata, num, 
sizeof(numeric));
 
-                                       ecpg_sqlda_align_add_size(next_offset, 
sizeof(int), num->ndigits + 1, &offset, &next_offset);
-                                       memcpy((char *) sqlda + offset, 
num->buf, num->ndigits + 1);
+                                       if (num->ndigits)
+                                       {
+                                               
ecpg_sqlda_align_add_size(next_offset, sizeof(int), num->ndigits + 1, &offset, 
&next_offset);
+                                               memcpy((char *) sqlda + offset, 
num->buf, num->ndigits + 1);
 
-                                       ((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);
 
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to