mirror of https://git.tukaani.org/xz.git
tuklib_mbstr_nonprint: Preserve the value of errno
A typical use case is like this:
printf("%s: %s\n", tuklib_mask_nonprint(filename), strerror(errno));
tuklib_mask_nonprint() may call mbrtowc() and malloc() which may modify
errno. If errno isn't preserved, the error message might be wrong if
a compiler decides to call tuklib_mask_nonprint() before strerror().
Fixes: 40e5733055
This commit is contained in:
parent
2a9e91d796
commit
c405264c03
|
@ -12,6 +12,7 @@
|
|||
#include "tuklib_mbstr_nonprint.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_MBRTOWC
|
||||
# include <wchar.h>
|
||||
|
@ -94,13 +95,18 @@ has_nonprint(const char *str, size_t len)
|
|||
extern bool
|
||||
tuklib_has_nonprint(const char *str)
|
||||
{
|
||||
return has_nonprint(str, strlen(str));
|
||||
const int saved_errno = errno;
|
||||
const bool ret = has_nonprint(str, strlen(str));
|
||||
errno = saved_errno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
extern const char *
|
||||
tuklib_mask_nonprint_r(const char *str, char **mem)
|
||||
{
|
||||
const int saved_errno = errno;
|
||||
|
||||
// Free the old string, if any.
|
||||
free(*mem);
|
||||
*mem = NULL;
|
||||
|
@ -108,8 +114,10 @@ tuklib_mask_nonprint_r(const char *str, char **mem)
|
|||
// If the whole input string contains only printable characters,
|
||||
// return the input string.
|
||||
const size_t len = strlen(str);
|
||||
if (!has_nonprint(str, len))
|
||||
if (!has_nonprint(str, len)) {
|
||||
errno = saved_errno;
|
||||
return str;
|
||||
}
|
||||
|
||||
// Allocate memory for the masked string. Since we use the single-byte
|
||||
// character '?' to mask non-printable characters, it's possible that
|
||||
|
@ -119,8 +127,10 @@ tuklib_mask_nonprint_r(const char *str, char **mem)
|
|||
// If allocation fails, return "???" because it should be safer than
|
||||
// returning the unmasked string.
|
||||
*mem = malloc(len + 1);
|
||||
if (*mem == NULL)
|
||||
if (*mem == NULL) {
|
||||
errno = saved_errno;
|
||||
return "???";
|
||||
}
|
||||
|
||||
// Replace all non-printable characters with '?'.
|
||||
char *dest = *mem;
|
||||
|
@ -139,6 +149,7 @@ tuklib_mask_nonprint_r(const char *str, char **mem)
|
|||
|
||||
*dest = '\0';
|
||||
|
||||
errno = saved_errno;
|
||||
return *mem;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ extern bool tuklib_has_nonprint(const char *str);
|
|||
/// \brief Check if a string contains any non-printable characters
|
||||
///
|
||||
/// \return false if str contains only valid multibyte characters and
|
||||
/// iswprint(3) returns non-zero for all of them; true otherwise
|
||||
/// iswprint(3) returns non-zero for all of them; true otherwise.
|
||||
/// The value of errno is preserved.
|
||||
///
|
||||
/// \note In case mbrtowc(3) isn't available, single-byte character set
|
||||
/// is assumed and isprint(3) is used instead of iswprint(3).
|
||||
|
@ -49,6 +50,7 @@ extern const char *tuklib_mask_nonprint_r(const char *str, char **mem);
|
|||
/// allocated memory is also stored to *mem. A modified string
|
||||
/// has the problematic characters replaced by '?'. If memory
|
||||
/// allocation fails, "???" is returned and *mem is NULL.
|
||||
/// The value of errno is preserved.
|
||||
|
||||
#define tuklib_mask_nonprint TUKLIB_SYMBOL(tuklib_mask_nonprint)
|
||||
extern const char *tuklib_mask_nonprint(const char *str);
|
||||
|
|
Loading…
Reference in New Issue