diff options
author | Ludovic Courtès <ludo@gnu.org> | 2017-12-22 11:12:57 +0100 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2017-12-22 11:12:57 +0100 |
commit | 6d391bf1a41e378e568cd148631b1beec7577e66 (patch) | |
tree | 34b57f47d051a48f9b47295b0974a94ea255b83c /libguile/posix.c | |
parent | 2c7d6031f3b334c3e0d6de9c8eb9961439c5166f (diff) | |
download | guile-6d391bf1a41e378e568cd148631b1beec7577e66.tar.gz |
Fix 'crypt' deadlock upon error.
* libguile/posix.c (scm_crypt): Take 'scm_i_misc_mutex' right before
calling 'crypt'. Move 'SCM_SYSERROR' call after 'scm_dynwind_end'.
* test-suite/tests/posix.test ("crypt"): New test prefix.
Diffstat (limited to 'libguile/posix.c')
-rw-r--r-- | libguile/posix.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/libguile/posix.c b/libguile/posix.c index 041b8b129..c39fc57b5 100644 --- a/libguile/posix.c +++ b/libguile/posix.c @@ -1,6 +1,6 @@ /* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, * 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, - * 2014, 2016 Free Software Foundation, Inc. + * 2014, 2016, 2017 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -1935,26 +1935,43 @@ SCM_DEFINE (scm_crypt, "crypt", 2, 0, 0, "crypt(3) library call.") #define FUNC_NAME s_scm_crypt { + int err; SCM ret; char *c_key, *c_salt, *c_ret; scm_dynwind_begin (0); - scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex); c_key = scm_to_locale_string (key); scm_dynwind_free (c_key); c_salt = scm_to_locale_string (salt); scm_dynwind_free (c_salt); + /* Take the lock because 'crypt' uses a static buffer. */ + scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex); + /* The Linux crypt(3) man page says crypt will return NULL and set errno on error. (Eg. ENOSYS if legal restrictions mean it cannot be implemented). */ c_ret = crypt (c_key, c_salt); + if (c_ret == NULL) - SCM_SYSERROR; + /* Note: Do not throw until we've released 'scm_i_misc_mutex' since + this would cause a deadlock down the path. */ + err = errno; + else + { + err = 0; + ret = scm_from_locale_string (c_ret); + } - ret = scm_from_locale_string (c_ret); scm_dynwind_end (); + + if (err != 0) + { + errno = err; + SCM_SYSERROR; + } + return ret; } #undef FUNC_NAME |