Commit b999d2a594 for freeswitch.com
commit b999d2a594f025ac0dd4d7b137635308ef298272
Author: Dmitry Verenitsin <morbit85@gmail.com>
Date: Sat Aug 8 23:10:24 2026 +0500
Merge commit from fork
In `udptl_rx_packet()`, decoded values from the error-recovery data were
used without checking them against their destination buffers:
- The FEC entry count is read as a single byte and drives both the
decode loop and the stored `fec_entries` later walked by the
reconstruction loop, allowing writes past the `fec[]`/`fec_len[]`
arrays, which hold only `LOCAL_FAX_MAX_FEC_PACKETS` entries. Reject a
larger count. `fec_entries` was also stored before the elements were
decoded, so a mid-loop reject left the slot advertising a count whose
`fec_len[]`/`fec[]` were stale or out of range; since `s->rx[]`
persists across packets, a later reconstruction pass could copy such a
stale length past the fixed `s->rx[].buf`. Commit the count only after
every element is decoded and bound-checked.
- Each redundancy secondary element length was copied into the fixed
`LOCAL_FAX_MAX_DATAGRAM`-sized `s->rx[].buf` without a size check,
unlike the primary packet. Reject an overlength element at decode
time.
diff --git a/src/mod/applications/mod_spandsp/udptl.c b/src/mod/applications/mod_spandsp/udptl.c
index 35b9f29f77..ec5ff32517 100644
--- a/src/mod/applications/mod_spandsp/udptl.c
+++ b/src/mod/applications/mod_spandsp/udptl.c
@@ -230,6 +230,10 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
for (i = 0; i < count; i++) {
if (decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i]) != 0)
return -1;
+ /* Secondary packets are copied into the fixed-size s->rx[].buf, so an overlength
+ entry cannot be tolerated any more than an overlength primary packet. */
+ if (lengths[total_count + i] > LOCAL_FAX_MAX_DATAGRAM)
+ return -1;
}
total_count += count;
}
@@ -286,7 +290,10 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
if (ptr + 1 > len)
return -1;
entries = buf[ptr++];
- s->rx[x].fec_entries = entries;
+ /* fec[]/fec_len[] hold only LOCAL_FAX_MAX_FEC_PACKETS entries; reject a larger
+ count before it bounds the decode and reconstruction loops. */
+ if (entries > LOCAL_FAX_MAX_FEC_PACKETS)
+ return -1;
/* Decode the elements */
for (i = 0; i < entries; i++) {
@@ -305,6 +312,9 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\n");
#endif
}
+ /* Commit the count only after all elements validate; an early return above leaves
+ fec_entries at 0, so reconstruction never reads a partially filled slot. */
+ s->rx[x].fec_entries = entries;
/* We should now be exactly at the end of the packet. If not, this is a fault. */
if (ptr != len)
return -1;