You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@thrift.apache.org by Nevo Hed <nh...@aereo.com> on 2012/06/20 04:16:38 UTC

Re: Deserialization failure with ruby [THRIFT-1632]

I have created a Jira bug report for this and submitted a patch (fix tested
with 0.7.0 & svn trunk)

https://issues.apache.org/jira/browse/THRIFT-1632

  -Nevo


$ svn diff
Index: memory_buffer.c
===================================================================
--- memory_buffer.c (revision 1351768)
+++ memory_buffer.c (working copy)
@@ -93,17 +93,13 @@
   int index;
   VALUE buf = GET_BUF(self);

+  index = FIX2INT(rb_ivar_get(self, index_ivar_id));
   while (i < size) {
-    index = FIX2INT(rb_ivar_get(self, index_ivar_id));
     if (index >= RSTRING_LEN(buf)) {
       rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer");
     }
     char byte = RSTRING_PTR(buf)[index++];

-    if (index >= GARBAGE_BUFFER_SIZE) {
-      rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2,
INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1)));
-      index = 0;
-    }
     rb_ivar_set(self, index_ivar_id, INT2FIX(index));

     if (i >= RSTRING_LEN(buffer_value)) {
@@ -112,6 +108,12 @@
     ((char*)RSTRING_PTR(buffer_value))[i] = byte;
     i++;
   }
+  if (index >= GARBAGE_BUFFER_SIZE) {
+    rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2,
INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1)));
+    index = 0;
+  }
+  rb_ivar_set(self, index_ivar_id, INT2FIX(index));
+
   return INT2FIX(i);
 }




On Tue, Jun 19, 2012 at 12:38 AM, Nevo Hed <nh...@aereo.com> wrote:

>
> This is tested with thrift 0.7.0, and as it is pretty sensitive (removing
> or changing the type of any of these definitions seems to make the problem
> go away)
> The failures are typically those of validation errors as you see below,
> but other have been seen as well.
>
> Has anyone seen anything like this?
>
> Thanks
>    -Nevo
>
> --8<------------test.thrift-----------------------------------------------
> enum En1 {
>   EN1_0 = 1
> }
>
> struct MapEl {
>   1: required En1 x1 = En1.EN1_0,
>   2: required i32 x2 = 2,
>   7: optional i32 x3 = 3,
>   8: optional i32 x4 = 4,
> }
>
> struct topStruct {
>   1: required i32            y1 = 1,
>   2: required i16            y2 = 2,
>   3: required i32            y3 = 3,
>   4: optional map<i32,MapEl> y4 = {},
> }
>
> --8<------------test.rb----------------------------------------------------
>
> #!/usr/bin/ruby
> require 'thrift'
> require 'gen-rb/test_types'
>
> begin
>   v=TopStruct.new
>
>   for i in 1..124 do
>     v.y4[i]=MapEl.new()
>   end
>
>   ruby_binary_protocol =
> Thrift::BinaryProtocol.new(Thrift::MemoryBufferTransport.new)
>
>   v.write(ruby_binary_protocol)
>   TopStruct.new.read(ruby_binary_protocol)
>   # drop read data on the floor
>
> rescue Exception => tx
>   print "Caught #{tx.class} exception: #{tx.message}\n"
>   print "Trace:\n  ", tx.backtrace.join("\n  "), "\n"
> end
> nil
>
> --8<----------------------------------------------------------------------
>
> $ /usr/bin/thrift --gen rb test.thrift && ruby test.rb
> Caught Thrift::ProtocolException exception: Invalid value of field x1!
> Trace:
>   ./gen-rb/test_types.rb:34:in `validate'
>   test.rb:15:in `read'
>   test.rb:15
>
>