From b3dee26c8738a2ed821d8097c54f8fcda0c50cf5 Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Wed, 28 Oct 2009 12:34:41 -0700 Subject: [PATCH] prevent stack overflow for massive binaries in c decoder --- History.txt | 1 + ext/decoder.c | 14 +++++++------- test/decode_spec.rb | 5 +++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/History.txt b/History.txt index 62a3068..f3e011f 100644 --- a/History.txt +++ b/History.txt @@ -1,6 +1,7 @@ == * Bug Fixes * Fix bignum encoding + * Prevent stack overflow for massive binaries in c decoder == 1.1.0 / 2009-10-08 * Minor Improvements diff --git a/ext/decoder.c b/ext/decoder.c index 01f2e78..2353b60 100644 --- a/ext/decoder.c +++ b/ext/decoder.c @@ -97,7 +97,7 @@ VALUE read_large_tuple(unsigned char **pData) { rb_raise(rb_eStandardError, "Invalid Type, not a large tuple"); } - int arity = read_4(pData); + unsigned int arity = read_4(pData); VALUE array = rb_ary_new2(arity); @@ -114,7 +114,7 @@ VALUE read_list(unsigned char **pData) { rb_raise(rb_eStandardError, "Invalid Type, not an erlang list"); } - int size = read_4(pData); + unsigned int size = read_4(pData); VALUE newref_class = rb_const_get(mErlectricity, rb_intern("List")); VALUE array = rb_funcall(newref_class, rb_intern("new"), 1, INT2NUM(size)); @@ -131,7 +131,7 @@ VALUE read_list(unsigned char **pData) { // primitives -void read_string_raw(unsigned char *dest, unsigned char **pData, int length) { +void read_string_raw(unsigned char *dest, unsigned char **pData, unsigned int length) { memcpy((char *) dest, (char *) *pData, length); *(dest + length) = (unsigned char) 0; *pData += length; @@ -142,12 +142,12 @@ VALUE read_bin(unsigned char **pData) { rb_raise(rb_eStandardError, "Invalid Type, not an erlang binary"); } - int length = read_4(pData); + unsigned int length = read_4(pData); - unsigned char buf[length + 1]; - read_string_raw(buf, pData, length); + VALUE rStr = rb_str_new((char *) *pData, length); + *pData += length; - return rb_str_new((char *) buf, length); + return rStr; } VALUE read_string(unsigned char **pData) { diff --git a/test/decode_spec.rb b/test/decode_spec.rb index f2bed9e..b178c85 100644 --- a/test/decode_spec.rb +++ b/test/decode_spec.rb @@ -127,6 +127,11 @@ get("f").should == :f end + specify "massive binaries should not overflow the stack" do + bin = [131,109,0,128,0,0].pack('c*') + ('a' * (8 * 1024 * 1024)) + assert_equal (8 * 1024 * 1024), Erlectricity::Decoder.decode(bin).size + end + specify "a good thing should be awesome" do get(%Q-[{options,{struct,[{test,<<"I'm chargin' mah lazer">>}]}},{passage,<<"Why doesn't this work?">>}]-).should == [[:options, [:struct, [[:test, "I'm chargin' mah lazer"]]]], [:passage, "Why doesn't this work?"]]