2009/7/4 Greg Stark <gsst...@mit.edu>:
> On Sat, Jul 4, 2009 at 10:31 PM, Greg Stark<gsst...@mit.edu> wrote:
>> It's pretty hard to guess where your bug is sitting here with no code
>> and no idea even what you've done to trigger it.
>>

see attachment - sorry, comments are czech

>> At a guess there someplace you haven't detoasted a datum that had to
>> be detoasted. But like I said that's just a guess.
>>

I have a problem with "in" function. So I have not a control over
process. I return a varlena value, that's all.

>
> Actually on further thought I think this smells like a memory
> management bug. Maybe you've either you've prematurely freed this data
> structure or realloc'd it without tracking the new pointer and have
> returned a pointer to the freed object.
>

I'll look on it. It looks strange. I don't use pfree. 2x or 3x use repalloc.

regards
Pavel Stehule

>
> --
> greg
> http://mit.edu/~gsstark/resume.pdf
>
#include "postgres.h"

#include <float.h>
#include <math.h>

#include "kokes.h"
#include "access/gist.h"
#include "access/skey.h"
#include "lib/stringinfo.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "libpq/pqformat.h"

PG_MODULE_MAGIC;

PG_FUNCTION_INFO_V1(kokes_in);
PG_FUNCTION_INFO_V1(kokes_out);
PG_FUNCTION_INFO_V1(kokes_send);
PG_FUNCTION_INFO_V1(kokes_recv);

Datum kokes_in(PG_FUNCTION_ARGS);
Datum kokes_out(PG_FUNCTION_ARGS);
Datum kokes_send(PG_FUNCTION_ARGS);
Datum kokes_recv(PG_FUNCTION_ARGS);

extern int      kokes_yyparse();
extern void kokes_scanner_init(const char *str);
extern void kokes_scanner_finish(void);
static void print_double_list(StringInfo str, double *data, unsigned long 
cntpnt);
static void print_short_list(StringInfo str, short int *data, unsigned long 
cntpnt);
static char *print_info(StringInfo str, char *buf);
static char *print_infos(StringInfo str, char *buf);
static char *print_atrs(StringInfo str, char *buf);

KokesData *kokes;

#define PORTABLE_SERIALIZATION

Datum
kokes_in(PG_FUNCTION_ARGS)
{
        char    *str;

        str = PG_GETARG_CSTRING(0);

        kokes_scanner_init(str);
        if (kokes_yyparse() != 0)
                ereport(ERROR, 
                                (errcode(ERRCODE_SYNTAX_ERROR),
                                 errmsg("bogus input")));

elog(NOTICE, "KOKES SIZE %d, pointer: %d, LEN: %d", VARSIZE( kokes), kokes, 
kokes->vl_len_);

        kokes_scanner_finish();

        PG_RETURN_KokesData(kokes);
}

Datum
kokes_out(PG_FUNCTION_ARGS)
{
    Kokes kokes;
    StringInfoData buf;
    char        *readbuf;

    initStringInfo(&buf);

    kokes = PG_GETARG_KokesData(0);

elog(NOTICE, "1");

    appendStringInfo(&buf, "((%u ", kokes->status);
    
elog(NOTICE, "2");
    
    appendStringInfo(&buf, "(%ld %ld %ld %ld) ", kokes->OOO[0], kokes->OOO[1], 
                                                kokes->OOO[2], kokes->OOO[3]);
    appendStringInfo(&buf, "%lu %lu %d %d)", kokes->key, kokes->cntpnt,
                                                kokes->layer, kokes->alias);

elog(NOTICE, ">>> %s", buf.data);

    print_double_list(&buf, KOKES_X_ARRAY(kokes), kokes->cntpnt);
    print_double_list(&buf, KOKES_Y_ARRAY(kokes), kokes->cntpnt);
    print_short_list(&buf, KOKES_SP_ARRAY(kokes), kokes->cntpnt);

    readbuf = print_infos(&buf, KOKES_INF_ARRAY(kokes));
    print_atrs(&buf, readbuf);

elog(NOTICE, "3");

    appendStringInfoChar(&buf, ')');

    PG_FREE_IF_COPY(kokes, 0);
    PG_RETURN_CSTRING(buf.data);
}

static void 
print_double_list(StringInfo str, double *data, unsigned long cntpnt)
{
    int i;

    appendStringInfo(str, " (");
    
    for (i = 0; i < cntpnt; i++)
            if (i > 0) 
                    appendStringInfo(str, " %g", data[i]);
            else
                    appendStringInfo(str, "%g", data[i]);

    appendStringInfoChar(str, ')');
}

