From ca62c0e1640e5d112679044434227024690b53bc Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Tue, 12 Dec 2023 09:24:43 +0100 Subject: Fix hex literals in json output Json does not allow 0x prefixes in hex numbers, so output hex numbers as quoted strings instead. Fixes bugzilla #1726, reported by Mark. Signed-off-by: Jozsef Kadlecsik --- include/libipset/session.h | 2 ++ lib/print.c | 19 ++++++++++--------- lib/session.c | 31 +++++++++++++++++-------------- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/include/libipset/session.h b/include/libipset/session.h index f0da10f..365e17e 100644 --- a/include/libipset/session.h +++ b/include/libipset/session.h @@ -84,6 +84,8 @@ enum ipset_envopt { IPSET_ENV_LIST_SETNAME = (1 << IPSET_ENV_BIT_LIST_SETNAME), IPSET_ENV_BIT_LIST_HEADER = 5, IPSET_ENV_LIST_HEADER = (1 << IPSET_ENV_BIT_LIST_HEADER), + IPSET_ENV_BIT_QUOTED = 6, + IPSET_ENV_QUOTED = (1 << IPSET_ENV_BIT_QUOTED), }; extern bool ipset_envopt_test(struct ipset_session *session, diff --git a/lib/print.c b/lib/print.c index 50f0ad6..6ea79cb 100644 --- a/lib/print.c +++ b/lib/print.c @@ -411,10 +411,11 @@ ipset_print_number(char *buf, unsigned int len, int ipset_print_hexnumber(char *buf, unsigned int len, const struct ipset_data *data, enum ipset_opt opt, - uint8_t env UNUSED) + uint8_t env) { size_t maxsize; const void *number; + const char *quoted = env & IPSET_ENV_QUOTED ? "\"" : ""; assert(buf); assert(len > 0); @@ -424,17 +425,17 @@ ipset_print_hexnumber(char *buf, unsigned int len, maxsize = ipset_data_sizeof(opt, AF_INET); D("opt: %u, maxsize %zu", opt, maxsize); if (maxsize == sizeof(uint8_t)) - return snprintf(buf, len, "0x%02"PRIx8, - *(const uint8_t *) number); + return snprintf(buf, len, "%s0x%02"PRIx8"%s", + quoted, *(const uint8_t *) number, quoted); else if (maxsize == sizeof(uint16_t)) - return snprintf(buf, len, "0x%04"PRIx16, - *(const uint16_t *) number); + return snprintf(buf, len, "%s0x%04"PRIx16"%s", + quoted, *(const uint16_t *) number, quoted); else if (maxsize == sizeof(uint32_t)) - return snprintf(buf, len, "0x%08"PRIx32, - *(const uint32_t *) number); + return snprintf(buf, len, "%s0x%08"PRIx32"%s", + quoted, *(const uint32_t *) number, quoted); else if (maxsize == sizeof(uint64_t)) - return snprintf(buf, len, "0x%016"PRIx64, - *(const uint64_t *) number); + return snprintf(buf, len, "%s0x%016"PRIx64"%s", + quoted, *(const uint64_t *) number, quoted); else assert(0); return 0; diff --git a/lib/session.c b/lib/session.c index a10238d..944e002 100644 --- a/lib/session.c +++ b/lib/session.c @@ -2277,23 +2277,26 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno) session->cmd = cmd; session->lineno = lineno; - /* Set default output mode */ - if (cmd == IPSET_CMD_LIST) { + if (cmd == IPSET_CMD_LIST || cmd == IPSET_CMD_SAVE) { + /* Set default output mode */ if (session->mode == IPSET_LIST_NONE) session->mode = IPSET_LIST_PLAIN; - } else if (cmd == IPSET_CMD_SAVE) { - if (session->mode == IPSET_LIST_NONE) - session->mode = IPSET_LIST_SAVE; + /* Reset just in case there are multiple modes in a session */ + ipset_envopt_unset(session, IPSET_ENV_QUOTED); + switch (session->mode) { + case IPSET_LIST_XML: + /* Start the root element in XML mode */ + safe_snprintf(session, "\n"); + break; + case IPSET_LIST_JSON: + /* Start the root element in json mode */ + ipset_envopt_set(session, IPSET_ENV_QUOTED); + safe_snprintf(session, "[\n"); + break; + default: + break; + } } - /* Start the root element in XML mode */ - if ((cmd == IPSET_CMD_LIST || cmd == IPSET_CMD_SAVE) && - session->mode == IPSET_LIST_XML) - safe_snprintf(session, "\n"); - - /* Start the root element in json mode */ - if ((cmd == IPSET_CMD_LIST || cmd == IPSET_CMD_SAVE) && - session->mode == IPSET_LIST_JSON) - safe_snprintf(session, "[\n"); D("next: build_msg"); /* Build new message or append buffered commands */ -- cgit v1.2.3