From 6d019a167e0a1bb5bfe4d374b575d6075e941b74 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Sun, 5 Mar 2023 08:02:42 -0500 Subject: [PATCH] heap-based buffer overflow in gf_base64_encode, CVE-2022-26967, Closes: #1007224 --- debian/patches/CVE-2022-26967.patch | 269 ++++++++++++++++++++++++++++ debian/patches/series | 1 + 2 files changed, 270 insertions(+) create mode 100644 debian/patches/CVE-2022-26967.patch diff --git a/debian/patches/CVE-2022-26967.patch b/debian/patches/CVE-2022-26967.patch new file mode 100644 index 0000000..606b238 --- /dev/null +++ b/debian/patches/CVE-2022-26967.patch @@ -0,0 +1,269 @@ +commit ea1eca00fd92fa17f0e25ac25652622924a9a6a0 +Author: jeanlf +Date: Thu Mar 10 15:43:11 2022 +0100 + + fixed #2138 + +diff --git a/include/gpac/base_coding.h b/include/gpac/base_coding.h +index 6dd73ab16..3a749b936 100644 +--- a/include/gpac/base_coding.h ++++ b/include/gpac/base_coding.h +@@ -56,7 +56,7 @@ Encodes a data buffer to Base64 + \param in_buffer_size input data buffer size + \param out_buffer output Base64 buffer location + \param out_buffer_size output Base64 buffer allocated size +-\return size of the encoded Base64 buffer ++\return size of the encoded Base64 buffer, 0 if error + \note the encoded data buffer is not NULL-terminated. + */ + u32 gf_base64_encode(const u8 *in_buffer, u32 in_buffer_size, u8 *out_buffer, u32 out_buffer_size); +@@ -80,7 +80,7 @@ Encodes a data buffer to Base16 + \param in_buffer_size input data buffer size + \param out_buffer output Base16 buffer location + \param out_buffer_size output Base16 buffer allocated size +-\return size of the encoded Base16 buffer ++\return size of the encoded Base16 buffer, 0 if error + \note the encoded data buffer is not NULL-terminated. + */ + u32 gf_base16_encode(u8 *in_buffer, u32 in_buffer_size, u8 *out_buffer, u32 out_buffer_size); +diff --git a/src/filters/dasher.c b/src/filters/dasher.c +index 3ecf25277..961e73cab 100644 +--- a/src/filters/dasher.c ++++ b/src/filters/dasher.c +@@ -2178,8 +2178,8 @@ static GF_List *dasher_get_content_protection_desc(GF_DasherCtx *ctx, GF_DashStr + pnode->type = GF_XML_TEXT_TYPE; + gf_list_add(node->content, pnode); + +- size_64 = 2*pssh_len; +- pnode->name = gf_malloc(size_64); ++ size_64 = 2*pssh_len + 3; ++ pnode->name = gf_malloc(sizeof(char) * size_64); + if (pnode->name) { + size_64 = gf_base64_encode((const char *)pssh_data, pssh_len, (char *)pnode->name, size_64); + pnode->name[size_64] = 0; +diff --git a/src/filters/write_generic.c b/src/filters/write_generic.c +index b77e30838..8191ab8ec 100644 +--- a/src/filters/write_generic.c ++++ b/src/filters/write_generic.c +@@ -778,12 +778,13 @@ static GF_Err ttml_embed_data(GF_XMLNode *node, u8 *aux_data, u32 aux_data_size, + GF_SAFEALLOC(node, GF_XMLNode) + if (!node) return GF_OUT_OF_MEM; + node->type = GF_XML_TEXT_TYPE; +- node->name = gf_malloc(sizeof(u8) * subs_size * 2); ++ u64 size_64 = (subs_size * 2) + 3; ++ node->name = gf_malloc(sizeof(char) * size_64); + if (!node->name) { + gf_free(node); + return GF_OUT_OF_MEM; + } +- subs_size = gf_base64_encode(aux_data + subs_offset, subs_size, (u8*) node->name, subs_size * 2); ++ subs_size = gf_base64_encode(aux_data + subs_offset, subs_size, (u8*) node->name, size_64); + node->name[subs_size] = 0; + return gf_list_add(data->content, node); + } +diff --git a/src/filters/write_nhml.c b/src/filters/write_nhml.c +index 045112578..2389f373f 100644 +--- a/src/filters/write_nhml.c ++++ b/src/filters/write_nhml.c +@@ -781,8 +781,8 @@ static void nhmldump_send_frame(GF_NHMLDumpCtx *ctx, char *data, u32 data_size, + gf_bs_write_data(ctx->bs_w, nhml, (u32) strlen(nhml)); + } else { + u32 d_size; +- if (ctx->b64_buffer_size<2*s_size) { +- ctx->b64_buffer_size = 2 * s_size; ++ if (ctx->b64_buffer_size < 2*s_size + 3) { ++ ctx->b64_buffer_size = 2 * s_size + 3; + ctx->b64_buffer = gf_realloc(ctx->b64_buffer, ctx->b64_buffer_size); + } + d_size = gf_base64_encode(data + offset_in_sample, s_size, ctx->b64_buffer, ctx->b64_buffer_size); +diff --git a/src/isomedia/box_dump.c b/src/isomedia/box_dump.c +index de181b498..8364f6c05 100644 +--- a/src/isomedia/box_dump.c ++++ b/src/isomedia/box_dump.c +@@ -5488,8 +5488,8 @@ GF_Err colr_box_dump(GF_Box *a, FILE * trace) + gf_fprintf(trace, "colour_type=\"%s\">\n", gf_4cc_to_str(ptr->colour_type)); + if (ptr->opaque != NULL) { + gf_fprintf(trace, "opaque_size; +- prof_data_64 = gf_malloc(size_64); ++ size_64 = 2*ptr->opaque_size+3; ++ prof_data_64 = gf_malloc(sizeof(char) * size_64); + size_64 = gf_base64_encode((const char *) ptr->opaque, ptr->opaque_size, (char *)prof_data_64, size_64); + prof_data_64[size_64] = 0; + gf_fprintf(trace, "%s", prof_data_64); +diff --git a/src/jsmods/core.c b/src/jsmods/core.c +index bf70ae8ce..6f0918f5b 100644 +--- a/src/jsmods/core.c ++++ b/src/jsmods/core.c +@@ -1877,14 +1877,15 @@ static JSValue js_sys_basecode_ex(JSContext *ctx, JSValueConst this_val, int arg + size_t data_size; + data = JS_GetArrayBuffer(ctx, &data_size, argv[0] ); + if (!data) return GF_JS_EXCEPTION(ctx); +- out_ptr = gf_malloc(sizeof(u8) * (1 + data_size * 2) ); ++ u32 size64 = (u32) data_size * 2 + 3; ++ out_ptr = gf_malloc(sizeof(char) * size64); + if (!out_ptr) { + e = GF_OUT_OF_MEM; + } else if (is_16) { +- out_size = gf_base16_encode((u8*) data, (u32) data_size, out_ptr, 1 + (u32) data_size * 2); ++ out_size = gf_base16_encode((u8*) data, (u32) data_size, out_ptr, size64); + e = out_size ? GF_OK : GF_NON_COMPLIANT_BITSTREAM; + } else { +- out_size = gf_base64_encode((u8*) data, (u32) data_size, out_ptr, 1 + (u32) data_size * 2); ++ out_size = gf_base64_encode((u8*) data, (u32) data_size, out_ptr, size64); + e = out_size ? GF_OK : GF_NON_COMPLIANT_BITSTREAM; + } + } +diff --git a/src/media_tools/crypt_tools.c b/src/media_tools/crypt_tools.c +index 4737b7ce0..6d2b25ca2 100644 +--- a/src/media_tools/crypt_tools.c ++++ b/src/media_tools/crypt_tools.c +@@ -280,7 +280,7 @@ static void cryptinfo_node_start(void *sax_cbck, const char *node_name, const ch + } + } + else if (!stricmp(att->name, "metadata")) { +- u32 l = 2 * (u32) strlen(att->value); ++ u32 l = 2 * (u32) strlen(att->value) + 3; + tkc->metadata = gf_malloc(sizeof(char) * l); + l = gf_base64_encode(att->value, (u32) strlen(att->value), tkc->metadata, l); + tkc->metadata[l] = 0; +diff --git a/src/media_tools/media_export.c b/src/media_tools/media_export.c +index f433648e0..9952383f1 100644 +--- a/src/media_tools/media_export.c ++++ b/src/media_tools/media_export.c +@@ -834,14 +834,12 @@ GF_Err gf_media_export_webvtt_metadata(GF_MediaExporter *dumper) + samp->data[samp->dataLength] = 0; + gf_fprintf(vtt, "%s\n", samp->data); + } else { +- u32 b64_size; ++ u32 b64_size = samp->dataLength*2 + 3; + char *b64; +- b64 = (char *)gf_malloc(samp->dataLength*3); +- b64_size = gf_base64_encode(samp->data, samp->dataLength, b64, samp->dataLength*3); +- if (b64_size != (u32)-1) { +- b64[b64_size] = 0; +- gf_fprintf(vtt, "%s\n", b64); +- } ++ b64 = (char *)gf_malloc(sizeof(char)*b64_size); ++ b64_size = gf_base64_encode(samp->data, samp->dataLength, b64, b64_size); ++ b64[b64_size] = 0; ++ gf_fprintf(vtt, "%s\n", b64); + gf_free(b64); + } + } +diff --git a/src/scene_manager/loader_svg.c b/src/scene_manager/loader_svg.c +index 314dbb41f..7c1f86f3f 100644 +--- a/src/scene_manager/loader_svg.c ++++ b/src/scene_manager/loader_svg.c +@@ -2,7 +2,7 @@ + * GPAC - Multimedia Framework C SDK + * + * Authors: Jean Le Feuvre, Cyril Concolato +- * Copyright (c) Telecom ParisTech 2000-2012 ++ * Copyright (c) Telecom ParisTech 2000-2022 + * All rights reserved + * + * This file is part of GPAC / Scene Management sub-project +@@ -259,10 +259,10 @@ static void svg_process_media_href(GF_SVG_Parser *parser, GF_Node *elt, XMLRI *i + } else { + char *mtype; + char *buf64; +- u64 size64; ++ u32 size64 = size*2 + 3; + char *ext; +- buf64 = (char *)gf_malloc((size_t)size*2); +- size64 = gf_base64_encode(buffer, (u32)size, buf64, (u32)size*2); ++ buf64 = (char *)gf_malloc(sizeof(char) * size64); ++ size64 = gf_base64_encode(buffer, (u32)size, buf64, size64); + buf64[size64] = 0; + mtype = "application/data"; + ext = strchr(iri->string, '.'); +diff --git a/src/scene_manager/scene_dump.c b/src/scene_manager/scene_dump.c +index 577cb7909..3104d23c3 100644 +--- a/src/scene_manager/scene_dump.c ++++ b/src/scene_manager/scene_dump.c +@@ -2,7 +2,7 @@ + * GPAC - Multimedia Framework C SDK + * + * Authors: Jean Le Feuvre +- * Copyright (c) Telecom ParisTech 2000-2012 ++ * Copyright (c) Telecom ParisTech 2000-2022 + * All rights reserved + * + * This file is part of GPAC / Scene Management sub-project +@@ -650,8 +650,8 @@ static void gf_dump_vrml_sffield(GF_SceneDumper *sdump, u32 type, void *ptr, Boo + str = ((SFString *)ptr)->buffer; + + if (node && (gf_node_get_tag(node)==TAG_MPEG4_BitWrapper)) { +- u32 bufsize = 50+ ((M_BitWrapper*)node)->buffer_len * 2; +- str = gf_malloc(sizeof(char)* bufsize); ++ u32 bufsize = 37 + ((M_BitWrapper*)node)->buffer_len * 2 + 3; ++ str = gf_malloc(sizeof(char) * bufsize); + if (str) { + s32 res; + strcpy(str, "data:application/octet-string;base64,"); +diff --git a/src/scene_manager/scene_engine.c b/src/scene_manager/scene_engine.c +index 14424bb26..f0400e656 100644 +--- a/src/scene_manager/scene_engine.c ++++ b/src/scene_manager/scene_engine.c +@@ -1105,8 +1105,9 @@ char *gf_seng_get_base64_iod(GF_SceneEngine *seng) + + size = 0; + gf_odf_desc_write((GF_Descriptor *) seng->ctx->root_od, &buffer, &size); +- buf64 = gf_malloc(size*2); +- size64 = gf_base64_encode( buffer, size, buf64, size*2); ++ size64 = size*2 + 3; ++ buf64 = gf_malloc(sizeof(char) * size64); ++ size64 = gf_base64_encode( buffer, size, buf64, size64); + buf64[size64] = 0; + gf_free(buffer); + return buf64; +diff --git a/src/utils/base_encoding.c b/src/utils/base_encoding.c +index 822ff98f5..c15808bc7 100644 +--- a/src/utils/base_encoding.c ++++ b/src/utils/base_encoding.c +@@ -42,6 +42,8 @@ u32 gf_base64_encode(const u8 *_in, u32 inSize, u8 *_out, u32 outSize) + + while (i < inSize) { + padding = 3 - (inSize - i); ++ if (j+4>=outSize) ++ return 0; + if (padding == 2) { + out[j] = base_64[in[i]>>2]; + out[j+1] = base_64[(in[i] & 0x03) << 4]; +@@ -147,14 +149,12 @@ u32 gf_base16_encode(u8 *_in, u32 inSize, u8 *_out, u32 outSize) + unsigned char *in = (unsigned char *)_in; + unsigned char *out = (unsigned char *)_out; + +- if (outSize < (inSize * 2)+1) return 0; ++ if (outSize < (inSize * 2)) return 0; + + for (i=0; i> 4)]; + out[2*i+1] = base_16[(in[i] & 0x0f)]; + } +- out[(inSize * 2)] = 0; +- + return inSize * 2; + } + +diff --git a/src/utils/xml_parser.c b/src/utils/xml_parser.c +index bcecc4de8..483c00ce3 100644 +--- a/src/utils/xml_parser.c ++++ b/src/utils/xml_parser.c +@@ -2333,12 +2333,13 @@ GF_Err gf_xml_parse_bit_sequence_bs(GF_XMLNode *bsroot, const char *parent_url, + bs = bs_orig; + if (bs_data) { + u8 *bs_data_out; +- bs_data_out = gf_malloc(sizeof(char)*2*bs_data_size); ++ u32 res = 2*bs_data_size + 3; ++ bs_data_out = gf_malloc(sizeof(char) * res); + if (!bs_data_out) { + e = GF_OUT_OF_MEM; + goto exit; + } +- u32 res = gf_base64_encode(bs_data, bs_data_size, bs_data_out, 2*bs_data_size); ++ res = gf_base64_encode(bs_data, bs_data_size, bs_data_out, res); + bs_data_out[res] = 0; + if (base64_prefix_bits) { + if (base64_prefix_bits % 8) { diff --git a/debian/patches/series b/debian/patches/series index 23d97ef..077a810 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -12,3 +12,4 @@ CVE-2022-2453.patch CVE-2022-2454.patch CVE-2022-38530.patch CVE-2022-36186.patch +CVE-2022-26967.patch -- 2.30.2