]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
[mod_amr, mod_amrwb] Fix input data corruption
authorDmitry Kunilov <38783480+dkunilov@users.noreply.github.com>
Wed, 24 Jan 2024 13:50:08 +0000 (16:50 +0300)
committerGitHub <noreply@github.com>
Wed, 24 Jan 2024 13:50:08 +0000 (16:50 +0300)
* 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>
src/mod/codecs/mod_amr/mod_amr.c
src/mod/codecs/mod_amrwb/mod_amrwb.c

index e7c45c7aff877d025bf862e52cf8f9877efaac96..0769f62f3aa0cc9995172e08fd0fbe6c7f7cd949 100644 (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");
        }
index 8be5f4d54128aead788935b0b5ee20d9b4f500ed..4ac3f25f37a8e12523912a19998fe61851032b89 100644 (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");
        }