Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #3114 (closed defect: fixed)

Opened 3 years ago

Last modified 2 years ago

(FIXED? #4461 r4156) PostgreSQL adapter doubly unescapes bytea using ruby-postgres

Reported by: junk@miriamtech.com Assigned to: rails@bitsweat.net
Priority: normal Milestone: 1.2
Component: ActiveRecord Version: 1.0.0
Severity: normal Keywords: postgresql postgres ruby-postgres
Cc:

Description

The ruby-postgres driver (2005-11-27 snapshot) unescapes bytea columsn before handing them back up to the Ruby layer:

    switch (PQftype(result, column)) {

    case BOOLOID:
      return *string == 't' ? Qtrue : Qfalse;

    case BYTEAOID:
      return pgconn_s_unescape_bytea(NULL, rb_tainted_str_new2(string));

    case NUMERICOID:
        ...

This seems like the right place to do the translation, especially if other translations ('t' => Qtrue, 'f' => Qfalse, etc) are being done here. But the ActiveRecord PostgreSQL Connection Adapter runs a second unescape on it:

    column = row[cel_index]
    if res.type(cel_index) == BYTEA_COLUMN_TYPE_OID
      column = unescape_bytea(column)
    end
    hashed_row[fields[cel_index]] = column

This results in data truncation (if the unescaped string includes any NULL zeroes) or data corruption (if the unescaped string includes any backslashes).

Change History

12/06/05 10:03:25 changed by meadow.nnick@gmail.com

You could use PGconn.translate_results = false, and all results will be returned as strings. Or, use a workaround:

    column = row[cel_index]
    if res.type(cel_index) == BYTEA_COLUMN_TYPE_OID && ! PGconn.respond_to?("translate_results=")
      column = unescape_bytea(column)
    end
    hashed_row[fields[cel_index]] = column

that snapshot version also fails on several ActiveRecord tests because of string value translation to ruby objects.

12/06/05 18:22:17 changed by junk@miriamtech.com

What is the preferred PostgreSQL driver? I was looking for one that could perform unescape_bytea natively instead of forcing ActiveRecord to do it, since ActiveRecord defers to the driver if it is capable enough:

if PGconn.respond_to? :unescape_bytea
  self.class.send(:define_method, :unescape_bytea) do |s|
    PGconn.unescape_bytea(s) if s
  end
else
 ...

03/09/06 22:09:15 changed by anonymous

  • version changed from 0.14.3 to 1.0.0.

03/11/06 00:04:40 changed by anonymous

  • milestone set to 1.1.

The ruby-postgres driver (2005-11-27 snapshot) is the preferred one.

03/14/06 07:22:50 changed by anonymous

  • keywords set to needs_review.

03/18/06 03:51:57 changed by david

  • keywords deleted.
  • owner changed from David to rails@bitsweat.net.

04/04/06 16:56:15 changed by anonymous

  • keywords set to postgresql postgres ruby-postgres.

04/05/06 06:46:09 changed by anonymous

  • summary changed from PostgreSQL adapter doubly unescapes bytea when using ruby-postgres interface to (FIXED? #4461 r4156) PostgreSQL adapter doubly unescapes bytea using ruby-postgres.

Someone from core please confirm that this is fixed by #4461 and r4156.

Don't want to close this one as anonymous.

11/20/06 13:10:50 changed by bitsweat

  • status changed from new to closed.
  • resolution set to fixed.