summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2016-04-30 22:28:04 +0900
committerLorenzo Colitti <lorenzo@google.com>2016-04-30 22:28:04 +0900
commitb8efc1b29a7de028fddca23a8234428ac149f783 (patch)
tree1e91f1b0ad3171a47199db4acf437b5cac2156a5
parent7e19898a6e0384e9c03d5f85d7f1b292590c1ec5 (diff)
downloadtests-b8efc1b29a7de028fddca23a8234428ac149f783.tar.gz
Test for socket calls returning uninitialized memory.android-wear-n-preview-3android-wear-n-preview-1android-n-preview-3
Bug: 28347599 Change-Id: I163db26458a24640013353848ddc42788770a0c8
-rw-r--r--net/test/csocket.py32
-rwxr-xr-xnet/test/csocket_test.py46
-rwxr-xr-xnet/test/leak_test.py51
3 files changed, 128 insertions, 1 deletions
diff --git a/net/test/csocket.py b/net/test/csocket.py
index 5dc495c..ad7fd9d 100644
--- a/net/test/csocket.py
+++ b/net/test/csocket.py
@@ -32,6 +32,7 @@ MsgHdr = cstruct.Struct("msghdr", "@LLLLLLi",
SockaddrIn = cstruct.Struct("sockaddr_in", "=HH4sxxxxxxxx", "family port addr")
SockaddrIn6 = cstruct.Struct("sockaddr_in6", "=HHI16sI",
"family port flowinfo addr scope_id")
+SockaddrStorage = cstruct.Struct("sockaddr_storage", "=H126s", "family data")
# Constants.
CMSG_ALIGNTO = struct.calcsize("@L") # The kernel defines this as sizeof(long).
@@ -108,7 +109,7 @@ def _MakeMsgControl(optlist):
def Bind(s, to):
- """Python wrapper for connect."""
+ """Python wrapper for bind."""
ret = libc.bind(s.fileno(), to.CPointer(), len(to))
MaybeRaiseSocketError(ret)
return ret
@@ -180,3 +181,32 @@ def Sendmsg(s, to, data, control, flags):
MaybeRaiseSocketError(ret)
return ret
+
+
+def Recvfrom(s, size, flags=0):
+ """Python wrapper for recvfrom."""
+ buf = ctypes.create_string_buffer(size)
+ addr = ctypes.create_string_buffer(len(SockaddrStorage))
+ alen = ctypes.c_int(len(addr))
+
+ ret = libc.recvfrom(s.fileno(), buf, len(buf), flags,
+ addr, ctypes.byref(alen))
+ MaybeRaiseSocketError(ret)
+
+ data = buf[:ret]
+ alen = alen.value
+ addr = addr.raw[:alen]
+
+ # Attempt to convert the address to something we understand.
+ if alen == 0:
+ addr = None
+ elif alen == len(SockaddrIn) and SockaddrIn(addr).family == socket.AF_INET:
+ addr = SockaddrIn(addr)
+ elif alen == len(SockaddrIn6) and SockaddrIn6(addr).family == socket.AF_INET6:
+ addr = SockaddrIn6(addr)
+ elif alen == len(SockaddrStorage): # Can this ever happen?
+ addr = SockaddrStorage(addr)
+ else:
+ pass # Unknown or malformed. Return the raw bytes.
+
+ return data, addr
diff --git a/net/test/csocket_test.py b/net/test/csocket_test.py
new file mode 100755
index 0000000..7c47598
--- /dev/null
+++ b/net/test/csocket_test.py
@@ -0,0 +1,46 @@
+#!/usr/bin/python
+#
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Unit tests for csocket."""
+
+import socket
+import unittest
+
+import csocket
+
+
+class CsocketTest(unittest.TestCase):
+
+ def CheckRecvfrom(self, family, addr):
+ s = socket.socket(family, socket.SOCK_DGRAM, 0)
+ s.bind((addr, 0))
+
+ addr = s.getsockname()
+ sockaddr = csocket.Sockaddr(addr)
+ s.sendto("foo", addr)
+ data, addr = csocket.Recvfrom(s, 4096, 0)
+ self.assertEqual("foo", data)
+ self.assertEqual(sockaddr, addr)
+
+ s.close()
+
+ def testRecvfrom(self):
+ self.CheckRecvfrom(socket.AF_INET, "127.0.0.1")
+ self.CheckRecvfrom(socket.AF_INET6, "::1")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/net/test/leak_test.py b/net/test/leak_test.py
new file mode 100755
index 0000000..c748155
--- /dev/null
+++ b/net/test/leak_test.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+#
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from errno import * # pylint: disable=wildcard-import
+from socket import * # pylint: disable=wildcard-import
+import threading
+import time
+import unittest
+
+import csocket
+import net_test
+
+
+class LeakTest(net_test.NetworkTest):
+
+ def testRecvfromLeak(self):
+ s = socket(AF_INET6, SOCK_DGRAM, 0)
+ s.bind(("::1", 0))
+
+ # Call shutdown on another thread while a recvfrom is in progress.
+ net_test.SetSocketTimeout(s, 200)
+ def ShutdownSocket():
+ time.sleep(0.1)
+ self.assertRaisesErrno(ENOTCONN, s.shutdown, SHUT_RDWR)
+
+ t = threading.Thread(target=ShutdownSocket)
+ t.start()
+
+ # This could have been written with just "s.recvfrom", but because we're
+ # testing for a bug where the kernel returns garbage, it's probably safer
+ # to call the syscall directly.
+ data, addr = csocket.Recvfrom(s, 4096)
+ self.assertEqual("", data)
+ self.assertEqual(None, addr)
+
+
+if __name__ == "__main__":
+ unittest.main()