diff options
author | Keith Bostic <keith.bostic@mongodb.com> | 2017-08-20 21:51:33 -0400 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2017-08-21 11:51:33 +1000 |
commit | 3cf393963c950a5f9d8207194dc08ba1016f4303 (patch) | |
tree | a78510239335fbc005f548ee3955fb26457914d3 | |
parent | b055251678e6b4fcc74a1f651432aadbfeecc0e4 (diff) | |
download | mongo-3cf393963c950a5f9d8207194dc08ba1016f4303.tar.gz |
WT-3522 lint (#3598)
* CID 1379736 (#1 of 1): Unchecked return value (CHECKED_RETURN) check_return: Calling __wt_spin_init without checking return value
* By decreasing WT_MAX_MODIFY_UPDATE from 100 to 10, we increased the likelihood of exceeding it when threads race, and we're prefer not to allocate memory in a return path. Add a few additional slots to the array we use to build up a list of modify records to apply.
* Split __wt_strndup() into two parts: __wt_strndup() which checks for NULL pointers and nul-terminates the copy, and __wt_memdup() which does a byte string copy and nothing more. Switch the WiredTiger calls that are doing byte copies (generally disk images or address chunks), to call __wt_memdup().
* Use ENOTSUP for unsupported operations, don't repeat the method name in the error message, the error functions output it already.
* MSVC Doesn't provide __func__, it has __FUNCTION__. There was a fix in the utility code, move that fix into the WiredTiger include files so it's generally available.
* Switch WiredTiger diagnostics that use __FILE__ to use __func__, it gives us a better indication of the error location if we don't have a file version (and takes up less text space, if anyone cares).
* clang static-analyzer complains we call __wt_config_gets() and trust it won't modify the value WT_CONFIG_ITEM if it returns WT_NOTFOUND.
* Add minor text to error messages to make it apparent which error occurred when WiredTiger is starting up.
-rw-r--r-- | dist/s_define.list | 1 | ||||
-rw-r--r-- | dist/s_string.ok | 2 | ||||
-rw-r--r-- | src/btree/bt_ovfl.c | 2 | ||||
-rw-r--r-- | src/btree/bt_rebalance.c | 4 | ||||
-rw-r--r-- | src/btree/bt_ret.c | 18 | ||||
-rw-r--r-- | src/btree/bt_slvg.c | 8 | ||||
-rw-r--r-- | src/btree/bt_split.c | 4 | ||||
-rw-r--r-- | src/conn/conn_cache_pool.c | 7 | ||||
-rw-r--r-- | src/cursor/cur_join.c | 1 | ||||
-rw-r--r-- | src/include/error.h | 2 | ||||
-rw-r--r-- | src/include/extern.h | 1 | ||||
-rw-r--r-- | src/include/misc.h | 8 | ||||
-rw-r--r-- | src/include/msvc.h | 5 | ||||
-rw-r--r-- | src/lsm/lsm_meta.c | 6 | ||||
-rw-r--r-- | src/lsm/lsm_tree.c | 4 | ||||
-rw-r--r-- | src/os_common/os_alloc.c | 30 | ||||
-rw-r--r-- | src/os_posix/os_fs.c | 5 | ||||
-rw-r--r-- | src/reconcile/rec_write.c | 6 | ||||
-rw-r--r-- | src/txn/txn_timestamp.c | 7 | ||||
-rw-r--r-- | test/windows/windows_shim.h | 5 |
20 files changed, 75 insertions, 51 deletions
diff --git a/dist/s_define.list b/dist/s_define.list index 9f94132f584..dcaf975434f 100644 --- a/dist/s_define.list +++ b/dist/s_define.list @@ -65,4 +65,5 @@ __F __WIREDTIGER_EXT_H_ __WIREDTIGER_H_ __WT_INTERNAL_H +__func__ __wt_bswap16 diff --git a/dist/s_string.ok b/dist/s_string.ok index 58b8137cad9..b0328399e7d 100644 --- a/dist/s_string.ok +++ b/dist/s_string.ok @@ -55,6 +55,7 @@ CET CFLAGS CHECKKEY CKPT +CLOEXEC CMP CONCAT CONFIG @@ -923,6 +924,7 @@ mem memalign membar memcpy +memdup memget memmove memset diff --git a/src/btree/bt_ovfl.c b/src/btree/bt_ovfl.c index fab38f3cc8d..ebd0eb0cb71 100644 --- a/src/btree/bt_ovfl.c +++ b/src/btree/bt_ovfl.c @@ -132,7 +132,7 @@ __ovfl_cache(WT_SESSION_IMPL *session, WT_PAGE *page, WT_CELL_UNPACK *unpack) WT_ERR(__wt_realloc_def(session, &track->remove_allocated, track->remove_next + 1, &track->remove)); track->remove[track->remove_next].cell = unpack->cell; - WT_ERR(__wt_strndup(session, + WT_ERR(__wt_memdup(session, tmp->data, tmp->size, &track->remove[track->remove_next].data)); track->remove[track->remove_next].size = tmp->size; ++track->remove_next; diff --git a/src/btree/bt_rebalance.c b/src/btree/bt_rebalance.c index 47c7888af35..a616ab7fc42 100644 --- a/src/btree/bt_rebalance.c +++ b/src/btree/bt_rebalance.c @@ -83,7 +83,7 @@ __rebalance_leaf_append(WT_SESSION_IMPL *session, WT_RET(__wt_calloc_one(session, ©_addr)); copy->addr = copy_addr; - WT_RET(__wt_strndup(session, addr, addr_len, ©_addr->addr)); + WT_RET(__wt_memdup(session, addr, addr_len, ©_addr->addr)); copy_addr->size = (uint8_t)addr_len; copy_addr->type = (uint8_t)addr_type; @@ -110,7 +110,7 @@ __rebalance_fl_append(WT_SESSION_IMPL *session, session, &rs->fl_allocated, rs->fl_next + 1, &rs->fl)); copy = &rs->fl[rs->fl_next++]; - WT_RET(__wt_strndup(session, addr, addr_len, ©->addr)); + WT_RET(__wt_memdup(session, addr, addr_len, ©->addr)); copy->size = (uint8_t)addr_len; copy->type = 0; diff --git a/src/btree/bt_ret.c b/src/btree/bt_ret.c index 120daed3935..49a2481062e 100644 --- a/src/btree/bt_ret.c +++ b/src/btree/bt_ret.c @@ -129,9 +129,17 @@ __value_return(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *cbt) } /* + * When threads race modifying a record, we can end up with more than the usual + * maximum number of modifications in an update list. We'd prefer not to + * allocate memory in a return path, so add a few additional slots to the array + * we use to build up a list of modify records to apply. + */ +#define WT_MODIFY_ARRAY_SIZE (WT_MAX_MODIFY_UPDATE + 10) + +/* * __value_return_upd -- * Change the cursor to reference an internal update structure return - * value. + * value. */ static inline int __value_return_upd( @@ -139,7 +147,7 @@ __value_return_upd( { WT_CURSOR *cursor; WT_DECL_RET; - WT_UPDATE **listp, *list[WT_MAX_MODIFY_UPDATE]; + WT_UPDATE **listp, *list[WT_MODIFY_ARRAY_SIZE]; u_int i; size_t allocated_bytes; @@ -178,12 +186,12 @@ __value_return_upd( * avoid memory allocation in normal cases, but we have * to handle the edge cases too. */ - if (i >= WT_MAX_MODIFY_UPDATE) { - if (i == WT_MAX_MODIFY_UPDATE) + if (i >= WT_MODIFY_ARRAY_SIZE) { + if (i == WT_MODIFY_ARRAY_SIZE) listp = NULL; WT_ERR(__wt_realloc_def( session, &allocated_bytes, i + 1, &listp)); - if (i == WT_MAX_MODIFY_UPDATE) + if (i == WT_MODIFY_ARRAY_SIZE) memcpy(listp, list, sizeof(list)); } listp[i++] = upd; diff --git a/src/btree/bt_slvg.c b/src/btree/bt_slvg.c index 1f686d904ec..2b5fb8b2db0 100644 --- a/src/btree/bt_slvg.c +++ b/src/btree/bt_slvg.c @@ -496,7 +496,7 @@ __slvg_trk_init(WT_SESSION_IMPL *session, trk->shared->ref = 1; trk->ss = ss; - WT_ERR(__wt_strndup(session, addr, addr_size, &trk->trk_addr)); + WT_ERR(__wt_memdup(session, addr, addr_size, &trk->trk_addr)); trk->trk_addr_size = (uint8_t)addr_size; trk->trk_size = size; trk->trk_gen = gen; @@ -683,7 +683,7 @@ __slvg_trk_leaf_ovfl( WT_CELL_FOREACH(btree, dsk, cell, unpack, i) { __wt_cell_unpack(cell, unpack); if (unpack->ovfl) { - WT_RET(__wt_strndup(session, unpack->data, + WT_RET(__wt_memdup(session, unpack->data, unpack->size, &trk->trk_ovfl_addr[ovfl_cnt].addr)); trk->trk_ovfl_addr[ovfl_cnt].size = (uint8_t)unpack->size; @@ -1171,7 +1171,7 @@ __slvg_col_build_internal( ref->page = NULL; WT_ERR(__wt_calloc_one(session, &addr)); - WT_ERR(__wt_strndup( + WT_ERR(__wt_memdup( session, trk->trk_addr, trk->trk_addr_size, &addr->addr)); addr->size = trk->trk_addr_size; addr->type = @@ -1824,7 +1824,7 @@ __slvg_row_build_internal( ref->page = NULL; WT_ERR(__wt_calloc_one(session, &addr)); - WT_ERR(__wt_strndup( + WT_ERR(__wt_memdup( session, trk->trk_addr, trk->trk_addr_size, &addr->addr)); addr->size = trk->trk_addr_size; addr->type = diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c index ac90d6693d3..42fd1bd1bd2 100644 --- a/src/btree/bt_split.c +++ b/src/btree/bt_split.c @@ -290,7 +290,7 @@ __split_ref_move(WT_SESSION_IMPL *session, WT_PAGE *from_home, if (ref_addr != NULL && !__wt_off_page(from_home, ref_addr)) { __wt_cell_unpack((WT_CELL *)ref_addr, &unpack); WT_RET(__wt_calloc_one(session, &addr)); - if ((ret = __wt_strndup( + if ((ret = __wt_memdup( session, unpack.data, unpack.size, &addr->addr)) != 0) { __wt_free(session, addr); return (ret); @@ -1612,7 +1612,7 @@ __wt_multi_to_ref(WT_SESSION_IMPL *session, ref->addr = addr; addr->size = multi->addr.size; addr->type = multi->addr.type; - WT_RET(__wt_strndup(session, + WT_RET(__wt_memdup(session, multi->addr.addr, addr->size, &addr->addr)); ref->state = WT_REF_DISK; } diff --git a/src/conn/conn_cache_pool.c b/src/conn/conn_cache_pool.c index 55393a86ba1..2791277b0d8 100644 --- a/src/conn/conn_cache_pool.c +++ b/src/conn/conn_cache_pool.c @@ -47,7 +47,7 @@ int __wt_cache_pool_config(WT_SESSION_IMPL *session, const char **cfg) { WT_CACHE_POOL *cp; - WT_CONFIG_ITEM cval; + WT_CONFIG_ITEM cval, cval_cache_size; WT_CONNECTION_IMPL *conn, *entry; WT_DECL_RET; char *pool_name; @@ -78,7 +78,7 @@ __wt_cache_pool_config(WT_SESSION_IMPL *session, const char **cfg) } if (__wt_config_gets(session, - &cfg[1], "cache_size", &cval) != WT_NOTFOUND) + &cfg[1], "cache_size", &cval_cache_size) != WT_NOTFOUND) WT_RET_MSG(session, EINVAL, "Only one of cache_size and shared_cache can be " "in the configuration"); @@ -221,8 +221,7 @@ __wt_cache_pool_config(WT_SESSION_IMPL *session, const char **cfg) F_SET(conn, WT_CONN_CACHE_POOL); err: __wt_spin_unlock(session, &__wt_process.spinlock); - if (!updating) - __wt_free(session, pool_name); + __wt_free(session, pool_name); if (ret != 0 && created) { __wt_free(session, cp->name); __wt_cond_destroy(session, &cp->cache_pool_cond); diff --git a/src/cursor/cur_join.c b/src/cursor/cur_join.c index e3ae9dbd9f6..38ccb32d2b9 100644 --- a/src/cursor/cur_join.c +++ b/src/cursor/cur_join.c @@ -457,7 +457,6 @@ __curjoin_entry_in_range(WT_SESSION_IMPL *session, WT_CURSOR_JOIN_ENTRY *entry, collator = (entry->index != NULL) ? entry->index->collator : NULL; endmax = &entry->ends[entry->ends_next]; disjunction = F_ISSET(entry, WT_CURJOIN_ENTRY_DISJUNCTION); - passed = false; /* * The iterator may have already satisfied some endpoint conditions. diff --git a/src/include/error.h b/src/include/error.h index 2d302fb6879..3b3c0769c90 100644 --- a/src/include/error.h +++ b/src/include/error.h @@ -118,7 +118,7 @@ #ifdef HAVE_DIAGNOSTIC #define WT_ASSERT(session, exp) do { \ if (!(exp)) \ - __wt_assert(session, 0, __FILE__, __LINE__, "%s", #exp);\ + __wt_assert(session, 0, __func__, __LINE__, "%s", #exp);\ } while (0) #else #define WT_ASSERT(session, exp) \ diff --git a/src/include/extern.h b/src/include/extern.h index 9a86dbc1a26..a46f5ba7dda 100644 --- a/src/include/extern.h +++ b/src/include/extern.h @@ -531,6 +531,7 @@ extern int __wt_malloc(WT_SESSION_IMPL *session, size_t bytes_to_allocate, void extern int __wt_realloc(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern int __wt_realloc_noclear(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern int __wt_realloc_aligned(WT_SESSION_IMPL *session, size_t *bytes_allocated_ret, size_t bytes_to_allocate, void *retp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); +extern int __wt_memdup(WT_SESSION_IMPL *session, const void *str, size_t len, void *retp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern int __wt_strndup(WT_SESSION_IMPL *session, const void *str, size_t len, void *retp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); extern void __wt_free_int(WT_SESSION_IMPL *session, const void *p_arg) WT_GCC_FUNC_DECL_ATTRIBUTE((visibility("default"))); extern int __wt_errno(void) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result)); diff --git a/src/include/misc.h b/src/include/misc.h index a6cb56dd852..7d58cbc8383 100644 --- a/src/include/misc.h +++ b/src/include/misc.h @@ -279,11 +279,11 @@ typedef void wt_timestamp_t; */ #ifdef HAVE_DIAGNOSTIC #define __wt_scr_alloc(session, size, scratchp) \ - __wt_scr_alloc_func(session, size, scratchp, __FILE__, __LINE__) + __wt_scr_alloc_func(session, size, scratchp, __func__, __LINE__) #define __wt_page_in(session, ref, flags) \ - __wt_page_in_func(session, ref, flags, __FILE__, __LINE__) + __wt_page_in_func(session, ref, flags, __func__, __LINE__) #define __wt_page_swap(session, held, want, flags) \ - __wt_page_swap_func(session, held, want, flags, __FILE__, __LINE__) + __wt_page_swap_func(session, held, want, flags, __func__, __LINE__) #else #define __wt_scr_alloc(session, size, scratchp) \ __wt_scr_alloc_func(session, size, scratchp) @@ -295,7 +295,7 @@ typedef void wt_timestamp_t; /* Called on unexpected code path: locate the failure. */ #define __wt_illegal_value(session, msg) \ - __wt_illegal_value_func(session, msg, __FILE__, __LINE__) + __wt_illegal_value_func(session, msg, __func__, __LINE__) /* Random number generator state. */ union __wt_rand_state { diff --git a/src/include/msvc.h b/src/include/msvc.h index f1fab2add9e..d9bbd2d505b 100644 --- a/src/include/msvc.h +++ b/src/include/msvc.h @@ -13,6 +13,11 @@ #define inline __inline +/* MSVC Doesn't provide __func__, it has __FUNCTION__ */ +#ifdef _MSC_VER +#define __func__ __FUNCTION__ +#endif + #define WT_PTRDIFFT_FMT "Id" /* ptrdiff_t format string */ #define WT_SIZET_FMT "Iu" /* size_t format string */ diff --git a/src/lsm/lsm_meta.c b/src/lsm/lsm_meta.c index 66ad24dee5b..3a4960aaec1 100644 --- a/src/lsm/lsm_meta.c +++ b/src/lsm/lsm_meta.c @@ -309,12 +309,10 @@ __lsm_meta_read_v1( continue; } WT_ERR(__wt_realloc_def(session, - &lsm_tree->old_alloc, nchunks + 1, - &lsm_tree->old_chunks)); + &lsm_tree->old_alloc, nchunks + 1, &lsm_tree->old_chunks)); WT_ERR(__wt_calloc_one(session, &chunk)); lsm_tree->old_chunks[nchunks++] = chunk; - WT_ERR(__wt_strndup(session, - lk.str, lk.len, &chunk->uri)); + WT_ERR(__wt_strndup(session, lk.str, lk.len, &chunk->uri)); F_SET(chunk, WT_LSM_CHUNK_ONDISK); } WT_ERR_NOTFOUND_OK(ret); diff --git a/src/lsm/lsm_tree.c b/src/lsm/lsm_tree.c index e6eccf96467..3a1165ec239 100644 --- a/src/lsm/lsm_tree.c +++ b/src/lsm/lsm_tree.c @@ -282,8 +282,8 @@ __wt_lsm_tree_setup_chunk( WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_SCHEMA)); __wt_epoch(session, &chunk->create_time); - __wt_spin_init(session, - &chunk->timestamp_spinlock, "LSM chunk timestamp"); + WT_RET(__wt_spin_init(session, + &chunk->timestamp_spinlock, "LSM chunk timestamp")); WT_RET(__wt_lsm_tree_chunk_name( session, lsm_tree, chunk->id, &chunk->uri)); diff --git a/src/os_common/os_alloc.c b/src/os_common/os_alloc.c index 388c9c8c18b..fe31403c3f5 100644 --- a/src/os_common/os_alloc.c +++ b/src/os_common/os_alloc.c @@ -251,29 +251,45 @@ __wt_realloc_aligned(WT_SESSION_IMPL *session, } /* + * __wt_memdup -- + * Duplicate a byte string of a given length. + */ +int +__wt_memdup(WT_SESSION_IMPL *session, const void *str, size_t len, void *retp) +{ + void *p; + + WT_RET(__wt_malloc(session, len, &p)); + + WT_ASSERT(session, p != NULL); /* quiet clang scan-build */ + + memcpy(p, str, len); + + *(void **)retp = p; + return (0); +} + +/* * __wt_strndup -- - * Duplicate a byte string of a given length (and NUL-terminate). + * ANSI strndup function. */ int __wt_strndup(WT_SESSION_IMPL *session, const void *str, size_t len, void *retp) { - void *p; + uint8_t *p; if (str == NULL) { *(void **)retp = NULL; return (0); } + /* Copy and nul-terminate. */ WT_RET(__wt_malloc(session, len + 1, &p)); WT_ASSERT(session, p != NULL); /* quiet clang scan-build */ - /* - * Don't change this to strncpy, we rely on this function to duplicate - * "strings" that contain nul bytes. - */ memcpy(p, str, len); - ((uint8_t *)p)[len] = '\0'; + p[len] = '\0'; *(void **)retp = p; return (0); diff --git a/src/os_posix/os_fs.c b/src/os_posix/os_fs.c index d0391537543..c72c116015f 100644 --- a/src/os_posix/os_fs.c +++ b/src/os_posix/os_fs.c @@ -550,7 +550,7 @@ __posix_open_file_cloexec(WT_SESSION_IMPL *session, int fd, const char *name) if ((f = fcntl(fd, F_GETFD)) == -1 || fcntl(fd, F_SETFD, f | FD_CLOEXEC) == -1) WT_RET_MSG(session, __wt_errno(), - "%s: handle-open: fcntl", name); + "%s: handle-open: fcntl(FD_CLOEXEC)", name); return (0); #else WT_UNUSED(session); @@ -602,7 +602,8 @@ __posix_open_file(WT_FILE_SYSTEM *file_system, WT_SESSION *wt_session, WT_SYSCALL_RETRY(( (pfh->fd = open(name, f, 0444)) == -1 ? -1 : 0), ret); if (ret != 0) - WT_ERR_MSG(session, ret, "%s: handle-open: open", name); + WT_ERR_MSG(session, ret, + "%s: handle-open: open-directory", name); WT_ERR(__posix_open_file_cloexec(session, pfh->fd, name)); goto directory_open; } diff --git a/src/reconcile/rec_write.c b/src/reconcile/rec_write.c index 10c2c0dc937..5d5b909eee5 100644 --- a/src/reconcile/rec_write.c +++ b/src/reconcile/rec_write.c @@ -3131,7 +3131,7 @@ no_slots: */ if (F_ISSET(r, WT_EVICT_SCRUB) || (F_ISSET(r, WT_EVICT_UPDATE_RESTORE) && r->supd_next > 0)) { - WT_RET(__wt_strndup(session, dsk, + WT_RET(__wt_memdup(session, dsk, dsk_dst->mem_size, &last->disk_image)); disk_image = last->disk_image; disk_image->recno = last->max_bnd_recno; @@ -3674,7 +3674,7 @@ supd_check_complete: #ifdef HAVE_DIAGNOSTIC verify_image = false; #endif - WT_ERR(__wt_strndup(session, addr, addr_size, &bnd->addr.addr)); + WT_ERR(__wt_memdup(session, addr, addr_size, &bnd->addr.addr)); bnd->addr.size = (uint8_t)addr_size; /* @@ -3711,7 +3711,7 @@ copy_image: __wt_verify_dsk_image( session, "[reconcile-image]", buf->data, 0, true) == 0); #endif - WT_ERR(__wt_strndup( + WT_ERR(__wt_memdup( session, buf->data, buf->size, &bnd->disk_image)); } if (!need_image) diff --git a/src/txn/txn_timestamp.c b/src/txn/txn_timestamp.c index 275ef941490..704a4c4da5c 100644 --- a/src/txn/txn_timestamp.c +++ b/src/txn/txn_timestamp.c @@ -262,8 +262,7 @@ __wt_txn_global_query_timestamp( WT_UNUSED(cfg); WT_RET_MSG(session, ENOTSUP, - "WT_CONNECTION.query_timestamp requires a version of WiredTiger " - "built with timestamp support"); + "requires a version of WiredTiger built with timestamp support"); #endif } @@ -454,7 +453,7 @@ __wt_txn_global_set_timestamp(WT_SESSION_IMPL *session, const char *cfg[]) WT_RET(__wt_txn_update_pinned_timestamp(session)); } #else - WT_RET_MSG(session, EINVAL, "set_timestamp requires a " + WT_RET_MSG(session, ENOTSUP, "set_timestamp requires a " "version of WiredTiger built with timestamp support"); #endif return (0); @@ -482,7 +481,7 @@ __wt_txn_set_timestamp(WT_SESSION_IMPL *session, const char *cfg[]) session, "commit", &txn->commit_timestamp, &cval)); __wt_txn_set_commit_timestamp(session); #else - WT_RET_MSG(session, EINVAL, "commit_timestamp requires a " + WT_RET_MSG(session, ENOTSUP, "commit_timestamp requires a " "version of WiredTiger built with timestamp support"); #endif } diff --git a/test/windows/windows_shim.h b/test/windows/windows_shim.h index ad9de676deb..5a065ed8a79 100644 --- a/test/windows/windows_shim.h +++ b/test/windows/windows_shim.h @@ -33,11 +33,6 @@ #define R_OK 04 #define X_OK R_OK -/* MSVC Doesn't provide __func__, it has __FUNCTION__ */ -#ifdef _MSC_VER -#define __func__ __FUNCTION__ -#endif - /* snprintf does not exist on <= VS 2013 */ #if _MSC_VER < 1900 #define snprintf __wt_snprintf |