From a1d8597b4fe37db5785eb252b9eb9dead474a31a Mon Sep 17 00:00:00 2001 From: Viktor Andreev Date: Mon, 10 Nov 2025 15:02:27 +0600 Subject: [PATCH] fix bug #76076 --- .../Logic/Biff_structures/PtgExtraArray.cpp | 24 ++++++++++++++----- .../Format/Logic/Biff_structures/SerNum.cpp | 12 +++++++++- .../Format/Logic/Biff_structures/SerStr.cpp | 6 ++++- OOXML/XlsxFormat/Worksheets/Worksheet.cpp | 3 +++ .../Worksheets/WorksheetChildOther.cpp | 5 +++- .../Worksheets/WorksheetChildOther.h | 2 ++ 6 files changed, 43 insertions(+), 9 deletions(-) diff --git a/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/PtgExtraArray.cpp b/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/PtgExtraArray.cpp index 3e6c96cea6..093a0de536 100644 --- a/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/PtgExtraArray.cpp +++ b/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/PtgExtraArray.cpp @@ -81,7 +81,12 @@ void PtgExtraArray::load(CFRecord& record) for(int i = 0; i < (tempcols) * (temprows); ++i) { if (record.getRdPtr() >= record.getDataSize()) - break; + { + unsigned char rec_type = SerAr::SerType::typeSerNil; + SerArPtr ser(SerAr::createSerAr(rec_type)); + array_.push_back(ser); + continue; + } unsigned char rec_type; record >> rec_type; if (record.getGlobalWorkbookInfo()->Version >= 0x0800) @@ -138,24 +143,31 @@ void PtgExtraArray::save(CFRecord& record) const std::wstring PtgExtraArray::toString() const { std::wstring ret_val; - unsigned char col_cnt = cols + 1; + unsigned char col_cnt = cols; if (array_.empty()) return L""; for(std::vector::const_iterator it = array_.begin(), itEnd = --array_.end(); it != itEnd; ++it) { - ret_val += (*it)->toString(); - if(--col_cnt) + auto tempVal = (*it)->toString(); + if(tempVal.empty()) + tempVal = L"#N/A"; + ret_val += tempVal; + if (col_cnt > 1) { ret_val += L','; + --col_cnt; } else { ret_val += L';'; - col_cnt = cols + 1; + col_cnt = cols; } } - ret_val += array_.back()->toString(); + auto tempVal = array_.back()->toString(); + if(tempVal.empty()) + tempVal = L"#N/A"; + ret_val += tempVal; return ret_val; } diff --git a/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/SerNum.cpp b/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/SerNum.cpp index f01548f273..ca0217cdfd 100644 --- a/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/SerNum.cpp +++ b/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/SerNum.cpp @@ -62,6 +62,13 @@ BiffStructurePtr SerNum::clone() void SerNum::load(CFRecord& record) { record >> xnum; + //excel limitations + constexpr double ExcelMin = 2.229e-308; + constexpr double ExcelMax = 9.99999999999999e+307; + if(xnum < ExcelMin) + xnum = ExcelMin; + else if(xnum > ExcelMax) + xnum = ExcelMax; } void SerNum::save(CFRecord& record) @@ -77,7 +84,10 @@ void SerNum::save(CFRecord& record) const std::wstring SerNum::toString() const { - return STR::double2str(xnum); + auto tempNum = STR::double2str(xnum); + if(tempNum == L"-nan") + tempNum = L"#NUM!"; + return tempNum; } diff --git a/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/SerStr.cpp b/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/SerStr.cpp index 491f06161a..7e71356ba4 100644 --- a/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/SerStr.cpp +++ b/MsBinaryFile/XlsFile/Format/Logic/Biff_structures/SerStr.cpp @@ -94,7 +94,11 @@ void SerStr::save(CFRecord& record) const std::wstring SerStr::toString() const { - return L"\"" + boost::algorithm::replace_all_copy(std::wstring(rgch), L"\"", L"\"\"") + L"\""; + std::wstring tempVal = rgch; + tempVal.erase(std::remove(tempVal.begin(), tempVal.end(), L'\0'), tempVal.end()); + if(tempVal.size() > 255) + tempVal.resize(255); + return L"\"" + boost::algorithm::replace_all_copy(tempVal, L"\"", L"\"\"") + L"\""; } diff --git a/OOXML/XlsxFormat/Worksheets/Worksheet.cpp b/OOXML/XlsxFormat/Worksheets/Worksheet.cpp index 2e27f269b1..66def02b8e 100644 --- a/OOXML/XlsxFormat/Worksheets/Worksheet.cpp +++ b/OOXML/XlsxFormat/Worksheets/Worksheet.cpp @@ -814,7 +814,10 @@ namespace OOX if(m_oRowBreaks.IsInit()) m_oRowBreaks->toXML(writer); if(m_oColBreaks.IsInit()) + { + m_oColBreaks->m_fRowBreak = false; m_oColBreaks->toXML(writer); + } if (m_oCellWatches.IsInit()) m_oCellWatches->toXML(writer); if(m_oDrawing.IsInit()) diff --git a/OOXML/XlsxFormat/Worksheets/WorksheetChildOther.cpp b/OOXML/XlsxFormat/Worksheets/WorksheetChildOther.cpp index fdc4e9371c..c3f51e9a32 100644 --- a/OOXML/XlsxFormat/Worksheets/WorksheetChildOther.cpp +++ b/OOXML/XlsxFormat/Worksheets/WorksheetChildOther.cpp @@ -3193,7 +3193,10 @@ namespace OOX } void CRowColBreaks::toXML(NSStringUtils::CStringBuilder& writer) const { - toXML2(writer, L"rowBreaks"); + if(m_fRowBreak) + toXML2(writer, L"rowBreaks"); + else + toXML2(writer, L"colBreaks"); } void CRowColBreaks::toXML2(NSStringUtils::CStringBuilder& writer, const std::wstring& sName) const { diff --git a/OOXML/XlsxFormat/Worksheets/WorksheetChildOther.h b/OOXML/XlsxFormat/Worksheets/WorksheetChildOther.h index c3d7a8c24d..7725da6524 100644 --- a/OOXML/XlsxFormat/Worksheets/WorksheetChildOther.h +++ b/OOXML/XlsxFormat/Worksheets/WorksheetChildOther.h @@ -754,6 +754,8 @@ namespace OOX public: nullable m_oCount; nullable m_oManualBreakCount; + + bool m_fRowBreak = true; }; class CSheetProtection : public WritingElement