diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index a50875fca..2eb9c45a9 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,9 @@
+2013-02-04  Corinna Vinschen  <corinna@vinschen.de>
+
+	* fhandler_socket.cc (fhandler_socket::bind): Fix length check of
+	AF_LOCAL filename so it never accesses memory beyond namelen.  Also
+	make sure filename is NUL-terminated.
+
 2013-01-31  Christopher Faylor  <me.cygwin2013@cgf.cx>
 
 	* DevNotes: Add entry cgf-000022.
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 6625eef05..6f13e51ce 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -900,17 +900,19 @@ fhandler_socket::bind (const struct sockaddr *name, int namelen)
     {
 #define un_addr ((struct sockaddr_un *) name)
       struct sockaddr_in sin;
-      int len = sizeof sin;
+      int len = namelen - offsetof (struct sockaddr_un, sun_path);
 
-      if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN)
+      /* Check that name is within bounds and NUL-terminated. */
+      if (len <= 1 || len > UNIX_PATH_LEN
+	  || !memchr (un_addr->sun_path, '\0', len))
 	{
-	  set_errno (ENAMETOOLONG);
+	  set_errno (len < 1 ? EINVAL : ENAMETOOLONG);
 	  goto out;
 	}
       sin.sin_family = AF_INET;
       sin.sin_port = 0;
       sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
-      if (::bind (get_socket (), (sockaddr *) &sin, len))
+      if (::bind (get_socket (), (sockaddr *) &sin, len = sizeof sin))
 	{
 	  syscall_printf ("AF_LOCAL: bind failed");
 	  set_winsock_errno ();