summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDon Anderson <dda@mongodb.com>2016-06-21 21:05:33 -0400
committerGitHub <noreply@github.com>2016-06-21 21:05:33 -0400
commitf782f62e9078fe158367f8e4c7f35a727c817bea (patch)
tree1b6acc12b264da7e28ffdc6c99b1d713112c6cad
parent64fd6a0180704843febd5a46157d2b50eb80b0a2 (diff)
downloadmongo-f782f62e9078fe158367f8e4c7f35a727c817bea.tar.gz
WT-2691 Use wrappers for ctype functions to avoid sign extension errors (#2818)
* Cast arguments for ctype functions to avoid sign extension errors. Create __wt_* versions of all ctype functions, and use them whenever wt_internal.h is available. Add check to prevent direct use of ctype functions from core source. * Change wrappers to use u_char arguments, and return bool. Remove unused wrappers. * Use u_char in preference to unsigned char. * Examples do not have u_char defined on Windows.
-rw-r--r--bench/wtperf/config.c11
-rw-r--r--dist/s_string.ok13
-rwxr-xr-xdist/s_style14
-rw-r--r--examples/c/ex_encrypt.c4
-rw-r--r--ext/datasources/helium/helium.c4
-rw-r--r--ext/test/kvs_bdb/kvs_bdb.c2
-rw-r--r--src/btree/bt_debug.c2
-rw-r--r--src/conn/conn_api.c2
-rw-r--r--src/cursor/cur_dump.c2
-rw-r--r--src/cursor/cur_json.c23
-rw-r--r--src/cursor/cur_std.c4
-rw-r--r--src/include/ctype.i69
-rw-r--r--src/include/packing.i2
-rw-r--r--src/include/wt_internal.h2
-rw-r--r--src/os_win/os_path.c2
-rw-r--r--src/schema/schema_project.c6
-rw-r--r--src/support/hex.c2
-rw-r--r--src/utilities/util_load_json.c4
-rw-r--r--src/utilities/util_misc.c2
-rw-r--r--test/format/ops.c2
-rw-r--r--test/salvage/salvage.c2
21 files changed, 136 insertions, 38 deletions
diff --git a/bench/wtperf/config.c b/bench/wtperf/config.c
index d8c2de6e587..0dc38287155 100644
--- a/bench/wtperf/config.c
+++ b/bench/wtperf/config.c
@@ -170,7 +170,7 @@ config_free(CONFIG *cfg)
if (config_opts[i].type == STRING_TYPE ||
config_opts[i].type == CONFIG_STRING_TYPE) {
pstr = (char **)
- ((unsigned char *)cfg + config_opts[i].offset);
+ ((u_char *)cfg + config_opts[i].offset);
free(*pstr);
*pstr = NULL;
}
@@ -431,7 +431,7 @@ config_opt(CONFIG *cfg, WT_CONFIG_ITEM *k, WT_CONFIG_ITEM *v)
fprintf(stderr, "\t%s\n", config_opts[i].name);
return (EINVAL);
}
- valueloc = ((unsigned char *)cfg + popt->offset);
+ valueloc = ((u_char *)cfg + popt->offset);
switch (popt->type) {
case BOOL_TYPE:
if (v->type != WT_CONFIG_ITEM_BOOL) {
@@ -560,7 +560,8 @@ config_opt_file(CONFIG *cfg, const char *filename)
linenum++;
/* Skip leading space. */
- for (ltrim = line; *ltrim && isspace(*ltrim); ltrim++)
+ for (ltrim = line; *ltrim && isspace((u_char)*ltrim);
+ ltrim++)
;
/*
@@ -579,7 +580,7 @@ config_opt_file(CONFIG *cfg, const char *filename)
}
/* Skip trailing space. */
- while (rtrim > ltrim && isspace(rtrim[-1]))
+ while (rtrim > ltrim && isspace((u_char)rtrim[-1]))
rtrim--;
/*
@@ -599,7 +600,7 @@ config_opt_file(CONFIG *cfg, const char *filename)
rtrim = comment;
/* Skip trailing space again. */
- while (rtrim > ltrim && isspace(rtrim[-1]))
+ while (rtrim > ltrim && isspace((u_char)rtrim[-1]))
rtrim--;
/*
diff --git a/dist/s_string.ok b/dist/s_string.ok
index 420006ccc6c..f2ecaedbc11 100644
--- a/dist/s_string.ok
+++ b/dist/s_string.ok
@@ -732,9 +732,20 @@ intrin
inuse
io
ip
+isalnum
+isalpha
+iscntrl
+isdigit
+isgraph
islocked
+islower
ispo
+isprint
+ispunct
isrc
+isspace
+isupper
+isxdigit
iter
iteratively
jnr
@@ -1061,7 +1072,9 @@ toklen
tokname
tokstart
toktype
+tolower
totalsec
+toupper
transactional
transactionally
trecno
diff --git a/dist/s_style b/dist/s_style
index 33ff718e0c6..79298ba6d5e 100755
--- a/dist/s_style
+++ b/dist/s_style
@@ -138,6 +138,20 @@ else
}
fi
+ # Use of ctype functions that sign extend their arguments.
+ if ! expr "$f" : 'bench/.*' > /dev/null &&
+ ! expr "$f" : 'test/csuite/.*' > /dev/null &&
+ ! expr "$f" : 'examples/.*' > /dev/null &&
+ ! expr "$f" : 'ext/.*' > /dev/null &&
+ ! expr "$f" : 'src/include/ctype.i' > /dev/null; then
+ if egrep '(#include.*["</]ctype.h[">]|\b(is(alnum|alpha|cntrl|digit|graph|lower|print|punct|space|upper|xdigit)|to(lower|toupper))\()' $f > $t; then
+ test -s $t && {
+ echo "$f: direct use of ctype.h functions, instead of ctype.i equivalents"
+ cat $t
+ }
+ fi
+ fi
+
tr -cd '[:alnum:][:space:][:punct:]' < $f |
unexpand |
sed -e 's/){/) {/' \
diff --git a/examples/c/ex_encrypt.c b/examples/c/ex_encrypt.c
index a919148aff0..3b3323bc091 100644
--- a/examples/c/ex_encrypt.c
+++ b/examples/c/ex_encrypt.c
@@ -122,8 +122,8 @@ do_rotate(char *buf, size_t len, int rotn)
* Now rotate
*/
for (i = 0; i < len; i++)
- if (isalpha(buf[i])) {
- if (islower(buf[i]))
+ if (isalpha((unsigned char)buf[i])) {
+ if (islower((unsigned char)buf[i]))
buf[i] = ((buf[i] - 'a') + rotn) % 26 + 'a';
else
buf[i] = ((buf[i] - 'A') + rotn) % 26 + 'A';
diff --git a/ext/datasources/helium/helium.c b/ext/datasources/helium/helium.c
index 0350f9a2752..2a66c9a0ca7 100644
--- a/ext/datasources/helium/helium.c
+++ b/ext/datasources/helium/helium.c
@@ -2196,8 +2196,8 @@ helium_session_open_cursor(WT_DATA_SOURCE *wtds, WT_SESSION *session,
EMSG_ERR(wtext, session, ret,
"value_format configuration: %s",
wtext->strerror(wtext, session, ret));
- ws->config_bitfield =
- v.len == 2 && isdigit(v.str[0]) && v.str[1] == 't';
+ ws->config_bitfield = v.len == 2 &&
+ isdigit((u_char)v.str[0]) && v.str[1] == 't';
if ((ret = config_parser->get(
config_parser, "helium_o_compress", &v)) != 0)
diff --git a/ext/test/kvs_bdb/kvs_bdb.c b/ext/test/kvs_bdb/kvs_bdb.c
index 05c522ff41f..3d78bca1d1b 100644
--- a/ext/test/kvs_bdb/kvs_bdb.c
+++ b/ext/test/kvs_bdb/kvs_bdb.c
@@ -831,7 +831,7 @@ kvs_session_open_cursor(WT_DATA_SOURCE *wtds, WT_SESSION *session,
goto err;
}
cursor->config_bitfield =
- v.len == 2 && isdigit(v.str[0]) && v.str[1] == 't';
+ v.len == 2 && isdigit((u_char)v.str[0]) && v.str[1] == 't';
if ((ret = writelock(wtext, session, &ds->rwlock)) != 0)
goto err;
diff --git a/src/btree/bt_debug.c b/src/btree/bt_debug.c
index cfe290ff6d3..c939ab5a5de 100644
--- a/src/btree/bt_debug.c
+++ b/src/btree/bt_debug.c
@@ -1162,7 +1162,7 @@ __debug_item(WT_DBG *ds, const char *tag, const void *data_arg, size_t size)
__dmsg(ds, "\t%s%s{", tag == NULL ? "" : tag, tag == NULL ? "" : " ");
for (data = data_arg, i = 0; i < size; ++i, ++data) {
ch = data[0];
- if (isprint(ch))
+ if (__wt_isprint(ch))
__dmsg(ds, "%c", ch);
else
__debug_hex_byte(ds, data[0]);
diff --git a/src/conn/conn_api.c b/src/conn/conn_api.c
index dde3fb6930e..203be62ac94 100644
--- a/src/conn/conn_api.c
+++ b/src/conn/conn_api.c
@@ -1298,7 +1298,7 @@ __conn_config_file(WT_SESSION_IMPL *session,
* the next character is a hash mark, skip to the next newline.
*/
for (;;) {
- for (*t++ = ','; --len > 0 && isspace(*++p);)
+ for (*t++ = ','; --len > 0 && __wt_isspace(*++p);)
;
if (len == 0)
break;
diff --git a/src/cursor/cur_dump.c b/src/cursor/cur_dump.c
index 32353e0a28d..3ad5c3f09a1 100644
--- a/src/cursor/cur_dump.c
+++ b/src/cursor/cur_dump.c
@@ -128,7 +128,7 @@ str2recno(WT_SESSION_IMPL *session, const char *p, uint64_t *recnop)
* forth -- none of them are OK with us. Check the string starts with
* digit, that turns off the special processing.
*/
- if (!isdigit(p[0]))
+ if (!__wt_isdigit(p[0]))
goto format;
errno = 0;
diff --git a/src/cursor/cur_json.c b/src/cursor/cur_json.c
index cec79306bce..e731dd03a96 100644
--- a/src/cursor/cur_json.c
+++ b/src/cursor/cur_json.c
@@ -319,7 +319,7 @@ __wt_json_unpack_char(u_char ch, u_char *buf, size_t bufsz, bool force_unicode)
u_char abbrev;
if (!force_unicode) {
- if (isprint(ch) && ch != '\\' && ch != '"') {
+ if (__wt_isprint(ch) && ch != '\\' && ch != '"') {
if (bufsz >= 1)
*buf = ch;
return (1);
@@ -390,7 +390,7 @@ __wt_json_column_init(WT_CURSOR *cursor, const char *keyformat,
}
for (nkeys = 0; *keyformat; keyformat++)
- if (!isdigit(*keyformat))
+ if (!__wt_isdigit(*keyformat))
nkeys++;
p = beginkey;
@@ -413,12 +413,13 @@ __wt_json_column_init(WT_CURSOR *cursor, const char *keyformat,
#define MATCH_KEYWORD(session, in, result, keyword, matchval) do { \
size_t _kwlen = strlen(keyword); \
- if (strncmp(in, keyword, _kwlen) == 0 && !isalnum(in[_kwlen])) { \
+ if (strncmp(in, keyword, _kwlen) == 0 && \
+ !__wt_isalnum(in[_kwlen])) { \
in += _kwlen; \
result = matchval; \
} else { \
const char *_bad = in; \
- while (isalnum(*in)) \
+ while (__wt_isalnum(*in)) \
in++; \
__wt_errx(session, "unknown keyword \"%.*s\" in JSON", \
(int)(in - _bad), _bad); \
@@ -460,7 +461,7 @@ __wt_json_token(WT_SESSION *wt_session, const char *src, int *toktype,
result = -1;
session = (WT_SESSION_IMPL *)wt_session;
- while (isspace(*src))
+ while (__wt_isspace(*src))
src++;
*tokstart = src;
@@ -520,13 +521,12 @@ __wt_json_token(WT_SESSION *wt_session, const char *src, int *toktype,
isfloat = false;
if (*src == '-')
src++;
- while ((ch = *src) != '\0' && isdigit(ch))
+ while ((ch = *src) != '\0' && __wt_isdigit(ch))
src++;
if (*src == '.') {
isfloat = true;
src++;
- while ((ch = *src) != '\0' &&
- isdigit(ch))
+ while ((ch = *src) != '\0' && __wt_isdigit(ch))
src++;
}
if (*src == 'e' || *src == 'E') {
@@ -534,8 +534,7 @@ __wt_json_token(WT_SESSION *wt_session, const char *src, int *toktype,
src++;
if (*src == '+' || *src == '-')
src++;
- while ((ch = *src) != '\0' &&
- isdigit(ch))
+ while ((ch = *src) != '\0' && __wt_isdigit(ch))
src++;
}
result = isfloat ? 'f' : 'i';
@@ -560,10 +559,10 @@ __wt_json_token(WT_SESSION *wt_session, const char *src, int *toktype,
default:
/* An illegal token, move past it anyway */
bad = src;
- isalph = isalnum(*src);
+ isalph = __wt_isalnum(*src);
src++;
if (isalph)
- while (*src != '\0' && isalnum(*src))
+ while (*src != '\0' && __wt_isalnum(*src))
src++;
__wt_errx(session, "unknown token \"%.*s\" in JSON",
(int)(src - bad), bad);
diff --git a/src/cursor/cur_std.c b/src/cursor/cur_std.c
index 7f220a3faa2..489734ce734 100644
--- a/src/cursor/cur_std.c
+++ b/src/cursor/cur_std.c
@@ -435,7 +435,7 @@ __wt_cursor_get_valuev(WT_CURSOR *cursor, va_list ap)
} else if (WT_STREQ(fmt, "S"))
*va_arg(ap, const char **) = cursor->value.data;
else if (WT_STREQ(fmt, "t") ||
- (isdigit(fmt[0]) && WT_STREQ(fmt + 1, "t")))
+ (__wt_isdigit(fmt[0]) && WT_STREQ(fmt + 1, "t")))
*va_arg(ap, uint8_t *) = *(uint8_t *)cursor->value.data;
else
ret = __wt_struct_unpackv(session,
@@ -496,7 +496,7 @@ __wt_cursor_set_valuev(WT_CURSOR *cursor, va_list ap)
sz = strlen(str) + 1;
buf->data = str;
} else if (WT_STREQ(fmt, "t") ||
- (isdigit(fmt[0]) && WT_STREQ(fmt + 1, "t"))) {
+ (__wt_isdigit(fmt[0]) && WT_STREQ(fmt + 1, "t"))) {
sz = 1;
WT_ERR(__wt_buf_initsize(session, buf, sz));
*(uint8_t *)buf->mem = (uint8_t)va_arg(ap, int);
diff --git a/src/include/ctype.i b/src/include/ctype.i
new file mode 100644
index 00000000000..b4a1ad9f318
--- /dev/null
+++ b/src/include/ctype.i
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2014-2016 MongoDB, Inc.
+ * Copyright (c) 2008-2014 WiredTiger, Inc.
+ * All rights reserved.
+ *
+ * See the file LICENSE for redistribution information.
+ */
+
+#include <ctype.h>
+
+/*
+ * __wt_isalnum --
+ * Wrap the ctype function without sign extension.
+ */
+static inline bool
+__wt_isalnum(u_char c)
+{
+ return (isalnum(c) != 0);
+}
+
+/*
+ * __wt_isalpha --
+ * Wrap the ctype function without sign extension.
+ */
+static inline bool
+__wt_isalpha(u_char c)
+{
+ return (isalpha(c) != 0);
+}
+
+/*
+ * __wt_isdigit --
+ * Wrap the ctype function without sign extension.
+ */
+static inline bool
+__wt_isdigit(u_char c)
+{
+ return (isdigit(c) != 0);
+}
+
+/*
+ * __wt_isprint --
+ * Wrap the ctype function without sign extension.
+ */
+static inline bool
+__wt_isprint(u_char c)
+{
+ return (isprint(c) != 0);
+}
+
+/*
+ * __wt_isspace --
+ * Wrap the ctype function without sign extension.
+ */
+static inline bool
+__wt_isspace(u_char c)
+{
+ return (isspace(c) != 0);
+}
+
+/*
+ * __wt_tolower --
+ * Wrap the ctype function without sign extension.
+ */
+static inline u_char
+__wt_tolower(u_char c)
+{
+ return ((u_char)tolower(c));
+}
diff --git a/src/include/packing.i b/src/include/packing.i
index 316169fbe06..78fd03c0741 100644
--- a/src/include/packing.i
+++ b/src/include/packing.i
@@ -138,7 +138,7 @@ __pack_next(WT_PACK *pack, WT_PACK_VALUE *pv)
next: if (pack->cur == pack->end)
return (WT_NOTFOUND);
- if (isdigit(*pack->cur)) {
+ if (__wt_isdigit(*pack->cur)) {
pv->havesize = 1;
pv->size = WT_STORE_SIZE(strtoul(pack->cur, &endsize, 10));
pack->cur = endsize;
diff --git a/src/include/wt_internal.h b/src/include/wt_internal.h
index 0c8abf36cfe..24de648612f 100644
--- a/src/include/wt_internal.h
+++ b/src/include/wt_internal.h
@@ -28,7 +28,6 @@ extern "C" {
#include <sys/time.h>
#include <sys/uio.h>
#endif
-#include <ctype.h>
#ifndef _WIN32
#include <dlfcn.h>
#endif
@@ -359,6 +358,7 @@ union __wt_rand_state;
#include "extern.h"
#include "verify_build.h"
+#include "ctype.i" /* required by packing.i */
#include "intpack.i" /* required by cell.i, packing.i */
#include "buf.i" /* required by cell.i */
diff --git a/src/os_win/os_path.c b/src/os_win/os_path.c
index e9532de2b38..220752ce7a1 100644
--- a/src/os_win/os_path.c
+++ b/src/os_win/os_path.c
@@ -19,7 +19,7 @@ __wt_absolute_path(const char *path)
* Check for a drive name (for example, "D:"), allow both forward and
* backward slashes.
*/
- if (strlen(path) >= 3 && isalpha(path[0]) && path[1] == ':')
+ if (strlen(path) >= 3 && __wt_isalpha(path[0]) && path[1] == ':')
path += 2;
return (path[0] == '/' || path[0] == '\\');
}
diff --git a/src/schema/schema_project.c b/src/schema/schema_project.c
index 4d29b2baa13..1addb720728 100644
--- a/src/schema/schema_project.c
+++ b/src/schema/schema_project.c
@@ -353,7 +353,8 @@ __wt_schema_project_slice(WT_SESSION_IMPL *session, WT_CURSOR **cp,
/* Make sure the types are compatible. */
WT_ASSERT(session,
- tolower(pv.type) == tolower(vpv.type));
+ __wt_tolower(pv.type) ==
+ __wt_tolower(vpv.type));
pv.u = vpv.u;
len = __pack_size(session, &pv);
@@ -459,7 +460,8 @@ __wt_schema_project_merge(WT_SESSION_IMPL *session,
WT_RET(__pack_next(&vpack, &vpv));
/* Make sure the types are compatible. */
WT_ASSERT(session,
- tolower(pv.type) == tolower(vpv.type));
+ __wt_tolower(pv.type) ==
+ __wt_tolower(vpv.type));
vpv.u = pv.u;
len = __pack_size(session, &vpv);
WT_RET(__wt_buf_grow(session,
diff --git a/src/support/hex.c b/src/support/hex.c
index d42a84154ca..ea23cac75a8 100644
--- a/src/support/hex.c
+++ b/src/support/hex.c
@@ -84,7 +84,7 @@ __wt_raw_to_esc_hex(
WT_RET(__wt_buf_init(session, to, size * 3 + 1));
for (p = from, t = to->mem, i = size; i > 0; --i, ++p)
- if (isprint((int)*p)) {
+ if (__wt_isprint((int)*p)) {
if (*p == '\\')
*t++ = '\\';
*t++ = *p;
diff --git a/src/utilities/util_load_json.c b/src/utilities/util_load_json.c
index 45688e5e107..2ad65178552 100644
--- a/src/utilities/util_load_json.c
+++ b/src/utilities/util_load_json.c
@@ -248,7 +248,7 @@ json_data(WT_SESSION *session,
keyformat = cursor->key_format;
isrec = strcmp(keyformat, "r") == 0;
for (nkeys = 0; *keyformat; keyformat++)
- if (!isdigit(*keyformat))
+ if (!__wt_isdigit(*keyformat))
nkeys++;
recno = 0;
@@ -471,7 +471,7 @@ json_peek(WT_SESSION *session, JSON_INPUT_STATE *ins)
if (!ins->peeking) {
while (!ins->ateof) {
- while (isspace(*ins->p))
+ while (__wt_isspace(*ins->p))
ins->p++;
if (*ins->p)
break;
diff --git a/src/utilities/util_misc.c b/src/utilities/util_misc.c
index f45f6b339f2..9579f71ebe0 100644
--- a/src/utilities/util_misc.c
+++ b/src/utilities/util_misc.c
@@ -108,7 +108,7 @@ util_str2recno(WT_SESSION *session, const char *p, uint64_t *recnop)
* forth -- none of them are OK with us. Check the string starts with
* digit, that turns off the special processing.
*/
- if (!isdigit(p[0]))
+ if (!__wt_isdigit(p[0]))
goto format;
errno = 0;
diff --git a/test/format/ops.c b/test/format/ops.c
index 7fd5563f486..66e1ef3912b 100644
--- a/test/format/ops.c
+++ b/test/format/ops.c
@@ -1476,7 +1476,7 @@ print_item(const char *tag, WT_ITEM *item)
else
for (; size > 0; --size, ++data) {
ch = data[0];
- if (isprint(ch))
+ if (__wt_isprint(ch))
fprintf(stderr, "%c", ch);
else
fprintf(stderr, "%x%x",
diff --git a/test/salvage/salvage.c b/test/salvage/salvage.c
index 497902e07b8..f010d348a1d 100644
--- a/test/salvage/salvage.c
+++ b/test/salvage/salvage.c
@@ -701,7 +701,7 @@ print_res(int key, int value, int cnt)
switch (page_type) { /* Print value */
case WT_PAGE_COL_FIX:
ch = value & 0x7f;
- if (isprint(ch)) {
+ if (__wt_isprint(ch)) {
if (ch == '\\')
fputc('\\', res_fp);
fputc(ch, res_fp);