From 41cdf9d1b4ff0dbc46dd87efb2d92cb61489588d 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 (cherry picked from commit bc08b05912122ebddb3aafbf06e5ad0deb17dd87) (cherry picked from commit a73ce2f12851440bc6d64e65a2da5b4c341e68fd) --- daemon/cli.c | 12 ++--- daemon/control_ng_flags_parser.c | 2 +- daemon/janus.c | 8 ++-- lib/codeclib.c | 6 +-- lib/str.h | 78 ++++++++++++++++---------------- 5 files changed, 54 insertions(+), 52 deletions(-) diff --git a/daemon/cli.c b/daemon/cli.c index d261e871a..99dd62958 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -1946,7 +1946,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 { @@ -1964,7 +1964,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 { @@ -1987,7 +1987,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 { @@ -2005,7 +2005,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 { @@ -2048,7 +2048,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 { @@ -2096,7 +2096,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 3807d9e90..c4e425a16 100644 --- a/daemon/control_ng_flags_parser.c +++ b/daemon/control_ng_flags_parser.c @@ -112,7 +112,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 7c0749cdd..e392a9925 100644 --- a/daemon/janus.c +++ b/daemon/janus.c @@ -1226,7 +1226,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; @@ -1259,7 +1259,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; @@ -1956,10 +1956,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/codeclib.c b/lib/codeclib.c index c95b5bf05..76549c0d6 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -3858,12 +3858,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; } static const char *evs_bw_strings[__EVS_BW_MAX] = { "nb", "wb", "swb", "fb" }; diff --git a/lib/str.h b/lib/str.h index cffa03ffa..4906019a9 100644 --- a/lib/str.h +++ b/lib/str.h @@ -136,14 +136,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) @@ -379,37 +379,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;