From 75cad931c48f09452a25bbe23d472bbdd68dfd59 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 24 Mar 2015 23:16:22 +0100 Subject: [PATCH] check all snprintf() callers and modify code to work correctly with the return value using tvh_strlcatf2() macro, fixes #2734 --- src/access.c | 23 +++++++++--------- src/descrambler/capmt.c | 2 ++ src/epg.c | 25 ++++++++++---------- src/htsp_server.c | 9 +++---- src/http.c | 6 ++--- src/input/mpegts/linuxdvb/linuxdvb_satconf.c | 2 +- src/input/mpegts/mpegts_pid.c | 3 +-- src/satip/rtp.c | 2 +- src/satip/rtsp.c | 8 +++---- src/subscriptions.c | 23 ++++++++---------- src/tvheadend.h | 15 ++++++++---- src/tvhlog.c | 18 +++++++------- 12 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/access.c b/src/access.c index 12fa4db3..af77d8f2 100644 --- a/src/access.c +++ b/src/access.c @@ -352,10 +352,11 @@ static void access_dump_a(access_t *a) { htsmsg_field_t *f; + size_t l = 0; char buf[1024]; int first; - snprintf(buf, sizeof(buf), + tvh_strlcatf2(buf, sizeof(buf), l, "%s:%s [%c%c%c%c%c%c%c%c%c], conn=%u, chmin=%llu, chmax=%llu%s", a->aa_representative ?: "", a->aa_username ?: "", @@ -378,14 +379,14 @@ access_dump_a(access_t *a) profile_t *pro = profile_find_by_uuid(htsmsg_field_get_str(f) ?: ""); if (pro) { if (first) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ", profile="); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s'%s'", + tvh_strlcatf2(buf, sizeof(buf), l, ", profile="); + tvh_strlcatf2(buf, sizeof(buf), l, "%s'%s'", first ? "" : ",", pro->pro_name ?: ""); first = 0; } } } else { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ", profile=ANY"); + tvh_strlcatf2(buf, sizeof(buf), l, ", profile=ANY"); } if (a->aa_dvrcfgs) { @@ -394,14 +395,14 @@ access_dump_a(access_t *a) dvr_config_t *cfg = dvr_config_find_by_uuid(htsmsg_field_get_str(f) ?: ""); if (cfg) { if (first) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ", dvr="); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s'%s'", + tvh_strlcatf2(buf, sizeof(buf), l, ", dvr="); + tvh_strlcatf2(buf, sizeof(buf), l, "%s'%s'", first ? "" : ",", cfg->dvr_config_name ?: ""); first = 0; } } } else { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ", dvr=ANY"); + tvh_strlcatf2(buf, sizeof(buf), l, ", dvr=ANY"); } if (a->aa_chtags) { @@ -410,14 +411,14 @@ access_dump_a(access_t *a) channel_tag_t *ct = channel_tag_find_by_uuid(htsmsg_field_get_str(f) ?: ""); if (ct) { if (first) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ", tags="); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s'%s'", + tvh_strlcatf2(buf, sizeof(buf), l, ", tags="); + tvh_strlcatf2(buf, sizeof(buf), l, "%s'%s'", first ? "" : ",", ct->ct_name ?: ""); first = 0; } } } else { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ", tag=ANY"); + tvh_strlcatf2(buf, sizeof(buf), l, ", tag=ANY"); } tvhtrace("access", "%s", buf); @@ -1074,7 +1075,7 @@ access_entry_class_prefix_get(void *o) s_addr = htonl(ai->ai_network); inet_ntop(AF_INET, &s_addr, addrbuf, sizeof(addrbuf)); } - pos += snprintf(buf+pos, sizeof(buf)-pos, ",%s/%d", addrbuf, ai->ai_prefixlen); + tvh_strlcatf2(buf, sizeof(buf), pos, ",%s/%d", addrbuf, ai->ai_prefixlen); } return &ret; } diff --git a/src/descrambler/capmt.c b/src/descrambler/capmt.c index ffd73699..206385fb 100644 --- a/src/descrambler/capmt.c +++ b/src/descrambler/capmt.c @@ -816,6 +816,8 @@ capmt_send_client_info(capmt_t *capmt) *(uint32_t *)(buf + 0) = htonl(DVBAPI_CLIENT_INFO); *(uint16_t *)(buf + 4) = htons(DVBAPI_PROTOCOL_VERSION); //supported protocol version int len = snprintf(buf + 7, sizeof(buf) - 7, "Tvheadend %s", tvheadend_version); + if (len >= sizeof(buf) - 7) + len = sizeof(buf) - 7 - 1; buf[6] = len; capmt_queue_msg(capmt, 0, 0, (uint8_t *)&buf, len + 7, CAPMT_MSG_FAST); diff --git a/src/epg.c b/src/epg.c index a000ae09..d1444693 100644 --- a/src/epg.c +++ b/src/epg.c @@ -1101,19 +1101,19 @@ size_t epg_episode_number_format epg_episode_num_t num; epg_episode_get_epnum(episode, &num); if ( num.e_num ) { - if (pre) i += snprintf(&buf[i], len-i, "%s", pre); + if (pre) tvh_strlcatf2(buf, len, i, "%s", pre); if ( sfmt && num.s_num ) { - i += snprintf(&buf[i], len-i, sfmt, num.s_num); + tvh_strlcatf2(buf, len, i, sfmt, num.s_num); if ( cfmt && num.s_cnt ) - i += snprintf(&buf[i], len-i, cfmt, num.s_cnt); - if (sep) i += snprintf(&buf[i], len-i, "%s", sep); + tvh_strlcatf2(buf, len, i, cfmt, num.s_cnt); + if (sep) tvh_strlcatf2(buf, len, i, "%s", sep); } - i += snprintf(&buf[i], len-i, efmt, num.e_num); + tvh_strlcatf2(buf, len, i, efmt, num.e_num); if ( cfmt && num.e_cnt ) - i+= snprintf(&buf[i], len-i, cfmt, num.e_cnt); + tvh_strlcatf2(buf, len, i, cfmt, num.e_cnt); } else if ( num.text ) { - if (pre) i += snprintf(&buf[i], len-i, "%s", pre); - i += snprintf(&buf[i], len-i, "%s", num.text); + if (pre) tvh_strlcatf2(buf, len, i, "%s", pre); + tvh_strlcatf2(buf, len, i, "%s", num.text); } return i; } @@ -2118,12 +2118,11 @@ size_t epg_genre_get_str ( const epg_genre_t *genre, int major_only, if (!_epg_genre_names[maj][0]) return 0; min = major_only ? 0 : (genre->code & 0xf); if (!min || major_prefix ) { - ret = snprintf(buf, len, "%s", _epg_genre_names[maj][0]); - if (min) ret += snprintf(buf+ret, len-ret, " : "); - } - if (min && _epg_genre_names[maj][min]) { - ret += snprintf(buf+ret, len-ret, "%s", _epg_genre_names[maj][min]); + tvh_strlcatf2(buf, len, ret, "%s", _epg_genre_names[maj][0]); + if (min) tvh_strlcatf2(buf, len, ret, " : "); } + if (min && _epg_genre_names[maj][min]) + tvh_strlcatf2(buf, len, ret, "%s", _epg_genre_names[maj][min]); return ret; } diff --git a/src/htsp_server.c b/src/htsp_server.c index 5dc97cfb..223bc182 100644 --- a/src/htsp_server.c +++ b/src/htsp_server.c @@ -572,21 +572,18 @@ htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp) if ((strstr(icon, "imagecache") == icon) && htsp->htsp_version < 8) { struct sockaddr_storage addr; socklen_t addrlen; - size_t p = 0; char url[256]; char buf[50]; addrlen = sizeof(addr); getsockname(htsp->htsp_fd, (struct sockaddr*)&addr, &addrlen); tcp_get_ip_str((struct sockaddr*)&addr, buf, 50); - strcpy(url, "http://"); - p = strlen(url); - p += snprintf(url+p, sizeof(url)-p, "%s%s%s:%d%s", + snprintf(url, sizeof(url), "http://%s%s%s:%d%s/%s", (addr.ss_family == AF_INET6)?"[":"", buf, (addr.ss_family == AF_INET6)?"]":"", tvheadend_webui_port, - tvheadend_webroot ?: ""); - snprintf(url+p, sizeof(url)-p, "/%s", icon); + tvheadend_webroot ?: "", + icon); htsmsg_add_str(out, "channelIcon", url); } else { if (htsp->htsp_version < 15) { diff --git a/src/http.c b/src/http.c index 766f5bd1..228b7951 100644 --- a/src/http.c +++ b/src/http.c @@ -534,17 +534,17 @@ dump_request(http_connection_t *hc) first = 1; TAILQ_FOREACH(ra, &hc->hc_req_args, link) { - ptr += snprintf(buf + ptr, sizeof(buf) - ptr, first ? "?%s=%s" : "&%s=%s", ra->key, ra->val); + tvh_strlcatf2(buf, sizeof(buf), ptr, first ? "?%s=%s" : "&%s=%s", ra->key, ra->val); first = 0; } first = 1; TAILQ_FOREACH(ra, &hc->hc_args, link) { - ptr += snprintf(buf + ptr, sizeof(buf) - ptr, first ? "{{%s=%s" : ",%s=%s", ra->key, ra->val); + tvh_strlcatf2(buf, sizeof(buf), ptr, first ? "{{%s=%s" : ",%s=%s", ra->key, ra->val); first = 0; } if (!first) - ptr += snprintf(buf + ptr, sizeof(buf) - ptr, "}}"); + tvh_strlcatf2(buf, sizeof(buf), ptr, "}}"); tvhtrace("http", "%s%s", hc->hc_url, buf); } diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index b704a2b4..9527ffc0 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -1426,7 +1426,7 @@ linuxdvb_diseqc_send for (i = 0; i < len; i++) { message.msg[3 + i] = (uint8_t)va_arg(ap, int); #if ENABLE_TRACE - c += snprintf(buf + c, sizeof(buf) - c, "%02X ", message.msg[3 + i]); + tvh_strlcatf2(buf, sizeof(buf), c, "%02X ", message.msg[3 + i]); #endif } va_end(ap); diff --git a/src/input/mpegts/mpegts_pid.c b/src/input/mpegts/mpegts_pid.c index cf691b2a..13b0a7d5 100644 --- a/src/input/mpegts/mpegts_pid.c +++ b/src/input/mpegts/mpegts_pid.c @@ -200,7 +200,6 @@ mpegts_pid_dump(mpegts_apids_t *pids, char *buf, int len) if (pids->all) return snprintf(buf, len, "all"); for (i = 0; i < pids->count && l + 1 < len; i++) - l += snprintf(buf + l, len - l, "%s%i", - i > 0 ? "," : "", pids->pids[i]); + tvh_strlcatf2(buf, len, l, "%s%i", i > 0 ? "," : "", pids->pids[i]); return l; } diff --git a/src/satip/rtp.c b/src/satip/rtp.c index bdc3961c..92a911da 100644 --- a/src/satip/rtp.c +++ b/src/satip/rtp.c @@ -516,7 +516,7 @@ satip_status_build(satip_rtp_session_t *rtp, char *buf, int len) return 0; } - return r; + return r >= len ? len - 1 : r; } /* diff --git a/src/satip/rtsp.c b/src/satip/rtsp.c index 636413ba..9298555f 100644 --- a/src/satip/rtsp.c +++ b/src/satip/rtsp.c @@ -1039,11 +1039,9 @@ play: dvb_mux_conf_str(dmc, buf, sizeof(buf)); r = strlen(buf); - if (r + 1 < sizeof(buf)) - r += snprintf(buf + r, sizeof(buf) - r, " pids "); - if (r + 1 < sizeof(buf) && - mpegts_pid_dump(&rs->pids, buf + r, sizeof(buf) - r) == 0) - snprintf(buf + r, sizeof(buf) - r, ""); + tvh_strlcatf2(buf, sizeof(buf), r, " pids "); + if (mpegts_pid_dump(&rs->pids, buf + r, sizeof(buf) - r) == 0) + tvh_strlcatf2(buf, sizeof(buf), r, ""); tvhdebug("satips", "%i/%s/%d: %s from %s:%d %s", rs->frontend, rs->session, rs->stream, diff --git a/src/subscriptions.c b/src/subscriptions.c index 40aaa6be..bac69d16 100644 --- a/src/subscriptions.c +++ b/src/subscriptions.c @@ -180,10 +180,10 @@ subscription_show_info(th_subscription_t *s) char buf[512]; channel_t *ch = s->ths_channel; source_info_t si; - size_t buflen; + size_t l = 0; s->ths_service->s_setsourceinfo(s->ths_service, &si); - buflen = snprintf(buf, sizeof(buf), + tvh_strlcatf2(buf, sizeof(buf), l, "\"%s\" subscribing on \"%s\", weight: %d, adapter: \"%s\", " "network: \"%s\", mux: \"%s\", provider: \"%s\", service: \"%s\"", s->ths_title, ch ? channel_get_name(ch) : "none", s->ths_weight, @@ -195,17 +195,16 @@ subscription_show_info(th_subscription_t *s) service_source_info_free(&si); if (s->ths_prch && s->ths_prch->prch_pro) - buflen += snprintf(buf + buflen, sizeof(buf) - buflen, + tvh_strlcatf2(buf, sizeof(buf), l, ", profile=\"%s\"", s->ths_prch->prch_pro->pro_name ?: ""); - if (s->ths_hostname) { - snprintf(buf + buflen, sizeof(buf) - buflen, + if (s->ths_hostname) + tvh_strlcatf2(buf, sizeof(buf), l, ", hostname=\"%s\", username=\"%s\", client=\"%s\"", s->ths_hostname ?: "", s->ths_username ?: "", s->ths_client ?: ""); - } tvhlog(LOG_INFO, "subscription", "%04X: %s", shortid(s), buf); } @@ -502,7 +501,7 @@ subscription_unsubscribe(th_subscription_t *s, int quiet) { service_t *t = s->ths_service; char buf[512]; - size_t buflen; + size_t l = 0; lock_assert(&global_lock); @@ -520,20 +519,18 @@ subscription_unsubscribe(th_subscription_t *s, int quiet) if (s->ths_channel != NULL) { LIST_REMOVE(s, ths_channel_link); - snprintf(buf, sizeof(buf), "\"%s\" unsubscribing from \"%s\"", + tvh_strlcatf2(buf, sizeof(buf), l, "\"%s\" unsubscribing from \"%s\"", s->ths_title, channel_get_name(s->ths_channel)); } else { - snprintf(buf, sizeof(buf), "\"%s\" unsubscribing", s->ths_title); + tvh_strlcatf2(buf, sizeof(buf), l, "\"%s\" unsubscribing", s->ths_title); } - if (s->ths_hostname) { - buflen = strlen(buf); - snprintf(buf + buflen, sizeof(buf) - buflen, + if (s->ths_hostname) + tvh_strlcatf2(buf, sizeof(buf), l, ", hostname=\"%s\", username=\"%s\", client=\"%s\"", s->ths_hostname ?: "", s->ths_username ?: "", s->ths_client ?: ""); - } tvhlog(quiet ? LOG_TRACE : LOG_INFO, "subscription", "%04X: %s", shortid(s), buf); if (t) { diff --git a/src/tvheadend.h b/src/tvheadend.h index 1fb91e67..934aea98 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -575,12 +575,19 @@ extern void scopedunlock(pthread_mutex_t **mtxp); #define scopedgloballock() scopedlock(&global_lock) -#define tvh_strdupa(n) ({ int tvh_l = strlen(n); \ - char *tvh_b = alloca(tvh_l + 1); \ - memcpy(tvh_b, n, tvh_l + 1); }) +#define tvh_strdupa(n) \ + ({ int tvh_l = strlen(n); \ + char *tvh_b = alloca(tvh_l + 1); \ + memcpy(tvh_b, n, tvh_l + 1); }) #define tvh_strlcatf(buf, size, fmt...) \ - snprintf((buf) + strlen(buf), (size) - strlen(buf), fmt) + ({ size_t __l = strlen(buf); \ + int __r = snprintf((buf) + __l, (size) - __l, fmt); \ + __r >= (size) - __l ? (size) - 1 : __l + __r }} + +#define tvh_strlcatf2(buf, size, ptr, fmt...) \ + do { int __r = snprintf((buf) + ptr, (size) - ptr, fmt); \ + ptr = __r >= (size) - ptr ? (size) - 1 : ptr + __r; } while (0) static inline const char *tvh_strbegins(const char *s1, const char *s2) { diff --git a/src/tvhlog.c b/src/tvhlog.c index ff4ebe07..7509da8d 100644 --- a/src/tvhlog.c +++ b/src/tvhlog.c @@ -74,7 +74,7 @@ tvhlog_get_subsys ( htsmsg_t *ss, char *subsys, size_t len ) if (ss) { HTSMSG_FOREACH(f, ss) { if (f->hmf_type != HMF_S64) continue; - c += snprintf(subsys+c, len-c, "%s%c%s", + tvh_strlcatf2(subsys, len, c, "%s%c%s", first ? "" : ",", f->hmf_s64 ? '+' : '-', f->hmf_name); @@ -168,7 +168,7 @@ tvhlog_process l = strftime(t, sizeof(t), "%F %T", &tm);// %d %H:%M:%S", &tm); if (options & TVHLOG_OPT_MILLIS) { int ms = msg->time.tv_usec / 1000; - snprintf(t+l, sizeof(t)-l, ".%03d", ms); + tvh_strlcatf2(t, sizeof(t), l, ".%03d", ms); } /* Comet (debug must still be enabled??) */ @@ -311,15 +311,15 @@ void tvhlogv ( const char *file, int line, /* Basic message */ l = 0; if (options & TVHLOG_OPT_THREAD) { - l += snprintf(buf + l, sizeof(buf) - l, "tid %ld: ", (long)pthread_self()); + tvh_strlcatf2(buf, sizeof(buf), l, "tid %ld: ", (long)pthread_self()); } - l += snprintf(buf + l, sizeof(buf) - l, "%s: ", subsys); + tvh_strlcatf2(buf, sizeof(buf), l, "%s: ", subsys); if (options & TVHLOG_OPT_FILELINE && severity >= LOG_DEBUG) - l += snprintf(buf + l, sizeof(buf) - l, "(%s:%d) ", file, line); + tvh_strlcatf2(buf, sizeof(buf), l, "(%s:%d) ", file, line); if (args) - l += vsnprintf(buf + l, sizeof(buf) - l, fmt, *args); + vsnprintf(buf + l, sizeof(buf) - l, fmt, *args); else - l += snprintf(buf + l, sizeof(buf) - l, "%s", fmt); + snprintf(buf + l, sizeof(buf) - l, "%s", fmt); /* Store */ tvhlog_msg_t *msg = calloc(1, sizeof(tvhlog_msg_t)); @@ -381,9 +381,9 @@ _tvhlog_hexdump(const char *file, int line, c = 0; for (i = 0; i < HEXDUMP_WIDTH; i++) { if (i >= len) - c += snprintf(str+c, sizeof(str)-c, " "); + tvh_strlcatf2(str, sizeof(str), c, " "); else - c += snprintf(str+c, sizeof(str)-c, "%02X ", data[i]); + tvh_strlcatf2(str, sizeof(str), c, "%02X ", data[i]); } for (i = 0; i < HEXDUMP_WIDTH; i++) { if (i < len) {