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
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:
If you run this through valgrind, it flags the ::ToUTF8CString for writing a character past the end of aPtr here:
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
Operating System
Linux
Compiler
GCC
Bitness
64-bit
OCCT Version
7.9
Additional Files
No response