Version in base suite: 0.95-5 Base version: catdoc_0.95-5 Target version: catdoc_0.95-6~deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/c/catdoc/catdoc_0.95-5.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/c/catdoc/catdoc_0.95-6~deb12u1.dsc changelog | 18 patches/0007-Added-guards-against-a-signed-text-length-when-parsi.patch | 61 ++ patches/0008-Added-a-guard-against-a-product-overflow-when-proces.patch | 46 ++ patches/0009-Added-guards-against-invalid-sector-sizes-when-tryin.patch | 228 ++++++++++ patches/series | 3 5 files changed, 356 insertions(+) diff -Nru catdoc-0.95/debian/changelog catdoc-0.95/debian/changelog --- catdoc-0.95/debian/changelog 2022-01-11 00:08:47.000000000 +0000 +++ catdoc-0.95/debian/changelog 2025-06-26 22:03:19.000000000 +0000 @@ -1,3 +1,21 @@ +catdoc (1:0.95-6~deb12u1) bookworm-security; urgency=high + + * Non-maintainer upload by the Security Team. + * Rebuild for bookworm-security + + -- Salvatore Bonaccorso Fri, 27 Jun 2025 00:03:19 +0200 + +catdoc (1:0.95-6) unstable; urgency=medium + + * Add patches prepared by Cisco Talos team to address multiple security + vulnerabilities: CVE-2024-48877, CVE-2024-52035, and CVE-2024-54028. + Thanks to Ali Rizvi-Santiago from the Talos team who found and fixed the + vulnerabilities, and to Salvatore Bonaccorso from the Debian Security Team + for all his help and infinite patience. + Closes: #1107168 + + -- Martina Ferrari Mon, 16 Jun 2025 16:10:01 +0000 + catdoc (1:0.95-5) unstable; urgency=medium * Update my name and email address. diff -Nru catdoc-0.95/debian/patches/0007-Added-guards-against-a-signed-text-length-when-parsi.patch catdoc-0.95/debian/patches/0007-Added-guards-against-a-signed-text-length-when-parsi.patch --- catdoc-0.95/debian/patches/0007-Added-guards-against-a-signed-text-length-when-parsi.patch 1970-01-01 00:00:00.000000000 +0000 +++ catdoc-0.95/debian/patches/0007-Added-guards-against-a-signed-text-length-when-parsi.patch 2025-06-26 22:03:19.000000000 +0000 @@ -0,0 +1,61 @@ +From: Ali Rizvi-Santiago +Date: Fri, 11 Apr 2025 12:08:01 -0500 +Subject: Added guards against a signed text length when parsing the + "WordDocument" stream. + +--- + src/analyze.c | 6 ++++-- + src/reader.c | 9 ++++++--- + 2 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/src/analyze.c b/src/analyze.c +index 6ed7ea6..2d0c2f9 100644 +--- a/src/analyze.c ++++ b/src/analyze.c +@@ -96,7 +96,7 @@ int analyze_format(FILE *f) { + ********************************************************************/ + int parse_word_header(unsigned char * buffer,FILE *f,int offset,long curpos) { + int flags,charset, ret_code=0; +- long textstart,textlen,i; ++ long textstart,textstop,textlen,i; + char buf[2]; + + if (verbose) { +@@ -161,7 +161,9 @@ int parse_word_header(unsigned char * buffer,FILE *f,int offset,long curpos) { + } + /* skipping to textstart and computing textend */ + textstart=getlong(buffer,24); +- textlen=getlong(buffer,28)-textstart; ++ textstop=getlong(buffer,28); ++ textlen=(textstart < textstop)? textstop - textstart : 0; ++ + textstart+=offset; + if (verbose) { + printf ("Textstart = %ld (hex %lx)\n",textstart+curpos,textstart+curpos); +diff --git a/src/reader.c b/src/reader.c +index d28878b..fd2d4c2 100644 +--- a/src/reader.c ++++ b/src/reader.c +@@ -96,8 +96,11 @@ int process_file(FILE *f,long stop) { + long offset=0; + int hyperlink_mode = 0; + unsigned short c; +- /* Now we are starting to read with get_unicode_char */ +- while (!catdoc_eof(f) && offset= 0 && offset0) { ++ if ((bufptr>0) && (bufptr < sizeof(buffer) / sizeof(buffer[0]) - 1)) { + buffer[++bufptr]=0; + output_paragraph(buffer); + } diff -Nru catdoc-0.95/debian/patches/0008-Added-a-guard-against-a-product-overflow-when-proces.patch catdoc-0.95/debian/patches/0008-Added-a-guard-against-a-product-overflow-when-proces.patch --- catdoc-0.95/debian/patches/0008-Added-a-guard-against-a-product-overflow-when-proces.patch 1970-01-01 00:00:00.000000000 +0000 +++ catdoc-0.95/debian/patches/0008-Added-a-guard-against-a-product-overflow-when-proces.patch 2025-06-26 22:03:19.000000000 +0000 @@ -0,0 +1,46 @@ +From: Ali Rizvi-Santiago +Date: Fri, 11 Apr 2025 12:08:44 -0500 +Subject: Added a guard against a product overflow when processing "SST" + records from the "Workbook" stream. + +--- + src/xlsparse.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/xlsparse.c b/src/xlsparse.c +index 53fc21c..c44ac89 100644 +--- a/src/xlsparse.c ++++ b/src/xlsparse.c +@@ -10,6 +10,8 @@ + #endif + #include + #include ++#include ++#include + #include "xls.h" + #include "catdoc.h" + #include "xltypes.h" +@@ -772,13 +774,21 @@ void parse_sst(unsigned char *sstbuf,int bufsize) { + unsigned char *barrier=(unsigned char *)sstbuf+bufsize; /*pointer to end of buffer*/ + unsigned char **parsedString;/*pointer into parsed array*/ + +- sstsize = getlong(sstbuf+4,0); ++ sstsize = getlong(sstbuf+4,0); // int ++ ++ // Guard the next allocation against a product overflow. ++ if (!(sstsize < INT_MAX / sizeof(unsigned char*))) { ++ errno = EOVERFLOW; ++ perror("SST size error"); ++ exit(1); ++ } ++ + sst=(unsigned char **)malloc(sstsize*sizeof(unsigned char *)); +- + if (sst == NULL) { + perror("SST allocation error"); + exit(1); + } ++ + memset(sst,0,sstsize*sizeof(char *)); + for (i=0,parsedString=sst,curString=sstbuf+8; + i +Date: Fri, 11 Apr 2025 12:09:13 -0500 +Subject: Added guards against invalid sector sizes when trying to read the + header from a document. + +--- + src/ole.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 107 insertions(+), 18 deletions(-) + +diff --git a/src/ole.c b/src/ole.c +index 30a0c50..a7b88c7 100644 +--- a/src/ole.c ++++ b/src/ole.c +@@ -19,11 +19,13 @@ + #include + #include + #include ++#include + + #include "catdoc.h" + + #define min(a,b) ((a) < (b) ? (a) : (b)) + ++int sectorShift, shortSectorShift; + long int sectorSize, shortSectorSize; + /* BBD Info */ + long int bbdNumBlocks; +@@ -105,18 +107,40 @@ FILE* ole_init(FILE *f, void *buffer, size_t bufSize) { + } else if (strncmp((char *)&oleBuf,ole_sign,8) != 0) { + return NULL; + } +- sectorSize = 1< fileLength) { ++ if ((bbdSize < 0) || (bbdSize > fileLength)) { + /* broken file, BBD size greater than entire file*/ + return NULL; + } +@@ -129,15 +153,34 @@ FILE* ole_init(FILE *f, void *buffer, size_t bufSize) { + return NULL; + } + memcpy(tmpBuf,oleBuf+0x4c,MSAT_ORIG_SIZE); +- mblock=getlong(oleBuf,0x44); +- msat_size=getlong(oleBuf,0x48); +- if (msat_size * sectorSize > fileLength) { ++ ++ /* ++ * Read the indirect fat (master sector allocation table). This is to allow ++ * modifying the fat without having to keep the whole thing in memory. This ++ * gets clamped similarly. ++ */ ++ mblock=getlong(oleBuf,0x44); // long int ++ msat_size=getlong(oleBuf,0x48); // long int ++ ++ if (!(msat_size < LONG_MAX / sectorSize)) { ++ free(tmpBuf); ++ return NULL; ++ } ++ ++ if ((msat_size < 0) || (msat_size * sectorSize > fileLength)) { + free(tmpBuf); + return NULL; + } + + /* fprintf(stderr, "msat_size=%ld\n", msat_size); */ + ++ /* ++ * This next loop is reading the entire indirect fat into "tmpBuf". Each ++ * time if there's another sector to be added, "tmpBuf" will be resized in ++ * order to read the sector indices that compose it. The sector size should ++ * be 2⁹ or 2⁹⁺¹, which should guarantee that there's always a uint32_t (4) ++ * sector index at the end of the sector. ++ */ + i=0; + while((mblock >= 0) && (i < msat_size)) { + unsigned char *newbuf; +@@ -163,6 +206,11 @@ FILE* ole_init(FILE *f, void *buffer, size_t bufSize) { + mblock=getlong(tmpBuf, MSAT_ORIG_SIZE+(sectorSize-4)*i); + } + ++ /* ++ * Now the indirect fat, containing the indices for the regular fat, is used ++ * to read the actual file allocation table. ++ */ ++ + /* fprintf(stderr, "bbdNumBlocks=%ld\n", bbdNumBlocks); */ + for(i=0; i< bbdNumBlocks; i++) { + long int bbdSector=getlong(tmpBuf,4*i); +@@ -182,23 +230,44 @@ FILE* ole_init(FILE *f, void *buffer, size_t bufSize) { + } + free(tmpBuf); + +-/* Read SBD into memory */ ++ /* ++ * Read SBD into memory. This is the fat for the minisectors in the file ++ * and is done by slowly growing "sbdMaxLen" which is used to contain the ++ * relevant sector indices. This could probably be simplified... ++ */ + sbdLen=0; + sbdMaxLen=10; + sbdCurrent = sbdStart = getlong(oleBuf,0x3c); + if (sbdStart > 0) { ++ // No need to check this since "sbdMaxLen" is a constant 10. + if((SBD=malloc(sectorSize*sbdMaxLen)) == NULL ) { + ole_finish(); + return NULL; + } + while(1) { +- fseek(newfile, 512+sbdCurrent*sectorSize, SEEK_SET); +- fread(SBD+sbdLen*sectorSize, 1, sectorSize, newfile); ++ ++ // If we're unable to seek to sector "sbdCurrent", then abort. ++ if (fseek(newfile, 512+sbdCurrent*sectorSize, SEEK_SET) < 0) { ++ ole_finish(); ++ return NULL; ++ ++ // If we couldn't read the full sector, then also abort. ++ } else if (fread(SBD+sbdLen*sectorSize, 1, sectorSize, newfile) != sectorSize) { ++ ole_finish(); ++ return NULL; ++ } ++ + sbdLen++; + if (sbdLen >= sbdMaxLen) { + unsigned char *newSBD; + +- sbdMaxLen+=5; ++ sbdMaxLen+=5; // long int ++ ++ if (!(sbdMaxLen < LONG_MAX / sectorSize)) { ++ ole_finish(); ++ return NULL; ++ } ++ + if ((newSBD=realloc(SBD, sectorSize*sbdMaxLen)) != NULL) { + SBD=newSBD; + } else { +@@ -226,13 +295,19 @@ FILE* ole_init(FILE *f, void *buffer, size_t bufSize) { + propMaxLen = 5; + propCurrent = propStart = getlong(oleBuf,0x30); + if (propStart >= 0) { ++ // No need to guard here since "propMaxLen" is a constant 5. + if((properties=malloc(propMaxLen*sectorSize)) == NULL ) { + ole_finish(); + return NULL; + } + while(1) { + /* fprintf(stderr, "propCurrent=%ld\n",propCurrent); */ +- fseek(newfile, 512+propCurrent*sectorSize, SEEK_SET); ++ if (fseek(newfile, 512+propCurrent*sectorSize, SEEK_SET) < 0) { ++ perror("reading properties catalog"); ++ ole_finish(); ++ return NULL; ++ } ++ + errno=0; + if (fread(properties+propLen*sectorSize, + 1, sectorSize, newfile)!=sectorSize) { +@@ -246,7 +321,12 @@ FILE* ole_init(FILE *f, void *buffer, size_t bufSize) { + if (propLen >= propMaxLen) { + unsigned char *newProp; + +- propMaxLen+=5; ++ propMaxLen+=5; // long int ++ if (!(propMaxLen < LONG_MAX / sectorSize)) { ++ ole_finish(); ++ return NULL; ++ } ++ + if ((newProp=realloc(properties, propMaxLen*sectorSize)) != NULL) + properties=newProp; + else { +@@ -388,7 +468,16 @@ FILE *ole_readdir(FILE *f) { + e->blocks[e->numOfBlocks++] = chainCurrent; + if (e->numOfBlocks >= chainMaxLen) { + long int *newChain; +- chainMaxLen+=25; ++ chainMaxLen+=25; // long int ++ ++ if (!(chainMaxLen < LONG_MAX / sizeof(long int))) { ++ errno = EOVERFLOW; ++ perror("Properties chain length error"); ++ free(e->blocks); ++ e->blocks=NULL; ++ return NULL; ++ } ++ + if ((newChain=realloc(e->blocks, + chainMaxLen*sizeof(long int))) != NULL) { + e->blocks=newChain; diff -Nru catdoc-0.95/debian/patches/series catdoc-0.95/debian/patches/series --- catdoc-0.95/debian/patches/series 2022-01-11 00:08:47.000000000 +0000 +++ catdoc-0.95/debian/patches/series 2025-06-26 22:03:19.000000000 +0000 @@ -4,3 +4,6 @@ 04-XLS_parsing_improvements.patch 05-CVE-2017-11110.patch 06-Fix_OLENAMELENGTH.patch +0007-Added-guards-against-a-signed-text-length-when-parsi.patch +0008-Added-a-guard-against-a-product-overflow-when-proces.patch +0009-Added-guards-against-invalid-sector-sizes-when-tryin.patch