Subject: Project function problem

From: "G. Andoh" <[email-masked]>
Date: Fri, 10 Apr 92 10:08:35 -0700

/*****************************************************************

  A project at Wolverhampton Polytechnic in England which involves
 the use of POSTGRES version 3.1 running on a SUN 3 (SUNOS 4.1):
   -------------------------------------------------

 Our attempts to create a user-defined type 'isbn_type' have
 not been successful to date. Please find below details of the
 various scripts and source code relevant to the specific
 function and user-defined type.

 Any assistance in locating the source of the problem would be
 appreciated.

/*
  POSTQUEL script for defining function 'isbn_in'
*/
define function isbn_in
(language="c",returntype=isbn_type)
arg is (char16) as "/u/cm7039/project/c-files/obj/isbn-in.o"
\p\g

/*
  POSTQUEL script for defining user type 'isbn_type'
*/
define type isbn_type
(internallength=36,input=isbn_in,output=isbn_out)
\p\g

/*
  Script for sample class 'book' used to hold values of
  type 'isbn_type'
*/
create book(num=isbn_type)
\p\g

/*-----------------------------------------------------------------

   Source code for function isbn_in
   ================================

 The following source code defines the input function for the
 user-defined type 'isbn_type'. Problems occur after the
 printf statement "Breaking out of isbn-in now ..." is displayed.

 the following error message is displayed:

 " Bus error - core dumped ".

------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "utils/geo-decls.h" /* Copied from ~postgres/src/lib/utils/H */

#define INPUT_LENGTH 13
#define NULL 0

/*
  Structure definition for
  user-defined type 'isbn_type'
*/

 typedef struct
  {
   char set_1;
   int set_2[2];
   int set_3[6];
   char set_4;
  }isbn_type;

/*
  Input function isbn_in
  for type 'isbn_type'
  - converts strings to internal
    storage format for 'isbn_type'
*/

 isbn_type *isbn_in(num_x)
  char *num_x;
  {
   int k,x,y;
   int q;
   char temp_array[INPUT_LENGTH],*temp_str,*z;
   isbn_type *result;

   x = 0;
   printf("Phase 1 ...\n");

   if (num_x==NULL) return(NULL);

   temp_str = num_x;

   for (k=0;k<INPUT_LENGTH;temp_str++)
	temp_array[k++] = *temp_str;

   printf("Phase 2 , stage %d\n",k);

   result = (isbn_type *)palloc(sizeof(isbn_type));
   printf("Palloc-sizeof operation done OK: = %u ...\n",
           psize(&result));

   result->set_1 = temp_array[0];
   printf("result->set_1=%c...\n",temp_array[0]);

   *z=temp_array[2];
   result->set_2[0]=atoi(z);
   printf("result->set_2[0]=%d...\n",result->set_2[0]);

   *z=temp_array[3];
   result->set_2[1]=atoi(z);
   printf("result->set_2[1]=%d...\n",result->set_2[1]);

   for (y=5;y<=10;y++)
    {
        q = x;
        *z = temp_array[y];
    	result->set_3[x++] = atoi(z);
        printf("result->set_3[%d]=%d...\n",q,result->set_3[q]);
    }

   result->set_4 = temp_array[12];
   printf("result->set_4=%c..\n",result->set_4);

   printf("Breaking out of isbn-in now...\n");
   return(result);
  }

 /*
    Sample 'Append' script for isbn_type in class 'book'
 */
 append book(num="0-47-183900-00"::isbn_type)

---

From: postarch (Postgres Mailing Archive)
Date: Fri, 10 Apr 92 14:04:02 PDT

>    if (num_x==NULL) return(NULL);

Don't return NULL from a pass by reference adt input function.  This
will lead to a core dump down the road.  You should palloc the right
amount of space and put in some value that specifies null for this type.
I don't think this is the current problem though...

>    result = (isbn_type *)palloc(sizeof(isbn_type));

You should always check the return of palloc:

     if (!result)
	elog(WARN, "Couldn't allocate %d bytes", sizeof(isbn_type));

elog(WARN, ...) causes the current xact to be aborted.  You will need to
include $POSTGRESHOME/lib/H/utils/log.h for the WARN const.

>    printf("Palloc-sizeof operation done OK: = %u ...\n",

You don't want the & (address of) operator here.

>         printf("result->set_3[%d]=%d...\n",q,result->set_3[q]);

You dereference z eight times without setting it to the address of allocated
space.  A dangerous practice that could lead to bad results.  You are
overwriting something.  If I had to guess I would say that this is problem.

In the postgres system when an adt function dumps core the backend dumps
core.  You should try to test your functions before you start dynamically
loading them, it's a lot easier to use a debugger than to use printf or
elog(NOTICE, "...")

Jeff Meredith
[email-masked]