Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird Bytes Added to Attribute After Save in Rails

We're experiencing an insane bug where seemingly random bytes are some 90% of the time being tacked on to an email field right at the point when the email is being saved. Here's an example of what might occur:

From params: '[email protected]'
Before validate: '[email protected]'
After validate: '[email protected]'
Before save: '[email protected]'
Value in object after save: '[email protected]'
Retrieve record just created by id, and fetch id: '[email protected]\u007f'

Where the heck did that \u007f (the UTF-8 delete character!!!) come from?! That's by far the most common garbage that shows up. Here's a list some other valid byte sequences that have appeared from time to time:

r\u007f
U\u007f
a\u007f
#m$\u007f

Sometimes I get totally garbage bits, I can't tell if there are more bytes than these due to a PG::CharacterNotInRepertoire error:

0xde 0x4d
0xf6 0x7f
0xbc
0xe3 0x6c 0x24

Given the PG::CharacterNotInRepertoire errors that occur, I'm assuming this is happening somewhere immediately before the value is being saved, but outside of the scope of my application code.

Note that this is strangely not happening for any other fields for the user.

Here are all the callbacks that currently touch the email address:

  • #strip! and #downcase! before validation
  • Format validation with the regex \A[A-Za-z0-9._%+-]+@(?:[A-Za-z0-9-]+\.)+[A-Za-z]{2,20}\z

Some app info:

  • Ruby v2.2.0
  • Rails v4.1.8
  • Postgres v9.3.2
  • PG v0.17.1
like image 576
fny Avatar asked Mar 06 '15 02:03

fny


2 Answers

Turns out that pg-ruby < v0.18.0 is incompatible with Ruby v2.2 despite there being no obvious warnings to the contrary...

https://bitbucket.org/ged/ruby-pg/issue/210/crazy-bytes-being-added-to-record

Upgrade now or get bit(s).

like image 157
fny Avatar answered Nov 16 '22 08:11

fny


Also be aware that if you're using Rails 4.2.0, there is an issue with pg 0.18.* that affects writing binary data. I currently have 4.2.0 monkey-patched with the the patch that will be in 4.2.1. See https://github.com/rails/rails/pull/17680 for details if you are running 4.2.0 with Ruby 2.2 (and thus with pg 0.18.). There may be similar issues on Rails 4.0. and 4.1.* - I haven't figured out which version have the patch, and whether those versions have been released yet.

My monkey-patch for 4.2.0 looks like:

# Should release in Rails 4.2.1
# PostgreSQL, Fix change detection caused by superfluous bytea unescaping
# See https://github.com/rails/rails/pull/17680
if Rails.version == '4.2.0'
  module ActiveRecord
    module ConnectionAdapters
      module PostgreSQL
        module OID # :nodoc:
          class Bytea < Type::Binary # :nodoc:
            def type_cast_from_database(value)
              return if value.nil?
              return value.to_s if value.is_a?(Type::Binary::Data)
              PGconn.unescape_bytea(super)
            end
          end
        end
      end
    end
  end
end
like image 35
tovodeverett Avatar answered Nov 16 '22 08:11

tovodeverett