Thread: BUG #12917: C program created by ecpg core dumped due to “varcharsize * offset”

The following bug has been logged on the website:

Bug reference:      12917
Logged by:          Chen Huajun
Email address:      chjischj@163.com
PostgreSQL version: 9.4.1
Operating system:   RHEL6.5
Description:

I found a strange code in ecpg.

1)Problem 1
src/interfaces/ecpg/ecpglib/data.c:241
    do
    {
        if (binary)
        {
            if (varcharsize == 0 || varcharsize * offset >= size)//!!! why
"varcharsize * offset" ? !!!
                memcpy(var + offset * act_tuple, pval, size);
...



According to the mean of varcharsize(from the following comment),i think the
"varcharsize * offset >= size" above should be "varcharsize >= size" or
"offset >= size".

src\interfaces\ecpg\ecpglib\execute.c:
/*------
* create a list of variables
…
* varcharsize - length of string in case we have a stringvariable, else 0
* offset - offset between ith and (i+1)th entry in an array, normally

*------*/

2)Problem 2
And that,according to the comment above, the varcharsize should be setted to
0 for non stringvariable data type.
But the varcharsize is setted to 1 in C code which created by ecpg. Does
this a problem, or just my misunderstand ?


src\interfaces\ecpg\test\expected\sql-desc.c:81

#line 23 "desc.pgc"


    { ECPGset_desc(__LINE__, "indesc", 1,ECPGd_data,
    ECPGt_int,&(val1),(long)1,(long)1,sizeof(int), ECPGd_EODT);
                       ^^^^^^


3)Test
The problem 1 could cause memory overflow, as the following.

Environment:
PG 9.4.1
RHEL6.5


Table and data:
create table empl(idnum integer, name char (10000000));
insert into empl values(1,'abcdddd1123444ddffdfdffddfdfffd');


test app:
binary.pgc:
----------------------
#include <stdio.h>
#include <stdlib.h>
EXEC SQL BEGIN DECLARE SECTION;
struct TBempl
{
  long idnum;
  char name[10000];
};
EXEC SQL END DECLARE SECTION;
int main (void)
{
  EXEC SQL BEGIN DECLARE SECTION;
  struct TBempl empl;
  EXEC SQL END DECLARE SECTION;
  ECPGdebug (1, stderr);
  empl.idnum = 1;
  EXEC SQL connect to postgres USER postgres;
  memset(empl.name, 0, 21L);
  EXEC SQL DECLARE B BINARY CURSOR FOR select name from empl where idnum
=:empl.idnum;
  EXEC SQL OPEN B;
  EXEC SQL FETCH B INTO :empl.name;
  EXEC SQL CLOSE B;
  printf ("name=%s, byte=", empl.name);
  printf("\n");
  EXEC SQL disconnect;
  exit (0);
}


Test:
export INCLUDE_PATH=/usr/local/pgsql/include
export LIB_PATH=/usr/local/pgsql/lib
export PATH=/usr/local/pgsql/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/pgsql/lib:$LD_LIBRARY_PATH
ecpg binary.pgc
gcc  binary.c  -o binary -I$INCLUDE_PATH -L$LIB_PATH -lecpg
./binary
[9547]: ECPGdebug: set to 1
[9547]: ECPGconnect: opening database regcob1 on <DEFAULT> port <DEFAULT>
for user postgres
[9547]: ecpg_execute on line 24: query: declare B binary cursor for select
name from empl where idnum = $1 ; with 1 parameter(s) on connection regcob1
[9547]: ecpg_execute on line 24: using PQexecParams
[9547]: ecpg_free_params on line 24: parameter 1 = 1
[9547]: ecpg_process_output on line 24: OK: DECLARE CURSOR
[9547]: ecpg_execute on line 25: query: fetch B; with 0 parameter(s) on
connection regcob1
[9547]: ecpg_execute on line 25: using PQexec
[9547]: ecpg_process_output on line 25: correctly got 1 tuples with 1
fields
[9547]: ecpg_get_data on line 25: RESULT: BINARY offset: 10000; array: no
セグメンテーション違反です (core dumped)

(gdb) bt
#0  0x0029557e in ecpg_get_data (results=0x8d673f8, act_tuple=0,
act_field=0, lineno=25, type=ECPGt_char, ind_type=ECPGt_NO_INDICATOR,
    var=0xbfaa7bf0 "abcdddd1123444ddffdfdffddfdfffd", ' ' <repeats 169
times>..., ind=0x0, varcharsize=10000, offset=10000, ind_offset=0,
    isarray=ECPG_ARRAY_NONE, compat=ECPG_COMPAT_PGSQL, force_indicator=1
'\001') at data.c:246
#1  0x0028d45e in ecpg_store_result (results=0x8d673f8, act_field=0,
stmt=0x8d667e0, var=0x8d66820) at execute.c:455
#2  0x00290770 in ecpg_process_output (stmt=0x8d667e0, clear_result=1
'\001') at execute.c:1693
#3  0x002911cc in ecpg_do (lineno=25, compat=0, force_indicator=1,
connection_name=0x0, questionmarks=0 '\000', st=0,
    query=0x8048908 "fetch B", args=0xbfaa7bac "\033") at execute.c:2056
#4  0x0029125a in ECPGdo (lineno=25, compat=0, force_indicator=1,
connection_name=0x0, questionmarks=0 '\000', st=0,
    query=0x8048908 "fetch B") at execute.c:2078
