On 08/12/14 02:29, Paul Eggert wrote: > Pádraig Brady wrote: >> BTW if free() may reset errno on some platforms then it's >> probably worth augmenting the gnulib free() wrapper >> to restore errno if needed, > > The documented GNU behavior for 'free' allows 'free' to set errno, right? So > why should the corresponding gnulib wrapper guarantee behavior above and > beyond > what GNU implements? > > It might make sense to have a variant of 'free' that preserves errno, but we > should probably give the variant a different name. 'noerr_free', say. >
Well gnu docs never mention errno wrt free() so I suppose it's therefore possible to be set to anything. I did check GNU,{free,net,open}bsd,solaris and none touch the errno for valid, NULL, or invalid pointers. However I suppose there are certain edge cases where the errno can be set. For example see the discussion at: http://lists.freebsd.org/pipermail/freebsd-arch/2012-June/012669.html Moreover since it's not practical to test for those cases at configure time, the POSIX note previously referenced in this thread is not possible to take advantage of portably. Hence I pushed the attached to address this. thanks, Pádraig.
From ec6a60bfd9ba0f12ec07809636891909ee7ded66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com> Date: Mon, 8 Dec 2014 09:46:38 +0000 Subject: [PATCH] vasnprintf: fix potential incorrect errno An adjustment of the previous commit c5c4f53b. * lib/vasnprintf.c (VASNPRINTF): free() generally doesn't set errno, but it can potentially in certain edge cases. Reported by Eric Blake. --- lib/vasnprintf.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 223be07..a73fad6 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -5179,18 +5179,21 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, /* SNPRINTF or sprintf failed. Save and use the errno that it has set, if any. */ int saved_errno = errno; + if (saved_errno == 0) + { + if (dp->conversion == 'c' || dp->conversion == 's') + saved_errno = EILSEQ; + else + saved_errno = EINVAL; + } if (!(result == resultbuf || result == NULL)) free (result); if (buf_malloced != NULL) free (buf_malloced); - errno = - (saved_errno != 0 - ? saved_errno - : (dp->conversion == 'c' || dp->conversion == 's' - ? EILSEQ - : EINVAL)); CLEANUP (); + + errno = saved_errno; return NULL; } -- 2.1.0