This patch adds some missing error handling to PGTYPESnumeric_div() in
ecpg's pgtypeslib: (1) we need to check the return value of sub_abs()
(2) we need to check the return value of 4 calls to digitbuf_alloc().
Per Coverity static analysis by EDB.
Barring any objections I'll apply this to CVS later today.
-Neil
Index: src/interfaces/ecpg/pgtypeslib/numeric.c
===================================================================
RCS file: /var/lib/cvs/pgsql/src/interfaces/ecpg/pgtypeslib/numeric.c,v
retrieving revision 1.21
diff -c -r1.21 numeric.c
*** src/interfaces/ecpg/pgtypeslib/numeric.c 24 May 2005 02:09:45 -0000 1.21
--- src/interfaces/ecpg/pgtypeslib/numeric.c 1 Jul 2005 01:47:51 -0000
***************
*** 1096,1101 ****
--- 1096,1103 ----
int stat = 0;
int rscale;
int res_dscale = select_div_scale(var1, var2, &rscale);
+ int err = -1;
+ NumericDigit *tmp_buf;
/*
* First of all division by zero check
***************
*** 1143,1148 ****
--- 1145,1152 ----
divisor[1].rscale = var2->ndigits;
divisor[1].sign = NUMERIC_POS;
divisor[1].buf = digitbuf_alloc(ndigits_tmp);
+ if (divisor[1].buf == NULL)
+ goto done;
divisor[1].digits = divisor[1].buf;
divisor[1].digits[0] = 0;
memcpy(&(divisor[1].digits[1]), var2->digits, ndigits_tmp - 1);
***************
*** 1155,1168 ****
dividend.rscale = var1->ndigits;
dividend.sign = NUMERIC_POS;
dividend.buf = digitbuf_alloc(var1->ndigits);
dividend.digits = dividend.buf;
memcpy(dividend.digits, var1->digits, var1->ndigits);
/*
! * Setup the result
*/
digitbuf_free(result->buf);
! result->buf = digitbuf_alloc(res_ndigits + 2);
res_digits = result->buf;
result->digits = res_digits;
result->ndigits = res_ndigits;
--- 1159,1179 ----
dividend.rscale = var1->ndigits;
dividend.sign = NUMERIC_POS;
dividend.buf = digitbuf_alloc(var1->ndigits);
+ if (dividend.buf == NULL)
+ goto done;
dividend.digits = dividend.buf;
memcpy(dividend.digits, var1->digits, var1->ndigits);
/*
! * Setup the result. Do the allocation in a temporary buffer
! * first, so we don't free result->buf unless we have successfully
! * allocated a buffer to replace it with.
*/
+ tmp_buf = digitbuf_alloc(res_ndigits + 2);
+ if (tmp_buf == NULL)
+ goto done;
digitbuf_free(result->buf);
! result->buf = tmp_buf;
res_digits = result->buf;
result->digits = res_digits;
result->ndigits = res_ndigits;
***************
*** 1201,1206 ****
--- 1212,1219 ----
memcpy(&divisor[guess], &divisor[1], sizeof(numeric));
divisor[guess].buf = digitbuf_alloc(divisor[guess].ndigits);
+ if (divisor[guess].buf == NULL)
+ goto done;
divisor[guess].digits = divisor[guess].buf;
for (i = divisor[1].ndigits - 1; i >= 0; i--)
{
***************
*** 1233,1239 ****
if (guess == 0)
continue;
! sub_abs(÷nd, &divisor[guess], ÷nd);
first_nextdigit = dividend.weight - weight_tmp;
first_have = 0;
--- 1246,1253 ----
if (guess == 0)
continue;
! if (sub_abs(÷nd, &divisor[guess], ÷nd) != 0)
! goto done;
first_nextdigit = dividend.weight - weight_tmp;
first_have = 0;
***************
*** 1269,1283 ****
if (result->ndigits == 0)
result->sign = NUMERIC_POS;
/*
* Tidy up
*/
! digitbuf_free(dividend.buf);
for (i = 1; i < 10; i++)
! digitbuf_free(divisor[i].buf);
! result->dscale = res_dscale;
! return 0;
}
--- 1283,1305 ----
if (result->ndigits == 0)
result->sign = NUMERIC_POS;
+ result->dscale = res_dscale;
+ err = 0; /* if we've made it this far, return success */
+
+ done:
/*
* Tidy up
*/
! if (dividend.buf != NULL)
! digitbuf_free(dividend.buf);
!
for (i = 1; i < 10; i++)
! {
! if (divisor[i].buf != NULL)
! digitbuf_free(divisor[i].buf);
! }
! return err;
}