Skip to content

memory overrun in ToUTF8CString #659

@michaelobrien-brightmachines

Description

Description

I am reading a STEP file and an XCAF document. I then use the XCAFPrs_DocumentExplorer and convert the node names from OCCT structures to std::string:

for(
XCAFPrs_DocumentExplorer i(anXdeDoc, XCAFPrs_DocumentExplorerFlags_None);
i.More();
i.Next()) {

const XCAFPrs_DocumentNode& aNode = i.Current();

Handle(TDataStd_Name) aNodeName;
if(
!aNode.Label.FindAttribute(TDataStd_Name::GetID(), aNodeName) ||
!aNode.RefLabel.FindAttribute(TDataStd_Name::GetID(), aNodeName)) {

INFO("Unable to get the node's name: " << aNode.Id);
}
REQUIRE(aNodeName->Get().Length() > 0);

unsigned int aBufferLength = aNodeName->Get().LengthOfCString();
char* aPtr = new char[aBufferLength];
REQUIRE(aNodeName->Get().ToUTF8CString(aPtr) == aBufferLength);

string aNameAsString(aPtr);
delete[] aPtr;
.....
}

If you run this through valgrind, it flags the ::ToUTF8CString for writing a character past the end of aPtr here:

921 Standard_Integer TCollection_ExtendedString::ToUTF8CString(Standard_PCharacter& theCString) const
922 {
923 NCollection_Utf16Iter anIterRead(mystring);
924 Standard_Utf8Char* anIterWrite = theCString;
925 if (*anIterRead == 0)
926 {
927 *anIterWrite = '\0';
928 return 0;
929 }
930
931 for (; *anIterRead != 0; ++anIterRead)
932 {
933 anIterWrite = anIterRead.GetUtf(anIterWrite);
934 }
935 *anIterWrite = '\0';
936 return Standard_Integer(anIterWrite - theCString);
937 }

The *anIterWrite = '\0' on line 935 is one past the end of the string length that is returned from LengthOfCString(). If I allocate a string with space for the null terminator:

char* aPtr = new char[aBufferLength + 1];

valgrind says the memory is correctly handled.

Expected Behavior

Not sure what the right way to handle this is. I'd argue LengthOfCString() should be at least 1 if in an empty string (line 927) the pointer is written to. My recommendation is not write to the buffer on 927 and then make sure LengthOfCString() accounts for the null on non-empty strings.

Actual Behavior

Current behavior writes one character past the recommended allocation size.

Sample Code or DRAW Tcl Script

 for(
XCAFPrs_DocumentExplorer i(anXdeDoc, XCAFPrs_DocumentExplorerFlags_None);
i.More();
i.Next()) {

const XCAFPrs_DocumentNode& aNode = i.Current();

Handle(TDataStd_Name) aNodeName;
if(
!aNode.Label.FindAttribute(TDataStd_Name::GetID(), aNodeName) ||
!aNode.RefLabel.FindAttribute(TDataStd_Name::GetID(), aNodeName)) {

INFO("Unable to get the node's name: " << aNode.Id);
}
REQUIRE(aNodeName->Get().Length() > 0);

unsigned int aBufferLength = aNodeName->Get().LengthOfCString();
char* aPtr = new char[aBufferLength];
REQUIRE(aNodeName->Get().ToUTF8CString(aPtr) == aBufferLength);

string aNameAsString(aPtr);
delete[] aPtr;
.....
}

Operating System

Linux

Compiler

GCC

Bitness

64-bit

OCCT Version

7.9

Additional Files

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    0. NewThe issue was created, but not updated by maintainer. Waiting for updates labels and categories2. BugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    Closed

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions