Re: user defined type

From: Michael Fuhr <mike(at)fuhr(dot)org>
To: Kjetil Haaland <kjetil(dot)haaland(at)student(dot)uib(dot)no>
Cc: pgsql-novice(at)postgresql(dot)org
Subject: Re: user defined type
Date: 2004-11-08 21:24:16
Message-ID: 20041108212416.GA68068@winnie.fuhr.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-novice

On Mon, Nov 08, 2004 at 01:26:55PM +0100, Kjetil Haaland wrote:

> typedef struct alignres {
> int value;
> char *fstring;
> }alignres;

If you want to store character data, I think the characters must
be stored in the structure itself; I don't think using a pointer
will work (somebody please correct me if I'm mistaken). So instead
of "char *fstring" you'll need "char fstring[x]", where "x" is the
maximum size of the character data. You could also use "char fstring[1]"
and allocate the alignres structure to be as big as necessary; if
you do that then you might want to review the paragraph regarding
TOAST-able types near the end of the "User-Defined Types" section
of the documentation.

http://www.postgresql.org/docs/7.4/static/xtypes.html

Make sure your CREATE TYPE statement has "internallength" set
correctly: either to the fixed size of the structure (including
character data) or to "variable". If you use "variable" then make
sure you add the required length field to the beginning of the
structure. See the CREATE TYPE documentation for more info.

http://www.postgresql.org/docs/7.4/static/sql-createtype.html

> if(sscanf(in, "(%d, %s)", &v, &first) != 2) {

The above line has several problems:

* For a %s conversion, sscanf() expects a pointer to character;
earlier you declared first as a char *, so you're passing a pointer
to a pointer to character. sscanf() also expects the pointer to
point to a buffer sufficiently large to hold the result; you haven't
allocated any space.

* %s is greedy, so it'll grab the closing parenthesis in addition
to what precedes it. Consider using %[ instead or make sure you
strip extraneous characters from the end of the result string.

* Your %s conversion doesn't specify a maximum field width, so
you risk a buffer overflow if the result buffer isn't at least
as large as the input string.

Additionally, consider using %[ instead of %d for the first field
and store the result in a character array so you can do better
validity checking than sscanf(). For example, you could then use
strtol() to check for overflow -- with sscanf() you'd just get bogus
numbers that don't match the input.

> char temp[4+sizeof(align->fstring)+4+4];

This line in your output function might not be allocating as much
space as you think. The sizeof expression evaluates to the size
of a pointer, not to the length of the data pointed to. You're
probably allocating about 16 bytes here, which might be less
than you need.

> sprintf(temp, "(%d, %s)",
> align->value,
> align->fstring);

By using sprintf() instead of snprintf() you again risk a buffer
overflow, especially since temp might be smaller than you were
expecting.

There might be other problems but those stood out when I looked
through the code. If you still have trouble then please post
the updated code and describe what happens when you try to use
the type.

Hope this helps.

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

In response to

Responses

Browse pgsql-novice by date

  From Date Subject
Next Message Ian Meyer 2004-11-09 03:27:39 Issue with sequence and transactions
Previous Message Molenda, Mark P 2004-11-08 20:13:28 Re: How to allow a JDBC to connect to my postgres databa