sb-bsd-sockets: foreign memory leak in GET-PROTOCOL-BY-NAME
authorNikodemus Siivola <nikodemus@sb-studio.net>
Wed, 16 Nov 2011 16:18:23 +0000 (18:18 +0200)
committerNikodemus Siivola <nikodemus@sb-studio.net>
Wed, 16 Nov 2011 16:30:44 +0000 (18:30 +0200)
  I blame WITH-ALIEN usage -- it masks the MAKE-ALIEN calls
  from the casual eye.

NEWS
contrib/sb-bsd-sockets/inet.lisp

diff --git a/NEWS b/NEWS
index 094ae41..d0c7328 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,7 @@ changes relative to sbcl-1.0.53:
     result in fasl-dumping internal type objects. (lp#890750)
   * bug fix: type mismatch on (setf aref) and function return values no
     longer result in fasl-dumping internal type objects.
+  * bug fix: SB-BSD-SOCKETS:GET-PROTOCOL-BY-NAME leaked foreign memory.
 
 changes in sbcl-1.0.53 relative to sbcl-1.0.52:
   * enhancement: on 64-bit targets, in src/compiler/generic/early-vm.lisp,
index e07f828..e4f7ff2 100644 (file)
@@ -82,46 +82,53 @@ a list of protocol aliases"
               (sockint::protoent-name protoent)
               (let ((index 0))
                 (loop
-                   for alias = (sb-alien:deref (sockint::protoent-aliases protoent) index)
-                   while (not (sb-alien:null-alien alias))
-                   do (incf index)
-                   collect (sb-alien::c-string-to-string (sb-alien:alien-sap alias)
-                                                         (sb-impl::default-external-format)
-                                                         'character))))))
+                  for alias = (sb-alien:deref
+                               (sockint::protoent-aliases protoent) index)
+                  while (not (sb-alien:null-alien alias))
+                  do (incf index)
+                  collect (sb-alien::c-string-to-string
+                           (sb-alien:alien-sap alias)
+                           (sb-impl::default-external-format)
+                           'character))))))
     #+(and sb-thread os-provides-getprotoby-r)
     (let ((buffer-length 1024)
-          (max-buffer 10000))
+          (max-buffer 10000)
+          (result-buf nil)
+          (buffer nil)
+          #-solaris
+          (result nil))
       (declare (type fixnum buffer-length)
                (type fixnum max-buffer))
       (loop
-         (sb-alien:with-alien ((result-buf (* sockint::protoent)
-                                           (sb-alien:make-alien sockint::protoent))
-                               (buffer (* char )
-                                       (sb-alien:make-alien sb-alien:char buffer-length))
-                               #-solaris
-                               (result (* (* sockint::protoent))
-                                       (sb-alien:make-alien (* sockint::protoent))))
-
-           (let ((res (sockint::getprotobyname-r name
-                                                 result-buf
-                                                 buffer
-                                                 buffer-length
-                                                 #-solaris
-                                                 result)))
-             (if (eql res 0)
-                 (progn
-                   #-solaris
-                   (when (sb-alien::null-alien (sb-alien:deref result 0))
-                     (error 'unknown-protocol :name name))
-                   (return-from get-protocol-by-name
-                     (protoent-to-values result-buf)))
-                 (let ((errno (sb-unix::get-errno)))
-                   (if (eql errno  sockint::erange)
-                       (progn
-                         (incf buffer-length 1024)
-                         (if (> buffer-length max-buffer)
-                             (error "Exceeded max-buffer of ~d" max-buffer)))
-                       (error "Unexpected errno ~d" errno))))))))
+        (unwind-protect
+             (progn
+               (setf result-buf (sb-alien:make-alien sockint::protoent)
+                     buffer (sb-alien:make-alien sb-alien:char buffer-length))
+               #-solaris
+               (setf result (sb-alien:make-alien (* sockint::protoent)))
+               (let ((res (sockint::getprotobyname-r
+                           name result-buf buffer buffer-length #-solaris result)))
+                 (cond ((eql res 0)
+                        #-solaris
+                        (when (sb-alien::null-alien (sb-alien:deref result 0))
+                          (error 'unknown-protocol :name name))
+                        (return-from get-protocol-by-name
+                          (protoent-to-values result-buf)))
+                       (t
+                        (let ((errno (sb-unix::get-errno)))
+                          (cond ((eql errno sockint::erange)
+                                 (incf buffer-length 1024)
+                                 (when (> buffer-length max-buffer)
+                                   (error "Exceeded max-buffer of ~d" max-buffer)))
+                                (t
+                                 (error "Unexpected errno ~d" errno))))))))
+          (when result-buf
+            (sb-alien:free-alien result-buf))
+          (when buffer
+            (sb-alien:free-alien buffer))
+          #-solaris
+          (when result
+            (sb-alien:free-alien result)))))
     #-(and sb-thread os-provides-getprotoby-r)
     (tagbody
        (flet ((get-it ()