Version in base suite: 2.1.3-1.3 Base version: librecad_2.1.3-1.3 Target version: librecad_2.1.3-1.3+deb11u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/libr/librecad/librecad_2.1.3-1.3.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/libr/librecad/librecad_2.1.3-1.3+deb11u1.dsc changelog | 25 + patches/CVE-2021-21898.patch | 371 +++++++++++++++++++ patches/CVE-2021-21899.patch | 821 +++++++++++++++++++++++++++++++++++++++++++ patches/CVE-2021-21900.patch | 172 +++++++++ patches/CVE-2021-45341.patch | 53 ++ patches/CVE-2021-45342.patch | 35 + patches/CVE-2021-45343.patch | 26 + patches/series | 6 8 files changed, 1509 insertions(+) diff -Nru librecad-2.1.3/debian/changelog librecad-2.1.3/debian/changelog --- librecad-2.1.3/debian/changelog 2021-01-28 23:22:36.000000000 +0000 +++ librecad-2.1.3/debian/changelog 2022-01-30 16:32:43.000000000 +0000 @@ -1,3 +1,28 @@ +librecad (2.1.3-1.3+deb11u1) bullseye-security; urgency=high + + * Non-maintainer upload by the Security Team. + * CVE-2021-21898: A code execution vulnerability exists in the + dwgCompressor::decompress18() functionality of LibreCad libdxfrw. A + specially-crafted .dwg file can lead to an out-of-bounds write. + * CVE-2021-21899: A code execution vulnerability exists in the + dwgCompressor::copyCompBytes21 functionality of LibreCad libdxfrw. A + specially-crafted .dwg file can lead to a heap buffer overflow. + * CVE-2021-21900: A code execution vulnerability exists in the + dxfRW::processLType() functionality of LibreCad libdxfrw. A + specially-crafted .dxf file can lead to a use-after-free + vulnerability. + * CVE-2021-45341: Buffer overflow vulnerabilities in CDataMoji of the jwwlib + component of LibreCAD allows an attacker to achieve Remote Code Execution + using a crafted JWW document. + * CVE-2021-45342: Buffer overflow vulnerabilities in CDataList of the jwwlib + component of LibreCAD allows an attacker to achieve Remote Code Execution + using a crafted JWW document. + * CVE-2021-45343: a NULL pointer dereference in the HATCH handling of + libdxfrw allows an attacker to crash the application using a crafted DXF + document. + + -- Aron Xu Mon, 31 Jan 2022 00:32:43 +0800 + librecad (2.1.3-1.3) unstable; urgency=medium * Non-maintainer upload. diff -Nru librecad-2.1.3/debian/patches/CVE-2021-21898.patch librecad-2.1.3/debian/patches/CVE-2021-21898.patch --- librecad-2.1.3/debian/patches/CVE-2021-21898.patch 1970-01-01 00:00:00.000000000 +0000 +++ librecad-2.1.3/debian/patches/CVE-2021-21898.patch 2022-01-30 16:32:04.000000000 +0000 @@ -0,0 +1,371 @@ +From ba3fa95648bef948e008dfbdd31a4d21badd71f0 Mon Sep 17 00:00:00 2001 +From: Armin Stebich +Date: Sun, 31 Oct 2021 21:35:24 +0100 +Subject: [PATCH] fixed out-of-bounds write vulnerability CVE-2021-21898 + +as reported in TALOS-2021-1349 / CVE-2021-21898, +dwgCompressor::decompress18() could be abused with a malformed DWG file +to force out-of-bounds write and possibly lead to malicious code +execution. +--- + src/intern/dwgreader18.cpp | 21 ++++-- + src/intern/dwgreader18.h | 2 +- + src/intern/dwgutil.cpp | 142 +++++++++++++++++++++++-------------- + src/intern/dwgutil.h | 17 +++-- + 4 files changed, 120 insertions(+), 62 deletions(-) + +Index: librecad-2.1.2/libraries/libdxfrw/src/intern/dwgreader18.cpp +=================================================================== +--- librecad-2.1.2.orig/libraries/libdxfrw/src/intern/dwgreader18.cpp ++++ librecad-2.1.2/libraries/libdxfrw/src/intern/dwgreader18.cpp +@@ -67,7 +67,7 @@ duint32 dwgReader18::checksum(duint32 se + } + + //called: Section page map: 0x41630e3b +-void dwgReader18::parseSysPage(duint8 *decompSec, duint32 decompSize){ ++bool dwgReader18::parseSysPage(duint8 *decompSec, duint32 decompSize){ + DRW_DBG("\nparseSysPage:\n "); + duint32 compSize = fileBuf->getRawLong32(); + DRW_DBG("Compressed size= "); DRW_DBG(compSize); DRW_DBG(", "); DRW_DBGH(compSize); +@@ -95,7 +95,10 @@ void dwgReader18::parseSysPage(duint8 *d + #endif + DRW_DBG("decompresing "); DRW_DBG(compSize); DRW_DBG(" bytes in "); DRW_DBG(decompSize); DRW_DBG(" bytes\n"); + dwgCompressor comp; +- comp.decompress18(tmpCompSec.data(), decompSec, compSize, decompSize); ++ if (!comp.decompress18(tmpCompSec.data(), decompSec, compSize, decompSize)) { ++ return false; ++ } ++ + #ifdef DRW_DBG_DUMP + for (unsigned int i=0, j=0; i< decompSize;i++) { + DRW_DBGH( decompSec[i]); +@@ -103,6 +106,8 @@ void dwgReader18::parseSysPage(duint8 *d + } else { DRW_DBG(", "); j++; } + } DRW_DBG("\n"); + #endif ++ ++ return true; + } + + //called ???: Section map: 0x4163003b +@@ -165,7 +170,9 @@ bool dwgReader18::parseDataPage(dwgSecti + pi.uSize = si.maxSize; + DRW_DBG("decompresing "); DRW_DBG(pi.cSize); DRW_DBG(" bytes in "); DRW_DBG(pi.uSize); DRW_DBG(" bytes\n"); + dwgCompressor comp; +- comp.decompress18(cData.data(), oData, pi.cSize, pi.uSize); ++ if (!comp.decompress18(cData.data(), oData, pi.cSize, pi.uSize)) { ++ return false; ++ } + } + return true; + } +@@ -302,7 +309,9 @@ bool dwgReader18::readFileHeader() { + return false; + } + std::vector tmpDecompSec(decompSize); +- parseSysPage(tmpDecompSec.data(), decompSize); ++ if (!parseSysPage(tmpDecompSec.data(), decompSize)) { ++ return false; ++ } + + //parses "Section page map" decompresed data + dwgBuffer buff2(tmpDecompSec.data(), decompSize, &decoder); +@@ -344,7 +353,9 @@ bool dwgReader18::readFileHeader() { + return false; + } + tmpDecompSec.resize(decompSize); +- parseSysPage(tmpDecompSec.data(), decompSize); ++ if (!parseSysPage(tmpDecompSec.data(), decompSize)) { ++ return false; ++ } + + //reads sections: + DRW_DBG("\n*** dwgReader18: reads sections:"); +Index: librecad-2.1.2/libraries/libdxfrw/src/intern/dwgreader18.h +=================================================================== +--- librecad-2.1.2.orig/libraries/libdxfrw/src/intern/dwgreader18.h ++++ librecad-2.1.2/libraries/libdxfrw/src/intern/dwgreader18.h +@@ -81,7 +81,7 @@ protected: + private: + void genMagicNumber(); + // dwgBuffer* bufObj; +- void parseSysPage(duint8 *decompSec, duint32 decompSize); //called: Section page map: 0x41630e3b ++ bool parseSysPage(duint8 *decompSec, duint32 decompSize); //called: Section page map: 0x41630e3b + bool parseDataPage(dwgSectionInfo si/*, duint8 *dData*/); //called ???: Section map: 0x4163003b + duint32 checksum(duint32 seed, duint8* data, duint32 sz); + +Index: librecad-2.1.2/libraries/libdxfrw/src/intern/dwgutil.cpp +=================================================================== +--- librecad-2.1.2.orig/libraries/libdxfrw/src/intern/dwgutil.cpp ++++ librecad-2.1.2/libraries/libdxfrw/src/intern/dwgutil.cpp +@@ -87,18 +87,18 @@ void dwgRSCodec::decode251I(unsigned cha + + duint32 dwgCompressor::twoByteOffset(duint32 *ll){ + duint32 cont = 0; +- duint8 fb = bufC[pos++]; +- cont = (fb >> 2) | (bufC[pos++] << 6); ++ duint8 fb = compressedByte(); ++ cont = (fb >> 2) | (compressedByte() << 6); + *ll = (fb & 0x03); + return cont; + } + + duint32 dwgCompressor::longCompressionOffset(){ + duint32 cont = 0; +- duint8 ll = bufC[pos++]; +- while (ll == 0x00){ ++ duint8 ll = compressedByte(); ++ while (ll == 0x00 && compressedGood) { + cont += 0xFF; +- ll = bufC[pos++]; ++ ll = compressedByte(); + } + cont += ll; + return cont; +@@ -107,60 +107,58 @@ duint32 dwgCompressor::longCompressionOf + duint32 dwgCompressor::long20CompressionOffset(){ + // duint32 cont = 0; + duint32 cont = 0x0F; +- duint8 ll = bufC[pos++]; +- while (ll == 0x00){ ++ duint8 ll = compressedByte(); ++ while (ll == 0x00 && compressedGood){ + // cont += 0xFF; +- ll = bufC[pos++]; ++ ll = compressedByte(); + } + cont += ll; + return cont; + } + + duint32 dwgCompressor::litLength18(){ +- duint32 cont=0; +- duint8 ll = bufC[pos++]; ++ duint32 cont = 0; ++ duint8 ll = compressedByte(); + //no literal length, this byte is next opCode + if (ll > 0x0F) { +- pos--; ++ --compressedPos; + return 0; + } + + if (ll == 0x00) { + cont = 0x0F; +- ll = bufC[pos++]; +- while (ll == 0x00){//repeat until ll != 0x00 +- cont +=0xFF; +- ll = bufC[pos++]; ++ ll = compressedByte(); ++ while (ll == 0x00 && compressedGood) {//repeat until ll != 0x00 ++ cont += 0xFF; ++ ll = compressedByte(); + } + } +- cont +=ll; +- cont +=3; //already sum 3 +- return cont; ++ ++ return cont + ll + 3; + } + +-void dwgCompressor::decompress18(duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize){ +- bufC = cbuf; +- bufD = dbuf; +- sizeC = csize -2; +- sizeD = dsize; ++bool dwgCompressor::decompress18(duint8 *cbuf, duint8 *dbuf, duint64 csize, duint64 dsize){ ++ compressedBuffer = cbuf; ++ decompBuffer = dbuf; ++ compressedSize = csize; ++ decompSize = dsize; ++ compressedPos=0; //current position in compressed buffer ++ decompPos=0; //current position in resulting decompressed buffer ++ + DRW_DBG("dwgCompressor::decompress, last 2 bytes: "); +- DRW_DBGH(bufC[sizeC]);DRW_DBGH(bufC[sizeC+1]);DRW_DBG("\n"); +- sizeC = csize; ++ DRW_DBGH(compressedBuffer[compressedSize - 2]);DRW_DBG(" ");DRW_DBGH(compressedBuffer[compressedSize - 1]);DRW_DBG("\n"); + +- duint32 compBytes; +- duint32 compOffset; +- duint32 litCount; +- +- pos=0; //current position in compresed buffer +- rpos=0; //current position in resulting decompresed buffer +- litCount = litLength18(); +- //copy first lileral lenght +- for (duint32 i=0; i < litCount; ++i) { +- bufD[rpos++] = bufC[pos++]; ++ duint32 compBytes {0}; ++ duint32 compOffset {0}; ++ duint32 litCount {litLength18()}; ++ ++ //copy first literal length ++ for (duint32 i = 0; i < litCount && buffersGood(); ++i) { ++ decompSet( compressedByte()); + } + +- while (pos < csize && (rpos < dsize+1)){//rpos < dsize to prevent crash more robust are needed +- duint8 oc = bufC[pos++]; //next opcode ++ while (buffersGood()) { ++ duint8 oc = compressedByte(); //next opcode + if (oc == 0x10){ + compBytes = longCompressionOffset()+ 9; + compOffset = twoByteOffset(&litCount) + 0x3FFF; +@@ -176,8 +174,6 @@ void dwgCompressor::decompress18(duint8 + compOffset = twoByteOffset(&litCount); + if (litCount == 0) + litCount= litLength18(); +-// else +-// oc = 0x00; + } else if (oc > 0x20 && oc< 0x40){ + compBytes = oc - 0x1E; + compOffset = twoByteOffset(&litCount); +@@ -185,38 +181,85 @@ void dwgCompressor::decompress18(duint8 + litCount= litLength18(); + } else if ( oc > 0x3F){ + compBytes = ((oc & 0xF0) >> 4) - 1; +- duint8 ll2 = bufC[pos++]; ++ duint8 ll2 = compressedByte(); + compOffset = (ll2 << 2) | ((oc & 0x0C) >> 2); + litCount = oc & 0x03; + if (litCount < 1){ + litCount= litLength18();} + } else if (oc == 0x11){ + DRW_DBG("dwgCompressor::decompress, end of input stream, Cpos: "); +- DRW_DBG(pos);DRW_DBG(", Dpos: ");DRW_DBG(rpos);DRW_DBG("\n"); +- return; //end of input stream ++ DRW_DBG(compressedPos);DRW_DBG(", Dpos: ");DRW_DBG(decompPos);DRW_DBG("\n"); ++ return true; //end of input stream + } else { //ll < 0x10 +- DRW_DBG("WARNING dwgCompressor::decompress, failed, illegal char, Cpos: "); +- DRW_DBG(pos);DRW_DBG(", Dpos: ");DRW_DBG(rpos);DRW_DBG("\n"); +- return; //fails, not valid +- } +- //copy "compresed data", TODO Needed verify out of bounds +- duint32 remaining = sizeD - (litCount+rpos); +- if (remaining < compBytes){ +- compBytes = remaining; +- DRW_DBG("WARNING dwgCompressor::decompress, bad compBytes size, Cpos: "); +- DRW_DBG(pos);DRW_DBG(", Dpos: ");DRW_DBG(rpos);DRW_DBG("\n"); +- } +- for (duint32 i=0, j= rpos - compOffset -1; i < compBytes; i++) { +- bufD[rpos++] = bufD[j++]; +- } +- //copy "uncompresed data", TODO Needed verify out of bounds +- for (duint32 i=0; i < litCount; i++) { +- bufD[rpos++] = bufC[pos++]; ++ DRW_DBG("WARNING dwgCompressor::decompress, failed, illegal char: "); DRW_DBGH(oc); ++ DRW_DBG(", Cpos: "); DRW_DBG(compressedPos); ++ DRW_DBG(", Dpos: "); DRW_DBG(decompPos); DRW_DBG("\n"); ++ return false; //fails, not valid ++ } ++ ++ //copy "compressed data", if size allows ++ if (decompSize < decompPos + compBytes) { ++ DRW_DBG("WARNING dwgCompressor::decompress18, bad compBytes size, Cpos: "); ++ DRW_DBG(compressedPos);DRW_DBG(", Dpos: ");DRW_DBG(decompPos);DRW_DBG(", need ");DRW_DBG(compBytes);DRW_DBG(", available ");DRW_DBG(decompSize - decompPos);DRW_DBG("\n"); ++ // only copy what we can fit ++ compBytes = decompSize - decompPos; ++ } ++ duint32 j {decompPos - compOffset - 1}; ++ for (duint32 i = 0; i < compBytes && buffersGood(); i++) { ++ decompSet( decompByte( j++)); ++ } ++ ++ //copy "uncompressed data", if size allows ++ if (decompSize < decompPos + litCount) { ++ DRW_DBG("WARNING dwgCompressor::decompress18, bad litCount size, Cpos: "); ++ DRW_DBG(compressedPos);DRW_DBG(", Dpos: ");DRW_DBG(decompPos);DRW_DBG(", need ");DRW_DBG(litCount);DRW_DBG(", available ");DRW_DBG(decompSize - decompPos);DRW_DBG("\n"); ++ // only copy what we can fit ++ litCount = decompSize - decompPos; ++ } ++ for (duint32 i=0; i < litCount && buffersGood(); i++) { ++ decompSet( compressedByte()); + } + } +- DRW_DBG("WARNING dwgCompressor::decompress, bad out, Cpos: ");DRW_DBG(pos);DRW_DBG(", Dpos: ");DRW_DBG(rpos);DRW_DBG("\n"); ++ ++ DRW_DBG("WARNING dwgCompressor::decompress, bad out, Cpos: ");DRW_DBG(compressedPos);DRW_DBG(", Dpos: ");DRW_DBG(decompPos);DRW_DBG("\n"); ++ return false; + } + ++duint32 dwgCompressor::compressedByte(void) ++{ ++ duint32 result {0}; ++ ++ compressedGood = (compressedPos < compressedSize); ++ if (compressedGood) { ++ result = compressedBuffer[compressedPos]; ++ ++compressedPos; ++ } ++ ++ return result; ++} ++ ++duint32 dwgCompressor::decompByte(const duint32 index) ++{ ++ if (index < decompSize) { ++ return decompBuffer[index]; ++ } ++ ++ return 0; ++} ++ ++void dwgCompressor::decompSet(const duint8 value) ++{ ++ decompGood = (decompPos < decompSize); ++ if (decompGood) { ++ decompBuffer[decompPos] = value; ++ ++decompPos; ++ } ++} ++ ++bool dwgCompressor::buffersGood(void) ++{ ++ return compressedGood && decompGood; ++} + + void dwgCompressor::decrypt18Hdr(duint8 *buf, duint32 size, duint32 offset){ + duint8 max = size / 4; +Index: librecad-2.1.2/libraries/libdxfrw/src/intern/dwgutil.h +=================================================================== +--- librecad-2.1.2.orig/libraries/libdxfrw/src/intern/dwgutil.h ++++ librecad-2.1.2/libraries/libdxfrw/src/intern/dwgutil.h +@@ -27,7 +27,7 @@ void decode251I(duint8 *in, duint8 *out, + class dwgCompressor { + public: + +- void decompress18(duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize); ++ bool decompress18(duint8 *cbuf, duint8 *dbuf, duint64 csize, duint64 dsize); + static void decrypt18Hdr(duint8 *buf, duint32 size, duint32 offset); + // static void decrypt18Data(duint8 *buf, duint32 size, duint32 offset); + static void decompress21(duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize); +@@ -42,13 +42,19 @@ private: + duint32 long20CompressionOffset(); + duint32 twoByteOffset(duint32 *ll); + +- duint8 *bufC; +- duint8 *bufD; +- duint32 sizeC; +- duint32 sizeD; +- duint32 pos; +- duint32 rpos; +- ++ duint32 compressedByte(void); ++ duint32 decompByte(const duint32 index); ++ void decompSet(const duint8 value); ++ bool buffersGood(void); ++ ++ duint8 *compressedBuffer {nullptr}; ++ duint32 compressedSize {0}; ++ duint32 compressedPos {0}; ++ bool compressedGood {true}; ++ duint8 *decompBuffer {nullptr}; ++ duint32 decompSize {0}; ++ duint32 decompPos {0}; ++ bool decompGood {true}; + }; + + namespace secEnum { diff -Nru librecad-2.1.3/debian/patches/CVE-2021-21899.patch librecad-2.1.3/debian/patches/CVE-2021-21899.patch --- librecad-2.1.3/debian/patches/CVE-2021-21899.patch 1970-01-01 00:00:00.000000000 +0000 +++ librecad-2.1.3/debian/patches/CVE-2021-21899.patch 2022-01-30 16:32:04.000000000 +0000 @@ -0,0 +1,821 @@ +From 6417118874333309aa10c4e59f954c3905a6e8b5 Mon Sep 17 00:00:00 2001 +From: Armin Stebich +Date: Wed, 10 Nov 2021 08:41:46 +0100 +Subject: [PATCH] fixed heap buffer overflow vulnerability CVE-2021-21899 + +as reported in TALOS-2021-1350 / CVE-2021-21899, +dwgCompressor::decompress21() could be abused with a malformed DWG file +to force heap buffer overflow and possibly lead to malicious code +execution. +--- + src/intern/dwgreader21.cpp | 27 +- + src/intern/dwgutil.cpp | 533 +++++++++++++------------------------ + src/intern/dwgutil.h | 75 ++++-- + 3 files changed, 253 insertions(+), 382 deletions(-) + +Index: librecad-2.1.2/libraries/libdxfrw/src/intern/dwgreader21.cpp +=================================================================== +--- librecad-2.1.2.orig/libraries/libdxfrw/src/intern/dwgreader21.cpp ++++ librecad-2.1.2/libraries/libdxfrw/src/intern/dwgreader21.cpp +@@ -70,8 +70,8 @@ bool dwgReader21::parseSysPage(duint64 s + fileBuf->getBytes(&tmpDataRaw.front(), fpsize); + std::vector tmpDataRS(fpsize); + dwgRSCodec::decode239I(&tmpDataRaw.front(), &tmpDataRS.front(), fpsize/255); +- dwgCompressor::decompress21(&tmpDataRS.front(), decompData, sizeCompressed, sizeUncompressed); +- return true; ++ ++ return dwgCompressor::decompress21(&tmpDataRS.front(), decompData, sizeCompressed, sizeUncompressed); + } + + bool dwgReader21::parseDataPage(dwgSectionInfo si, duint8 *dData){ +@@ -108,7 +108,9 @@ bool dwgReader21::parseDataPage(dwgSecti + DRW_DBG("\npage uncomp size: "); DRW_DBG(pi.uSize); DRW_DBG(" comp size: "); DRW_DBG(pi.cSize); + DRW_DBG("\noffset: "); DRW_DBG(pi.startOffset); + duint8 *pageData = dData + pi.startOffset; +- dwgCompressor::decompress21(&tmpPageRS.front(), pageData, pi.cSize, pi.uSize); ++ if (!dwgCompressor::decompress21(&tmpPageRS.front(), pageData, pi.cSize, pi.uSize)) { ++ return false; ++ } + + #ifdef DRW_DBG_DUMP + DRW_DBG("\n\nSection OBJECTS decompresed data=\n"); +@@ -164,8 +166,10 @@ bool dwgReader21::readFileHeader() { + std::vector compByteStr(fileHdrCompLength); + fileHdrBuf.getBytes(compByteStr.data(), fileHdrCompLength); + fileHdrData.resize(fileHdrDataLength); +- dwgCompressor::decompress21(compByteStr.data(), &fileHdrData.front(), +- fileHdrCompLength, fileHdrDataLength); ++ if (!dwgCompressor::decompress21(compByteStr.data(), &fileHdrData.front(), ++ fileHdrCompLength, fileHdrDataLength)) { ++ return false; ++ } + } + + #ifdef DRW_DBG_DUMP +@@ -226,11 +230,11 @@ bool dwgReader21::readFileHeader() { + DRW_DBG("\ndwgReader21::parse page map:\n"); + std::vector PagesMapData(PagesMapSizeUncompressed); + +- bool ret = parseSysPage(PagesMapSizeCompressed, PagesMapSizeUncompressed, +- PagesMapCorrectionFactor, 0x480+PagesMapOffset, +- &PagesMapData.front()); +- if (!ret) ++ if (!parseSysPage(PagesMapSizeCompressed, PagesMapSizeUncompressed, ++ PagesMapCorrectionFactor, 0x480+PagesMapOffset, ++ &PagesMapData.front())) { + return false; ++ } + + duint64 address = 0x480; + duint64 i = 0; +@@ -256,10 +260,10 @@ bool dwgReader21::readFileHeader() { + DRW_DBG("\n*** dwgReader21: Processing Section Map ***\n"); + std::vector SectionsMapData(SectionsMapSizeUncompressed); + dwgPageInfo sectionMap = sectionPageMapTmp[SectionsMapId]; +- ret = parseSysPage(SectionsMapSizeCompressed, SectionsMapSizeUncompressed, +- SectionsMapCorrectionFactor, sectionMap.address, &SectionsMapData.front()); +- if (!ret) ++ if (!parseSysPage( SectionsMapSizeCompressed, SectionsMapSizeUncompressed, ++ SectionsMapCorrectionFactor, sectionMap.address, &SectionsMapData.front()) ) { + return false; ++ } + + //reads sections: + //Note: compressed value are not stored in file then, commpresed field are use to store +Index: librecad-2.1.2/libraries/libdxfrw/src/intern/dwgutil.cpp +=================================================================== +--- librecad-2.1.2.orig/libraries/libdxfrw/src/intern/dwgutil.cpp ++++ librecad-2.1.2/libraries/libdxfrw/src/intern/dwgutil.cpp +@@ -85,6 +85,15 @@ void dwgRSCodec::decode251I(unsigned cha + } + } + ++duint8 *dwgCompressor::compressedBuffer {nullptr}; ++duint32 dwgCompressor::compressedSize {0}; ++duint32 dwgCompressor::compressedPos {0}; ++bool dwgCompressor::compressedGood {true}; ++duint8 *dwgCompressor::decompBuffer {nullptr}; ++duint32 dwgCompressor::decompSize {0}; ++duint32 dwgCompressor::decompPos {0}; ++bool dwgCompressor::decompGood {true}; ++ + duint32 dwgCompressor::twoByteOffset(duint32 *ll){ + duint32 cont = 0; + duint8 fb = compressedByte(); +@@ -142,8 +151,8 @@ bool dwgCompressor::decompress18(duint8 + decompBuffer = dbuf; + compressedSize = csize; + decompSize = dsize; +- compressedPos=0; //current position in compressed buffer +- decompPos=0; //current position in resulting decompressed buffer ++ compressedPos = 0; ++ decompPos = 0; + + DRW_DBG("dwgCompressor::decompress, last 2 bytes: "); + DRW_DBGH(compressedBuffer[compressedSize - 2]);DRW_DBG(" ");DRW_DBGH(compressedBuffer[compressedSize - 1]);DRW_DBG("\n"); +@@ -225,9 +234,9 @@ bool dwgCompressor::decompress18(duint8 + return false; + } + +-duint32 dwgCompressor::compressedByte(void) ++duint8 dwgCompressor::compressedByte(void) + { +- duint32 result {0}; ++ duint8 result {0}; + + compressedGood = (compressedPos < compressedSize); + if (compressedGood) { +@@ -238,7 +247,29 @@ duint32 dwgCompressor::compressedByte(vo + return result; + } + +-duint32 dwgCompressor::decompByte(const duint32 index) ++duint8 dwgCompressor::compressedByte(const duint32 index) ++{ ++ if (index < compressedSize) { ++ return compressedBuffer[index]; ++ } ++ ++ return 0; ++} ++ ++duint32 dwgCompressor::compressedHiByte(void) ++{ ++ return static_cast(compressedByte()) << 8; ++} ++ ++bool dwgCompressor::compressedInc(const dint32 inc /*= 1*/) ++{ ++ compressedPos += inc; ++ compressedGood = (compressedPos <= compressedSize); ++ ++ return compressedGood; ++} ++ ++duint8 dwgCompressor::decompByte(const duint32 index) + { + if (index < decompSize) { + return decompBuffer[index]; +@@ -277,418 +308,213 @@ void dwgCompressor::decrypt18Hdr(duint8 + *pHdr++ ^= secMask; + }*/ + +-duint32 dwgCompressor::litLength21(duint8 *cbuf, duint8 oc, duint32 *si){ +- +- duint32 srcIndex=*si; +- +- duint32 length = oc + 8; +- if (length == 0x17) { +- duint32 n = cbuf[srcIndex++]; ++duint32 dwgCompressor::litLength21(duint8 opCode) ++{ ++ duint32 length = 8u + opCode; ++ if (0x17 == length) { ++ duint32 n = compressedByte(); + length += n; +- if (n == 0xff) { ++ if (0xffu == n) { + do { +- n = cbuf[srcIndex++]; +- n |= (duint32)(cbuf[srcIndex++] << 8); ++ n = compressedByte(); ++ n |= compressedHiByte(); + length += n; +- } while (n == 0xffff); ++ } ++ while (0xffffu == n); + } + } + +- *si = srcIndex; + return length; + } + +-void dwgCompressor::decompress21(duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize){ +- duint32 srcIndex=0; +- duint32 dstIndex=0; +- duint32 length=0; +- duint32 sourceOffset; +- duint8 opCode; +- +- opCode = cbuf[srcIndex++]; ++bool dwgCompressor::decompress21(duint8 *cbuf, duint8 *dbuf, duint64 csize, duint64 dsize){ ++ compressedBuffer = cbuf; ++ decompBuffer = dbuf; ++ compressedSize = csize; ++ decompSize = dsize; ++ compressedPos = 0; ++ decompPos = 0; ++ compressedGood = true; ++ decompGood = true; ++ ++ duint32 length {0}; ++ duint32 sourceOffset {0}; ++ duint8 opCode {compressedByte()}; + if ((opCode >> 4) == 2){ +- srcIndex = srcIndex +2; +- length = cbuf[srcIndex++] & 0x07; ++ compressedInc( 2); ++ length = compressedByte() & 0x07; + } + +- while (srcIndex < csize && (dstIndex < dsize+1)){//dstIndex < dsize to prevent crash more robust are needed +- if (length == 0) +- length = litLength21(cbuf, opCode, &srcIndex); +- copyCompBytes21(cbuf, dbuf, length, srcIndex, dstIndex); +- srcIndex += length; +- dstIndex += length; +- if (dstIndex >=dsize) break; //check if last chunk are compresed & terminate ++ while (buffersGood()) { ++ if (length == 0) { ++ length = litLength21(opCode); ++ } ++ copyCompBytes21( length); ++ ++ if (decompPos >= decompSize) { ++ break; //check if last chunk are compressed & terminate ++ } + + length = 0; +- opCode = cbuf[srcIndex++]; +- readInstructions21(cbuf, &srcIndex, &opCode, &sourceOffset, &length); ++ opCode = compressedByte(); ++ readInstructions21( opCode, sourceOffset, length); + while (true) { + //prevent crash with corrupted data +- if (sourceOffset > dstIndex){ ++ if (sourceOffset > decompPos) { + DRW_DBG("\nWARNING dwgCompressor::decompress21 => sourceOffset> dstIndex.\n"); +- DRW_DBG("csize = "); DRW_DBG(csize); DRW_DBG(" srcIndex = "); DRW_DBG(srcIndex); +- DRW_DBG("\ndsize = "); DRW_DBG(dsize); DRW_DBG(" dstIndex = "); DRW_DBG(dstIndex); +- sourceOffset = dstIndex; ++ DRW_DBG("csize = "); DRW_DBG(compressedSize); DRW_DBG(" srcIndex = "); DRW_DBG(compressedPos); ++ DRW_DBG("\ndsize = "); DRW_DBG(decompSize); DRW_DBG(" dstIndex = "); DRW_DBG(decompPos); ++ sourceOffset = decompPos; + } + //prevent crash with corrupted data +- if (length > dsize - dstIndex){ ++ if (length > decompSize - decompPos){ + DRW_DBG("\nWARNING dwgCompressor::decompress21 => length > dsize - dstIndex.\n"); +- DRW_DBG("csize = "); DRW_DBG(csize); DRW_DBG(" srcIndex = "); DRW_DBG(srcIndex); +- DRW_DBG("\ndsize = "); DRW_DBG(dsize); DRW_DBG(" dstIndex = "); DRW_DBG(dstIndex); +- length = dsize - dstIndex; +- srcIndex = csize;//force exit ++ DRW_DBG("csize = "); DRW_DBG(compressedSize); DRW_DBG(" srcIndex = "); DRW_DBG(compressedPos); ++ DRW_DBG("\ndsize = "); DRW_DBG(decompSize); DRW_DBG(" dstIndex = "); DRW_DBG(decompPos); ++ length = decompSize - decompPos; ++ compressedPos = compressedSize; //force exit ++ compressedGood = false; + } +- sourceOffset = dstIndex-sourceOffset; ++ sourceOffset = decompPos - sourceOffset; + for (duint32 i=0; i< length; i++) +- dbuf[dstIndex++] = dbuf[sourceOffset+i]; ++ decompSet( decompByte( sourceOffset + i)); + + length = opCode & 7; +- if ((length != 0) || (srcIndex >= csize)) { ++ if ((length != 0) || (compressedPos >= compressedSize)) { + break; + } +- opCode = cbuf[srcIndex++]; ++ opCode = compressedByte(); + if ((opCode >> 4) == 0) { + break; + } + if ((opCode >> 4) == 15) { + opCode &= 15; + } +- readInstructions21(cbuf, &srcIndex, &opCode, &sourceOffset, &length); ++ readInstructions21( opCode, sourceOffset, length); ++ } ++ ++ if (compressedPos >= compressedSize) { ++ break; + } + } +- DRW_DBG("\ncsize = "); DRW_DBG(csize); DRW_DBG(" srcIndex = "); DRW_DBG(srcIndex); +- DRW_DBG("\ndsize = "); DRW_DBG(dsize); DRW_DBG(" dstIndex = "); DRW_DBG(dstIndex);DRW_DBG("\n"); ++ DRW_DBG("\ncsize = "); DRW_DBG(compressedSize); DRW_DBG(" srcIndex = "); DRW_DBG(compressedPos); ++ DRW_DBG("\ndsize = "); DRW_DBG(decompSize); DRW_DBG(" dstIndex = "); DRW_DBG(decompPos);DRW_DBG("\n"); ++ ++ return buffersGood(); + } + +-void dwgCompressor::readInstructions21(duint8 *cbuf, duint32 *si, duint8 *oc, duint32 *so, duint32 *l){ +- duint32 length; +- duint32 srcIndex = *si; +- duint32 sourceOffset; +- unsigned char opCode = *oc; +- switch ((opCode >> 4)) { ++void dwgCompressor::readInstructions21(duint8 &opCode, duint32 &sourceOffset, duint32 &length){ ++ ++ switch (opCode >> 4) { + case 0: +- length = (opCode & 0xf) + 0x13; +- sourceOffset = cbuf[srcIndex++]; +- opCode = cbuf[srcIndex++]; ++ length = (opCode & 0x0f) + 0x13; ++ sourceOffset = compressedByte(); ++ opCode = compressedByte(); + length = ((opCode >> 3) & 0x10) + length; + sourceOffset = ((opCode & 0x78) << 5) + 1 + sourceOffset; + break; + case 1: + length = (opCode & 0xf) + 3; +- sourceOffset = cbuf[srcIndex++]; +- opCode = cbuf[srcIndex++]; ++ sourceOffset = compressedByte(); ++ opCode = compressedByte(); + sourceOffset = ((opCode & 0xf8) << 5) + 1 + sourceOffset; + break; + case 2: +- sourceOffset = cbuf[srcIndex++]; +- sourceOffset = ((cbuf[srcIndex++] << 8) & 0xff00) | sourceOffset; ++ sourceOffset = compressedByte(); ++ sourceOffset = (compressedHiByte() & 0xff00) | sourceOffset; + length = opCode & 7; + if ((opCode & 8) == 0) { +- opCode = cbuf[srcIndex++]; ++ opCode = compressedByte(); + length = (opCode & 0xf8) + length; + } else { +- sourceOffset++; +- length = (cbuf[srcIndex++] << 3) + length; +- opCode = cbuf[srcIndex++]; ++ ++sourceOffset; ++ length = (static_cast(compressedByte()) << 3) + length; ++ opCode = compressedByte(); + length = (((opCode & 0xf8) << 8) + length) + 0x100; + } + break; + default: + length = opCode >> 4; + sourceOffset = opCode & 15; +- opCode = cbuf[srcIndex++]; ++ opCode = compressedByte(); + sourceOffset = (((opCode & 0xf8) << 1) + sourceOffset) + 1; + break; + } +- *oc = opCode; +- *si = srcIndex; +- *so = sourceOffset; +- *l = length; + } + ++const duint8 dwgCompressor::CopyOrder21_01[] = {0}; ++const duint8 dwgCompressor::CopyOrder21_02[] = {1,0}; ++const duint8 dwgCompressor::CopyOrder21_03[] = {2,1,0}; ++const duint8 dwgCompressor::CopyOrder21_04[] = {0,1,2,3}; ++const duint8 dwgCompressor::CopyOrder21_05[] = {4,0,1,2,3}; ++const duint8 dwgCompressor::CopyOrder21_06[] = {5,1,2,3,4,0}; ++const duint8 dwgCompressor::CopyOrder21_07[] = {6,5,1,2,3,4,0}; ++const duint8 dwgCompressor::CopyOrder21_08[] = {0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_09[] = {8,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_10[] = {9,1,2,3,4,5,6,7,8,0}; ++const duint8 dwgCompressor::CopyOrder21_11[] = {10,9,1,2,3,4,5,6,7,8,0}; ++const duint8 dwgCompressor::CopyOrder21_12[] = {8,9,10,11,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_13[] = {12,8,9,10,11,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_14[] = {13,9,10,11,12,1,2,3,4,5,6,7,8,0}; ++const duint8 dwgCompressor::CopyOrder21_15[] = {14,13,9,10,11,12,1,2,3,4,5,6,7,8,0}; ++const duint8 dwgCompressor::CopyOrder21_16[] = {8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_17[] = {9,10,11,12,13,14,15,16,8,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_18[] = {17,9,10,11,12,13,14,15,16,1,2,3,4,5,6,7,8,0}; ++const duint8 dwgCompressor::CopyOrder21_19[] = {18,17,16,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_20[] = {16,17,18,19,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_21[] = {20,16,17,18,19,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_22[] = {21,20,16,17,18,19,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_23[] = {22,21,20,16,17,18,19,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_24[] = {16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_25[] = {17,18,19,20,21,22,23,24,16,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_26[] = {25,17,18,19,20,21,22,23,24,16,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_27[] = {26,25,17,18,19,20,21,22,23,24,16,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_28[] = {24,25,26,27,16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_29[] = {28,24,25,26,27,16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_30[] = {29,28,24,25,26,27,16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 dwgCompressor::CopyOrder21_31[] = {30,26,27,28,29,18,19,20,21,22,23,24,25,10,11,12,13,14,15,16,17,2,3,4,5,6,7,8,9,1,0}; ++const duint8 dwgCompressor::CopyOrder21_32[] = {24,25,26,27,28,29,30,31,16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; ++const duint8 *dwgCompressor::CopyOrder21[dwgCompressor::Block21OrderArray] = { ++ nullptr, ++ CopyOrder21_01, CopyOrder21_02, CopyOrder21_03, CopyOrder21_04, ++ CopyOrder21_05, CopyOrder21_06, CopyOrder21_07, CopyOrder21_08, ++ CopyOrder21_09, CopyOrder21_10, CopyOrder21_11, CopyOrder21_12, ++ CopyOrder21_13, CopyOrder21_14, CopyOrder21_15, CopyOrder21_16, ++ CopyOrder21_17, CopyOrder21_18, CopyOrder21_19, CopyOrder21_20, ++ CopyOrder21_21, CopyOrder21_22, CopyOrder21_23, CopyOrder21_24, ++ CopyOrder21_25, CopyOrder21_26, CopyOrder21_27, CopyOrder21_28, ++ CopyOrder21_29, CopyOrder21_30, CopyOrder21_31, CopyOrder21_32 ++}; + +-void dwgCompressor::copyCompBytes21(duint8 *cbuf, duint8 *dbuf, duint32 l, duint32 si, duint32 di){ +- duint32 length =l; +- duint32 dix = di; +- duint32 six = si; +- +- while (length > 31){ +- //in doc: 16-31, 0-15 +- for (duint32 i = six+24; i index) && buffersGood(); ++index) { ++ decompSet( compressedByte( compressedPos + order[index])); ++ } ++ compressedInc( length); ++} ++ ++bool dwgCompressor::copyCompBytes21(duint32 length) ++{ ++ DRW_DBG("\ncopyCompBytes21() "); DRW_DBG(length); DRW_DBG("\n"); ++ ++ while (length >= MaxBlock21Length) { ++ copyBlock21( MaxBlock21Length); ++ length -= MaxBlock21Length; ++ } ++ ++ copyBlock21( length); ++ ++ return buffersGood(); + } + + +Index: librecad-2.1.2/libraries/libdxfrw/src/intern/dwgutil.h +=================================================================== +--- librecad-2.1.2.orig/libraries/libdxfrw/src/intern/dwgutil.h ++++ librecad-2.1.2/libraries/libdxfrw/src/intern/dwgutil.h +@@ -25,36 +25,79 @@ void decode251I(duint8 *in, duint8 *out, + }; + + class dwgCompressor { ++ enum R21Consts { ++ MaxBlock21Length = 32, ++ Block21OrderArray, ++ }; ++ + public: + + bool decompress18(duint8 *cbuf, duint8 *dbuf, duint64 csize, duint64 dsize); + static void decrypt18Hdr(duint8 *buf, duint32 size, duint32 offset); + // static void decrypt18Data(duint8 *buf, duint32 size, duint32 offset); +- static void decompress21(duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize); ++ static bool decompress21(duint8 *cbuf, duint8 *dbuf, duint64 csize, duint64 dsize); + + private: + duint32 litLength18(); +- static duint32 litLength21(duint8 *cbuf, duint8 oc, duint32 *si); +- static void copyCompBytes21(duint8 *cbuf, duint8 *dbuf, duint32 l, duint32 si, duint32 di); +- static void readInstructions21(duint8 *cbuf, duint32 *si, duint8 *oc, duint32 *so, duint32 *l); ++ static duint32 litLength21(duint8 opCode); ++ static bool copyCompBytes21(duint32 length); ++ static void readInstructions21(duint8 &opCode, duint32 &sourceOffset, duint32 &length); + + duint32 longCompressionOffset(); + duint32 long20CompressionOffset(); + duint32 twoByteOffset(duint32 *ll); + +- duint32 compressedByte(void); +- duint32 decompByte(const duint32 index); +- void decompSet(const duint8 value); +- bool buffersGood(void); +- +- duint8 *compressedBuffer {nullptr}; +- duint32 compressedSize {0}; +- duint32 compressedPos {0}; +- bool compressedGood {true}; +- duint8 *decompBuffer {nullptr}; +- duint32 decompSize {0}; +- duint32 decompPos {0}; +- bool decompGood {true}; ++ static duint8 compressedByte(void); ++ static duint8 compressedByte(const duint32 index); ++ static duint32 compressedHiByte(void); ++ static bool compressedInc(const dint32 inc = 1); ++ static duint8 decompByte(const duint32 index); ++ static void decompSet(const duint8 value); ++ static bool buffersGood(void); ++ static void copyBlock21(const duint32 length); ++ ++ static duint8 *compressedBuffer; ++ static duint32 compressedSize; ++ static duint32 compressedPos; ++ static bool compressedGood; ++ static duint8 *decompBuffer; ++ static duint32 decompSize; ++ static duint32 decompPos; ++ static bool decompGood; ++ ++ static const duint8 CopyOrder21_01[]; ++ static const duint8 CopyOrder21_02[]; ++ static const duint8 CopyOrder21_03[]; ++ static const duint8 CopyOrder21_04[]; ++ static const duint8 CopyOrder21_05[]; ++ static const duint8 CopyOrder21_06[]; ++ static const duint8 CopyOrder21_07[]; ++ static const duint8 CopyOrder21_08[]; ++ static const duint8 CopyOrder21_09[]; ++ static const duint8 CopyOrder21_10[]; ++ static const duint8 CopyOrder21_11[]; ++ static const duint8 CopyOrder21_12[]; ++ static const duint8 CopyOrder21_13[]; ++ static const duint8 CopyOrder21_14[]; ++ static const duint8 CopyOrder21_15[]; ++ static const duint8 CopyOrder21_16[]; ++ static const duint8 CopyOrder21_17[]; ++ static const duint8 CopyOrder21_18[]; ++ static const duint8 CopyOrder21_19[]; ++ static const duint8 CopyOrder21_20[]; ++ static const duint8 CopyOrder21_21[]; ++ static const duint8 CopyOrder21_22[]; ++ static const duint8 CopyOrder21_23[]; ++ static const duint8 CopyOrder21_24[]; ++ static const duint8 CopyOrder21_25[]; ++ static const duint8 CopyOrder21_26[]; ++ static const duint8 CopyOrder21_27[]; ++ static const duint8 CopyOrder21_28[]; ++ static const duint8 CopyOrder21_29[]; ++ static const duint8 CopyOrder21_30[]; ++ static const duint8 CopyOrder21_31[]; ++ static const duint8 CopyOrder21_32[]; ++ static const duint8 *CopyOrder21[Block21OrderArray]; + }; + + namespace secEnum { diff -Nru librecad-2.1.3/debian/patches/CVE-2021-21900.patch librecad-2.1.3/debian/patches/CVE-2021-21900.patch --- librecad-2.1.3/debian/patches/CVE-2021-21900.patch 1970-01-01 00:00:00.000000000 +0000 +++ librecad-2.1.3/debian/patches/CVE-2021-21900.patch 2022-01-30 16:32:04.000000000 +0000 @@ -0,0 +1,172 @@ +From fcd977cc7f8f6cc7f012e5b72d33cf7d77b3fa69 Mon Sep 17 00:00:00 2001 +From: Armin Stebich +Date: Wed, 10 Nov 2021 16:40:17 +0100 +Subject: [PATCH] fixed heap use after free vulnerability CVE-2021-21900 + +as reported in TALOS-2021-1351 / CVE-2021-21900, +DRW_TableEntry::parseCode had the potential to trigger an use after free exception with a malformed DXF file. +--- + src/drw_objects.cpp | 31 ++++++++++++++----- + src/drw_objects.h | 75 +++++++++++++++++++++++---------------------- + 2 files changed, 63 insertions(+), 43 deletions(-) + +Index: librecad-2.1.2/libraries/libdxfrw/src/drw_objects.cpp +=================================================================== +--- librecad-2.1.2.orig/libraries/libdxfrw/src/drw_objects.cpp ++++ librecad-2.1.2/libraries/libdxfrw/src/drw_objects.cpp +@@ -50,23 +50,40 @@ void DRW_TableEntry::parseCode(int code, + case 1011: + case 1012: + case 1013: +- curr = new DRW_Variant(code, DRW_Coord(reader->getDouble(), 0.0, 0.0)); +- extData.push_back(curr); ++ // don't trust in X, Y, Z order! ++ if (nullptr != curr) { ++ curr->setCoordX( reader->getDouble()); ++ } ++ else { ++ curr = new DRW_Variant( code, DRW_Coord( reader->getDouble(), 0.0, 0.0)); ++ extData.push_back(curr); ++ } + break; + case 1020: + case 1021: + case 1022: + case 1023: +- if (curr) +- curr->setCoordY(reader->getDouble()); ++ // don't trust in X, Y, Z order! ++ if (nullptr != curr) { ++ curr->setCoordY( reader->getDouble()); ++ } ++ else { ++ curr = new DRW_Variant( code, DRW_Coord( 0.0, reader->getDouble(), 0.0)); ++ extData.push_back(curr); ++ } + break; + case 1030: + case 1031: + case 1032: + case 1033: +- if (curr) +- curr->setCoordZ(reader->getDouble()); +- curr=NULL; ++ // don't trust in X, Y, Z order! ++ if (nullptr != curr) { ++ curr->setCoordZ( reader->getDouble()); ++ } ++ else { ++ curr = new DRW_Variant( code, DRW_Coord( 0.0, 0.0, reader->getDouble())); ++ extData.push_back(curr); ++ } + break; + case 1040: + case 1041: +Index: librecad-2.1.2/libraries/libdxfrw/src/drw_objects.h +=================================================================== +--- librecad-2.1.2.orig/libraries/libdxfrw/src/drw_objects.h ++++ librecad-2.1.2/libraries/libdxfrw/src/drw_objects.h +@@ -55,33 +55,34 @@ namespace DRW { + */ + class DRW_TableEntry { + public: +- //initializes default values +- DRW_TableEntry() { +- tType = DRW::UNKNOWNT; +- flags = 0; +- numReactors = xDictFlag = 0; +- parentHandle = 0; +- curr = NULL; +- } ++ ++ DRW_TableEntry() {} + + virtual~DRW_TableEntry() { +- for (std::vector::iterator it=extData.begin(); it!=extData.end(); ++it) ++ for (std::vector::iterator it = extData.begin(); it != extData.end(); ++it) { + delete *it; ++ } + + extData.clear(); + } + +- DRW_TableEntry(const DRW_TableEntry& e) { +- tType = e.tType; +- handle = e.handle; +- parentHandle = e.parentHandle; +- name = e.name; +- flags = e.flags; +- numReactors = e.numReactors; +- xDictFlag = e.xDictFlag; +- curr = e.curr; +- for (std::vector::const_iterator it=e.extData.begin(); it!=e.extData.end(); ++it){ +- extData.push_back(new DRW_Variant(*(*it))); ++ DRW_TableEntry(const DRW_TableEntry& e) : ++ tType {e.tType}, ++ handle {e.handle}, ++ parentHandle {e.parentHandle}, ++ name {e.name}, ++ flags {e.flags}, ++ xDictFlag {e.xDictFlag}, ++ numReactors {e.numReactors}, ++ curr {nullptr} ++ { ++ for (std::vector::const_iterator it = e.extData.begin(); it != e.extData.end(); ++it) { ++ DRW_Variant *src = *it; ++ DRW_Variant *dst = new DRW_Variant( *src); ++ extData.push_back( dst); ++ if (src == e.curr) { ++ curr = dst; ++ } + } + } + +@@ -89,30 +90,32 @@ protected: + void parseCode(int code, dxfReader *reader); + virtual bool parseDwg(DRW::Version version, dwgBuffer *buf, duint32 bs=0) = 0; + bool parseDwg(DRW::Version version, dwgBuffer *buf, dwgBuffer* strBuf, duint32 bs=0); +- void reset(){ +- flags =0; +- for (std::vector::iterator it=extData.begin(); it!=extData.end(); ++it) ++ void reset() { ++ flags = 0; ++ for (std::vector::iterator it = extData.begin(); it != extData.end(); ++it) { + delete *it; ++ } + extData.clear(); ++ curr = nullptr; + } + + public: +- enum DRW::TTYPE tType; /*!< enum: entity type, code 0 */ +- duint32 handle; /*!< entity identifier, code 5 */ +- int parentHandle; /*!< Soft-pointer ID/handle to owner object, code 330 */ +- UTF8STRING name; /*!< entry name, code 2 */ +- int flags; /*!< Flags relevant to entry, code 70 */ +- std::vector extData; /*!< FIFO list of extended data, codes 1000 to 1071*/ +- +-private: +- DRW_Variant* curr; ++ enum DRW::TTYPE tType {DRW::UNKNOWNT}; /*!< enum: entity type, code 0 */ ++ duint32 handle {0}; /*!< entity identifier, code 5 */ ++ int parentHandle {0}; /*!< Soft-pointer ID/handle to owner object, code 330 */ ++ UTF8STRING name; /*!< entry name, code 2 */ ++ int flags {0}; /*!< Flags relevant to entry, code 70 */ ++ std::vector extData; /*!< FIFO list of extended data, codes 1000 to 1071*/ + + //***** dwg parse ********/ + protected: +- dint16 oType; +- duint8 xDictFlag; +- dint32 numReactors; // +- duint32 objSize; //RL 32bits object data size in bits ++ dint16 oType {0}; ++ duint8 xDictFlag {0}; ++ dint32 numReactors {0}; ++ duint32 objSize {0}; //RL 32bits object data size in bits ++ ++private: ++ DRW_Variant* curr {nullptr}; + }; + + diff -Nru librecad-2.1.3/debian/patches/CVE-2021-45341.patch librecad-2.1.3/debian/patches/CVE-2021-45341.patch --- librecad-2.1.3/debian/patches/CVE-2021-45341.patch 1970-01-01 00:00:00.000000000 +0000 +++ librecad-2.1.3/debian/patches/CVE-2021-45341.patch 2022-01-30 16:32:04.000000000 +0000 @@ -0,0 +1,53 @@ +From f3502963eaf379a429bc9da73c1224c5db649997 Mon Sep 17 00:00:00 2001 +From: eldstal +Date: Sat, 18 Dec 2021 20:27:34 +0100 +Subject: [PATCH 03/14] Added bounds checking to CDataMoji in jww parser. + +This fixes issue #1462 +--- + libraries/jwwlib/src/jwwdoc.h | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/libraries/jwwlib/src/jwwdoc.h b/libraries/jwwlib/src/jwwdoc.h +index fc8cd217..a11bc63a 100644 +--- a/libraries/jwwlib/src/jwwdoc.h ++++ b/libraries/jwwlib/src/jwwdoc.h +@@ -521,7 +521,17 @@ cout << "MojiData1:" << m_strFontName << endl; + }else + { + ifstr >> wd; ++ ++ DWORD skip = 0; ++ if (wd > 511) { ++ skip = wd - 511; ++ wd = 511; ++ } ++ + ifstr.read(buf,wd); ++ ++ if (skip != 0) ifstr.ignore(skip); ++ + buf[wd] = '\0'; + m_strFontName = buf; + #ifdef DATA_DUMP +@@ -539,7 +549,17 @@ cout << "MojiData3:" << m_string << endl; + }else + { + ifstr >> wd; ++ ++ DWORD skip = 0; ++ if (wd > 511) { ++ skip = wd - 511; ++ wd = 511; ++ } ++ + ifstr.read(buf,wd); ++ ++ if (skip != 0) ifstr.ignore(skip); ++ + buf[wd] = '\0'; + m_string = buf; + #ifdef DATA_DUMP +-- +2.30.2 + diff -Nru librecad-2.1.3/debian/patches/CVE-2021-45342.patch librecad-2.1.3/debian/patches/CVE-2021-45342.patch --- librecad-2.1.3/debian/patches/CVE-2021-45342.patch 1970-01-01 00:00:00.000000000 +0000 +++ librecad-2.1.3/debian/patches/CVE-2021-45342.patch 2022-01-30 16:32:04.000000000 +0000 @@ -0,0 +1,35 @@ +From 4edcbe72679f95cb60979c77a348c1522a20b0f4 Mon Sep 17 00:00:00 2001 +From: eldstal +Date: Sat, 18 Dec 2021 23:55:22 +0100 +Subject: [PATCH 04/14] Added bounds check to CDataList in JWW parser + +This fixes issue #1464 +--- + libraries/jwwlib/src/jwwdoc.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/libraries/jwwlib/src/jwwdoc.h b/libraries/jwwlib/src/jwwdoc.h +index fc8cd217..7ccf2d83 100644 +--- a/libraries/jwwlib/src/jwwdoc.h ++++ b/libraries/jwwlib/src/jwwdoc.h +@@ -793,7 +793,17 @@ cout << "MojiData1:" << m_strName << endl; + }else + { + ifstr >> wd; ++ ++ DWORD skip = 0; ++ if (wd > 511) { ++ skip = wd - 511; ++ wd = 511; ++ } ++ + ifstr.read(buf,wd); ++ ++ if (skip != 0) ifstr.ignore(skip); ++ + buf[wd] = '\0'; + m_strName = buf; + #ifdef DATA_DUMP +-- +2.30.2 + diff -Nru librecad-2.1.3/debian/patches/CVE-2021-45343.patch librecad-2.1.3/debian/patches/CVE-2021-45343.patch --- librecad-2.1.3/debian/patches/CVE-2021-45343.patch 1970-01-01 00:00:00.000000000 +0000 +++ librecad-2.1.3/debian/patches/CVE-2021-45343.patch 2022-01-30 16:32:04.000000000 +0000 @@ -0,0 +1,26 @@ +From 5771425808bd16e78e1c6f28728c0712c47316f7 Mon Sep 17 00:00:00 2001 +From: eldstal +Date: Sun, 19 Dec 2021 17:57:07 +0100 +Subject: [PATCH 05/14] Added NULL check for hatch code 93 + +This fixes issue #1468 +--- + libraries/libdxfrw/src/drw_entities.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libraries/libdxfrw/src/drw_entities.cpp b/libraries/libdxfrw/src/drw_entities.cpp +index b4f6cd02..9c9d9b77 100644 +--- a/libraries/libdxfrw/src/drw_entities.cpp ++++ b/libraries/libdxfrw/src/drw_entities.cpp +@@ -1805,7 +1805,7 @@ void DRW_Hatch::parseCode(int code, dxfReader *reader){ + break; + case 93: + if (pline) pline->vertexnum = reader->getInt32(); +- else loop->numedges = reader->getInt32();//aqui reserve ++ else if (loop) loop->numedges = reader->getInt32();//aqui reserve + break; + case 98: //seed points ?? + clearEntities(); +-- +2.30.2 + diff -Nru librecad-2.1.3/debian/patches/series librecad-2.1.3/debian/patches/series --- librecad-2.1.3/debian/patches/series 2021-01-28 23:22:36.000000000 +0000 +++ librecad-2.1.3/debian/patches/series 2022-01-30 16:32:29.000000000 +0000 @@ -3,3 +3,9 @@ 0001-fix-build-with-Qt-5.11.patch CVE-2018-19105.patch 0001-Fix-build-with-Qt-5.15-missing-QPainterPath-include.patch +CVE-2021-21898.patch +CVE-2021-21899.patch +CVE-2021-21900.patch +CVE-2021-45341.patch +CVE-2021-45342.patch +CVE-2021-45343.patch