From f843eb3d31bf9f0a77c4ceaf07f40e792a13b17b Mon Sep 17 00:00:00 2001 From: Aaron Gyes Date: Sun, 25 Sep 2016 21:50:55 -0700 Subject: [PATCH] Add a template to parse integers easily/correctly (#3405) * Adds a template to parse integers easily. It's not enough to use intmax_t and check for empty strings: there are limits. Adds a template to make it easy to parse an integer of any type. Adds a compiler flag to flag existing dangers. * nix warning, include , fix namespace error. on MacOS `xcodebuild -quiet` will flag these intmax_t -> * conversions, just use that if you want to find them. --- src/builtin.cpp | 4 ++-- src/common.h | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/builtin.cpp b/src/builtin.cpp index 9ba131622..694527b9b 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -1594,8 +1594,8 @@ int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_lis e.param1.job_id = job_id; } } else { - pid_t pid = wcstoimax(w.woptarg, &end, 10); - if (pid < 1 || !(*w.woptarg != L'\0' && *end == L'\0')) { + pid_t pid; + if (!(parse_integer(w.woptarg, &pid)) || pid < 1) { append_format(*out_err, _(L"%ls: Invalid process id '%ls'"), argv[0], w.woptarg); res = STATUS_BUILTIN_ERROR; diff --git a/src/common.h b/src/common.h index b41e1600a..4449f898f 100644 --- a/src/common.h +++ b/src/common.h @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -692,6 +695,21 @@ ssize_t read_loop(int fd, void *buff, size_t count); void __attribute__((noinline)) debug(int level, const char *msg, ...); void __attribute__((noinline)) debug(int level, const wchar_t *msg, ...); +/// Parse an integer and check limits for type +/// The only way to be safe from overflows is intmax_t. +/// Do that, and make sure the result isn't bigger than the maximum supported for whatever type. +template +bool parse_integer(const wchar_t *in, T* out) { + wchar_t *end; + intmax_t res = wcstoimax(in, &end, 0); + + if (!(*in != L'\0' && *end == L'\0')) return false; + if (std::numeric_limits::max() < res || res < std::numeric_limits::min()) return false; + + *out = static_cast(res); + return true; +} + /// Replace special characters with backslash escape sequences. Newline is replaced with \n, etc. /// /// \param in The string to be escaped