User-defined-type in C crashing PostgreSQL server: What am I doing wrong?

From: "J(dot) Greg Davidson" <jgd(at)well(dot)com>
To: pgsql-general(at)postgresql(dot)org
Subject: User-defined-type in C crashing PostgreSQL server: What am I doing wrong?
Date: 2006-11-18 21:07:15
Message-ID: 1163884035.28566.108.camel@localhost
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Hello,

My user-defined types are crashing the PostgreSQL server and I don't
understand why. I've been trying to figure it out on my own for overr
a week. I've cooked what I'm doing down to the essentials and I'm
asking for help. Help: What am I doing wrong?

* Sections of this message:
** Overview with psql session
** SQL code
** C Code
** gdb backtraces
*** gdb backtrace after SELECT ARRAY[ pair_tag_id(3, 4) ];
*** gdb backtrace after SELECT x from pair_tag_id(3, 4) x;
*** gdb backtrace after SELECT ROW( pair_tag_id(3, 4) );
** Thanks for your help!

** Overview wiith psql session

Tested with: PostgreSQL-8.1.4 and PostgreSQL-8.2beta3,
installed from source with
./configure ... --enable-debug --enable-cassert
Platform: SuSE Linux 10.0 on i686 Dell Notebook Computer

I have a simple one-word datatype called a "pair", which consists of a
1-byte "tag" and a 3-byte "id".

-- At first, it seems to work:

pairs=# select pair_tag_id(3, 4);
pair_tag_id
-------------------------
<pair tag="3" id="4" />
(1 row)

pairs=# select tag_pair(pair_tag_id(3, 4));
tag_pair
----------
3
(1 row)

pairs=# select id_pair(pair_tag_id(3, 4));
id_pair
---------
4
(1 row)

-- But all three of these crash the server with Signal 11:

SELECT ARRAY[ pair_tag_id(3, 4) ];

SELECT x from pair_tag_id(3, 4) x;

SELECT ROW( pair_tag_id(3, 4) );

-- Note: Nothing special about 3 and 4, all values I've tried behave
-- the same!

** SQL code

-- CREATE TYPE pair; -- PostgreSQL 8.2

CREATE OR REPLACE
FUNCTION pair_in(cstring) RETURNS pair
AS 'pair.so' LANGUAGE 'c' STRICT;

CREATE OR REPLACE
FUNCTION pair_out(pair) RETURNS cstring
AS 'pair.so' LANGUAGE 'c' STRICT;

CREATE TYPE pair (
INTERNALLENGTH = 4, -- 32-bits
INPUT = pair_in,
OUTPUT = pair_out
);

CREATE OR REPLACE
FUNCTION tag_pair(pair) RETURNS integer
AS 'pair.so' LANGUAGE 'c' STRICT;

CREATE OR REPLACE
FUNCTION id_pair(pair) RETURNS integer
AS 'pair.so' LANGUAGE 'c' STRICT;

CREATE OR REPLACE
FUNCTION pair_tag_id(integer, integer) RETURNS pair
AS 'pair.so' LANGUAGE 'c' STRICT;

** C Code

$ cc -fpic -I/Ubuntu/usr/local/pgsql-8.1.4/include/server -Wall -c -o
pair.o pair.c
$ cc -shared -o pair.so pair.o
$ cat pair.c

#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <postgres.h> /* general Postgres declarations */
#include <fmgr.h> /* for argument/result macros */

#define PAIR_TAG_WIDTH 8
#define PAIR_MAX_TAG ( (1U << PAIR_TAG_WIDTH) - 1)
#define PAIR_MAX_ID ( (int) (INT_MAX >> PAIR_TAG_WIDTH) )
#define PAIR_MIN_ID ( -PAIR_MAX_ID )

typedef long pairs; // a tag plus an ID
typedef unsigned tags;
#define F_TAG "tag: %u " // Format string for tags
typedef long ids;
#define F_ID "id: %ld " // Format string for ids

typedef char *StrPtr; // '\0' terminated modifiable string
typedef const char *Str; // '\0' terminated constant string

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

inline pairs TagPairId (tags tag, ids id) {
return (id << PAIR_TAG_WIDTH) | tag;
}
inline tags TagPair(pairs v) {
return v & ~(~0U << PAIR_TAG_WIDTH);
}
inline ids IdPair(pairs v) {
return v >> PAIR_TAG_WIDTH;
}

