ports/134300: PL/ruby corrupts data since Ruby upgrade to 1.8.7

pmc at citylink.dinoex.sub.org pmc at citylink.dinoex.sub.org
Wed May 6 19:30:06 UTC 2009


>Number:         134300
>Category:       ports
>Synopsis:       PL/ruby corrupts data since Ruby upgrade to 1.8.7
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed May 06 19:30:05 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator:     Peter Much
>Release:        FreeBSD 7.2-PRERELEASE i386
>Organization:
n/a
>Environment:
System: FreeBSD edge.oper.dinoex.org 7.2-PRERELEASE FreeBSD 7.2-PRERELEASE #3: Thu Apr 23 23:44:42 CEST 2009 root@:/usr/src/sys/i386/compile/E1R72V1 i386

ruby-1.8.7.72_1,1
postgresql-server-8.2.13
postgresql-plruby-0.5.0_1

Problem is not dependend on OS version.
Most likely not dependend on Postgresql version.

>Description:

Since the Ruby upgrade from 1.8.6.287 to 1.8.7.72 (which is forced
from default values in ports/Mk and therefore should be supposed to
be a stable version) the databases/postgresql-plruby port silently
produces wrong computation results, leading to database corruption.

Functions written in PL/ruby can return either simple values or
database records (SETOF record). The problem appears with functions
returning SETOF record. These functions do now ignore the parameters
given into them and instead compute with whatever value they seem fit,
producing nonsense results.

The problem was tracked down to different compile parameters of
PL/ruby. The PL/ruby package uses an extconf.rb script to create 
the makefiles. This script tests the existence of the ruby function
rb_block_call, and if found, different code will be compiled which
uses that function.

With Ruby 1.8.6.287 that function was not found, with Ruby 1.8.7.72
it is found.

It seems that either this function rb_block_call in the FreeBSD
Ruby installation 1.8.7.72, or the specific code that calls that
function from PL/ruby, is in some way broken.

When upgrading PL/ruby to the newer available version 0.5.3 , the 
malfunction is still present. But this newer version is improved
insofar that it seems to detect a problem with the parameters and
throws an error message, forcing a transaction rollback and 
eliminating the risk of silent data corruption.

I have mailed the author of PL/ruby (after detecting the problem,
before doing thorough analysis), but have not gotten a reply.

>How-To-Repeat:

Compile the beforementioned versions of ruby and PL/ruby from ports.
Check that "make configure" of "PL/ruby" will report:
	>checking for rb_block_call()... yes

Testing for the presence of the malfunction can be done in the
following way:

1. Have a running postgresQL database
2. Enable PL/ruby within that database as explained in
   the PKGMESSAGE of the PL/ruby port. 
3. Create the following PL/ruby function within the database:

create function ev_test(boolean)
returns setof record as
'if args[0]
yield [1]
end
if !args[0]
yield [2]
end'
LANGUAGE 'plruby' STABLE;

4. Call this function twice:

SELECT * FROM ev_test(true) AS (a int4);
SELECT * FROM ev_test(false) AS (a int4);

If both calls show the same result, the malfunction is present.
(When using PL/ruby 0.5.3, there will be no results shown, instead
an error message will report incompatible type of argv or something
similar.)

The test-suite contained with PL/ruby will also show the problem.

>Fix:

Suppress the use of rb_block_call when compiling PL/ruby,
drop the following patch into /usr/ports/databases/postgresql-plruby/files:

*** extconf.rb.orig   Tue Sep 19 14:39:28 2006
--- extconf.rb        Wed May  6 19:16:11 2009
***************
*** 152,159 ****
     $CFLAGS += " -DHAVE_RB_INITIALIZE_COPY"
  end
  
- have_func("rb_block_call")
- 
  if version.to_i >= 74
     if !have_header("server/utils/array.h")
        if !have_header("utils/array.h")
--- 152,157 ----


It should be further investigated: where exactly the malfunction happens,
what this function rb_block_call is good for (I have no idea) and why
it seems to have appeared between Ruby 1.8.6 and 1.8.7.

It could also be feasible to upgrade the PL/ruby port to version
0.5.3, as not only the error checking seems to be improved, but it
is also reported that this newer version is necessary when upgrading
PostgresQL to Version 8.3

>Release-Note:
>Audit-Trail:
>Unformatted:



More information about the freebsd-ports-bugs mailing list