include/tools/json_writer.hxx     |   18 +++++++++++++++++
 tools/source/misc/json_writer.cxx |   39 ++++++++++++++++++++++++++++++++++++--
 2 files changed, 55 insertions(+), 2 deletions(-)

New commits:
commit 496fcccfa655f250086c10de9e3c05f5fcf43f3f
Author:     Szymon Kłos <[email protected]>
AuthorDate: Wed Dec 8 11:53:35 2021 +0100
Commit:     Michael Meeks <[email protected]>
CommitDate: Mon Jan 31 17:01:33 2022 +0100

    jsonwriter: ensure correct number of bytes is available
    
    In some functions author forgot that addCommaBeforeField()
    can add additional two characters.
    
    I didn't change cases where more bytes than needed are requested.
    
    Additional change is that in debug mode there is a marker at the
    end of allocated buffer - we check that after every write to
    detect overflow. No need to request more space for a marker as
    we always allocate "needed size * 2".
    
    Change-Id: I28066797b0ba833e408b0a731abc01b7fd989da3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126535
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129163
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <[email protected]>

diff --git a/include/tools/json_writer.hxx b/include/tools/json_writer.hxx
index 72ed59edadc5..700e82b9a2c6 100644
--- a/include/tools/json_writer.hxx
+++ b/include/tools/json_writer.hxx
@@ -89,6 +89,24 @@ private:
     void writeEscapedOUString(const OUString& rPropVal);
     std::pair<char*, int> extractDataImpl();
     void ensureSpace(int noMoreBytesRequired);
+
+    // overflow validation in debug mode
+    static constexpr unsigned char JSON_WRITER_DEBUG_MARKER = 0xde;
+
+    inline void addValidationMark()
+    {
+#ifndef NDEBUG
+        *(mpBuffer + mSpaceAllocated - 1) = JSON_WRITER_DEBUG_MARKER;
+#endif
+    }
+
+    inline void validate()
+    {
+#ifndef NDEBUG
+        unsigned char c = *(mpBuffer + mSpaceAllocated - 1);
+        assert(c == JSON_WRITER_DEBUG_MARKER);
+#endif
+    }
 };
 
 /**
diff --git a/tools/source/misc/json_writer.cxx 
b/tools/source/misc/json_writer.cxx
index d6e34179f930..7730a9a603d5 100644
--- a/tools/source/misc/json_writer.cxx
+++ b/tools/source/misc/json_writer.cxx
@@ -30,6 +30,8 @@ JsonWriter::JsonWriter()
     ++mPos;
     *mPos = ' ';
     ++mPos;
+
+    addValidationMark();
 }
 
 JsonWriter::~JsonWriter()
@@ -41,7 +43,7 @@ JsonWriter::~JsonWriter()
 ScopedJsonWriterNode JsonWriter::startNode(const char* pNodeName)
 {
     auto len = strlen(pNodeName);
-    ensureSpace(len + 6);
+    ensureSpace(len + 8);
 
     addCommaBeforeField();
 
@@ -53,6 +55,9 @@ ScopedJsonWriterNode JsonWriter::startNode(const char* 
pNodeName)
     mPos += 5;
     mStartNodeCount++;
     mbFirstFieldInNode = true;
+
+    validate();
+
     return ScopedJsonWriterNode(*this);
 }
 
@@ -64,12 +69,14 @@ void JsonWriter::endNode()
     *mPos = '}';
     ++mPos;
     mbFirstFieldInNode = false;
+
+    validate();
 }
 
 ScopedJsonWriterArray JsonWriter::startArray(const char* pNodeName)
 {
     auto len = strlen(pNodeName);
-    ensureSpace(len + 6);
+    ensureSpace(len + 8);
 
     addCommaBeforeField();
 
@@ -81,6 +88,9 @@ ScopedJsonWriterArray JsonWriter::startArray(const char* 
pNodeName)
     mPos += 5;
     mStartNodeCount++;
     mbFirstFieldInNode = true;
+
+    validate();
+
     return ScopedJsonWriterArray(*this);
 }
 
@@ -92,6 +102,8 @@ void JsonWriter::endArray()
     *mPos = ']';
     ++mPos;
     mbFirstFieldInNode = false;
+
+    validate();
 }
 
 ScopedJsonWriterStruct JsonWriter::startStruct()
@@ -106,6 +118,9 @@ ScopedJsonWriterStruct JsonWriter::startStruct()
     ++mPos;
     mStartNodeCount++;
     mbFirstFieldInNode = true;
+
+    validate();
+
     return ScopedJsonWriterStruct(*this);
 }
 
@@ -117,6 +132,8 @@ void JsonWriter::endStruct()
     *mPos = '}';
     ++mPos;
     mbFirstFieldInNode = false;
+
+    validate();
 }
 
 static char getEscapementChar(char ch)
@@ -211,6 +228,8 @@ void JsonWriter::writeEscapedOUString(const OUString& 
rPropVal)
             ++mPos;
         }
     }
+
+    validate();
 }
 
 void JsonWriter::put(const char* pPropName, const OUString& rPropVal)
@@ -234,6 +253,8 @@ void JsonWriter::put(const char* pPropName, const OUString& 
rPropVal)
 
     *mPos = '"';
     ++mPos;
+
+    validate();
 }
 
 void JsonWriter::put(const char* pPropName, std::string_view rPropVal)
@@ -287,6 +308,8 @@ void JsonWriter::put(const char* pPropName, 
std::string_view rPropVal)
 
     *mPos = '"';
     ++mPos;
+
+    validate();
 }
 
 void JsonWriter::put(const char* pPropName, sal_Int64 nPropVal)
@@ -305,6 +328,8 @@ void JsonWriter::put(const char* pPropName, sal_Int64 
nPropVal)
     mPos += 3;
 
     mPos += sprintf(mPos, "%" SAL_PRIdINT64, nPropVal);
+
+    validate();
 }
 
 void JsonWriter::put(const char* pPropName, double fPropVal)
@@ -324,6 +349,8 @@ void JsonWriter::put(const char* pPropName, double fPropVal)
 
     memcpy(mPos, sPropVal.getStr(), sPropVal.getLength());
     mPos += sPropVal.getLength();
+
+    validate();
 }
 
 void JsonWriter::put(const char* pPropName, bool nPropVal)
@@ -347,6 +374,8 @@ void JsonWriter::put(const char* pPropName, bool nPropVal)
         pVal = "false";
     memcpy(mPos, pVal, strlen(pVal));
     mPos += strlen(pVal);
+
+    validate();
 }
 
 void JsonWriter::putSimpleValue(const OUString& rPropVal)
@@ -363,6 +392,8 @@ void JsonWriter::putSimpleValue(const OUString& rPropVal)
 
     *mPos = '"';
     ++mPos;
+
+    validate();
 }
 
 void JsonWriter::putRaw(std::string_view rRawBuf)
@@ -373,6 +404,8 @@ void JsonWriter::putRaw(std::string_view rRawBuf)
 
     memcpy(mPos, rRawBuf.data(), rRawBuf.size());
     mPos += rRawBuf.size();
+
+    validate();
 }
 
 void JsonWriter::addCommaBeforeField()
@@ -398,6 +431,8 @@ void JsonWriter::ensureSpace(int noMoreBytesRequired)
         mpBuffer = static_cast<char*>(realloc(mpBuffer, newSize));
         mPos = mpBuffer + currentUsed;
         mSpaceAllocated = newSize;
+
+        addValidationMark();
     }
 }
 

Reply via email to