Core dump in PL/pgSQL ...

Started by Hans-Juergen Schoenigabout 19 years ago3 messages
#1Hans-Juergen Schoenig
postgres@cybertec.at

one of our customers here found a bug in PL/pgSQL.
this is how you can create this one:

CREATE OR REPLACE FUNCTION "public"."make_victim_history" () RETURNS
trigger AS $body$ DECLARE

schemarec RECORD;
exec_schemaselect text;
curs2 refcursor;

BEGIN

exec_schemaselect := 'SELECT nspname FROM pg_class c JOIN
pg_namespace n ON n.oid = c.relnamespace WHERE c.oid = ' || TG_RELID;

OPEN curs2 FOR EXECUTE exec_schemaselect;
FETCH curs2 INTO schemarec;
CLOSE curs2;

RAISE NOTICE 'schemarecord: %',schemarec.nspname;

RAISE NOTICE 'begin new block';
BEGIN
RAISE NOTICE 'insert now';
EXECUTE 'insert into public_history.victim SELECT * from
public.victim where id=1;';

EXCEPTION
WHEN OTHERS THEN
-- do nothing
END;

RETURN NEW;
END;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

--TABLE ERSTELLEN
CREATE TABLE "public"."victim" (
"id" BIGINT,
"name" TEXT,
"created" TIMESTAMP WITHOUT TIME ZONE,
"create_user" BIGINT,
"changed" TIMESTAMP WITHOUT TIME ZONE,
"change_user" BIGINT,
"state" SMALLINT
) WITHOUT OIDS;

INSERT INTO victim VALUES (1, 'hans', now(), 2, now(), 3, 4);

-- TRIGGER ERSTELLEN
CREATE TRIGGER "victim_tr" BEFORE UPDATE OR DELETE ON
"public"."victim" FOR EACH ROW EXECUTE PROCEDURE
"public"."make_victim_history"();

-- BAD BAD STATEMENT
UPDATE public.victim SET changed=NOW(), change_user = 1;

a quick fix is to prevent the language from freeing the tuple twice -
this should safely prevent the core dump here.
we still have to make sure that the tuple if freed properly. stay tuned.
here is the patch ...

hans

diff -rc postgresql-8.2.0-orig/src/backend/executor/spi.c  
postgresql-8.2.0/src/backend/executor/spi.c
*** postgresql-8.2.0-orig/src/backend/executor/spi.c	Tue Nov 21  
23:35:29 2006
--- postgresql-8.2.0/src/backend/executor/spi.c	Tue Dec 19 15:04:42 2006
***************
*** 264,270 ****
   		/* free Executor memory the same as _SPI_end_call would do */
   		MemoryContextResetAndDeleteChildren(_SPI_current->execCxt);
   		/* throw away any partially created tuple-table */
! 		SPI_freetuptable(_SPI_current->tuptable);
   		_SPI_current->tuptable = NULL;
   	}
   }
--- 264,270 ----
   		/* free Executor memory the same as _SPI_end_call would do */
   		MemoryContextResetAndDeleteChildren(_SPI_current->execCxt);
   		/* throw away any partially created tuple-table */
! //		SPI_freetuptable(_SPI_current->tuptable);
   		_SPI_current->tuptable = NULL;
   	}
   }

--
Cybertec Geschwinde & Schönig GmbH
Schöngrabern 134; A-2020 Hollabrunn
Tel: +43/1/205 10 35 / 340
www.postgresql.at, www.cybertec.at

#2Stefan Kaltenbrunner
stefan@kaltenbrunner.cc
In reply to: Hans-Juergen Schoenig (#1)
Re: Core dump in PL/pgSQL ...

Hans-Juergen Schoenig wrote:

[...]

a quick fix is to prevent the language from freeing the tuple twice -
this should safely prevent the core dump here.
we still have to make sure that the tuple if freed properly. stay tuned.
here is the patch ...

this seems to be already fixed with:

http://archives.postgresql.org/pgsql-committers/2006-12/msg00063.php

Stefan

#3Hans-Juergen Schoenig
postgres@cybertec.at
In reply to: Stefan Kaltenbrunner (#2)
Re: Core dump in PL/pgSQL ...

oh sorry, i think i missed that one ...
many thanks,

hans

On Dec 19, 2006, at 3:42 PM, Stefan Kaltenbrunner wrote:

Hans-Juergen Schoenig wrote:

[...]

a quick fix is to prevent the language from freeing the tuple
twice - this should safely prevent the core dump here.
we still have to make sure that the tuple if freed properly. stay
tuned.
here is the patch ...

this seems to be already fixed with:

http://archives.postgresql.org/pgsql-committers/2006-12/msg00063.php

Stefan

---------------------------(end of
broadcast)---------------------------
TIP 6: explain analyze is your friend

--
Cybertec Geschwinde & Schönig GmbH
Schöngrabern 134; A-2020 Hollabrunn
Tel: +43/1/205 10 35 / 340
www.postgresql.at, www.cybertec.at