Limiting maximum RPC message length

Hans Ole Rafaelsen <[email protected]> Sun, 09 Aug 2009 18:48:09 +0200
Newsgroups gmane.comp.lang.ocaml.lib.net.devel
Message-ID <[email protected]>
Hi.

The message length given in the RPC message is checked for validity in 
that the message length is less than Sys.max_string_length. If that is 
found to hold, a string with the size given in the message is created.

On a 32bit system this is 32MB but on a 64bit this value is fairly 
large. So just connecting to a RPC server and sending some 'junk' (e.g: 
echo dddd | nc 127.0.0.1 10000 -q 1) causes the application to allocate 
several gigabytes of memory.

Here is a simple patch for rpc_transport.ml(i) that allows the user to 
set the maximum length of RPC messages. Can something along these lines 
be included into further versions on Ocamlnet?

Kindest regards,

Hans Ole Rafaelsen

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july

_______________________________________________
Ocamlnet-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ocamlnet-devel
ocamlnet-2.2.9_message_length.patch (text/x-patch, 2.9 KB)
diff -cr ocamlnet-2.2.9/src/rpc/rpc_transport.ml ocamlnet-2.2.9_message_length/src/rpc/rpc_transport.ml
*** ocamlnet-2.2.9/src/rpc/rpc_transport.ml	2007-11-01 23:12:32.000000000 +0100
--- ocamlnet-2.2.9_message_length/src/rpc/rpc_transport.ml	2009-08-09 17:33:36.000000000 +0200
***************
*** 25,30 ****
--- 25,33 ----
  
  exception Error of string
  
+ let max_message_length = ref Sys.max_string_length
+ 
+ 
  class type rpc_multiplex_controller =
  object
    method alive : bool
***************
*** 320,335 ****
  	      if rm_buffer_len = 4 then (
  		rm_last <- (Char.code rm_buffer.[0]) >= 128;
  		let rm_0 = (Char.chr ((Char.code rm_buffer.[0]) land 0x7f)) in
  		let ok =
  		  try
  		    rm <-
  		      Rtypes.int_of_uint4
  		      (Rtypes.mk_uint4 
  			 (rm_0,rm_buffer.[1],rm_buffer.[2],rm_buffer.[3]));
! 		    if rm > Sys.max_string_length then
! 		      raise(Rtypes.Cannot_represent "");
! 		    if rd_queue_len + rm > Sys.max_string_length then
! 		      raise(Rtypes.Cannot_represent "");
  		    true
  		  with
  		    | Rtypes.Cannot_represent _ -> false in
--- 323,345 ----
  	      if rm_buffer_len = 4 then (
  		rm_last <- (Char.code rm_buffer.[0]) >= 128;
  		let rm_0 = (Char.chr ((Char.code rm_buffer.[0]) land 0x7f)) in
+ 		let old_rm = rm in
  		let ok =
  		  try
  		    rm <-
  		      Rtypes.int_of_uint4
  		      (Rtypes.mk_uint4 
  			 (rm_0,rm_buffer.[1],rm_buffer.[2],rm_buffer.[3]));
! 		    if rm > !max_message_length then
! 		      (
! 			rm <- old_rm;
! 			raise(Rtypes.Cannot_represent "")
! 		      );
! 		    if rd_queue_len + rm > !max_message_length then
! 		      (
! 			rm <- old_rm;
! 			raise(Rtypes.Cannot_represent "")
! 		      );
  		    true
  		  with
  		    | Rtypes.Cannot_represent _ -> false in
***************
*** 562,564 ****
--- 572,588 ----
        fd esys in
    new stream_rpc_multiplex_controller sockname peername None mplex esys
  ;;
+ 
+ let set_max_message_length length =
+   if length < Sys.max_string_length then
+     begin
+       max_message_length := length;
+       true
+     end
+   else
+     false
+ ;;
+ 
+ let get_max_message_length () =
+   !max_message_length
+ ;;
diff -cr ocamlnet-2.2.9/src/rpc/rpc_transport.mli ocamlnet-2.2.9_message_length/src/rpc/rpc_transport.mli
*** ocamlnet-2.2.9/src/rpc/rpc_transport.mli	2007-11-01 23:12:32.000000000 +0100
--- ocamlnet-2.2.9_message_length/src/rpc/rpc_transport.mli	2009-08-09 17:48:58.000000000 +0200
***************
*** 172,174 ****
--- 172,184 ----
           Unixqueue.event_system ->
              rpc_multiplex_controller
    (** The class is exported for the SSL transporter *)
+ 
+ val set_max_message_length : int -> bool
+   (** Set the max length for RPC messages. 
+ 
+       Return true if length is aceptable 
+       (less than Sys.max_string_length), false otherwise
+   *)
+ 
+ val get_max_message_length : unit -> int
+   (** Return max length for RPC messages *)