From 3d4ad9f46bc90d083d1cbe881e06f1863ea0ef94 Mon Sep 17 00:00:00 2001 From: Nitzan Carmi Date: Tue, 10 Mar 2020 10:50:51 +0000 Subject: [PATCH] Allow hexadecimal number format convention parsing Allow parsing of the hexadecimal number standard format (e.g. `0x`). Signed-off-by: Nitzan Carmi --- json_tokener.c | 40 +++++++++++++++++++++++++++++++++++++++- json_tokener.h | 2 ++ json_util.c | 11 +++++++++-- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/json_tokener.c b/json_tokener.c index 68795c6..ce94dda 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -242,6 +242,30 @@ struct json_object* json_tokener_parse_verbose(const char *str, /* End optimization macro defs */ +int json_tokener_number_has_hex_prefix(const char *number) +{ + char *ptr_x; + + /* Find 'x' location on string, if exist */ + ptr_x = strchr(number, 'x'); + if (!ptr_x) + return 0; + + /* Check if 'x' located in a valid place */ + switch (ptr_x - number) { + case 1: + /* Positive Hex number, must start with '0x' */ + return (number[0] == '0'); + case 2: + /* Negative Hex number, must start with '-0x' */ + return (number[0] == '-') && (number[1] == '0'); + default: + return 0; + } + + return 0; +} + struct json_object* json_tokener_parse_ex(struct json_tokener *tok, const char *str, int len) { @@ -736,7 +760,21 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, int case_len=0; int is_exponent=0; int negativesign_next_possible_location=1; - while(c && strchr(json_number_chars, c)) { + const char *json_valid_chars = json_number_chars; + if (json_tokener_number_has_hex_prefix(str)) { + json_valid_chars = json_hex_chars; + /* Advance pointers after the `0x` prefix */ + while (c != 'x') { + case_len++; + if (!PEEK_CHAR(c, tok) || !ADVANCE_CHAR(str, tok)) { + tok->err = json_tokener_error_parse_number; + goto out; + } + } + if (!PEEK_CHAR(c, tok)) + goto out; + } + while(c && strchr(json_valid_chars, c)) { ++case_len; /* non-digit characters checks */ diff --git a/json_tokener.h b/json_tokener.h index 274e548..cbf4167 100644 --- a/json_tokener.h +++ b/json_tokener.h @@ -148,6 +148,8 @@ typedef struct json_tokener json_tokener; */ #define JSON_TOKENER_VALIDATE_UTF8 0x10 +int json_tokener_number_has_hex_prefix(const char *number); + /** * Given an error previously returned by json_tokener_get_error(), * return a human readable description of the error. diff --git a/json_util.c b/json_util.c index 1c1fa46..4be32b1 100644 --- a/json_util.c +++ b/json_util.c @@ -10,6 +10,7 @@ */ #include "config.h" +#include "json_tokener.h" #undef realloc #include "strerror_override.h" @@ -223,9 +224,12 @@ int json_parse_int64(const char *buf, int64_t *retval) { char *end = NULL; int64_t val; + int base; errno = 0; - val = strtoll(buf, &end, 10); + base = json_tokener_number_has_hex_prefix(buf) ? 16 : 10; + + val = strtoll(buf, &end, base); if (end != buf) *retval = val; return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0; @@ -235,14 +239,17 @@ int json_parse_uint64(const char *buf, uint64_t *retval) { char *end = NULL; uint64_t val; + int base; + errno = 1; + base = json_tokener_number_has_hex_prefix(buf) ? 16 : 10; while (*buf == ' ') { buf++; } if (*buf == '-') errno = 0; - val = strtoull(buf, &end, 10); + val = strtoull(buf, &end, base); if (end != buf) *retval = val; return ((errno == 0) || (end == buf)) ? 1 : 0;