From cb3d83d0606d5267752895151bb3c229c48d6fb6 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 19 May 2020 12:03:23 +0100 Subject: [PATCH 14/19] common/include: Add ASCII-only ctype header and ascii_is* functions. Our existing uses of were not necessarily safe if the locale was changed. Also I removed the unnecessary use of isascii, deprecated by POSIX.1-2008. (cherry picked from commit 9f34db74786fdc92b290a7d47e4b003bd84fec69) --- .gitignore | 1 + common/include/Makefile.am | 6 +++ common/include/ascii-ctype.h | 60 ++++++++++++++++++++++++++ common/include/test-ascii-ctype.c | 63 ++++++++++++++++++++++++++++ plugins/partitioning/partition-gpt.c | 12 +++--- plugins/sh/Makefile.am | 1 + plugins/sh/call.c | 6 +-- server/backend.c | 7 ++-- server/public.c | 4 +- 9 files changed, 146 insertions(+), 14 deletions(-) create mode 100644 common/include/ascii-ctype.h create mode 100644 common/include/test-ascii-ctype.c diff --git a/.gitignore b/.gitignore index e25bd99b..523894b7 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ Makefile.in /aclocal.m4 /autom4te.cache /common/bitmap/test-bitmap +/common/include/test-ascii-ctype /common/include/test-byte-swapping /common/include/test-current-dir-name /common/include/test-isaligned diff --git a/common/include/Makefile.am b/common/include/Makefile.am index 4482de37..d7b0d7a8 100644 --- a/common/include/Makefile.am +++ b/common/include/Makefile.am @@ -34,6 +34,7 @@ include $(top_srcdir)/common-rules.mk # These headers contain only common code shared by the core server, # plugins and/or filters. They are not installed. EXTRA_DIST = \ + ascii-ctype.h \ byte-swapping.h \ exit-with-parent.h \ get-current-dir-name.h \ @@ -50,6 +51,7 @@ EXTRA_DIST = \ # Unit tests. TESTS = \ + test-ascii-ctype \ test-byte-swapping \ test-current-dir-name \ test-isaligned \ @@ -62,6 +64,10 @@ TESTS = \ $(NULL) check_PROGRAMS = $(TESTS) +test_ascii_ctype_SOURCES = test-ascii-ctype.c ascii-ctype.h +test_ascii_ctype_CPPFLAGS = -I$(srcdir) +test_ascii_ctype_CFLAGS = $(WARNINGS_CFLAGS) + test_byte_swapping_SOURCES = test-byte-swapping.c byte-swapping.h test_byte_swapping_CPPFLAGS = -I$(srcdir) test_byte_swapping_CFLAGS = $(WARNINGS_CFLAGS) diff --git a/common/include/ascii-ctype.h b/common/include/ascii-ctype.h new file mode 100644 index 00000000..5e8bf237 --- /dev/null +++ b/common/include/ascii-ctype.h @@ -0,0 +1,60 @@ +/* nbdkit + * Copyright (C) 2013-2020 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Normal ctype functions are affected by the current locale. For + * example isupper() might recognize Ä in some but not all locales. + * These functions match only 7 bit ASCII characters. + */ + +#ifndef NBDKIT_ASCII_CTYPE_H +#define NBDKIT_ASCII_CTYPE_H + +#define ascii_isalnum(c) (ascii_isalpha (c) || ascii_isdigit (c)) + +#define ascii_isalpha(c) \ + (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) + +#define ascii_isdigit(c) \ + ((c) >= '0' && (c) <= '9') + +#define ascii_isspace(c) \ + ((c) == '\t' || (c) == '\n' || (c) == '\f' || (c) == '\r' || (c) == ' ') + +#define ascii_isxdigit(c) \ + ((c) == '0' || (c) == '1' || (c) == '2' || (c) == '3' || (c) == '4' || \ + (c) == '5' || (c) == '6' || (c) == '7' || (c) == '8' || (c) == '9' || \ + (c) == 'a' || (c) == 'b' || (c) == 'c' || \ + (c) == 'd' || (c) == 'e' || (c) == 'f' || \ + (c) == 'A' || (c) == 'B' || (c) == 'C' || \ + (c) == 'D' || (c) == 'E' || (c) == 'F') + +#endif /* NBDKIT_ASCII_CTYPE_H */ diff --git a/common/include/test-ascii-ctype.c b/common/include/test-ascii-ctype.c new file mode 100644 index 00000000..edf27aa6 --- /dev/null +++ b/common/include/test-ascii-ctype.c @@ -0,0 +1,63 @@ +/* nbdkit + * Copyright (C) 2020 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Red Hat nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +#include "ascii-ctype.h" + +int +main (void) +{ + assert (ascii_isspace (' ')); + assert (ascii_isspace ('\t')); + assert (ascii_isspace ('\n')); + assert (! ascii_isspace ('a')); + + assert (ascii_isalpha ('a')); + assert (ascii_isalpha ('Z')); + assert (ascii_isalpha ('z')); + assert (! ascii_isalpha (' ')); + assert (! ascii_isalpha ('0')); + { const char *s = "Ä"; assert (! ascii_isalpha (s[0])); } + { const char *s = "®"; assert (! ascii_isalpha (s[0])); } + + assert (ascii_isdigit ('0')); + assert (ascii_isdigit ('9')); + { const char *s = "Ø"; assert (! ascii_isdigit (s[0])); } /* U+00D8 */ + { const char *s = "9"; assert (! ascii_isdigit (s[0])); } /* U+FF19 */ + + exit (EXIT_SUCCESS); +} diff --git a/plugins/partitioning/partition-gpt.c b/plugins/partitioning/partition-gpt.c index 75b4643a..819e9abe 100644 --- a/plugins/partitioning/partition-gpt.c +++ b/plugins/partitioning/partition-gpt.c @@ -36,12 +36,12 @@ #include #include #include -#include #include #include #include +#include "ascii-ctype.h" #include "byte-swapping.h" #include "efi-crc32.h" @@ -244,19 +244,19 @@ parse_guid (const char *str, char *out) return -1; for (i = 0; i < 8; ++i) - if (!isxdigit (str[i])) + if (!ascii_isxdigit (str[i])) return -1; for (i = 9; i < 13; ++i) - if (!isxdigit (str[i])) + if (!ascii_isxdigit (str[i])) return -1; for (i = 14; i < 18; ++i) - if (!isxdigit (str[i])) + if (!ascii_isxdigit (str[i])) return -1; for (i = 19; i < 23; ++i) - if (!isxdigit (str[i])) + if (!ascii_isxdigit (str[i])) return -1; for (i = 24; i < 36; ++i) - if (!isxdigit (str[i])) + if (!ascii_isxdigit (str[i])) return -1; /* The first, second and third blocks are parsed as little endian, diff --git a/plugins/sh/Makefile.am b/plugins/sh/Makefile.am index 445cdcd5..1f42b64c 100644 --- a/plugins/sh/Makefile.am +++ b/plugins/sh/Makefile.am @@ -48,6 +48,7 @@ nbdkit_sh_plugin_la_SOURCES = \ nbdkit_sh_plugin_la_CPPFLAGS = \ -I$(top_srcdir)/include \ + -I$(top_srcdir)/common/include \ -I$(top_srcdir)/common/utils \ $(NULL) nbdkit_sh_plugin_la_CFLAGS = $(WARNINGS_CFLAGS) diff --git a/plugins/sh/call.c b/plugins/sh/call.c index 2d99a120..ae0cc0ac 100644 --- a/plugins/sh/call.c +++ b/plugins/sh/call.c @@ -44,10 +44,10 @@ #include #include #include -#include #include +#include "ascii-ctype.h" #include "cleanup.h" #include "utils.h" @@ -392,7 +392,7 @@ handle_script_error (const char *argv0, char *ebuf, size_t len) } if (skip && ebuf[skip]) { - if (!isspace ((unsigned char) ebuf[skip])) { + if (!ascii_isspace ((unsigned char) ebuf[skip])) { /* Treat 'EINVALID' as EIO, not EINVAL */ err = EIO; skip = 0; @@ -400,7 +400,7 @@ handle_script_error (const char *argv0, char *ebuf, size_t len) else do skip++; - while (isspace ((unsigned char) ebuf[skip])); + while (ascii_isspace ((unsigned char) ebuf[skip])); } while (len > 0 && ebuf[len-1] == '\n') diff --git a/server/backend.c b/server/backend.c index 208c07b1..9add341f 100644 --- a/server/backend.c +++ b/server/backend.c @@ -37,13 +37,14 @@ #include #include #include -#include #include -#include "internal.h" +#include "ascii-ctype.h" #include "minmax.h" +#include "internal.h" + /* Helpers for registering a new backend. */ /* Use: @@ -100,7 +101,7 @@ backend_load (struct backend *b, const char *name, void (*load) (void)) for (i = 0; i < len; ++i) { unsigned char c = name[i]; - if (!(isascii (c) && isalnum (c))) { + if (! ascii_isalnum (c)) { fprintf (stderr, "%s: %s: %s.name ('%s') field " "must contain only ASCII alphanumeric characters\n", diff --git a/server/public.c b/server/public.c index 418945fe..98b78482 100644 --- a/server/public.c +++ b/server/public.c @@ -45,13 +45,13 @@ #include #include #include -#include #include #include #include #include #include +#include "ascii-ctype.h" #include "get-current-dir-name.h" #include "internal.h" @@ -210,7 +210,7 @@ nbdkit_parse_int64_t (const char *what, const char *str, int64_t *rp) */ #define PARSE_ERROR_IF_NEGATIVE \ do { \ - while (isspace (*str)) \ + while (ascii_isspace (*str)) \ str++; \ if (*str == '-') { \ nbdkit_error ("%s: negative numbers are not allowed", what); \ -- 2.18.2