mirror of
https://github.com/irssi/irssi.git
synced 2025-04-26 04:51:11 -05:00
Merge pull request #706 from dequis/parse-uint
Add parse_uint function to improve integer overflow handling
This commit is contained in:
commit
31b9d115b0
119
src/core/misc.c
119
src/core/misc.c
@ -750,10 +750,42 @@ int nearest_power(int num)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_time_interval(const char *time, int *msecs)
|
/* Parses unsigned integers from strings with decent error checking.
|
||||||
|
* Returns true on success, false otherwise (overflow, no valid number, etc)
|
||||||
|
* There's a 31 bit limit so the output can be assigned to signed positive ints */
|
||||||
|
int parse_uint(const char *nptr, char **endptr, int base, guint *number)
|
||||||
|
{
|
||||||
|
char *endptr_;
|
||||||
|
gulong parsed;
|
||||||
|
|
||||||
|
/* strtoul accepts whitespace and plus/minus signs, for some reason */
|
||||||
|
if (!i_isdigit(*nptr)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
parsed = strtoul(nptr, &endptr_, base);
|
||||||
|
|
||||||
|
if (errno || endptr_ == nptr || parsed >= (1U << 31)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endptr) {
|
||||||
|
*endptr = endptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (number) {
|
||||||
|
*number = (guint) parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_time_interval_uint(const char *time, guint *msecs)
|
||||||
{
|
{
|
||||||
const char *desc;
|
const char *desc;
|
||||||
int number, sign, len, ret, digits;
|
guint number;
|
||||||
|
int sign, len, ret, digits;
|
||||||
|
|
||||||
*msecs = 0;
|
*msecs = 0;
|
||||||
|
|
||||||
@ -769,8 +801,11 @@ int parse_time_interval(const char *time, int *msecs)
|
|||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (i_isdigit(*time)) {
|
if (i_isdigit(*time)) {
|
||||||
number = number*10 + (*time - '0');
|
char *endptr;
|
||||||
time++;
|
if (!parse_uint(time, &endptr, 10, &number)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
time = endptr;
|
||||||
digits = TRUE;
|
digits = TRUE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -835,10 +870,11 @@ int parse_time_interval(const char *time, int *msecs)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_size(const char *size, int *bytes)
|
static int parse_size_uint(const char *size, guint *bytes)
|
||||||
{
|
{
|
||||||
const char *desc;
|
const char *desc;
|
||||||
int number, len;
|
guint number, multiplier, limit;
|
||||||
|
int len;
|
||||||
|
|
||||||
*bytes = 0;
|
*bytes = 0;
|
||||||
|
|
||||||
@ -846,8 +882,11 @@ int parse_size(const char *size, int *bytes)
|
|||||||
number = 0;
|
number = 0;
|
||||||
while (*size != '\0') {
|
while (*size != '\0') {
|
||||||
if (i_isdigit(*size)) {
|
if (i_isdigit(*size)) {
|
||||||
number = number*10 + (*size - '0');
|
char *endptr;
|
||||||
size++;
|
if (!parse_uint(size, &endptr, 10, &number)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
size = endptr;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -869,14 +908,31 @@ int parse_size(const char *size, int *bytes)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_ascii_strncasecmp(desc, "gbytes", len) == 0)
|
multiplier = 0;
|
||||||
*bytes += number * 1024*1024*1024;
|
limit = 0;
|
||||||
if (g_ascii_strncasecmp(desc, "mbytes", len) == 0)
|
|
||||||
*bytes += number * 1024*1024;
|
if (g_ascii_strncasecmp(desc, "gbytes", len) == 0) {
|
||||||
if (g_ascii_strncasecmp(desc, "kbytes", len) == 0)
|
multiplier = 1U << 30;
|
||||||
*bytes += number * 1024;
|
limit = 2U << 0;
|
||||||
if (g_ascii_strncasecmp(desc, "bytes", len) == 0)
|
}
|
||||||
*bytes += number;
|
if (g_ascii_strncasecmp(desc, "mbytes", len) == 0) {
|
||||||
|
multiplier = 1U << 20;
|
||||||
|
limit = 2U << 10;
|
||||||
|
}
|
||||||
|
if (g_ascii_strncasecmp(desc, "kbytes", len) == 0) {
|
||||||
|
multiplier = 1U << 10;
|
||||||
|
limit = 2U << 20;
|
||||||
|
}
|
||||||
|
if (g_ascii_strncasecmp(desc, "bytes", len) == 0) {
|
||||||
|
multiplier = 1;
|
||||||
|
limit = 2U << 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limit && number > limit) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*bytes += number * multiplier;
|
||||||
|
|
||||||
/* skip punctuation */
|
/* skip punctuation */
|
||||||
while (*size != '\0' && i_ispunct(*size))
|
while (*size != '\0' && i_ispunct(*size))
|
||||||
@ -886,6 +942,37 @@ int parse_size(const char *size, int *bytes)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int parse_size(const char *size, int *bytes)
|
||||||
|
{
|
||||||
|
guint bytes_;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = parse_size_uint(size, &bytes_);
|
||||||
|
|
||||||
|
if (bytes_ > (1U << 31)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*bytes = bytes_;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_time_interval(const char *time, int *msecs)
|
||||||
|
{
|
||||||
|
guint msecs_;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = parse_time_interval_uint(time, &msecs_);
|
||||||
|
|
||||||
|
if (msecs_ > (1U << 31)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*msecs = msecs_;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char *ascii_strup(char *str)
|
char *ascii_strup(char *str)
|
||||||
{
|
{
|
||||||
char *s;
|
char *s;
|
||||||
|
@ -71,6 +71,7 @@ int expand_escape(const char **data);
|
|||||||
int nearest_power(int num);
|
int nearest_power(int num);
|
||||||
|
|
||||||
/* Returns TRUE / FALSE */
|
/* 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_time_interval(const char *time, int *msecs);
|
||||||
int parse_size(const char *size, int *bytes);
|
int parse_size(const char *size, int *bytes);
|
||||||
|
|
||||||
|
@ -275,6 +275,8 @@ static char *get_special_value(char **cmd, SERVER_REC *server, void *item,
|
|||||||
static int get_alignment_args(char **data, int *align, int *flags, char *pad)
|
static int get_alignment_args(char **data, int *align, int *flags, char *pad)
|
||||||
{
|
{
|
||||||
char *str;
|
char *str;
|
||||||
|
char *endptr;
|
||||||
|
guint align_;
|
||||||
|
|
||||||
*align = 0;
|
*align = 0;
|
||||||
*flags = ALIGN_CUT|ALIGN_PAD;
|
*flags = ALIGN_CUT|ALIGN_PAD;
|
||||||
@ -295,10 +297,11 @@ static int get_alignment_args(char **data, int *align, int *flags, char *pad)
|
|||||||
return FALSE; /* expecting number */
|
return FALSE; /* expecting number */
|
||||||
|
|
||||||
/* get the alignment size */
|
/* get the alignment size */
|
||||||
while (i_isdigit(*str)) {
|
if (!parse_uint(str, &endptr, 10, &align_)) {
|
||||||
*align = (*align) * 10 + (*str-'0');
|
return FALSE;
|
||||||
str++;
|
|
||||||
}
|
}
|
||||||
|
str = endptr;
|
||||||
|
*align = align_;
|
||||||
|
|
||||||
/* get the pad character */
|
/* get the pad character */
|
||||||
while (*str != '\0' && *str != ']') {
|
while (*str != '\0' && *str != ']') {
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "themes.h"
|
#include "themes.h"
|
||||||
#include "recode.h"
|
#include "recode.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
static const char *format_backs = "04261537";
|
static const char *format_backs = "04261537";
|
||||||
static const char *format_fores = "kbgcrmyw";
|
static const char *format_fores = "kbgcrmyw";
|
||||||
@ -870,8 +871,9 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str,
|
|||||||
{
|
{
|
||||||
static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
|
static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
|
||||||
const char *start;
|
const char *start;
|
||||||
int fg, bg, flags, num, i;
|
char *endptr;
|
||||||
unsigned int num2;
|
int fg, bg, flags, i;
|
||||||
|
guint num, num2;
|
||||||
|
|
||||||
if (*str != '[')
|
if (*str != '[')
|
||||||
return str;
|
return str;
|
||||||
@ -886,8 +888,10 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str,
|
|||||||
if (*str == '\0') return start;
|
if (*str == '\0') return start;
|
||||||
|
|
||||||
if (i_isdigit(*str)) {
|
if (i_isdigit(*str)) {
|
||||||
num = num*10 + (*str-'0');
|
if (!parse_uint(str, &endptr, 10, &num)) {
|
||||||
continue;
|
return start;
|
||||||
|
}
|
||||||
|
str = endptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*str != ';' && *str != 'm')
|
if (*str != ';' && *str != 'm')
|
||||||
@ -958,8 +962,12 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str,
|
|||||||
/* ANSI indexed color or RGB color */
|
/* ANSI indexed color or RGB color */
|
||||||
if (*str != ';') break;
|
if (*str != ';') break;
|
||||||
str++;
|
str++;
|
||||||
for (num2 = 0; i_isdigit(*str); str++)
|
|
||||||
num2 = num2*10 + (*str-'0');
|
if (!parse_uint(str, &endptr, 10, &num2)) {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
str = endptr;
|
||||||
|
|
||||||
if (*str == '\0') return start;
|
if (*str == '\0') return start;
|
||||||
|
|
||||||
switch (num2) {
|
switch (num2) {
|
||||||
@ -1006,8 +1014,12 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str,
|
|||||||
/* indexed */
|
/* indexed */
|
||||||
if (*str != ';') break;
|
if (*str != ';') break;
|
||||||
str++;
|
str++;
|
||||||
for (num2 = 0; i_isdigit(*str); str++)
|
|
||||||
num2 = num2*10 + (*str-'0');
|
if (!parse_uint(str, &endptr, 10, &num2)) {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
str = endptr;
|
||||||
|
|
||||||
if (*str == '\0') return start;
|
if (*str == '\0') return start;
|
||||||
|
|
||||||
if (num == 38) {
|
if (num == 38) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user