diff options
| author | Don Anderson <dda@mongodb.com> | 2016-06-21 21:05:33 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-06-21 21:05:33 -0400 |
| commit | f782f62e9078fe158367f8e4c7f35a727c817bea (patch) | |
| tree | 1b6acc12b264da7e28ffdc6c99b1d713112c6cad | |
| parent | 64fd6a0180704843febd5a46157d2b50eb80b0a2 (diff) | |
| download | mongo-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.c | 11 | ||||
| -rw-r--r-- | dist/s_string.ok | 13 | ||||
| -rwxr-xr-x | dist/s_style | 14 | ||||
| -rw-r--r-- | examples/c/ex_encrypt.c | 4 | ||||
| -rw-r--r-- | ext/datasources/helium/helium.c | 4 | ||||
| -rw-r--r-- | ext/test/kvs_bdb/kvs_bdb.c | 2 | ||||
| -rw-r--r-- | src/btree/bt_debug.c | 2 | ||||
| -rw-r--r-- | src/conn/conn_api.c | 2 | ||||
| -rw-r--r-- | src/cursor/cur_dump.c | 2 | ||||
| -rw-r--r-- | src/cursor/cur_json.c | 23 | ||||
| -rw-r--r-- | src/cursor/cur_std.c | 4 | ||||
| -rw-r--r-- | src/include/ctype.i | 69 | ||||
| -rw-r--r-- | src/include/packing.i | 2 | ||||
| -rw-r--r-- | src/include/wt_internal.h | 2 | ||||
| -rw-r--r-- | src/os_win/os_path.c | 2 | ||||
| -rw-r--r-- | src/schema/schema_project.c | 6 | ||||
| -rw-r--r-- | src/support/hex.c | 2 | ||||
| -rw-r--r-- | src/utilities/util_load_json.c | 4 | ||||
| -rw-r--r-- | src/utilities/util_misc.c | 2 | ||||
| -rw-r--r-- | test/format/ops.c | 2 | ||||
| -rw-r--r-- | test/salvage/salvage.c | 2 |
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); |
