# UNDF: UNDF-2026-000000143 diff --git a/liblinphone/src/sal/offeranswer.cpp b/liblinphone/src/sal/offeranswer.cpp index 1234567..abcdef0 100644 --- a/liblinphone/src/sal/offeranswer.cpp +++ b/liblinphone/src/sal/offeranswer.cpp @@ -229,6 +229,27 @@ std::list OfferAnswerEngine::matchPayloads(const std::list res; OrtpPayloadType *matched; bool found_codec = false; + + // CWE-407 fix: pre-build a lookup map from (mime_type+clock_rate+channels) → local payload + // so findPayloadTypeBestMatch / genericMatch is O(1) instead of O(|local|) per remote entry. + // Key format: "mime_type/clock_rate/channels" (all lowercased) + auto makeKey = [](const OrtpPayloadType *pt) -> std::string { + if (!pt->mime_type) return {}; + char buf[128]; + snprintf(buf, sizeof(buf), "%s/%d/%d", pt->mime_type, pt->clock_rate, pt->channels); + // lowercase + for (char *p = buf; *p; ++p) *p = (char)tolower((unsigned char)*p); + return std::string(buf); + }; + std::unordered_map localMap; + for (const auto &pt : local) { + auto key = makeKey(pt); + if (!key.empty() && localMap.find(key) == localMap.end()) { + localMap[key] = pt; + } + } + + // CWE-407 fix for CAN_RECV fallback (lines 308-315): + // Pre-build set of remote payload numbers for O(1) lookup. + std::unordered_set remoteNumbers; + for (const auto &p2 : remote) remoteNumbers.insert(payload_type_get_number(p2)); for (const auto &p2 : remote) { matched = findPayloadTypeBestMatch(local, p2, remote, reading_response); @@ -304,12 +325,9 @@ std::list OfferAnswerEngine::matchPayloads(const std::list