Skip to content

Commit fc9ece3

Browse files
authored
Add strlcat variant that uses memccpy for writing SDPs (#2835)
1 parent f62bba6 commit fc9ece3

File tree

3 files changed

+54
-22
lines changed

3 files changed

+54
-22
lines changed

sdp-utils.c

+18-17
Original file line numberDiff line numberDiff line change
@@ -919,26 +919,26 @@ char *janus_sdp_write(janus_sdp *imported) {
919919
janus_refcount_increase(&imported->ref);
920920
char *sdp = g_malloc(1024), mline[JANUS_BUFSIZE], buffer[512];
921921
*sdp = '\0';
922-
size_t sdplen = 1024, mlen = sizeof(mline);
922+
size_t sdplen = 1024, mlen = sizeof(mline), offset = 0, moffset = 0;
923923
/* v= */
924924
g_snprintf(buffer, sizeof(buffer), "v=%d\r\n", imported->version);
925-
janus_strlcat(sdp, buffer, sdplen);
925+
janus_strlcat_fast(sdp, buffer, sdplen, &offset);
926926
/* o= */
927927
g_snprintf(buffer, sizeof(buffer), "o=%s %"SCNu64" %"SCNu64" IN %s %s\r\n",
928928
imported->o_name, imported->o_sessid, imported->o_version,
929929
imported->o_ipv4 ? "IP4" : "IP6", imported->o_addr);
930-
janus_strlcat(sdp, buffer, sdplen);
930+
janus_strlcat_fast(sdp, buffer, sdplen, &offset);
931931
/* s= */
932932
g_snprintf(buffer, sizeof(buffer), "s=%s\r\n", imported->s_name);
933-
janus_strlcat(sdp, buffer, sdplen);
933+
janus_strlcat_fast(sdp, buffer, sdplen, &offset);
934934
/* t= */
935935
g_snprintf(buffer, sizeof(buffer), "t=%"SCNu64" %"SCNu64"\r\n", imported->t_start, imported->t_stop);
936-
janus_strlcat(sdp, buffer, sdplen);
936+
janus_strlcat_fast(sdp, buffer, sdplen, &offset);
937937
/* c= */
938938
if(imported->c_addr != NULL) {
939939
g_snprintf(buffer, sizeof(buffer), "c=IN %s %s\r\n",
940940
imported->c_ipv4 ? "IP4" : "IP6", imported->c_addr);
941-
janus_strlcat(sdp, buffer, sdplen);
941+
janus_strlcat_fast(sdp, buffer, sdplen, &offset);
942942
}
943943
/* a= */
944944
GList *temp = imported->attributes;
@@ -949,62 +949,63 @@ char *janus_sdp_write(janus_sdp *imported) {
949949
} else {
950950
g_snprintf(buffer, sizeof(buffer), "a=%s\r\n", a->name);
951951
}
952-
janus_strlcat(sdp, buffer, sdplen);
952+
janus_strlcat_fast(sdp, buffer, sdplen, &offset);
953953
temp = temp->next;
954954
}
955955
/* m= */
956956
temp = imported->m_lines;
957957
while(temp) {
958958
mline[0] = '\0';
959+
moffset = 0;
959960
janus_sdp_mline *m = (janus_sdp_mline *)temp->data;
960961
g_snprintf(buffer, sizeof(buffer), "m=%s %d %s", m->type_str, m->port, m->proto);
961-
janus_strlcat(mline, buffer, mlen);
962+
janus_strlcat_fast(mline, buffer, mlen, &moffset);
962963
if(m->port == 0 && m->type != JANUS_SDP_APPLICATION) {
963964
/* Remove all payload types/formats if we're rejecting the media */
964965
g_list_free_full(m->fmts, (GDestroyNotify)g_free);
965966
m->fmts = NULL;
966967
g_list_free(m->ptypes);
967968
m->ptypes = NULL;
968969
m->ptypes = g_list_append(m->ptypes, GINT_TO_POINTER(0));
969-
janus_strlcat(mline, " 0", mlen);
970+
janus_strlcat_fast(mline, " 0", mlen, &moffset);
970971
} else {
971972
if(m->proto != NULL && strstr(m->proto, "RTP") != NULL) {
972973
/* RTP profile, use payload types */
973974
GList *ptypes = m->ptypes;
974975
while(ptypes) {
975976
g_snprintf(buffer, sizeof(buffer), " %d", GPOINTER_TO_INT(ptypes->data));
976-
janus_strlcat(mline, buffer, mlen);
977+
janus_strlcat_fast(mline, buffer, mlen, &moffset);
977978
ptypes = ptypes->next;
978979
}
979980
} else {
980981
/* Something else, use formats */
981982
GList *fmts = m->fmts;
982983
while(fmts) {
983984
g_snprintf(buffer, sizeof(buffer), " %s", (char *)(fmts->data));
984-
janus_strlcat(mline, buffer, mlen);
985+
janus_strlcat_fast(mline, buffer, mlen, &moffset);
985986
fmts = fmts->next;
986987
}
987988
}
988989
}
989-
janus_strlcat(mline, "\r\n", mlen);
990+
janus_strlcat_fast(mline, "\r\n", mlen, &moffset);
990991
/* c= */
991992
if(m->c_addr != NULL) {
992993
g_snprintf(buffer, sizeof(buffer), "c=IN %s %s\r\n",
993994
m->c_ipv4 ? "IP4" : "IP6", m->c_addr);
994-
janus_strlcat(mline, buffer, mlen);
995+
janus_strlcat_fast(mline, buffer, mlen, &moffset);
995996
}
996997
if(m->port > 0) {
997998
/* b= */
998999
if(m->b_name != NULL) {
9991000
g_snprintf(buffer, sizeof(buffer), "b=%s:%"SCNu32"\r\n", m->b_name, m->b_value);
1000-
janus_strlcat(mline, buffer, mlen);
1001+
janus_strlcat_fast(mline, buffer, mlen, &moffset);
10011002
}
10021003
}
10031004
/* a= (note that we don't format the direction if it's JANUS_SDP_DEFAULT) */
10041005
const char *direction = m->direction != JANUS_SDP_DEFAULT ? janus_sdp_mdirection_str(m->direction) : NULL;
10051006
if(direction != NULL) {
10061007
g_snprintf(buffer, sizeof(buffer), "a=%s\r\n", direction);
1007-
janus_strlcat(mline, buffer, mlen);
1008+
janus_strlcat_fast(mline, buffer, mlen, &moffset);
10081009
}
10091010
GList *temp2 = m->attributes;
10101011
while(temp2) {
@@ -1019,7 +1020,7 @@ char *janus_sdp_write(janus_sdp *imported) {
10191020
} else {
10201021
g_snprintf(buffer, sizeof(buffer), "a=%s\r\n", a->name);
10211022
}
1022-
janus_strlcat(mline, buffer, mlen);
1023+
janus_strlcat_fast(mline, buffer, mlen, &moffset);
10231024
temp2 = temp2->next;
10241025
}
10251026
/* Append the generated m-line to the SDP */
@@ -1033,7 +1034,7 @@ char *janus_sdp_write(janus_sdp *imported) {
10331034
sdplen = sdplen*2;
10341035
sdp = g_realloc(sdp, sdplen);
10351036
}
1036-
janus_strlcat(sdp, mline, sdplen);
1037+
janus_strlcat_fast(sdp, mline, sdplen, &offset);
10371038
/* Move on */
10381039
temp = temp->next;
10391040
}

utils.c

+22-1
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,31 @@ char *janus_string_replace(char *message, const char *old_string, const char *ne
275275
size_t janus_strlcat(char *dest, const char *src, size_t dest_size) {
276276
size_t ret = g_strlcat(dest, src, dest_size);
277277
if(ret >= dest_size)
278-
JANUS_LOG(LOG_ERR, "janus_strlcat: truncation occurred, %lu >= %lu\n", ret, dest_size);
278+
JANUS_LOG(LOG_ERR, "Truncation occurred, %lu >= %lu\n", ret, dest_size);
279279
return ret;
280280
}
281281

282+
int janus_strlcat_fast(char *dest, const char *src, size_t dest_size, size_t *offset) {
283+
if(dest == NULL || src == NULL || offset == NULL) {
284+
JANUS_LOG(LOG_ERR, "Invalid arguments\n");
285+
return -1;
286+
}
287+
if(*offset >= dest_size) {
288+
JANUS_LOG(LOG_ERR, "Offset is beyond the buffer size\n");
289+
return -2;
290+
}
291+
char *p = memccpy(dest + *offset, src, 0, dest_size - *offset);
292+
if(p == NULL) {
293+
JANUS_LOG(LOG_ERR, "Truncation occurred, %lu >= %lu\n",
294+
*offset + strlen(src), dest_size);
295+
*offset = dest_size;
296+
*(dest + dest_size -1) = '\0';
297+
return -3;
298+
}
299+
*offset = (p - dest - 1);
300+
return 0;
301+
}
302+
282303
int janus_mkdir(const char *dir, mode_t mode) {
283304
char tmp[256];
284305
char *p = NULL;

utils.h

+14-4
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,22 @@ gint64 janus_get_real_time(void);
5050
char *janus_string_replace(char *message, const char *old_string, const char *new_string) G_GNUC_WARN_UNUSED_RESULT;
5151

5252
/*! \brief Helper method to concatenate strings and log an error if truncation occured
53-
* @param[in] dest destination buffer, already containing one nul-terminated string
54-
* @param[in] src source buffer
55-
* @param[in] dest_size length of dest buffer in bytes (not length of existing string inside dest)
56-
* @returns size of attempted result, if retval >= dest_size, truncation occurred (and an error will be logged). */
53+
* @param[in] dest Destination buffer, already containing one nul-terminated string
54+
* @param[in] src Source buffer
55+
* @param[in] dest_size Length of dest buffer in bytes (not length of existing string inside dest)
56+
* @returns Size of attempted result, if retval >= dest_size, truncation occurred (and an error will be logged). */
5757
size_t janus_strlcat(char *dest, const char *src, size_t dest_size);
5858

59+
/*! \brief Alternative helper method to concatenate strings and log an error if truncation occured,
60+
* which uses memccpy instead of g_strlcat and so is supposed to be faster
61+
* @note The offset attribute is input/output, and updated any time the method is called
62+
* @param[in] dest Destination buffer, already containing one nul-terminated string
63+
* @param[in] src Source buffer
64+
* @param[in] dest_size Length of dest buffer in bytes (not length of existing string inside dest)
65+
* @param[in] offset Offset of where to start appending, in the destination buffer
66+
* @returns 0 in case of success, a negative integer otherwise */
67+
int janus_strlcat_fast(char *dest, const char *src, size_t dest_size, size_t *offset);
68+
5969
/*! \brief Helper to parse yes/no|true/false configuration values
6070
* @param value The configuration value to parse
6171
* @returns true if the value contains a "yes", "YES", "true", TRUE", "1", false otherwise */

0 commit comments

Comments
 (0)