repalloc bug

Started by Giacomo Carielloover 22 years ago4 messagesbugs
Jump to latest

Your name: Giacomo Cariello
Your email address: jwk@bug.it

System Configuration
---------------------
Architecture (example: Intel Pentium) : CHOST="i686-pc-linux-gnu",
CPU=athlon-xp

Operating System (example: Linux 2.0.26 ELF) : Gentoo Linux 1.4 (kernel
version 2.4.20, ELF, glibc 2.3.2)

PostgreSQL version (example: PostgreSQL-7.3.4): PostgreSQL-7.3.4

Compiler used (example: gcc 2.95.2) : from gcc -v: gcc version
3.2.3 20030422 (Gentoo Linux 1.4 3.2.3-r2, propolice)

Please enter a FULL description of your problem:
------------------------------------------------
Using repalloc in some functions in a shared library I load, the effect is
not the desidered one: the allocated area gets overwritten and causes
segfault once the function returns or calls SPI_finish()

Please describe a way to repeat the problem. Please try to provide a
concise reproducible example, if at all possible:
----------------------------------------------------------------------
hrm...I noticed some memory areas palloc'ed during a SRF initialization get
overwritten. Also backend tends to crash randomly.
As of now I fixed using palloc/memcpy variant to achieve the same result.

If you know how this problem might be fixed, list the solution below:
---------------------------------------------------------------------
no clue.

Giacomo Cariello, jwk@bug.it
KeyID: 3072/1024/0x409C9044
Fingerprint: 7984 10FD 0460 4202 BF90 3881 CDE4 D78E 409C 9044

"Put that mic in my hand and let me kick out the jams!" - MC5

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Giacomo Cariello (#1)
Re: repalloc bug

Giacomo Cariello <jwk@bug.it> writes:

Using repalloc in some functions in a shared library I load, the effect is
not the desidered one: the allocated area gets overwritten and causes
segfault once the function returns or calls SPI_finish()

The odds that this is a bug in repalloc, and not in your own code, are
nil.

regards, tom lane

In reply to: Tom Lane (#2)
Re: repalloc bug

The odds that this is a bug in repalloc, and not in your own code, are
nil.

regards, tom lane

Dear Tom Lane,
Thanks for quick response. Trying to focus what kind of bug could infest my
code, I reduced the code to a small example that illustrates the infaust
effect. I've tried to follow as much as possible the manual, so I'm trying
to figure what's wrong.

This is the source code:
---> snip <---
#include <postgres.h>
#include <fmgr.h>
#include <funcapi.h>
#include <commands/trigger.h>
#include <executor/spi.h>
#include <catalog/pg_type.h>
#include <sys/types.h>
#include <ctype.h>

typedef struct
{
TupleDesc tupdesc;
u_int32_t size;
u_int8_t *buf;
} repalloc_test_t;

void repalloc_bubble(u_int8_t *buf, u_int32_t s)
{
buf = repalloc(buf, s);
bzero(buf, s);
}

PG_FUNCTION_INFO_V1(repalloc_test);

Datum repalloc_test(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
repalloc_test_t *d;
u_int32_t i;
MemoryContext oldcontext;

funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
d = funcctx->user_fctx = (repalloc_test_t *)
palloc(sizeof(repalloc_test_t));
bzero(d, sizeof(repalloc_test_t));
d->tupdesc = RelationNameGetTupleDesc("repalloc_type");
d->size = 32;
d->buf = palloc(d->size);
bzero(d->buf, d->size);
for(i = 0; i < d->size; i++)
elog(WARNING, "TEST A: d->buf[%d] = %d", i, d->buf[i]);
d->size = 64;
repalloc_bubble(d->buf, d->size);
for(i = 0; i < d->size; i++)
elog(WARNING, "TEST B: d->buf[%d] = %d", i, d->buf[i]);
funcctx->slot = TupleDescGetSlot(d->tupdesc);
MemoryContextSwitchTo(oldcontext);
funcctx = SRF_PERCALL_SETUP();
SRF_RETURN_DONE(funcctx);
}
----> snip <-----

I've then created the following script to load the library and execute it:

---> snip <---
CREATE TYPE "repalloc_type" AS
(
"count" integer,
"size" integer
);
CREATE OR REPLACE FUNCTION repalloc_test() RETURNS setof repalloc_type AS
'path/to/lib.so' LANGUAGE C IMMUTABLE WITH (isStrict);
SELECT * FROM repalloc_test();
DROP FUNCTION repalloc_test();
DROP TYPE repalloc_type;
---> snip <---

This is the output of the WARNING messages:

---> snip <---
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[0] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[1] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[2] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[3] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[4] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[5] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[6] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[7] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[8] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[9] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[10] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[11] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[12] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[13] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[14] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[15] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[16] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[17] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[18] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[19] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[20] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[21] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[22] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[23] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[24] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[25] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[26] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[27] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[28] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[29] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[30] = 0
psql:repalloc_test.sql:7: WARNING: TEST A: d->buf[31] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[0] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[1] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[2] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[3] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[4] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[5] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[6] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[7] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[8] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[9] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[10] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[11] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[12] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[13] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[14] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[15] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[16] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[17] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[18] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[19] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[20] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[21] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[22] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[23] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[24] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[25] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[26] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[27] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[28] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[29] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[30] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[31] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[32] = 248
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[33] = 196
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[34] = 49
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[35] = 8
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[36] = 128
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[37] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[38] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[39] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[40] = 179
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[41] = 104
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[42] = 236
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[43] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[44] = 99
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[45] = 111
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[46] = 117
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[47] = 110
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[48] = 116
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[49] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[50] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[51] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[52] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[53] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[54] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[55] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[56] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[57] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[58] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[59] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[60] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[61] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[62] = 0
psql:repalloc_test.sql:7: WARNING: TEST B: d->buf[63] = 0
---> snip <---

As you may notice, I never write into d->buf, nor I "overflow" any of the
other values and all the buffers are correctly allocated, but still d->buf
gets overwritten. I may be possibly using the API incorrectly, so could you
please help me understand what's actually failing?

Giacomo Cariello, jwk@bug.it
KeyID: 3072/1024/0x409C9044
Fingerprint: 7984 10FD 0460 4202 BF90 3881 CDE4 D78E 409C 9044

"Put that mic in my hand and let me kick out the jams!" - MC5

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Giacomo Cariello (#3)
Re: repalloc bug

Giacomo Cariello <jwk@bug.it> writes:

void repalloc_bubble(u_int8_t *buf, u_int32_t s)
{
buf = repalloc(buf, s);
bzero(buf, s);
}

repalloc_bubble(d->buf, d->size);

This doesn't update d->buf in the calling function; the result of
repalloc is only assigned to repalloc_bubble's local variable buf.

regards, tom lane