static void 
print_short_list(StringInfo str, short int *data, unsigned long cntpnt)
{
    int i;

    appendStringInfo(str, " (");
    
    for (i = 0; i < cntpnt; i++)
            if (i > 0) 
                    appendStringInfo(str, " %d", data[i]);
            else
                    appendStringInfo(str, "%d", data[i]);

    appendStringInfoChar(str, ')');
}



static char *
print_info(StringInfo str, char *buf)
{
        GINFLEN ginflen = *((GINFLEN *) buf);
        int processed_chars = 0;

        buf += sizeof(GINFLEN);
        appendStringInfoChar(str, '(');

        /* pokud ma bod informace zobraz je */
        if (*buf != '\0')
        {
                while (processed_chars < ginflen)
                {
                        if (processed_chars != 0)
                                appendStringInfoChar(str, ' ');
                        appendStringInfo(str, "%c='", *buf++);
                        processed_chars += 1;

                        while (*buf != '\t' && *buf != '\0')
                        {
                                appendStringInfoChar(str, *buf++);
                                processed_chars += 1;
                        }

                        appendStringInfoChar(str, '\'');

                        if (*buf++ == '\0')
                                break;

                        processed_chars += 1;
                }
        }

        appendStringInfoChar(str, ')');
        return buf;
}

static char *
print_infos(StringInfo str, char *buf)
{
        GATRLEN gatrlen = *((GATRLEN *) buf);
        char    *endbuf;

        buf += sizeof(GATRLEN);
        endbuf = buf + gatrlen;
        appendStringInfo(str, " (");

        while (buf < endbuf)
        {
                buf = print_info(str, buf);
        }

        appendStringInfoChar(str, ')');
        return buf;
}

static char *
print_atrs(StringInfo str, char *buf)
{
        GATRLEN gatrlen = *((GATRLEN *) buf);
        int     processed_chars = 0;

        buf += sizeof(GATRLEN);
        appendStringInfo(str, " (");
        while (processed_chars++ < gatrlen)
        {
                char    c = *buf++;

                switch (c)
                {
                        case '\0':
                                appendStringInfoChar(str, '\'');
                                break;
                        case '=':
                                appendStringInfo(str, "='");
                                break;
                        case '\n':
                                appendStringInfo(str, "' ");
                                break;
                        default:
                                appendStringInfoChar(str, c);
                }
        }       

        appendStringInfoChar(str, ')');
        return buf;
}


/*
 * Serializace je jednoducha - prenese se pole bytu.
 * Tato serializace je funkci pouze pri shode uladani poradi bajtu!
 * tj. je nezbytne aby server bezel na stejne platforme (z pohledu
 * poradi ukladni bajtu) jako klient - pokud by tato podminka neplatila
 * musel by se polozky struktury serializovat samostatne!!
 * coz by nebyl az takovy problem a patrne by to nebylo nijak zvlast
 * poznat na vykonu a bylo by to prenositelne, tj. do dalsi verze
 * pridat variantu
 */
 
#define FILLINT(kokes, buf, field)      kokes->field = pq_getmsgint(buf, 
sizeof(kokes->field)) 
#define PUTINT(kokes, buf, field)       pq_sendint(&buf, kokes->field, 
sizeof(kokes->field))
 
Datum
kokes_recv(PG_FUNCTION_ARGS)
{
        StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
        Kokes           kokes;
#ifdef PORTABLE_SERIALIZATION
        unsigned long cntpnt;
        int     i;
        size_t size;
        double  *aux_dp;
        short int       *aux_sp;
#endif

#ifndef PORTABLE_SERIALIZATION
        kokes = palloc(buf->len + VARHDRSZ);
        pq_copymsgbytes(buf, VARDATA(kokes), buf->len);
        SET_VARSIZE(kokes, buf->len + VARHDRSZ);
#else
        cntpnt = pq_getmsgint(buf, sizeof(unsigned long));              
        size = offsetof(KokesData, data[0])  + (2 * sizeof(double)*cntpnt) 
                                + sizeof(short int)*cntpnt;
        kokes = (Kokes) palloc(size);
        kokes->cntpnt = cntpnt;
        FILLINT(kokes, buf, status);
        FILLINT(kokes, buf, key);
        FILLINT(kokes, buf, layer);
        FILLINT(kokes, buf, alias);
        FILLINT(kokes, buf, reserva);
        
        FILLINT(kokes, buf, OOO[0]);
        FILLINT(kokes, buf, OOO[1]);
        FILLINT(kokes, buf, OOO[2]);
        FILLINT(kokes, buf, OOO[3]);

        aux_dp = KOKES_X_ARRAY(kokes);
        for (i = 0; i < kokes->cntpnt; i++)
                *aux_dp++ = pq_getmsgfloat8(buf);
                
        aux_dp = KOKES_Y_ARRAY(kokes);
        for (i = 0; i < kokes->cntpnt; i++)
                *aux_dp++ = pq_getmsgfloat8(buf);
                
        aux_sp = KOKES_SP_ARRAY(kokes);
        for (i = 0; i < kokes->cntpnt; i++)
                *aux_sp++ = pq_getmsgint(buf, sizeof(short int));
#endif

        PG_RETURN_KokesData(kokes);
}