#5  0x08048749 in main ()
(gdb) list
241    do
242    {
243       if (binary)
244        {
245        if (varcharsize == 0 || varcharsize * offset >= size)
246        memcpy(var + offset * act_tuple, pval, size);  //!!! core dumped here
!!!
247        else
248        {
249        memcpy(var + offset * act_tuple, pval, varcharsize * offset);
250



On Mon, Mar 30, 2015 at 8:13 PM, <chjischj@163.com> wrote:
>
> Table and data:
> create table empl(idnum integer, name char (10000000));
> insert into empl values(1,'abcdddd1123444ddffdfdffddfdfffd');

So the table used in your test uses char(10000000), which is a
datatype that completes with spaces strings stored that have a length
shorter than the limit. So even if you store a string of n characters,
what will be stored are those n characters, followed by 10,000,000 - n
spaces.

>
> EXEC SQL BEGIN DECLARE SECTION;
> struct TBempl
> {
>   long idnum;
>   char name[10000];
> };


And this test expects that result of column "name" does not contain
more 10k characters, so your data set is incompatible with your test,
explaining the crash you are seeing.
--
Michael
T24gMjAxNS0wNC0wNiAxMDoyMyAsIE1pY2hhZWwgUGFxdWllciBXcm90ZTogQW5kIHRoaXMgdGVz
dCBleHBlY3RzIHRoYXQgcmVzdWx0IG9mIGNvbHVtbiAibmFtZSIgZG9lcyBub3QgY29udGFpbiBt
b3JlIDEwayBjaGFyYWN0ZXJzLCBzbyB5b3VyIGRhdGEgc2V0IGlzIGluY29tcGF0aWJsZSB3aXRo
IHlvdXIgdGVzdCwgZXhwbGFpbmluZyB0aGUgY3Jhc2ggeW91IGFyZSBzZWVpbmcuIC0tIE1pY2hh
ZWwgLS0tLS0tLS0tLS0tLS0tIFRoYW5rcyBmb3IgeW91ciBhbnN3ZXIsYnV0IGkgc3RpbGwgY2Fu
IG5vdCB1bmRlcnN0YW5kIHdoeSBoZXJlIGlzICJ2YXJjaGFyc2l6ZSAqIG9mZnNldCA+PSBzaXpl
Iiwgd2hpbGUgaW4gdGhlIG5vbiBiaW5hcnkgYnJhbmNoIHRoYXQgaXMgInZhcmNoYXJzaXplID49
IHNpemUiIGFuZCB3b3JrcyBmaW5lIG9uIHRoZSBzYW1lIHRlc3QgY2FzZSh0cnVuY2F0ZSBzaXpl
IHRvIHZhcmNoYXJzaXplKS7CoCBiaW5hcnkucGdjOsKgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS3C
oCDCoEVYRUMgU1FMIERFQ0xBUkUgQiBCSU5BUlkgQ1VSU09SIEZPUiBzZWxlY3QgbmFtZSBmcm9t
IGVtcGwgd2hlcmUgaWRudW0gPTplbXBsLmlkbnVtO8KgID09Pih0aGUgbm9uIGJpbmFyeSBicmFu
Y2ggd29ya3MgZmluZSnCoCDCoEVYRUMgU1FMIERFQ0xBUkUgQiBDVVJTT1IgRk9SIHNlbGVjdCBu
YW1lIGZyb20gZW1wbCB3aGVyZSBpZG51bSA9OmVtcGwuaWRudW07wqAgc3JjL2ludGVyZmFjZXMv
ZWNwZy9lY3BnbGliL2RhdGEuYzo0NjbCoCBpZiAoYmluYXJ5KcKgIHvCoCDCoCDCoCDCoGlmICh2
YXJjaGFyc2l6ZSA9PSAwIHx8IHZhcmNoYXJzaXplICogb2Zmc2V0ID49IHNpemUpwqAgwqAgwqAg
wqDCoCDCoCDCoG1lbWNweSh2YXIgKyBvZmZzZXQgKiBhY3RfdHVwbGUsIHB2YWwsIHNpemUpOy8v
ISEhIG1lbW9yeSBvdmVyZmxvdyBmb3IgQklOQVJZIENVUlNPUiAhISHCoCDCoCDCoCDCoGVsc2XC
oCDCoCDCoCDCoHvCoCDCoCDCoCDCoMKgIMKgIMKgbWVtY3B5KHZhciArIG9mZnNldCAqIGFjdF90
dXBsZSwgcHZhbCwgdmFyY2hhcnNpemUgKiBvZmZzZXQpO8KgIMKgIMKgIMKgIMKgLi4uwqAgwqAg
wqAgwqAgwqB9wqAgLi4uwqAgfcKgIGVsc2XCoCB7wqAgLi4uwqAgwqAgwqAgwqBpZiAodmFyY2hh
cnNpemUgPT0gMCB8fCB2YXJjaGFyc2l6ZSA+IHNpemUpwqAgwqAgwqAgwqB7wqAgwqAgwqAgwqDC
oCDCoCDCoHN0cm5jcHkoc3RyLCBwdmFsLCBzaXplICsgMSk7wqAgwqAgwqAgwqAuLi7CoCDCoCDC
oCDCoH3CoCDCoCDCoCDCoGVsc2XCoCDCoCDCoCDCoHvCoCDCoCDCoCDCoMKgIMKgIMKgc3RybmNw
eShzdHIsIHB2YWwsIHZhcmNoYXJzaXplKTsvLyEhISB0cnVuY2F0ZSBzaXplIHRvIHZhcmNoYXJz
aXplIGZvciBOT04gQklOQVJZIENVUlNPUiAhISHCoCDCoCDCoCDCoC4uLsKgIMKgIMKgIMKgfcKg
IC4uLsKgIC0twqAgUmVnYXJkcywgQ2hlbiBIdWFqdW4=