[mod_amr, mod_amrwb] Fix input data corruption

* Fix input data corruption in AMR and AMRWB codecs

* [amr/amrwb] Check encoded frame size before decoding

* [mod_amr, mod_amrwb] Coding guidelines cleanup.

---------

Co-authored-by: Dmitry Kunilov <dmitry.kunilov@upm.solutions>
Co-authored-by: Andrey Volk <andywolk@gmail.com>
This commit is contained in:
Dmitry Kunilov 2024-01-24 16:50:08 +03:00 committed by GitHub
parent d3c60820d7
commit d148a3e412
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 32 additions and 6 deletions

View File

@ -250,6 +250,7 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
int x, i, argc, fmtptmp_pos;
char *argv[10];
char fmtptmp[128];
char *fmtp_dup = NULL;
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
@ -283,13 +284,19 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
switch_set_flag(context, AMR_OPT_OCTET_ALIGN);
}
if (codec->fmtp_in) {
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
fmtp_dup = strdup(codec->fmtp_in);
switch_assert(fmtp_dup);
argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
char *data = argv[x];
char *arg;
while (*data && *data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
if (!strcasecmp(data, "octet-align")) {
@ -325,13 +332,17 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
} else if (!strcasecmp(data, "mode-set")) {
int y, m_argc;
char *m_argv[SWITCH_AMR_MODES-1];
m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0])));
for (y = 0; y < m_argc; y++) {
context->enc_modes |= (1 << atoi(m_argv[y]));
}
}
}
}
free(fmtp_dup);
}
if (context->enc_modes) {
@ -475,13 +486,15 @@ static switch_status_t switch_amr_decode(switch_codec_t *codec,
return SWITCH_STATUS_FALSE;
#else
struct amr_context *context = codec->private_info;
unsigned char *buf = encoded_data;
unsigned char buf[SWITCH_AMR_OUT_MAX_SIZE];
uint8_t tmp[SWITCH_AMR_OUT_MAX_SIZE];
if (!context) {
if (!context || encoded_data_len > SWITCH_AMR_OUT_MAX_SIZE) {
return SWITCH_STATUS_FALSE;
}
memcpy(buf, encoded_data, encoded_data_len);
if (globals.debug) {
switch_amr_info(codec, buf, encoded_data_len, switch_test_flag(context, AMR_OPT_OCTET_ALIGN) ? 1 : 0, "AMR decoder");
}

View File

@ -198,6 +198,7 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
int x, i, argc, fmtptmp_pos;
char *argv[10];
char fmtptmp[128];
char *fmtp_dup = NULL;
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
@ -222,13 +223,19 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
}
if (codec->fmtp_in) {
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
fmtp_dup = strdup(codec->fmtp_in);
switch_assert(fmtp_dup);
argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
for (x = 0; x < argc; x++) {
char *data = argv[x];
char *arg;
while (*data && *data == ' ') {
data++;
}
if ((arg = strchr(data, '='))) {
*arg++ = '\0';
if (!strcasecmp(data, "octet-align")) {
@ -264,7 +271,9 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
} else if (!strcasecmp(data, "mode-set")) {
int y, m_argc;
char *m_argv[SWITCH_AMRWB_MODES-1]; /* AMRWB has 9 modes */
m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0])));
for (y = 0; y < m_argc; y++) {
context->enc_modes |= (1 << atoi(m_argv[y]));
context->enc_mode = atoi(m_argv[y]);
@ -272,6 +281,8 @@ static switch_status_t switch_amrwb_init(switch_codec_t *codec, switch_codec_fla
}
}
}
free(fmtp_dup);
}
if (context->enc_modes && !globals.mode_set_overwrite) {
@ -401,13 +412,15 @@ static switch_status_t switch_amrwb_decode(switch_codec_t *codec,
return SWITCH_STATUS_FALSE;
#else
struct amrwb_context *context = codec->private_info;
unsigned char *buf = encoded_data;
unsigned char buf[SWITCH_AMRWB_OUT_MAX_SIZE];
uint8_t tmp[SWITCH_AMRWB_OUT_MAX_SIZE];
if (!context) {
if (!context || encoded_data_len > SWITCH_AMRWB_OUT_MAX_SIZE) {
return SWITCH_STATUS_FALSE;
}
memcpy(buf, encoded_data, encoded_data_len);
if (globals.debug) {
switch_amrwb_info(codec, buf, encoded_data_len, switch_test_flag(context, AMRWB_OPT_OCTET_ALIGN) ? 1 : 0, "AMRWB decoder");
}