Datum
kokes_send(PG_FUNCTION_ARGS)
{
        Kokes kokes = PG_GETARG_KokesData(0);
        StringInfoData          buf;
#ifdef PORTABLE_SERIALIZATION
        int     i;
        double  *aux_dp;
        short int       *aux_sp;
#endif

        pq_begintypsend(&buf);
#ifndef PORTABLE_SERIALIZATION
        pq_sendbytes(&buf, VARDATA(kokes), 
                                VARSIZE(kokes) - VARHDRSZ);
#else
        PUTINT(kokes, buf, cntpnt);
        PUTINT(kokes, buf, status);
        PUTINT(kokes, buf, key);
        PUTINT(kokes, buf, layer);
        PUTINT(kokes, buf, alias);
        PUTINT(kokes, buf, reserva);
        
        PUTINT(kokes, buf, OOO[0]);
        PUTINT(kokes, buf, OOO[1]);
        PUTINT(kokes, buf, OOO[2]);
        PUTINT(kokes, buf, OOO[3]);

        aux_dp = KOKES_X_ARRAY(kokes);
        for (i = 0; i < kokes->cntpnt; i++)
                pq_sendfloat8(&buf, *aux_dp++);
                
        aux_dp = KOKES_Y_ARRAY(kokes);
        for (i = 0; i < kokes->cntpnt; i++)
                pq_sendfloat8(&buf, *aux_dp++);
                
        aux_sp = KOKES_SP_ARRAY(kokes);
        for (i = 0; i < kokes->cntpnt; i++)
                pq_sendint(&buf, *aux_sp++, sizeof(short int));
#endif
        
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}

/*
 * Pro gepro Pavel Stěhule, srpen-listopad 2008
 */
 
typedef struct KokesData
{
        int32   vl_len_;                /* varlena header */
        unsigned short status;
        long OOO[4];
        unsigned long key;
        unsigned long cntpnt;
        unsigned short layer;
        unsigned short alias;
        unsigned long reserva;
        char data[1];                   
} KokesData;

typedef struct KokesData *Kokes;

typedef unsigned short GINFLEN;    /* typ délka informace na jednom bodu */
typedef unsigned GATRLEN;          /* typ délka atributu k objektu a všech 
informací v objektu */

#define KOKES_X_ARRAY(kokes)    ((double *) kokes->data)
#define KOKES_Y_ARRAY(kokes)    ((double *)     (KOKES_X_ARRAY(kokes)  + 
kokes->cntpnt))
#define KOKES_SP_ARRAY(kokes)   ((short int *)  (KOKES_Y_ARRAY(kokes)  + 
kokes->cntpnt))
#define KOKES_INF_ARRAY(kokes)  ((char*)        (KOKES_SP_ARRAY(kokes) + 
kokes->cntpnt))

#define DatumGetKokesData(x)    ((KokesData*)DatumGetPointer(x))
#define PG_GETARG_KokesData(x)  DatumGetKokesData( 
PG_DETOAST_DATUM(PG_GETARG_DATUM(x)) )
#define PG_RETURN_KokesData(x)  PG_RETURN_POINTER(x)

/*
 * Informace jsou serializovany do nasledujiciho formatu:
 *   INFPNT := GINFLEN _inf \t _inf \t _inf [ .. ] \0      - informace k 
jednomu bodu
 *   INFALL := GATRLEN INFPNT INFPNT INFPNT  [ .. ]
 *
 */
typedef struct _inf
{
                char    name;           /* a..zA..Z_, pokud bod nema informace 
obsahuje 0 */
                char    *value;         /* muze byt "" nebo NULL */
                struct _inf *next;              /* odkaz na dalsi informaci */
} _inf;

/* 
 * Atributy jsou serializovany do nasledujiciho formatu:
 *    ATR    := char[] '=' char[] 
 *    ATRALL := GATRLEN ATR \n ATR \n ATR \0
 *
 */
typedef struct _atr
{
                char    *name;          /* (a..zA..Z0..9}{1,256}, název 
atributu */
                char    *value;         /* muže být "" nebo NULL */
                struct _atr *next;              /* odkaz na další atribut */
} _atr;

unsigned alloclen_info_atr(struct _inf **inf, struct _atr *atr, unsigned 
cntpnt);
void copy_and_add_info(struct _inf **inf, struct _atr *atr, Kokes kokes);

Attachment: parse.y
Description: Binary data

-- 
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