Issue 5422 - strerror(errno) problems
Summary: strerror(errno) problems
Status: VERIFIED FIXED
Alias: None
Product: OpenLDAP
Classification: Unclassified
Component: slapd (show other issues)
Version: unspecified
Hardware: All All
: --- normal
Target Milestone: 2.5.0
Assignee: OpenLDAP project
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-03-13 17:17 UTC by Hallvard Furuseth
Modified: 2020-10-14 20:59 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Hallvard Furuseth 2008-03-13 17:17:05 UTC
Full_Name: Hallvard B Furuseth
Version: HEAD, RE23, RE24
OS: 
URL: 
Submission from: (NULL) (129.240.6.233)
Submitted by: hallvard


"grep -i strerror" shows some places <strerror/STRERROR>(errno)
are passed to Debug().  However Debug() can evaluate its arguments
twice: for -d output and syslog.  Thus it can syslog the wrong
message, since the -d stdio call can change errno.

Also strerror() can return NULL, which can break with Debug(%s).
STRERROR() fixes that, but not the duplicate call.  And strerror
too can change errno:-(  So the STRERROR() variant
  #elif defined( HAVE_STRERROR )
  #define STRERROR(e) ( strerror(e) ? strerror(e) : _AC_ERRNO_UNKNOWN )
in include/ac/errno.h isn't quite safe either.

I suggest we put something like below in ac/string.h or
ac/errno.h, then we can usually say
	if (whatever) {
		DEF_STRERROR(msg, errno);
		Debug(..., msg, ...);
	}

ac/something.h:
#define DEF_STRERROR(msg, err) \
	DECL_STRERROR(msg); \
	SET_STRERROR(msg, err)

#ifdef HAVE_SYS_ERRLIST
#define DECL_STRERROR(msg) \
	unsigned int msg##_err_; \
	const char *msg
#define SET_STRERROR(msg, err) \
	((void)(msg = (msg##_err_ = (e)) < (unsigned) sys_nerr \
			? sys_errlist[msg##_err_] : _AC_ERRNO_UNKNOWN))

#elif <threaded> && defined( HAVE_NONPOSIX_STRERROR_R )
#define DECL_STRERROR(msg) \
	char msg##_buf_[80]; \
	const char *msg
#define SET_STRERROR(msg, err) \
	((void) ((msg = strerror_r(err, msg##_buf_, 80)) || \
		(msg = _AC_ERRNO_UNKNOWN)))

#elif <threaded> && defined( HAVE_STRERROR_R )
#define DECL_STRERROR(msg) \
	char msg##_buf_[80]; \
	const char *msg
#define SET_STRERROR(msg, err) \
	((void) (msg = strerror_r(err, msg##_buf_, 80) != -1 \
		? msg##_buf_ : _AC_ERRNO_UNKNOWN))

#elif defined( HAVE_STRERROR )
#define DECL_STRERROR(msg) \
	const char *msg
#define SET_STRERROR(msg, err) \
	((void) ((msg = strerror(err)) || (msg = _AC_ERRNO_UNKNOWN)))

#else
#define DECL_STRERROR(msg)	const char *msg
#define SET_STRERROR(msg, err)	((void) (msg = "Unknown error"))
#endif


Don't know what the #if <threaded> test should look like, see ITS#5421.

Comment 1 Howard Chu 2008-04-09 10:26:50 UTC
moved from Incoming to Development
Comment 2 Quanah Gibson-Mount 2020-09-25 20:57:03 UTC
  • 3f5293e1 
by Ondřej Kuzník at 2020-09-24T23:34:36+00:00 
ITS#5422 Save errno before passing it to Debug()