From 9255ff687a81f5ef842e7071bb91ad6544a4d923 Mon Sep 17 00:00:00 2001 From: JIJINBEI <87472238+jijinbei@users.noreply.github.com> Date: Wed, 29 Apr 2026 05:42:31 +0900 Subject: [PATCH] CI/Build - Enable -Werror on GCC/Clang (#1209) - Inject `-Werror` (plus select warning toggles) into the shared GitHub Action used for configuring Linux/macOS builds. - Replace several `0` / `CopyFromParent`-style null constants with `nullptr` to satisfy `-Wzero-as-null-pointer-constant`. - Add defensive bounds/clamps and initialization to avoid fixed-buffer overreads/memcpy/sort issues and uninitialized reads. --- .github/actions/configure-occt/action.yml | 3 ++- .../TKTObj/TObj/TObj_Persistence.hxx | 2 +- .../TKDEIGES/IGESData/IGESData_IGESWriter.cxx | 2 +- .../TKDESTEP/StepData/StepData_EnumTool.cxx | 2 +- .../TKDEVRML/VrmlData/VrmlData_Node.hxx | 3 ++- .../TKMath/MathRoot/MathRoot_Trig.hxx | 3 ++- .../TKMath/Poly/Poly_MergeNodesTool.cxx | 4 ++- .../TKernel/FlexLexer/FlexLexer.h | 6 ++--- .../Message/Message_PrinterOStream.cxx | 2 +- .../NCollection/NCollection_LocalArray.hxx | 18 ++++++++----- .../ApproxInt/ApproxInt_MultiLine.gxx | 2 +- .../TKMesh/BRepMesh/delabella.pxx | 4 +-- .../TKOpenGl/OpenGl/OpenGl_Context.hxx | 4 +-- .../TKOpenGl/OpenGl/OpenGl_Window_1.mm | 2 +- src/Visualization/TKService/Xw/Xw_Window.cxx | 25 ++++++++++--------- .../SelectMgr/SelectMgr_BaseIntersector.cxx | 4 ++- 16 files changed, 50 insertions(+), 36 deletions(-) diff --git a/.github/actions/configure-occt/action.yml b/.github/actions/configure-occt/action.yml index aef3f75c3c..d919bb81ae 100644 --- a/.github/actions/configure-occt/action.yml +++ b/.github/actions/configure-occt/action.yml @@ -152,6 +152,7 @@ runs: cmake -G "Unix Makefiles" \ -D CMAKE_C_COMPILER=${{ inputs.compiler == 'clang' && 'clang' || 'gcc' }} \ -D CMAKE_CXX_COMPILER=${{ inputs.compiler == 'clang' && 'clang++' || 'g++' }} \ + -D CMAKE_CXX_FLAGS="-Werror -Wzero-as-null-pointer-constant -Wno-unknown-warning-option -Wno-error=array-bounds -Wno-error=maybe-uninitialized -Wno-error=stringop-overflow -Wno-deprecated-declarations -Wno-error=cast-function-type-mismatch" \ -D BUILD_USE_PCH=${{ inputs.build-use-pch }} \ -D BUILD_OPT_PROFILE=${{ inputs.build-opt-profile }} \ -D BUILD_INCLUDE_SYMLINK=ON \ @@ -167,7 +168,6 @@ runs: -D BUILD_GTEST=ON \ -D BUILD_CPP_STANDARD=C++17 \ -D INSTALL_GTEST=ON \ - -D CMAKE_CXX_FLAGS="-Werror -Wall -Wextra -Wno-deprecated-declarations -Wno-unknown-warning-option -Wno-error=cast-function-type-mismatch" \ ${{ inputs.additional-cmake-flags }} .. echo "Configuration completed successfully for macOS" shell: bash @@ -183,6 +183,7 @@ runs: cmake -G "Unix Makefiles" \ -D CMAKE_C_COMPILER=${{ inputs.compiler == 'clang' && 'clang' || 'gcc' }} \ -D CMAKE_CXX_COMPILER=${{ inputs.compiler == 'clang' && 'clang++' || 'g++' }} \ + -D CMAKE_CXX_FLAGS="-Werror -Wzero-as-null-pointer-constant -Wno-unknown-warning-option -Wno-error=array-bounds -Wno-error=maybe-uninitialized -Wno-error=stringop-overflow" \ -D BUILD_USE_PCH=${{ inputs.build-use-pch }} \ -D BUILD_INCLUDE_SYMLINK=ON \ -D BUILD_OPT_PROFILE=${{ inputs.build-opt-profile }} \ diff --git a/src/ApplicationFramework/TKTObj/TObj/TObj_Persistence.hxx b/src/ApplicationFramework/TKTObj/TObj/TObj_Persistence.hxx index 781f9566d5..770ae2f381 100644 --- a/src/ApplicationFramework/TKTObj/TObj/TObj_Persistence.hxx +++ b/src/ApplicationFramework/TKTObj/TObj/TObj_Persistence.hxx @@ -117,7 +117,7 @@ private: name::Persistence_ name::myPersistence_; \ occ::handle name::Persistence_::New(const TDF_Label& aLabel) const \ { \ - return new name((const TObj_Persistence*)0, aLabel); \ + return new name(static_cast(nullptr), aLabel); \ } #endif diff --git a/src/DataExchange/TKDEIGES/IGESData/IGESData_IGESWriter.cxx b/src/DataExchange/TKDEIGES/IGESData/IGESData_IGESWriter.cxx index 57d919d0ec..455c2e4a07 100644 --- a/src/DataExchange/TKDEIGES/IGESData/IGESData_IGESWriter.cxx +++ b/src/DataExchange/TKDEIGES/IGESData/IGESData_IGESWriter.cxx @@ -304,7 +304,7 @@ void IGESData_IGESWriter::DirPart(const occ::handle& anent) if (anent->HasShortLabel()) { occ::handle slab = anent->ShortLabel(); - for (i = 0; i < slab->Length(); i++) + for (i = 0; i < slab->Length() && i < 8; i++) label[i] = slab->Value(i + 1); } if (anent->HasSubScriptNumber()) diff --git a/src/DataExchange/TKDESTEP/StepData/StepData_EnumTool.cxx b/src/DataExchange/TKDESTEP/StepData/StepData_EnumTool.cxx index b60d8fb618..a0a3a566f2 100644 --- a/src/DataExchange/TKDESTEP/StepData/StepData_EnumTool.cxx +++ b/src/DataExchange/TKDESTEP/StepData/StepData_EnumTool.cxx @@ -101,7 +101,7 @@ StepData_EnumTool::StepData_EnumTool(const char* const e0, void StepData_EnumTool::AddDefinition(const char* const term) { - char text[80]; + char text[80] = {0}; if (!term) return; if (term[0] == '\0') diff --git a/src/DataExchange/TKDEVRML/VrmlData/VrmlData_Node.hxx b/src/DataExchange/TKDEVRML/VrmlData/VrmlData_Node.hxx index 8adc746071..172f08d696 100644 --- a/src/DataExchange/TKDEVRML/VrmlData/VrmlData_Node.hxx +++ b/src/DataExchange/TKDEVRML/VrmlData/VrmlData_Node.hxx @@ -23,7 +23,8 @@ #include #include -#define VRMLDATA_LCOMPARE(aa, bb) ((strncmp(aa, bb, sizeof(bb) - 1)) ? 0L : (aa += sizeof(bb) - 1)) +#define VRMLDATA_LCOMPARE(aa, bb) \ + ((strncmp(aa, bb, sizeof(bb) - 1)) ? nullptr : (aa += sizeof(bb) - 1)) struct VrmlData_InBuffer; class VrmlData_Scene; diff --git a/src/FoundationClasses/TKMath/MathRoot/MathRoot_Trig.hxx b/src/FoundationClasses/TKMath/MathRoot/MathRoot_Trig.hxx index 9563b91ab0..1a25b16978 100644 --- a/src/FoundationClasses/TKMath/MathRoot/MathRoot_Trig.hxx +++ b/src/FoundationClasses/TKMath/MathRoot/MathRoot_Trig.hxx @@ -348,7 +348,8 @@ inline TrigResult Trigonometric(double theA, return aResult; } - aNZer = aPoly.NbRoots; + // NbRoots is bounded by the fixed storage capacity; clamp defensively. + aNZer = std::min(aPoly.NbRoots, aZer.size()); for (size_t i = 0; i < aNZer; ++i) { aZer[i] = aPoly.Roots[i]; diff --git a/src/FoundationClasses/TKMath/Poly/Poly_MergeNodesTool.cxx b/src/FoundationClasses/TKMath/Poly/Poly_MergeNodesTool.cxx index 95447dd773..b0f57f1913 100644 --- a/src/FoundationClasses/TKMath/Poly/Poly_MergeNodesTool.cxx +++ b/src/FoundationClasses/TKMath/Poly/Poly_MergeNodesTool.cxx @@ -360,7 +360,9 @@ void Poly_MergeNodesTool::PushLastElement(int theNbNodes) if (myToMergeElems) { NCollection_Vec4 aSorted = myNodeInds; - std::sort(aSorted.ChangeData(), aSorted.ChangeData() + theNbNodes); + // theNbNodes is bounded by the Vec4 capacity; clamp defensively. + const int aNbToSort = std::min(theNbNodes, 4); + std::sort(aSorted.ChangeData(), aSorted.ChangeData() + aNbToSort); if (!myElemMap.Add(aSorted)) { ++myNbMergedElems; diff --git a/src/FoundationClasses/TKernel/FlexLexer/FlexLexer.h b/src/FoundationClasses/TKernel/FlexLexer/FlexLexer.h index 59c8df6140..b653539979 100644 --- a/src/FoundationClasses/TKernel/FlexLexer/FlexLexer.h +++ b/src/FoundationClasses/TKernel/FlexLexer/FlexLexer.h @@ -81,7 +81,7 @@ extern "C++" return yylex(); } - int yylex(std::istream* new_in, std::ostream* new_out = 0) + int yylex(std::istream* new_in, std::ostream* new_out = nullptr) { switch_streams(new_in, new_out); return yylex(); @@ -122,7 +122,7 @@ extern "C++" // arg_yyin and arg_yyout default to the cin and cout, but we // only make that assignment when initializing in yylex(). yyFlexLexer(std::istream& arg_yyin, std::ostream& arg_yyout); - yyFlexLexer(std::istream* arg_yyin = 0, std::ostream* arg_yyout = 0); + yyFlexLexer(std::istream* arg_yyin = nullptr, std::ostream* arg_yyout = nullptr); private: void ctor_common(); @@ -142,7 +142,7 @@ extern "C++" virtual int yylex(); virtual void switch_streams(std::istream& new_in, std::ostream& new_out); - virtual void switch_streams(std::istream* new_in = 0, std::ostream* new_out = 0); + virtual void switch_streams(std::istream* new_in = nullptr, std::ostream* new_out = nullptr); virtual int yywrap(); protected: diff --git a/src/FoundationClasses/TKernel/Message/Message_PrinterOStream.cxx b/src/FoundationClasses/TKernel/Message/Message_PrinterOStream.cxx index 70c3d4cbb1..b8e8368038 100644 --- a/src/FoundationClasses/TKernel/Message/Message_PrinterOStream.cxx +++ b/src/FoundationClasses/TKernel/Message/Message_PrinterOStream.cxx @@ -218,7 +218,7 @@ void Message_PrinterOStream::SetConsoleTextColor(Standard_OStream* theOStream return; } - const char* aCode; + const char* aCode = ""; switch (theTextColor) { case Message_ConsoleColor_Default: diff --git a/src/FoundationClasses/TKernel/NCollection/NCollection_LocalArray.hxx b/src/FoundationClasses/TKernel/NCollection/NCollection_LocalArray.hxx index b80a6fd194..3bb41a35ab 100644 --- a/src/FoundationClasses/TKernel/NCollection/NCollection_LocalArray.hxx +++ b/src/FoundationClasses/TKernel/NCollection/NCollection_LocalArray.hxx @@ -180,15 +180,17 @@ public: { if (theOther.isInline()) { + // When the source is inline, mySize is bounded by MAX_ARRAY_SIZE. + const size_t aNb = std::min(mySize, static_cast(MAX_ARRAY_SIZE)); if constexpr (IS_TRIVIAL) { - std::memcpy(inlinePtr(), theOther.inlinePtr(), mySize * sizeof(theItem)); + std::memcpy(inlinePtr(), theOther.inlinePtr(), aNb * sizeof(theItem)); } else { - for (size_t i = 0; i < mySize; ++i) + for (size_t i = 0; i < aNb; ++i) new (inlinePtr() + i) theItem(std::move(theOther.inlinePtr()[i])); - for (size_t i = 0; i < mySize; ++i) + for (size_t i = 0; i < aNb; ++i) theOther.inlinePtr()[i].~theItem(); } } @@ -212,7 +214,9 @@ public: { Deallocate(); myPtr = inlinePtr(); - std::memcpy(inlinePtr(), theOther.inlinePtr(), mySize * sizeof(theItem)); + // When the source is inline, mySize is bounded by MAX_ARRAY_SIZE. + const size_t aNb = std::min(mySize, static_cast(MAX_ARRAY_SIZE)); + std::memcpy(inlinePtr(), theOther.inlinePtr(), aNb * sizeof(theItem)); } else if (!isInline()) { @@ -240,9 +244,11 @@ public: Standard::Free(myPtr); myPtr = inlinePtr(); mySize = theOther.mySize; - for (size_t i = 0; i < mySize; ++i) + // When the source is inline, mySize is bounded by MAX_ARRAY_SIZE. + const size_t aNb = std::min(mySize, static_cast(MAX_ARRAY_SIZE)); + for (size_t i = 0; i < aNb; ++i) new (inlinePtr() + i) theItem(std::move(theOther.inlinePtr()[i])); - for (size_t i = 0; i < mySize; ++i) + for (size_t i = 0; i < aNb; ++i) theOther.inlinePtr()[i].~theItem(); } else diff --git a/src/ModelingAlgorithms/TKGeomAlgo/ApproxInt/ApproxInt_MultiLine.gxx b/src/ModelingAlgorithms/TKGeomAlgo/ApproxInt/ApproxInt_MultiLine.gxx index e391ba8bca..5d9aa2e297 100644 --- a/src/ModelingAlgorithms/TKGeomAlgo/ApproxInt/ApproxInt_MultiLine.gxx +++ b/src/ModelingAlgorithms/TKGeomAlgo/ApproxInt/ApproxInt_MultiLine.gxx @@ -110,7 +110,7 @@ ApproxInt_MultiLine::ApproxInt_MultiLine(const Handle_TheLine& line, const bool P2DOnFirst, const int IndMin, const int IndMax) - : PtrOnmySvSurfaces(0), + : PtrOnmySvSurfaces(nullptr), myLine(line), indicemin(std::min(IndMin, IndMax)), indicemax(std::max(IndMin, IndMax)), diff --git a/src/ModelingAlgorithms/TKMesh/BRepMesh/delabella.pxx b/src/ModelingAlgorithms/TKMesh/BRepMesh/delabella.pxx index dba612c90d..bc9f0aa201 100644 --- a/src/ModelingAlgorithms/TKMesh/BRepMesh/delabella.pxx +++ b/src/ModelingAlgorithms/TKMesh/BRepMesh/delabella.pxx @@ -68,11 +68,11 @@ struct IDelaBella // it is treated as 2*sizeof coordinate type virtual int Triangulate(int points, const float* x, - const float* y = 0, + const float* y = nullptr, int advance_bytes = 0) = 0; virtual int Triangulate(int points, const double* x, - const double* y = 0, + const double* y = nullptr, int advance_bytes = 0) = 0; // num of points passed to last call to Triangulate() diff --git a/src/Visualization/TKOpenGl/OpenGl/OpenGl_Context.hxx b/src/Visualization/TKOpenGl/OpenGl/OpenGl_Context.hxx index 4da36f3835..5d2e33ce29 100644 --- a/src/Visualization/TKOpenGl/OpenGl/OpenGl_Context.hxx +++ b/src/Visualization/TKOpenGl/OpenGl/OpenGl_Context.hxx @@ -278,7 +278,7 @@ public: bool Init(EAGLContext* theGContext, const bool theIsCoreProfile = false) { return Init((Aspect_Drawable)0, - (Aspect_Display)0, + (Aspect_Display) nullptr, (Aspect_RenderingContext)theGContext, theIsCoreProfile); } @@ -288,7 +288,7 @@ public: bool Init(NSOpenGLContext* theGContext, const bool theIsCoreProfile = false) { return Init((Aspect_Drawable)0, - (Aspect_Display)0, + (Aspect_Display) nullptr, (Aspect_RenderingContext)theGContext, theIsCoreProfile); } diff --git a/src/Visualization/TKOpenGl/OpenGl/OpenGl_Window_1.mm b/src/Visualization/TKOpenGl/OpenGl/OpenGl_Window_1.mm index 1a86166fc3..0f407ee33c 100644 --- a/src/Visualization/TKOpenGl/OpenGl/OpenGl_Window_1.mm +++ b/src/Visualization/TKOpenGl/OpenGl/OpenGl_Window_1.mm @@ -76,7 +76,7 @@ void OpenGl_Window::Init (const occ::handle& theDriver, const occ::handle& theShareCtx) { myGlContext = new OpenGl_Context (theCaps); - myOwnGContext = (theGContext == 0); + myOwnGContext = (theGContext == nullptr); myPlatformWindow = thePlatformWindow; mySizeWindow = theSizeWindow; #if defined(__APPLE__) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE diff --git a/src/Visualization/TKService/Xw/Xw_Window.cxx b/src/Visualization/TKService/Xw/Xw_Window.cxx index eac592448a..ae648008c0 100644 --- a/src/Visualization/TKService/Xw/Xw_Window.cxx +++ b/src/Visualization/TKService/Xw/Xw_Window.cxx @@ -75,18 +75,19 @@ Xw_Window::Xw_Window(const occ::handle& theXDisplay, aWinAttr.border_pixel = 0; aWinAttr.override_redirect = False; - myXWindow = (Window)XCreateWindow(aDisp, - aParent, - myXLeft, - myYTop, - thePxWidth, - thePxHeight, - 0, - aVisInfo != nullptr ? aVisInfo->depth : CopyFromParent, - InputOutput, - aVisInfo != nullptr ? aVisInfo->visual : CopyFromParent, - CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, - &aWinAttr); + myXWindow = + (Window)XCreateWindow(aDisp, + aParent, + myXLeft, + myYTop, + thePxWidth, + thePxHeight, + 0, + aVisInfo != nullptr ? aVisInfo->depth : CopyFromParent, + InputOutput, + aVisInfo != nullptr ? aVisInfo->visual : static_cast(nullptr), + CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, + &aWinAttr); if (myXWindow == 0) { throw Aspect_WindowDefinitionError("Xw_Window, Unable to create window"); diff --git a/src/Visualization/TKV3d/SelectMgr/SelectMgr_BaseIntersector.cxx b/src/Visualization/TKV3d/SelectMgr/SelectMgr_BaseIntersector.cxx index 72d09f0a74..91c2eb4cfb 100644 --- a/src/Visualization/TKV3d/SelectMgr/SelectMgr_BaseIntersector.cxx +++ b/src/Visualization/TKV3d/SelectMgr/SelectMgr_BaseIntersector.cxx @@ -244,7 +244,9 @@ bool SelectMgr_BaseIntersector::RayCylinderIntersection(const double theBottomR return false; } - std::sort(anIntersections, anIntersections + aNbIntersections); + // aNbIntersections is bounded by the fixed 4-element buffer; clamp defensively. + const int aNbToSort = std::min(aNbIntersections, 4); + std::sort(anIntersections, anIntersections + aNbToSort); theTimeEnter = anIntersections[0]; if (aNbIntersections > 1) {