Subject: | Bug + Patch: tcpecho.pl example script memory allocation |
In SSLeay.pm, tcp_read_all(), the default buffer size is set to 2 billion bytes (a bit smaller than 2 GB). The subsequent sysread() call attempts to allocate $how_much memory. In the case where no argument is supplied to tcp_read_all(), this defaults to the aforementioned 2 billion bytes.
This may or may not be viewed as problematic in and of itself, in that so long as the invoker passes in a reasonable $how_much value the memory allocation will be possible. However, lacking a passed in $how_much value, the memory allocation done by the sysread() call is very likely to fail.
While the ssl_read_all() code also has a default $how_much value of 2 billion bytes, the underlying code invokes SSL_read(), which actually uses a 32k buffer size to chunk the reads, thereby avoiding a huge memory allocation request up front.
The above problem rears its head in the test script for this module in test 5, which invokes the tcpecho.pl example script. This script (which was new for version 1.25) does not pass in a $how_much value for tcp_read_all(). Therefore, the sysread() attempts to allocate 2 billion bytes, which fails due to ENOMEM.
For dealing with the most immediate issue, a patch like the one included below can be used to make the tcpecho.pl pass a reasonable $how_much buffer size to tcp_read_all(). This will allow the test to succeed.
diff -Pur Net_SSLeay.pm-1.25.orig/examples/tcpecho.pl Net_SSLeay.pm-1.25/examples/tcpecho.pl
--- Net_SSLeay.pm-1.25.orig/examples/tcpecho.pl Sun Aug 17 03:44:47 2003
+++ Net_SSLeay.pm-1.25/examples/tcpecho.pl Tue Jan 25 12:42:32 2005
@@ -14,6 +14,8 @@
($port) = @ARGV;
$our_ip = "\x7F\0\0\x01";
+$READ_MAX = 1048576;
+
$trace = 2;
use Socket;
use Net::SSLeay;
@@ -43,7 +45,7 @@
# Connected. Exchange some data.
#
- $got = Net::SSLeay::tcp_read_all() or die "$$: read failed";
+ $got = Net::SSLeay::tcp_read_all($READ_MAX) or die "$$: read failed";
print "tcpecho $$: got " . length($got) . " bytes\n" if $trace==2;
print "tcpecho: Got `$got' (" . length ($got) . " chars)\n" if $trace>2;
$got = uc $got;