Add support for more strict config value validation

This patch adds functions to get int, uint, double value from string
with error checking and range specification.
These functions don't allow overflow and outside of the range values.

In addition, it adds parser_result cases "MALFORMED" and "OUT_OF_RANGE" to make
reason of parse error more clear.

Signed-off-by: Ken ICHIKAWA <ichikawa.ken@jp.fujitsu.com>
master
Ken ICHIKAWA 2013-06-04 13:57:22 +09:00 committed by Richard Cochran
parent a29b3bc4f9
commit 306f83e7b1
4 changed files with 106 additions and 6 deletions

View File

@ -30,12 +30,6 @@ enum config_section {
UNKNOWN_SECTION, UNKNOWN_SECTION,
}; };
enum parser_result {
PARSED_OK,
NOT_PARSED,
BAD_VALUE,
};
static enum parser_result parse_section_line(char *s, enum config_section *section) static enum parser_result parse_section_line(char *s, enum config_section *section)
{ {
if (!strcasecmp(s, "[global]")) { if (!strcasecmp(s, "[global]")) {
@ -512,6 +506,14 @@ int config_read(char *name, struct config *cfg)
fprintf(stderr, "%s is a bad value for option %s at line %d\n", fprintf(stderr, "%s is a bad value for option %s at line %d\n",
value, option, line_num); value, option, line_num);
goto parse_error; goto parse_error;
case MALFORMED:
fprintf(stderr, "%s is a malformed value for option %s at line %d\n",
value, option, line_num);
goto parse_error;
case OUT_OF_RANGE:
fprintf(stderr, "%s is an out of range value for option %s at line %d\n",
value, option, line_num);
goto parse_error;
} }
break; break;

View File

@ -46,6 +46,14 @@ struct interface {
#define CFG_IGNORE_USE_SYSLOG (1 << 5) #define CFG_IGNORE_USE_SYSLOG (1 << 5)
#define CFG_IGNORE_VERBOSE (1 << 6) #define CFG_IGNORE_VERBOSE (1 << 6)
enum parser_result {
PARSED_OK,
NOT_PARSED,
BAD_VALUE,
MALFORMED,
OUT_OF_RANGE,
};
struct config { struct config {
/* configuration override */ /* configuration override */
int cfg_ignore; int cfg_ignore;

44
util.c
View File

@ -16,7 +16,9 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "sk.h" #include "sk.h"
@ -190,3 +192,45 @@ int leap_second_status(uint64_t ts, int leap_set, int *leap, int *utc_offset)
return leap_status; return leap_status;
} }
enum parser_result get_ranged_int(const char *str_val, int *result, int min, int max)
{
long parsed_val;
char *endptr = NULL;
errno = 0;
parsed_val = strtol(str_val, &endptr, 0);
if (*endptr != '\0' || endptr == str_val)
return MALFORMED;
if (errno == ERANGE || parsed_val < min || parsed_val > max)
return OUT_OF_RANGE;
*result = parsed_val;
return PARSED_OK;
}
enum parser_result get_ranged_uint(const char *str_val, unsigned int *result, unsigned int min, unsigned int max)
{
unsigned long parsed_val;
char *endptr = NULL;
errno = 0;
parsed_val = strtoul(str_val, &endptr, 0);
if (*endptr != '\0' || endptr == str_val)
return MALFORMED;
if (errno == ERANGE || parsed_val < min || parsed_val > max)
return OUT_OF_RANGE;
*result = parsed_val;
return PARSED_OK;
}
enum parser_result get_ranged_double(const char *str_val, double *result, double min, double max)
{
double parsed_val;
char *endptr = NULL;
errno = 0;
parsed_val = strtod(str_val, &endptr);
if (*endptr != '\0' || endptr == str_val)
return MALFORMED;
if (errno == ERANGE || parsed_val < min || parsed_val > max)
return OUT_OF_RANGE;
*result = parsed_val;
return PARSED_OK;
}

46
util.h
View File

@ -20,6 +20,7 @@
#ifndef HAVE_UTIL_H #ifndef HAVE_UTIL_H
#define HAVE_UTIL_H #define HAVE_UTIL_H
#include "config.h"
#include "ddt.h" #include "ddt.h"
/** /**
@ -114,4 +115,49 @@ int is_utc_ambiguous(uint64_t ts);
* inserted, -1 if leap second will be deleted. * inserted, -1 if leap second will be deleted.
*/ */
int leap_second_status(uint64_t ts, int leap_set, int *leap, int *utc_offset); int leap_second_status(uint64_t ts, int leap_set, int *leap, int *utc_offset);
/**
* Get an integer value from string with error checking and range
* specification.
*
* @param str_val String which contains an integer value.
* @param result Parsed value is stored in here.
* @param min Lower limit. Return OUT_OF_RANGE if parsed value
* is less than min.
* @param max Upper Limit. Return OUT_OF_RANGE if parsed value
* is bigger than max.
* @return PARSED_OK on success, MALFORMED if str_val is malformed,
* OUT_OF_RANGE if str_val is out of range.
*/
enum parser_result get_ranged_int(const char *str_val, int *result, int min, int max);
/**
* Get an unsigned integer value from string with error checking and range
* specification.
*
* @param str_val String which contains an unsigned integer value.
* @param result Parsed value is stored in here.
* @param min Lower limit. Return OUT_OF_RANGE if parsed value
* is less than min.
* @param max Upper Limit. Return OUT_OF_RANGE if parsed value
* is bigger than max.
* @return PARSED_OK on success, MALFORMED if str_val is malformed,
* OUT_OF_RANGE if str_val is out of range.
*/
enum parser_result get_ranged_uint(const char *str_val, unsigned int *result, unsigned int min, unsigned int max);
/**
* Get a double value from string with error checking and range
* specification.
*
* @param str_val String which contains a double value.
* @param result Parsed value is stored in here.
* @param min Lower limit. Return OUT_OF_RANGE if parsed value
* is less than min.
* @param max Upper Limit. Return OUT_OF_RANGE if parsed value
* is bigger than max.
* @return PARSED_OK on success, MALFORMED if str_val is malformed,
* OUT_OF_RANGE if str_val is out of range.
*/
enum parser_result get_ranged_double(const char *str_val, double *result, double min, double max);
#endif #endif