From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: soeren@soeren-tempel.net Newsgroups: gmane.lisp.guile.devel,gmane.lisp.guile.bugs Subject: [PATCH] load-foreign-library: perform substring match on library files Date: Sat, 23 Jul 2022 13:09:20 +0200 Message-ID: <20220723110919.30107-1-soeren@soeren-tempel.net> References: <23TGNISPS9PPL.2YOENNQD9V56X@8pit.net> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="20023"; mail-complaints-to="usenet@ciao.gmane.io" Cc: guile-devel@gnu.org To: bug-guile@gnu.org Original-X-From: guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org Sat Jul 23 14:41:30 2022 Return-path: Envelope-to: guile-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oFERl-000521-ML for guile-devel@m.gmane-mx.org; Sat, 23 Jul 2022 14:41:30 +0200 Original-Received: from localhost ([::1]:51030 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oFERj-0007i4-EZ for guile-devel@m.gmane-mx.org; Sat, 23 Jul 2022 08:41:27 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:38036) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oFD1M-0003AM-6U; Sat, 23 Jul 2022 07:10:08 -0400 Original-Received: from magnesium.8pit.net ([45.76.88.171]:19212) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oFD1J-00022N-MQ; Sat, 23 Jul 2022 07:10:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=opensmtpd; bh=BhkY6Xe2GU yM0zbrkEwred86gwWh9yHDxIvRixqPANM=; h=references:in-reply-to:date: subject:cc:to:from; d=soeren-tempel.net; b=nnazJ49FIfHh0dptAjOd9LTqTbJ qeB8vvXeLeNPx5PBqmexxH3iYmCPha7lMOC2h2SyUyhiXj0IXRlV/MrZes9ei71fBNvLsX 4mcWfIkbXsMlDFP6U2lmqzywl97EqNsBBKKJ3NhyW7NJaqH3v8RcEKX3vDEX0ijQ6ttAIh uG78= Original-Received: from localhost (ipb218e485.dynamic.kabel-deutschland.de [178.24.228.133]) by magnesium.8pit.net (OpenSMTPD) with ESMTPSA id 54d12e93 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:YES); Sat, 23 Jul 2022 13:09:56 +0200 (CEST) X-Mailer: git-send-email 2.37.1 In-Reply-To: <23TGNISPS9PPL.2YOENNQD9V56X@8pit.net> Received-SPF: pass client-ip=45.76.88.171; envelope-from=soeren@soeren-tempel.net; helo=magnesium.8pit.net X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sat, 23 Jul 2022 08:41:02 -0400 X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org Original-Sender: "guile-devel" Xref: news.gmane.io gmane.lisp.guile.devel:21269 gmane.lisp.guile.bugs:10306 Archived-At: From: Sören Tempel This patch is a fix for bug #49232 [1]. To summarize this bug, the current load-foreign-library implementation does not load versioned sonames (e.g. libfoo.so.5) which are common on Linux. This is an issue for us at Alpine Linux since we ship unversioned sonames (e.g. libfoo.so) separately. Please refer to the original bug report for details. This patch attempts to fix this issue by performing a substring match on library files in load-foreign-library. That is, when loading the library file for `libfoo` the new algorithm will perform a substring prefix match and return the first file which starts with `libfoo.so`. Therefore, the new algorithm will match both `libfoo.so.5` and `libfoo.so` while the current algorithm only matched the latter. In order to implement this, the new algorithm has to perform a readdir(2) syscall on directories in $LD_LIBRARY_PATH instead of just checking for the presence of a single file in each directory. Discussion: It may be desirable to make the prefix substring check more strict, presently `libzstd.something` would also match. While I believe it to be unlikely that such files exist in $LD_LIBRARY_PATH we could also perform a substring match against `basename + ext + #\.`, i.e. libzstd.so., libstzstd.so.1, libzstd.so.1.5.2 etc would match but libzstd.something wouldn't. Furthermore, if both libzstd.so.1 and libzstd.so exist in $LD_LIBRARY_PATH then the algorithm proposed here may prefer the former (depending on the readdir(2) file order). * module/system/foreign-library.scm (file-exists-in-path-with-extension): perform a substring match on library files to also match versioned .so files. * modules/system/foreign-library.scm (load-foreign-library): Perform a fuzzy substring search even if the library file contains a path-separator. [1]: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=49232 Signed-off-by: Sören Tempel --- This is my first patch for guile, if I missed anything please let me know. Also, I am not subscribed to the list so please CC me. module/system/foreign-library.scm | 63 +++++++++++++++++-------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/module/system/foreign-library.scm b/module/system/foreign-library.scm index dc426385f..87e5a3afc 100644 --- a/module/system/foreign-library.scm +++ b/module/system/foreign-library.scm @@ -57,30 +57,33 @@ (else '(".so")))) -(define (has-extension? head exts) - (match exts - (() #f) - ((ext . exts) - (or (string-contains head ext) - (has-extension? head exts))))) - -(define (file-exists-with-extension head exts) - (if (has-extension? head exts) - (and (file-exists? head) head) - (let lp ((exts exts)) - (match exts - (() #f) - ((ext . exts) - (let ((head (string-append head ext))) - (if (file-exists? head) - head - (lp exts)))))))) +(define (filename-matches-with-extension? filename basename exts) + (let lp ((exts exts)) + (match exts + (() #f) + ((ext . exts) + ;; Fuzzy comparison of filename with basename + ext. If the + ;; latter is a prefix of the former, consider it a match. This + ;; allows matching .so files with versions, e.g. libfoo.so.5. + (let ((prefix (string-append basename ext))) + (or (string-prefix? prefix filename) + (lp exts))))))) + +(define (file-exists-in-dir-with-extension dir basename exts) + (let* ((dir-stream (opendir dir)) + (ret (let loop ((fn (readdir dir-stream))) + (and (not (eof-object? fn)) + (if (filename-matches-with-extension? fn basename exts) + (in-vicinity dir fn) + (loop (readdir dir-stream))))))) + (closedir dir-stream) + ret)) (define (file-exists-in-path-with-extension basename path exts) (match path (() #f) ((dir . path) - (or (file-exists-with-extension (in-vicinity dir basename) exts) + (or (file-exists-in-dir-with-extension dir basename exts) (file-exists-in-path-with-extension basename path exts))))) (define path-separator @@ -198,16 +201,18 @@ name." (dlopen* #f)) ((or (absolute-file-name? filename) (string-any file-name-separator? filename)) - (cond - ((or (file-exists-with-extension filename extensions) - (and search-ltdl-library-path? - (file-exists-with-extension - (in-vicinity (in-vicinity (dirname filename) ".libs") - (basename filename)) - extensions))) - => dlopen*) - (else - (error-not-found)))) + (let ((dirname (dirname filename)) + (basename (basename filename))) + (cond + ((or (file-exists-in-dir-with-extension dirname basename extensions) + (and search-ltdl-library-path? + (file-exists-in-dir-with-extension + (in-vicinity dirname ".libs") + basename + extensions))) + => dlopen*) + (else + (error-not-found))))) ((file-exists-in-path-with-extension filename search-path extensions) => dlopen*) (search-system-paths?