diff options
author | dequis <dx@dxzone.com.ar> | 2017-05-17 06:18:49 -0300 |
---|---|---|
committer | dequis <dx@dxzone.com.ar> | 2017-05-18 00:21:11 -0300 |
commit | 632b0ce5e68ce32ade90382cb64fbb8d1e75090d (patch) | |
tree | 77cf6da3879340823f77d6d7c9ec11ca88dece83 /src/core/misc.h | |
parent | 10cea6169694808ab2bf2caf9451cfac2db0d9da (diff) | |
download | irssi-632b0ce5e68ce32ade90382cb64fbb8d1e75090d.zip |
Add parse_uint function to improve integer overflow handling
Originally found by oss-fuzz (issue 525) in get_ansi_color using ubsan.
After a lot of analysis I'm 99% sure this isn't security relevant so
it's fine to handle this publicly.
The fix is mainly adding a function that does it right and use it
everywhere. This is harder than it seems because the strtol() family of
functions doesn't have the friendliest of interfaces.
Aside from get_ansi_color(), there were other pieces of code that used
the same (out*10+(*in-'0')) pattern, like the parse_size() and
parse_time_interval() functions, which are mostly used for settings.
Those are interesting cases, since they multiply the parsed number
(resulting in more overflows) and they write to a signed integer
parameter (which can accidentally make the uints negative without UB)
Thanks to Pascal Cuoq for enlightening me about the undefined behavior
of parse_size (and, in particular, the implementation-defined behavior
of one of the WIP versions of this commit, where something like signed
integer overflow happened, but it was legal). Also for writing
tis-interpreter, which is better than ubsan to verify these things.
Diffstat (limited to 'src/core/misc.h')
-rw-r--r-- | src/core/misc.h | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/src/core/misc.h b/src/core/misc.h index 00637da0..375744db 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -71,6 +71,7 @@ int expand_escape(const char **data); int nearest_power(int num); /* Returns TRUE / FALSE */ +int parse_uint(const char *nptr, char **endptr, int base, guint *number); int parse_time_interval(const char *time, int *msecs); int parse_size(const char *size, int *bytes); |