Skip to content

Commit 6ff7844

Browse files
committed
ssl: prevent SSLSocket#sysread* from leaking uninitialized data
Set the length of the buffer string to 0 first, and adjust to the size successfully read by the SSL_read() call later. This is needed because the buffer string may be provided by the caller.
1 parent 6c5e6b3 commit 6ff7844

File tree

2 files changed

+37
-9
lines changed

2 files changed

+37
-9
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: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,30 @@ def test_read_nonblock_no_exception
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)