#define FUNCTION_DEFINE(f) \
PG_FUNCTION_INFO_V1(f); \
Datum (f)(PG_FUNCTION_ARGS)

FUNCTION_DEFINE(pair_tag_id) { // (tags, ids) -> pair
tags tag = PG_GETARG_INT32(0);
ids id = PG_GETARG_INT32(1);
PG_RETURN_INT32( TagPairId( tag, id) );
}

FUNCTION_DEFINE(tag_pair) { // (pair) -> tags
PG_RETURN_INT32( TagPair( PG_GETARG_INT32(0) ) );
}

FUNCTION_DEFINE(id_pair) { // (pair) -> ids
PG_RETURN_INT32( IdPair( PG_GETARG_INT32(0) ) );
}

inline StrPtr NewStr( Str old ) {
return strcpy( palloc(strlen(old)+1), old );
}

StrPtr PairToXMLStr(Str message, pairs p) {
tags tag = TagPair(p);
ids id = IdPair(p);
Str msg = message ? message : "";
Str format = message
? "<pair tag=\"%u\" id=\"%d\">%s</pair>"
: "<pair tag=\"%u\" id=\"%d\" %s/>";
// I tried with both of the next two lines, just in case: same behavior
// char buffer[strlen(format) + strlen(msg) + 2 * 20]; // gcc extension
char * buffer = palloc(strlen(format) + strlen(msg) + 2 * 20);
sprintf(buffer, format, tag, id, msg);
return NewStr(buffer);
}

FUNCTION_DEFINE(pair_in) { // cstring -> pair
PG_RETURN_INT32(0);
}

FUNCTION_DEFINE(pair_out) { // pair -> cstring
PG_RETURN_CSTRING( PairToXMLStr( NULL, PG_GETARG_INT32(0) ) );
}

** gdb backtraces

