From f343df558792c0e8163689e144fe571ff7def290 Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Tue, 9 Jul 2024 16:13:17 +0200 Subject: [PATCH] MT#60480 Limitation of origin id/ver to 64bits (unsigned long long) SDP session origin id and version are limited by it's size to 64 bits (8 bytes), that is because we are using `unsigned long long` type for both id and version. Hence the maximum value it can hold is two sixty-forth power, so equals: 18,446,744,073,709,551,615 In case one intentionally sets it to something like: "o=- 18446744073709551615 18446744073709551615 IN IP4 192.168.0.1" SEMS gets overwhelmed with that conversion inside the code make it just to a string literal 'F'. To overcome it, just use __uint128 (which is of 128bits size) for the session origin id and version. Change-Id: I2ad9659aa81dad79969749053dc3fd0d69e2cbd2 --- apps/sbc/CallLeg.cpp | 2 +- apps/sbc/SBCCallLeg.cpp | 2 +- core/AmB2BSession.cpp | 6 +++--- core/AmB2BSession.h | 4 ++-- core/AmOfferAnswer.cpp | 5 +++-- core/AmSdp.cpp | 8 ++++---- core/AmSdp.h | 6 ++++-- core/AmUtils.cpp | 33 +++++++++++++++++++++++++++++++++ core/AmUtils.h | 19 +++++++++++++++++++ 9 files changed, 70 insertions(+), 15 deletions(-) diff --git a/apps/sbc/CallLeg.cpp b/apps/sbc/CallLeg.cpp index a10fd89b..969d5935 100644 --- a/apps/sbc/CallLeg.cpp +++ b/apps/sbc/CallLeg.cpp @@ -1891,7 +1891,7 @@ void CallLeg::createResumeRequest(AmSdp &sdp) * be good enough for unholding (might be held already with zero conncetions) */ /* keep sessV incremented each time sending SDP offer (hold/resume) */ non_hold_sdp.origin.sessV++; - DBG("Increasing session version in SDP origin line to %llu", non_hold_sdp.origin.sessV); + DBG("Increasing session version in SDP origin line to %s", uint128ToStr(non_hold_sdp.origin.sessV).c_str()); if (!non_hold_sdp.media.empty()) { sdp = non_hold_sdp; diff --git a/apps/sbc/SBCCallLeg.cpp b/apps/sbc/SBCCallLeg.cpp index 25a73b79..6f58ecef 100644 --- a/apps/sbc/SBCCallLeg.cpp +++ b/apps/sbc/SBCCallLeg.cpp @@ -1847,7 +1847,7 @@ void SBCCallLeg::createHoldRequest(AmSdp &sdp) } else { /* increase sessV */ sdp.origin.sessV++; - TRACE("Increasing session version in SDP origin line to %llu", sdp.origin.sessV); + TRACE("Increasing session version in SDP origin line to %s", uint128ToStr(sdp.origin.sessV).c_str()); } AmB2BMedia *ms = getMediaSession(); diff --git a/core/AmB2BSession.cpp b/core/AmB2BSession.cpp index 0f00acca..d51c6ff8 100644 --- a/core/AmB2BSession.cpp +++ b/core/AmB2BSession.cpp @@ -616,7 +616,7 @@ void AmB2BSession::saveLocalSdpOrigin(const AmSdp& sdp) previous_origin_sessId = sdp.origin.sessId; previous_origin_sessV = sdp.origin.sessV; DBG("Remembering initial SDP Origin (Id %s V %s)\n", - ulonglong2str(sdp.origin.sessId).c_str(), ulonglong2str(sdp.origin.sessV).c_str()); + uint128ToStr(sdp.origin.sessId).c_str(), uint128ToStr(sdp.origin.sessV).c_str()); } } @@ -656,10 +656,10 @@ void AmB2BSession::updateLocalSdpOrigin(AmSdp& sdp) { // remember the current SDP for the next time previous_sdp = sdp; DBG("SDP changed; updating Origin (Id %s V %s)\n", - ulonglong2str(sdp.origin.sessId).c_str(), ulonglong2str(sdp.origin.sessV).c_str()); + uint128ToStr(sdp.origin.sessId).c_str(), uint128ToStr(sdp.origin.sessV).c_str()); } else { DBG("SDP unchanged; keeping Origin (Id %s V %s)\n", - ulonglong2str(sdp.origin.sessId).c_str(), ulonglong2str(sdp.origin.sessV).c_str()); + uint128ToStr(sdp.origin.sessId).c_str(), uint128ToStr(sdp.origin.sessV).c_str()); } } } diff --git a/core/AmB2BSession.h b/core/AmB2BSession.h index dca3b776..3afe6659 100644 --- a/core/AmB2BSession.h +++ b/core/AmB2BSession.h @@ -161,8 +161,8 @@ private: // we have to use the same "o=" line with potentially increasing session version in SDP SdpOrigin sdp_origin; AmSdp previous_sdp; - unsigned long long previous_origin_sessId; - unsigned long long previous_origin_sessV; + __uint128_t previous_origin_sessId; + __uint128_t previous_origin_sessV; protected: /** Tell if the session should diff --git a/core/AmOfferAnswer.cpp b/core/AmOfferAnswer.cpp index 27f25a27..b640d6f1 100644 --- a/core/AmOfferAnswer.cpp +++ b/core/AmOfferAnswer.cpp @@ -28,6 +28,7 @@ #include "AmOfferAnswer.h" #include "AmSipDialog.h" +#include "AmUtils.h" #include "AmSipHeaders.h" #include "log.h" @@ -380,8 +381,8 @@ int AmOfferAnswer::onReplyOut(AmSipReply& reply) } else { force_no_sdp_update = (sdp_local.origin.sessV == parser_sdp.origin.sessV); if (force_no_sdp_update) - DBG("Forcing no OA state update (no SDP changes, same session version: was <%llu>, now is <%llu>).\n", - sdp_local.origin.sessV, parser_sdp.origin.sessV); + DBG("Forcing no OA state update (no SDP changes, same session version: was <%s>, now is <%s>).\n", + uint128ToStr(sdp_local.origin.sessV).c_str(), uint128ToStr(parser_sdp.origin.sessV).c_str()); } } diff --git a/core/AmSdp.cpp b/core/AmSdp.cpp index 4668cfd3..67181519 100644 --- a/core/AmSdp.cpp +++ b/core/AmSdp.cpp @@ -315,8 +315,8 @@ int AmSdp::parse(const char* _sdp_msg) void AmSdp::print(string& body) const { string out_buf = "v="+int2str(version)+"\r\n" - "o="+origin.user+" "+ulonglong2str(origin.sessId)+" "+ - ulonglong2str(origin.sessV)+" IN "; + "o="+origin.user+" "+uint128ToStr(origin.sessId)+" "+ + uint128ToStr(origin.sessV)+" IN "; if (!origin.conn.address.empty()) if (origin.conn.address.find(".") != std::string::npos) @@ -1285,7 +1285,7 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s) break; } string id(origin_line, int(next-origin_line)-1); - str2ull(id, origin.sessId); + str2uint128(id, origin.sessId); origin_line = next; origin_st = VERSION_ST; break; @@ -1300,7 +1300,7 @@ static void parse_sdp_origin(AmSdp* sdp_msg, char* s) break; } string version(origin_line, int(next-origin_line)-1); - str2ull(version, origin.sessV); + str2uint128(version, origin.sessV); origin_line = next; origin_st = NETTYPE; break; diff --git a/core/AmSdp.h b/core/AmSdp.h index 52298f48..4b82c373 100644 --- a/core/AmSdp.h +++ b/core/AmSdp.h @@ -28,6 +28,8 @@ #ifndef __SdpParser__ #define __SdpParser__ +#include + #include #include #include @@ -81,8 +83,8 @@ struct SdpConnection struct SdpOrigin { string user; - unsigned long long sessId; - unsigned long long sessV; + __uint128_t sessId; + __uint128_t sessV; SdpConnection conn; SdpOrigin() : user(), conn() {} diff --git a/core/AmUtils.cpp b/core/AmUtils.cpp index b1476bde..74ef0989 100644 --- a/core/AmUtils.cpp +++ b/core/AmUtils.cpp @@ -56,6 +56,18 @@ static char _int2str_lookup[] = { '0', '1', '2', '3', '4', '5', '6' , '7', '8', '9' }; +string uint128ToStr(__uint128_t val) +{ + std::string result; + /* support 0 values */ + if (val == 0) + return "0"; + while (val != 0) { + result.insert(result.begin(), '0' + (val % 10)); + val /= 10; + } + return result; +} string ull2str(unsigned long long val) { @@ -375,6 +387,27 @@ bool str2long(char*& str, long& result, char sep) return false; } +bool str2uint128(const string& str, __uint128_t & result) +{ + char* s = (char*)str.c_str(); + result = str2uint128(s); + return (result ? true : false); +} + +__uint128_t str2uint128(const char* str) { + __uint128_t result = 0; + while (*str) { + if (*str < '0' || *str > '9') { + DBG("Invalid character in string '%s'\n", str); + result = 0; + break; + } + result = result * 10 + (*str - '0'); + str++; + } + return result; +} + // long int could probably be the same size as int bool str2ull(const string& str, unsigned long long& result) { diff --git a/core/AmUtils.h b/core/AmUtils.h index 5e3d55d9..1a8ba3a1 100644 --- a/core/AmUtils.h +++ b/core/AmUtils.h @@ -64,6 +64,11 @@ typedef unsigned char HASHHEX[HASHHEXLEN+1]; */ string ull2str(unsigned long long val); +/** + * Convert an unsigned int128 to a string. + */ +string uint128ToStr(__uint128_t val); + /** * Convert an int to a string. */ @@ -170,6 +175,20 @@ bool str2long(const string& str, long& result); */ bool str2long(char*& str, long& result, char sep = ' '); +/** + * Convert a string to a unsigned int128. + * @param str [in] string to convert. + * @param result [out] result unsinged int128. + * @return true on success. + */ +bool str2uint128(const string& str, __uint128_t & result); +/** + * Convert a char array to a unsigned int128. + * @param str [in] string to convert. + * @return 0 (failed) or converted unsigned int128 value. + */ +__uint128_t str2uint128(const char* str); + /** * Convert a string to a unsigned long long int. * @param str [in] string to convert.