Skip to content

Commit 295dd1d

Browse files
authored
Merge pull request #153 from rhenium/ky/ssl-read-fix-leak-uninitialized
ssl: prevent SSLSocket#sysread* from leaking uninitialized data
2 parents 45bec38 + 6ff7844 commit 295dd1d

File tree

2 files changed

+39
-11
lines changed

2 files changed

+39
-11
lines changed

ext/openssl/ossl_ssl.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,20 +1688,26 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
16881688
}
16891689

16901690
ilen = NUM2INT(len);
1691-
if(NIL_P(str)) str = rb_str_new(0, ilen);
1692-
else{
1693-
StringValue(str);
1694-
rb_str_modify(str);
1695-
rb_str_resize(str, ilen);
1691+
if (NIL_P(str))
1692+
str = rb_str_new(0, ilen);
1693+
else {
1694+
StringValue(str);
1695+
if (RSTRING_LEN(str) >= ilen)
1696+
rb_str_modify(str);
1697+
else
1698+
rb_str_modify_expand(str, ilen - RSTRING_LEN(str));
16961699
}
1697-
if(ilen == 0) return str;
1700+
OBJ_TAINT(str);
1701+
rb_str_set_len(str, 0);
1702+
if (ilen == 0)
1703+
return str;
16981704

16991705
GetSSL(self, ssl);
17001706
io = rb_attr_get(self, id_i_io);
17011707
GetOpenFile(io, fptr);
17021708
if (ssl_started(ssl)) {
17031709
for (;;){
1704-
nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LENINT(str));
1710+
nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
17051711
switch(ssl_get_error(ssl, nread)){
17061712
case SSL_ERROR_NONE:
17071713
goto end;
@@ -1751,8 +1757,6 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
17511757

17521758
end:
17531759
rb_str_set_len(str, nread);
1754-
OBJ_TAINT(str);
1755-
17561760
return str;
17571761
}
17581762

test/test_pair.rb

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def test_read_nonblock
218218
assert_nothing_raised("[ruby-core:20298]") { ret = s2.read_nonblock(10) }
219219
assert_equal("def\n", ret)
220220
s1.close
221-
sleep 0.1
221+
IO.select([s2])
222222
assert_raise(EOFError) { s2.read_nonblock(10) }
223223
}
224224
end
@@ -234,11 +234,35 @@ def test_read_nonblock_no_exception
234234
assert_nothing_raised("[ruby-core:20298]") { ret = s2.read_nonblock(10, exception: false) }
235235
assert_equal("def\n", ret)
236236
s1.close
237-
sleep 0.1
237+
IO.select([s2])
238238
assert_equal(nil, s2.read_nonblock(10, exception: false))
239239
}
240240
end
241241

242+
def test_read_with_outbuf
243+
ssl_pair { |s1, s2|
244+
s1.write("abc\n")
245+
buf = ""
246+
ret = s2.read(2, buf)
247+
assert_same ret, buf
248+
assert_equal "ab", ret
249+
250+
buf = "garbage"
251+
ret = s2.read(2, buf)
252+
assert_same ret, buf
253+
assert_equal "c\n", ret
254+
255+
buf = "garbage"
256+
assert_equal :wait_readable, s2.read_nonblock(100, buf, exception: false)
257+
assert_equal "", buf
258+
259+
s1.close
260+
buf = "garbage"
261+
assert_equal nil, s2.read(100, buf)
262+
assert_equal "", buf
263+
}
264+
end
265+
242266
def test_write_nonblock
243267
ssl_pair {|s1, s2|
244268
assert_equal 3, s1.write_nonblock("foo")

0 commit comments

Comments
 (0)