From bc08b05912122ebddb3aafbf06e5ad0deb17dd87 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Mon, 31 Aug 2026 11:23:05 -0400 Subject: [PATCH] MT#65420 stricter str_to_X family Has the benefit of not needing to write to the buffer Change-Id: I5897d4fcd7a37e143bceb5569b9bfa1237593b3e --- daemon/cli.c | 12 ++--- daemon/control_ng_flags_parser.c | 2 +- daemon/janus.c | 8 ++-- lib/evs.c | 6 +-- lib/str.h | 78 ++++++++++++++++---------------- 5 files changed, 54 insertions(+), 52 deletions(-) diff --git a/daemon/cli.c b/daemon/cli.c index 736efd5d5..07df96a99 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -1947,7 +1947,7 @@ static void cli_incoming_media_add_db(str *instr, struct cli_writer *cw, const c return ; } - unsigned long long id = str_to_ui(instr, 0); + unsigned long long id = str_to_ull(instr, 0); if (id == 0 || id == ULLONG_MAX) cw->cw_printf(cw, "Invalid ID '" STR_FORMAT "'\n", STR_FMT(instr)); else { @@ -1965,7 +1965,7 @@ static void cli_incoming_media_reload_db(str *instr, struct cli_writer *cw, cons return ; } - unsigned long long id = str_to_ui(instr, 0); + unsigned long long id = str_to_ull(instr, 0); if (id == 0 || id == ULLONG_MAX) cw->cw_printf(cw, "Invalid ID '" STR_FORMAT "'\n", STR_FMT(instr)); else { @@ -1988,7 +1988,7 @@ static void cli_incoming_media_add_cache(str *instr, struct cli_writer *cw, cons return ; } - unsigned long long id = str_to_ui(instr, 0); + unsigned long long id = str_to_ull(instr, 0); if (id == 0 || id == ULLONG_MAX) cw->cw_printf(cw, "Invalid ID '" STR_FORMAT "'\n", STR_FMT(instr)); else { @@ -2006,7 +2006,7 @@ static void cli_incoming_media_reload_cache(str *instr, struct cli_writer *cw, c return ; } - unsigned long long id = str_to_ui(instr, 0); + unsigned long long id = str_to_ull(instr, 0); if (id == 0 || id == ULLONG_MAX) cw->cw_printf(cw, "Invalid ID '" STR_FORMAT "'\n", STR_FMT(instr)); else { @@ -2049,7 +2049,7 @@ static void cli_incoming_media_evict_db(str *instr, struct cli_writer *cw, const str token; while (str_token_sep(&token, instr, ' ')) { - unsigned long long id = str_to_ui(&token, 0); + unsigned long long id = str_to_ull(&token, 0); if (id == 0 || id == ULLONG_MAX) cw->cw_printf(cw, "Invalid ID '" STR_FORMAT "'\n", STR_FMT(&token)); else { @@ -2097,7 +2097,7 @@ static void cli_incoming_media_evict_cache(str *instr, struct cli_writer *cw, co str token; while (str_token_sep(&token, instr, ' ')) { - unsigned long long id = str_to_ui(&token, 0); + unsigned long long id = str_to_ull(&token, 0); if (id == 0 || id == ULLONG_MAX) cw->cw_printf(cw, "Invalid ID '" STR_FORMAT "'\n", STR_FMT(&token)); else { diff --git a/daemon/control_ng_flags_parser.c b/daemon/control_ng_flags_parser.c index abff3c7e2..95d1123e4 100644 --- a/daemon/control_ng_flags_parser.c +++ b/daemon/control_ng_flags_parser.c @@ -111,7 +111,7 @@ static long long rtpp_get_int_str(rtpp_pos *a, long long def) { str s; if (!rtpp_get_str(a, &s)) return def; - return str_to_i(&s, def); + return str_to_ll(&s, def); } static bool rtpp_dict_list_end_rewind(rtpp_pos *pos) { // check for dict/list end, which is only valid if it doesn't also start one diff --git a/daemon/janus.c b/daemon/janus.c index 2f2ba3d56..a82b02892 100644 --- a/daemon/janus.c +++ b/daemon/janus.c @@ -1231,7 +1231,7 @@ void janus_rtc_up(struct call_monologue *ml) { return; // the monologue tag is the handle ID - uint64_t handle = str_to_ui(&ml->tag, 0); + uint64_t handle = str_to_ull(&ml->tag, 0); if (!handle) return; @@ -1264,7 +1264,7 @@ void janus_media_up(struct call_media *media) { return; // the monologue tag is the handle ID - uint64_t handle = str_to_ui(&ml->tag, 0); + uint64_t handle = str_to_ull(&ml->tag, 0); if (!handle) return; @@ -1961,10 +1961,10 @@ const char *websocket_janus_post(struct websocket_message *wm) { goto done; if (!str_token_sep(&s, &uri, '/')) goto done; - session_id = str_to_ui(&s, 0); + session_id = str_to_ull(&s, 0); if (!str_token_sep(&s, &uri, '/')) goto done; - handle_id = str_to_ui(&s, 0); + handle_id = str_to_ull(&s, 0); done: return websocket_janus_process_json(wm, session_id, handle_id); diff --git a/lib/evs.c b/lib/evs.c index 6d5c55d53..9d90d8e52 100644 --- a/lib/evs.c +++ b/lib/evs.c @@ -474,12 +474,12 @@ static unsigned int str_to_i_k(str *s) { str intg; str frac = *s; if (str_token(&intg, &frac, '.')) { - unsigned int ret = str_to_i(s, 0) * 1000; + unsigned int ret = str_to_u(&intg, 0) * 1000; if (frac.len > 1) // at most one decimal digit frac.len = 1; - return ret + str_to_i(&frac, 0) * 100; + return ret + str_to_u(&frac, 0) * 100; } - return str_to_i(s, 0) * 1000; + return str_to_u(s, 0) * 1000; } diff --git a/lib/str.h b/lib/str.h index 07c3211bb..421896b8f 100644 --- a/lib/str.h +++ b/lib/str.h @@ -137,14 +137,14 @@ __attribute__((nonnull(1, 2))) ACCESS(read_write, 1) ACCESS(read_write, 2) INLINE void str_swap(str *a, str *b); -/* parses a string into an int, returns default if conversion fails */ -__attribute__((nonnull(1))) -ACCESS(read_only, 1) -INLINE long long str_to_i(const str *s, long long def); -/* parses a string into an uint, returns default if conversion fails */ -__attribute__((nonnull(1))) -ACCESS(read_only, 1) -INLINE unsigned long long str_to_ui(const str *s, unsigned long long def); + +__attribute__((nonnull(1))) ACCESS(read_only, 1) INLINE long str_to_l(const str *s, long def); +__attribute__((nonnull(1))) ACCESS(read_only, 1) INLINE unsigned long str_to_ul(const str *s, unsigned long def); +__attribute__((nonnull(1))) ACCESS(read_only, 1) INLINE int str_to_i(const str *s, int def); +__attribute__((nonnull(1))) ACCESS(read_only, 1) INLINE unsigned int str_to_u(const str *s, unsigned int def); +__attribute__((nonnull(1))) ACCESS(read_only, 1) INLINE long long str_to_ll(const str *s, long long def); +__attribute__((nonnull(1))) ACCESS(read_only, 1) INLINE unsigned long long str_to_ull(const str *s, unsigned long long def); + /* extracts the first/next token into "new_token" and modifies "ori_and_remaidner" in place */ __attribute__((nonnull(1, 2))) ACCESS(write_only, 1) @@ -380,37 +380,39 @@ INLINE void str_swap(str *a, str *b) { *b = t; } -INLINE long long str_to_i(const str *s, long long def) { - char c, *ep; - long long ret; - if (s->len <= 0) - return def; - c = s->s[s->len]; - s->s[s->len] = '\0'; - ret = strtoll(s->s, &ep, 10); - s->s[s->len] = c; - if (ep == s->s) - return def; - if (ret > INT_MAX) - return def; - if (ret < INT_MIN) - return def; - return ret; -} +#define MAX_LONG_LONG_LEN 21 // assume 64 bits +#define MAX_LONG_LEN 21 // assume 64 bits +#define MAX_INT_LEN 11 // assume 32 bits + +#define str_to_x(type, name, max_len, fn, min_val, max_val) \ + INLINE type name(const str *s, type def) { \ + char *ep; \ + char buf[max_len + 1]; \ + type ret; \ + if (s->len <= 0) \ + return def; \ + if (s->len > max_len) \ + return def; \ + memcpy(buf, s->s, s->len); \ + buf[s->len] = '\0'; \ + errno = 0; \ + ret = fn(buf, &ep, 10); \ + if (*ep != '\0') \ + return def; \ + if (ret == max_val && errno == ERANGE) \ + return def; \ + if (ret == min_val && errno == ERANGE) \ + return def; \ + return ret; \ + } + +str_to_x(long long, str_to_ll, MAX_LONG_LONG_LEN, strtoll, LLONG_MIN, LLONG_MAX) +str_to_x(unsigned long long, str_to_ull, MAX_LONG_LONG_LEN, strtoll, ULLONG_MAX, ULLONG_MAX) +str_to_x(long, str_to_l, MAX_LONG_LEN, strtol, LONG_MIN, LONG_MAX) +str_to_x(unsigned long, str_to_ul, MAX_LONG_LEN, strtol, ULONG_MAX, ULONG_MAX) +str_to_x(int, str_to_i, MAX_INT_LEN, strtol, INT_MIN, INT_MAX) +str_to_x(unsigned int, str_to_u, MAX_INT_LEN, strtoul, INT_MAX, INT_MAX) -INLINE unsigned long long str_to_ui(const str *s, unsigned long long def) { - char c, *ep; - unsigned long long ret; - if (s->len <= 0) - return def; - c = s->s[s->len]; - s->s[s->len] = '\0'; - ret = strtoull(s->s, &ep, 10); - s->s[s->len] = c; - if (ep == s->s) - return def; - return ret; -} INLINE bool str_token(str *new_token, str *ori_and_remainder, int sep) { *new_token = *ori_and_remainder;