# gdb bin/postgres data/core
GNU gdb 6.3
...
Core was generated by `postgres: greg pairs [local] SELECT
'.

Program terminated with signal 11, Segmentation fault.
...

*** gdb backtrace after SELECT ARRAY[ pair_tag_id(3, 4) ];
(gdb) backtrace
#0 0xb7d2a07d in memmove () from /lib/tls/libc.so.6
#1 0x00000403 in ?? ()
#2 0x081ed694 in ArrayCastAndSet (src=138452140, typlen=1027,
typbyval=<value optimized out>, typalign=105 'i',
dest=0x8409cac "\177\177\177\177~", '\177' <repeats 195 times>...)
at arrayfuncs.c:3673
#3 0x081ed92a in CopyArrayEls (array=<value optimized out>,
values=0x8409ba4,
nulls=0x8409bb8 "", nitems=1, typlen=4, typbyval=0 '\0',
typalign=105 'i',
freedata=0 '\0') at arrayfuncs.c:872
#4 0x081edbde in construct_md_array (elems=0x8409ba4, nulls=0x8409bb8
"",
ndims=1, dims=0xbfaaddc0, lbs=0xbfaadda8, elmtype=164377, elmlen=4,
elmbyval=0 '\0', elmalign=105 'i') at arrayfuncs.c:2863
#5 0x0815ae43 in ExecEvalArray (astate=0x8407e58, econtext=0x8407dc0,
isNull=0x84085cc "", isDone=0x84085e0) at execQual.c:2266
#6 0x08159b54 in ExecProject (projInfo=0x8408520, isDone=0xbfaade7c)
at execQual.c:3986
#7 0x08167e83 in ExecResult (node=0x8407d34) at nodeResult.c:157
#8 0x08156673 in ExecProcNode (node=0x8407d34) at execProcnode.c:334
#9 0x08154dc0 in ExecutorRun (queryDesc=0x84077c0,
direction=ForwardScanDirection, count=0) at execMain.c:1081
#10 0x081e3129 in PortalRunSelect (portal=0x83fecdc,
forward=<value optimized out>, count=0, dest=0x83f299c) at
pquery.c:831
#11 0x081e441a in PortalRun (portal=0x83fecdc, count=2147483647,
---Type <return> to continue, or q <return> to quit---

*** gdb backtrace after SELECT x from pair_tag_id(3, 4) x;

(gdb) backtrace
#0 0xb7d2a58c in memcpy () from /lib/tls/libc.so.6
#1 0x0807b58f in heap_fill_tuple (tupleDesc=0x842053c,
values=0xbfaaddb8,
isnull=0xbfaadb8c "", data=0x842053c "", infomask=0x8420538,
bit=0x0)
at heaptuple.c:180
#2 0x0807c0e6 in heap_form_tuple (tupleDescriptor=0x841aeec,
values=0xbfaaddb8, isnull=0xbfaadb8c "") at heaptuple.c:745
#3 0x0815aac9 in ExecMakeTableFunctionResult (funcexpr=0x841a930,
econtext=0x841a718, expectedDesc=0x841a7fc, returnDesc=0x842053c)
at execQual.c:1457
#4 0x08167c0c in FunctionNext (node=0x841a68c) at nodeFunctionscan.c:69
#5 0x0815c7d8 in ExecScan (node=0x841a68c, accessMtd=0x8167bb0
<FunctionNext>)
at execScan.c:68
#6 0x08167824 in ExecFunctionScan (node=0x841a68c) at
nodeFunctionscan.c:110
#7 0x081566ec in ExecProcNode (node=0x841a68c) at execProcnode.c:371
#8 0x08154dc0 in ExecutorRun (queryDesc=0x8403450,
direction=ForwardScanDirection, count=0) at execMain.c:1081
#9 0x081e3129 in PortalRunSelect (portal=0x83fa96c,
forward=<value optimized out>, count=0, dest=0x83d96c4) at
pquery.c:831
#10 0x081e441a in PortalRun (portal=0x83fa96c, count=2147483647,
dest=0x83d96c4, altdest=0x83d96c4, completionTag=0xbfaae0ba "")
at pquery.c:684
#11 0x081dffaa in exec_simple_query (
query_string=0x83d774c "SELECT x from pair_tag_id(3, 4) x;")
---Type <return> to continue, or q <return> to quit---

*** gdb backtrace after SELECT ROW( pair_tag_id(3, 4) );

(gdb) backtrace
#0 0xb7d2a58c in memcpy () from /lib/tls/libc.so.6
#1 0x0807b58f in heap_fill_tuple (tupleDesc=0x8411d84,
values=0x8411d2c,
isnull=0x8411d40 "", data=0x8411d84 "", infomask=0x8411d80, bit=0x0)
at heaptuple.c:180
#2 0x0807c0e6 in heap_form_tuple (tupleDescriptor=0x8403954,
values=0x8411d2c, isnull=0x8411d40 "") at heaptuple.c:745
#3 0x08158a53 in ExecEvalRow (rstate=0x8403928, econtext=0x8403890,
isNull=0x84041a8 "", isDone=0x84041bc) at execQual.c:2479
#4 0x08159b54 in ExecProject (projInfo=0x84040fc, isDone=0xbfaade7c)
at execQual.c:3986
#5 0x08167e83 in ExecResult (node=0x8403804) at nodeResult.c:157
#6 0x08156673 in ExecProcNode (node=0x8403804) at execProcnode.c:334
#7 0x08154dc0 in ExecutorRun (queryDesc=0x8403290,
direction=ForwardScanDirection, count=0) at execMain.c:1081
#8 0x081e3129 in PortalRunSelect (portal=0x840726c,
forward=<value optimized out>, count=0, dest=0x8416454) at
pquery.c:831
#9 0x081e441a in PortalRun (portal=0x840726c, count=2147483647,
dest=0x8416454, altdest=0x8416454, completionTag=0xbfaae0ba "")
at pquery.c:684
#10 0x081dffaa in exec_simple_query (
query_string=0x83d774c "SELECT ROW( pair_tag_id(3, 4) );")
at postgres.c:939
#11 0x081e0f6e in PostgresMain (argc=4, argv=<value optimized out>,
---Type <return> to continue, or q <return> to quit---

** Thanks for your help!

_Greg

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Martijn van Oosterhout 2006-11-18 22:15:07 Re: User-defined-type in C crashing PostgreSQL server: What am I doing wrong?
Previous Message Matt Miller 2006-11-18 17:42:03 Re: [GENERAL] Allowing SYSDATE to Work